mirror of
https://github.com/Icinga/icinga2.git
synced 2026-02-19 02:29:16 -05:00
Allow to set extra headers in HTTP responses
Use case: Allow settings headers like Strict-Transport-Security if one likes. How this headers would benefit the Icinga 2 API is questionable, but there are security scanners that see HTTPS and complain about it, so this gives an easy way to make them happy (with this probably being the only benefit).
This commit is contained in:
parent
aca67f6d88
commit
985db970bb
4 changed files with 38 additions and 0 deletions
|
|
@ -8,6 +8,7 @@
|
|||
#include "remote/apifunction.hpp"
|
||||
#include "remote/configpackageutility.hpp"
|
||||
#include "remote/configobjectutility.hpp"
|
||||
#include "remote/httputility.hpp"
|
||||
#include "base/atomic-file.hpp"
|
||||
#include "base/convert.hpp"
|
||||
#include "base/defer.hpp"
|
||||
|
|
@ -2008,6 +2009,31 @@ void ApiListener::ValidateTlsHandshakeTimeout(const Lazy<double>& lvalue, const
|
|||
BOOST_THROW_EXCEPTION(ValidationError(this, { "tls_handshake_timeout" }, "Value must be greater than 0."));
|
||||
}
|
||||
|
||||
void ApiListener::ValidateHttpResponseHeaders(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
|
||||
{
|
||||
ObjectImpl::ValidateHttpResponseHeaders(lvalue, utils);
|
||||
|
||||
if (Dictionary::Ptr headers = lvalue(); headers) {
|
||||
ObjectLock lock(headers);
|
||||
for (auto& [name, value] : headers) {
|
||||
if (!HttpUtility::IsValidHeaderName(name.GetData())) {
|
||||
BOOST_THROW_EXCEPTION(ValidationError(this, { "http_response_headers", name },
|
||||
"Header name is invalid."));
|
||||
}
|
||||
|
||||
if (!value.IsString()) {
|
||||
BOOST_THROW_EXCEPTION(ValidationError(this, { "http_response_headers", name },
|
||||
"Header value must be a string."));
|
||||
}
|
||||
|
||||
if (!HttpUtility::IsValidHeaderValue(value.Get<String>().GetData())) {
|
||||
BOOST_THROW_EXCEPTION(ValidationError(this, { "http_response_headers", name },
|
||||
"Header value is invalid."));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ApiListener::IsHACluster()
|
||||
{
|
||||
Zone::Ptr zone = Zone::GetLocalZone();
|
||||
|
|
|
|||
|
|
@ -170,6 +170,7 @@ public:
|
|||
protected:
|
||||
void ValidateTlsProtocolmin(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
|
||||
void ValidateTlsHandshakeTimeout(const Lazy<double>& lvalue, const ValidationUtils& utils) override;
|
||||
void ValidateHttpResponseHeaders(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
|
||||
|
||||
private:
|
||||
Shared<boost::asio::ssl::context>::Ptr m_SSLContext;
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ class ApiListener : ConfigObject
|
|||
[config, deprecated] String access_control_allow_headers;
|
||||
[config, deprecated] String access_control_allow_methods;
|
||||
|
||||
[config] Dictionary::Ptr http_response_headers;
|
||||
|
||||
[state, no_user_modify] Timestamp log_message_timestamp;
|
||||
|
||||
|
|
|
|||
|
|
@ -466,6 +466,16 @@ void HttpServerConnection::ProcessMessages(boost::asio::yield_context yc)
|
|||
request.Parser().body_limit(-1);
|
||||
|
||||
response.set(http::field::server, l_ServerHeader);
|
||||
if (auto listener (ApiListener::GetInstance()); listener) {
|
||||
if (Dictionary::Ptr headers = listener->GetHttpResponseHeaders(); headers) {
|
||||
ObjectLock lock(headers);
|
||||
for (auto& [header, value] : headers) {
|
||||
if (value.IsString()) {
|
||||
response.set(header, value.Get<String>());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!EnsureValidHeaders(buf, request, response, m_ShuttingDown, yc)) {
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in a new issue