Limit HTTP body size

This commit is contained in:
Noah Hilverling 2018-02-19 13:33:58 +01:00 committed by Jean Flach
parent 817415f6a5
commit 2823ebb831
3 changed files with 55 additions and 16 deletions

View File

@ -208,23 +208,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.
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:
Permissions | URL Endpoint | Supports Filters
------------------------------|---------------|-----------------
actions/<action> | /v1/actions | Yes
config/query | /v1/config | No
config/modify | /v1/config | No
console | /v1/console | No
events/<type> | /v1/events | No
objects/query/<type> | /v1/objects | Yes
objects/create/<type> | /v1/objects | No
objects/modify/<type> | /v1/objects | Yes
objects/delete/<type> | /v1/objects | Yes
status/query | /v1/status | Yes
templates/<type> | /v1/templates | Yes
types | /v1/types | Yes
variables | /v1/variables | Yes
Permissions | URL Endpoint | Supports Filters | Max Body Size in MB
------------------------------|---------------|-------------------|---------------------
actions/<action> | /v1/actions | Yes | 1
config/query | /v1/config | No | 1
config/modify | /v1/config | No | 512
console | /v1/console | No | 512
events/<type> | /v1/events | No | 1
objects/query/<type> | /v1/objects | Yes | 1
objects/create/<type> | /v1/objects | No | 512
objects/modify/<type> | /v1/objects | Yes | 512
objects/delete/<type> | /v1/objects | Yes | 512
status/query | /v1/status | Yes | 1
templates/<type> | /v1/templates | Yes | 1
types | /v1/types | Yes | 1
variables | /v1/variables | Yes | 1
The required actions or types can be replaced by using a wildcard match ("\*").

View File

@ -36,7 +36,8 @@ ApiUser::Ptr ApiUser::GetByClientCN(const String& cn)
return nullptr;
}
ApiUser::Ptr ApiUser::GetByAuthHeader(const String& auth_header) {
ApiUser::Ptr ApiUser::GetByAuthHeader(const String& auth_header)
{
String::SizeType pos = auth_header.FindFirstOf(" ");
String username, password;

View File

@ -95,6 +95,7 @@ void HttpServerConnection::Disconnect()
bool HttpServerConnection::ProcessMessage()
{
bool res;
HttpResponse response(m_Stream, m_CurrentRequest);
@ -186,6 +187,16 @@ bool HttpServerConnection::ProcessMessage()
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") {
String continueResponse = "HTTP/1.1 100 Continue\r\n\r\n";
m_Stream->Write(continueResponse.CStr(), continueResponse.GetLength());
@ -276,6 +287,29 @@ bool HttpServerConnection::ManageHeaders(HttpResponse& response)
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;
}