Merge pull request #6595 from Icinga/feature/limit-anonymous-rpc-connections

Allow to configure anonymous clients limit inside the ApiListener object
This commit is contained in:
Michael Friedrich 2018-09-06 13:26:46 +02:00 committed by GitHub
commit 7e0f2f07a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 22 additions and 6 deletions

View File

@ -61,6 +61,7 @@ Configuration Attributes:
bind\_port | Number | **Optional.** The port the api listener should be bound to. Defaults to `5665`.
accept\_config | Boolean | **Optional.** Accept zone configuration. Defaults to `false`.
accept\_commands | Boolean | **Optional.** Accept remote commands. Defaults to `false`.
max\_anonymous\_clients | Number | **Optional.** Limit the number of anonymous client connections (not configured endpoints and signing requests).
cipher\_list | String | **Optional.** Cipher list that is allowed. For a list of available ciphers run `openssl ciphers`. Defaults to `ALL:!LOW:!WEAK:!MEDIUM:!EXP:!NULL`.
tls\_protocolmin | String | **Optional.** Minimum TLS protocol version. Must be one of `TLSv1`, `TLSv1.1` or `TLSv1.2`. Defaults to `TLSv1`.
access\_control\_allow\_origin | Array | **Optional.** Specifies an array of origin URLs that may access the API. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Origin)

View File

@ -49,6 +49,14 @@ New [Icinga constants](17-language-reference.md#icinga-constants) have been adde
The keywords `namespace` and `using` are now [reserved](17-language-reference.md#reserved-keywords) for the namespace functionality provided
with v2.10. Read more about how it works [here](17-language-reference.md#namespaces).
### Configuration: ApiListener <a id="upgrading-to-2-10-configuration-apilistener"></a>
Anonymous JSON-RPC connections in the cluster can now be configured with `max_anonymous_clients`
attribute.
The corresponding REST API results from `/v1/status/ApiListener` in `json_rpc` have been renamed
from `clients` to `anonymous_clients` to better reflect their purpose. Authenticated clients
are counted as connected endpoints. A similar change is there for the performance data metrics.
### API: schedule-downtime Action <a id="upgrading-to-2-10-api-schedule-downtime-action"></a>
The attribute `child_options` was previously accepting 0,1,2 for specific child downtime settings.

View File

@ -566,7 +566,9 @@ void ApiListener::NewClientHandlerInternal(const Socket::Ptr& client, const Stri
m_SyncQueue.Enqueue(std::bind(&ApiListener::SyncClient, this, aclient, endpoint, needSync));
} else {
if (!AddAnonymousClient(aclient)) {
Log(LogNotice, "ApiListener", "Ignoring anonymous JSON-RPC connection. Max connections exceeded.");
Log(LogNotice, "ApiListener")
<< "Ignoring anonymous JSON-RPC connection " << conninfo
<< ". Max connections (" << GetMaxAnonymousClients() << ") exceeded.";
aclient->Disconnect();
}
}
@ -1315,7 +1317,7 @@ std::pair<Dictionary::Ptr, Dictionary::Ptr> ApiListener::GetStatus()
}
/* connection stats */
size_t jsonRpcClients = GetAnonymousClients().size();
size_t jsonRpcAnonymousClients = GetAnonymousClients().size();
size_t httpClients = GetHttpClients().size();
size_t workQueueItems = JsonRpcConnection::GetWorkQueueLength();
size_t workQueueCount = JsonRpcConnection::GetWorkQueueCount();
@ -1336,7 +1338,7 @@ std::pair<Dictionary::Ptr, Dictionary::Ptr> ApiListener::GetStatus()
{ "zones", connectedZones },
{ "json_rpc", new Dictionary({
{ "clients", jsonRpcClients },
{ "anonymous_clients", jsonRpcAnonymousClients },
{ "work_queue_items", workQueueItems },
{ "work_queue_count", workQueueCount },
{ "sync_queue_items", syncQueueItems },
@ -1356,7 +1358,7 @@ std::pair<Dictionary::Ptr, Dictionary::Ptr> ApiListener::GetStatus()
perfdata->Set("num_conn_endpoints", Convert::ToDouble(allConnectedEndpoints->GetLength()));
perfdata->Set("num_not_conn_endpoints", Convert::ToDouble(allNotConnectedEndpoints->GetLength()));
perfdata->Set("num_json_rpc_clients", jsonRpcClients);
perfdata->Set("num_json_rpc_anonymous_clients", jsonRpcAnonymousClients);
perfdata->Set("num_http_clients", httpClients);
perfdata->Set("num_json_rpc_work_queue_items", workQueueItems);
perfdata->Set("num_json_rpc_work_queue_count", workQueueCount);
@ -1384,7 +1386,8 @@ double ApiListener::CalculateZoneLag(const Endpoint::Ptr& endpoint)
bool ApiListener::AddAnonymousClient(const JsonRpcConnection::Ptr& aclient)
{
boost::mutex::scoped_lock lock(m_AnonymousClientsLock);
if (m_AnonymousClients.size() > 100)
if (GetMaxAnonymousClients() >= 0 && m_AnonymousClients.size() + 1 > GetMaxAnonymousClients())
return false;
m_AnonymousClients.insert(aclient);

View File

@ -50,6 +50,9 @@ class ApiListener : ConfigObject
[config] bool accept_config;
[config] bool accept_commands;
[config] int max_anonymous_clients {
default {{{ return -1; }}}
};
[config] String ticket_salt;

View File

@ -248,7 +248,8 @@ void JsonRpcConnection::MessageHandler(const String& jsonString)
bool JsonRpcConnection::ProcessMessage()
{
ssize_t maxMessageLength = 64 * 1024;
/* Limit for anonymous clients (signing requests and not configured endpoints. */
ssize_t maxMessageLength = 1024 * 1024;
if (m_Endpoint)
maxMessageLength = -1; /* no limit */