mirror of https://github.com/Icinga/icinga2.git
Limit HTTP body size
This commit is contained in:
parent
3fe818b44b
commit
4b77afedcd
|
@ -201,23 +201,27 @@ The [regex function](18-library-reference.md#global-functions-regex) is availabl
|
||||||
|
|
||||||
More information about filters can be found in the [filters](12-icinga2-api.md#icinga2-api-filters) chapter.
|
More information about filters can be found in the [filters](12-icinga2-api.md#icinga2-api-filters) chapter.
|
||||||
|
|
||||||
|
Note that the permissions a API user has also specify the max body size of their requests.
|
||||||
|
A API user with `*` permissions is allowed to send 512 MB.
|
||||||
|
|
||||||
|
|
||||||
Available permissions for specific URL endpoints:
|
Available permissions for specific URL endpoints:
|
||||||
|
|
||||||
Permissions | URL Endpoint | Supports Filters
|
Permissions | URL Endpoint | Supports Filters | Max Body Size in MB
|
||||||
------------------------------|---------------|-----------------
|
------------------------------|---------------|-------------------|---------------------
|
||||||
actions/<action> | /v1/actions | Yes
|
actions/<action> | /v1/actions | Yes | 1
|
||||||
config/query | /v1/config | No
|
config/query | /v1/config | No | 1
|
||||||
config/modify | /v1/config | No
|
config/modify | /v1/config | No | 512
|
||||||
console | /v1/console | No
|
console | /v1/console | No | 512
|
||||||
events/<type> | /v1/events | No
|
events/<type> | /v1/events | No | 1
|
||||||
objects/query/<type> | /v1/objects | Yes
|
objects/query/<type> | /v1/objects | Yes | 1
|
||||||
objects/create/<type> | /v1/objects | No
|
objects/create/<type> | /v1/objects | No | 512
|
||||||
objects/modify/<type> | /v1/objects | Yes
|
objects/modify/<type> | /v1/objects | Yes | 512
|
||||||
objects/delete/<type> | /v1/objects | Yes
|
objects/delete/<type> | /v1/objects | Yes | 512
|
||||||
status/query | /v1/status | Yes
|
status/query | /v1/status | Yes | 1
|
||||||
templates/<type> | /v1/templates | Yes
|
templates/<type> | /v1/templates | Yes | 1
|
||||||
types | /v1/types | Yes
|
types | /v1/types | Yes | 1
|
||||||
variables | /v1/variables | Yes
|
variables | /v1/variables | Yes | 1
|
||||||
|
|
||||||
The required actions or types can be replaced by using a wildcard match ("\*").
|
The required actions or types can be replaced by using a wildcard match ("\*").
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,8 @@ ApiUser::Ptr ApiUser::GetByClientCN(const String& cn)
|
||||||
return ApiUser::Ptr();
|
return ApiUser::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
ApiUser::Ptr ApiUser::GetByAuthHeader(const String& auth_header) {
|
ApiUser::Ptr ApiUser::GetByAuthHeader(const String& auth_header)
|
||||||
|
{
|
||||||
String::SizeType pos = auth_header.FindFirstOf(" ");
|
String::SizeType pos = auth_header.FindFirstOf(" ");
|
||||||
String username, password;
|
String username, password;
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ void HttpServerConnection::Disconnect(void)
|
||||||
|
|
||||||
bool HttpServerConnection::ProcessMessage(void)
|
bool HttpServerConnection::ProcessMessage(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
bool res;
|
bool res;
|
||||||
HttpResponse response(m_Stream, m_CurrentRequest);
|
HttpResponse response(m_Stream, m_CurrentRequest);
|
||||||
|
|
||||||
|
@ -186,6 +187,16 @@ bool HttpServerConnection::ProcessMessage(void)
|
||||||
|
|
||||||
bool HttpServerConnection::ManageHeaders(HttpResponse& response)
|
bool HttpServerConnection::ManageHeaders(HttpResponse& response)
|
||||||
{
|
{
|
||||||
|
static const size_t defaultContentLengthLimit = 1 * 1028 * 1028;
|
||||||
|
static const Dictionary::Ptr specialContentLengthLimits = new Dictionary({
|
||||||
|
{"*", 512 * 1028 * 1028},
|
||||||
|
{"config/modify", 512 * 1028 * 1028},
|
||||||
|
{"console", 512 * 1028 * 1028},
|
||||||
|
{"objects/create", 512 * 1028 * 1028},
|
||||||
|
{"objects/modify", 512 * 1028 * 1028},
|
||||||
|
{"objects/delete", 512 * 1028 * 1028}
|
||||||
|
});
|
||||||
|
|
||||||
if (m_CurrentRequest.Headers->Get("expect") == "100-continue") {
|
if (m_CurrentRequest.Headers->Get("expect") == "100-continue") {
|
||||||
String continueResponse = "HTTP/1.1 100 Continue\r\n\r\n";
|
String continueResponse = "HTTP/1.1 100 Continue\r\n\r\n";
|
||||||
m_Stream->Write(continueResponse.CStr(), continueResponse.GetLength());
|
m_Stream->Write(continueResponse.CStr(), continueResponse.GetLength());
|
||||||
|
@ -276,6 +287,29 @@ bool HttpServerConnection::ManageHeaders(HttpResponse& response)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t maxSize = defaultContentLengthLimit;
|
||||||
|
|
||||||
|
Array::Ptr permissions = m_AuthenticatedUser->GetPermissions();
|
||||||
|
ObjectLock olock(permissions);
|
||||||
|
|
||||||
|
for (const Value& permission : permissions) {
|
||||||
|
std::vector<String> permissionParts = String(permission).Split("/");
|
||||||
|
String permissionPath = permissionParts[0] + (permissionParts.size() > 1 ? "/" + permissionParts[1] : "");
|
||||||
|
int size = specialContentLengthLimits->Get(permissionPath);
|
||||||
|
maxSize = size > maxSize ? size : maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t contentLength = m_CurrentRequest.Headers->Get("content-length");
|
||||||
|
|
||||||
|
if (contentLength > maxSize) {
|
||||||
|
response.SetStatus(400, "Bad Request");
|
||||||
|
String msg = String("<h1>Content length exceeded maximum</h1>");
|
||||||
|
response.WriteBody(msg.CStr(), msg.GetLength());
|
||||||
|
response.Finish();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue