Skip to content

ApiListener: Add external_ca flag to control renewal behavior #9026

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/09-object-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -1109,6 +1109,7 @@ Configuration Attributes:
access\_control\_allow\_headers | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP headers can be used when making the actual request. Defaults to `Authorization`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Headers)
access\_control\_allow\_methods | String | **Deprecated.** Used in response to a preflight request to indicate which HTTP methods can be used when making the actual request. Defaults to `GET, POST, PUT, DELETE`. [(MDN docs)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Access-Control-Allow-Methods)
environment | String | **Optional.** Used as suffix in TLS SNI extension name; default from constant `ApiEnvironment`, which is empty.
external_ca | String | **Optional.** Certificates used are not managed by Icinga, disables certificate renewal logic inside Icinga's RPC API. Especially useful for external roots with intermediate chain certificates.

The attributes `access_control_allow_credentials`, `access_control_allow_headers` and `access_control_allow_methods`
are controlled by Icinga 2 and are not changeable by config any more.
Expand All @@ -1128,6 +1129,9 @@ file(s) there are newer.

Please check the [upgrading chapter](16-upgrading-icinga-2.md#upgrading-to-2-8-certificate-paths) for more details.

When certificates from Puppet or any corporate root CA is used, you should enable `external_ca` to disable some
certificate handling logic within the API connection routines of Icinga 2.

While Icinga 2 and the underlying OpenSSL library use sane and secure defaults, the attributes
`cipher_list` and `tls_protocolmin` can be used to increase communication security. A good source
for a more secure configuration is provided by the [Mozilla Wiki](https://wiki.mozilla.org/Security/Server_Side_TLS).
Expand Down
5 changes: 2 additions & 3 deletions lib/remote/apilistener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,9 +770,8 @@ void ApiListener::SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoi
endpoint->SetSyncing(true);
}

Zone::Ptr myZone = Zone::GetLocalZone();

if (myZone->GetParent() == eZone) {
// When external_ca is not configured and client is from parent zone, evaluate certificate renewal.
if (!GetExternalCa() && Zone::GetLocalZone()->GetParent() == eZone) {
Log(LogInformation, "ApiListener")
<< "Requesting new certificate for this Icinga instance from endpoint '" << endpoint->GetName() << "'.";

Expand Down
1 change: 1 addition & 0 deletions lib/remote/apilistener.ti
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class ApiListener : ConfigObject
[config, deprecated] String access_control_allow_headers;
[config, deprecated] String access_control_allow_methods;

[config] bool external_ca;

[state, no_user_modify] Timestamp log_message_timestamp;

Expand Down
14 changes: 10 additions & 4 deletions lib/remote/jsonrpcconnection-pki.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,19 @@ REGISTER_APIFUNCTION(UpdateCertificate, pki, &UpdateCertificateHandler);

Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params)
{
ApiListener::Ptr listener = ApiListener::GetInstance();

Dictionary::Ptr result = new Dictionary();

// When external_ca is configured, ignore any request via RPC.
if (listener->GetExternalCa()) {
return Empty;
}

String certText = params->Get("cert_request");

std::shared_ptr<X509> cert;

Dictionary::Ptr result = new Dictionary();

/* Use the presented client certificate if not provided. */
if (certText.IsEmpty()) {
auto stream (origin->FromClient->GetStream());
Expand All @@ -48,7 +55,6 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona
return result;
}

ApiListener::Ptr listener = ApiListener::GetInstance();
std::shared_ptr<X509> cacert = GetX509Certificate(listener->GetDefaultCaPath());

String cn = GetCertificateCN(cert);
Expand Down Expand Up @@ -328,7 +334,7 @@ Value UpdateCertificateHandler(const MessageOrigin::Ptr& origin, const Dictionar

ApiListener::Ptr listener = ApiListener::GetInstance();

if (!listener)
if (!listener || listener->GetExternalCa())
return Empty;

std::shared_ptr<X509> oldCert = GetX509Certificate(listener->GetDefaultCertPath());
Expand Down