From c5c17928a6e11c7996822dfd794ed994a8227ce7 Mon Sep 17 00:00:00 2001 From: Mattia Codato Date: Wed, 12 Apr 2023 17:30:04 +0200 Subject: [PATCH] Allow to exec command on endpoint where the checkable is not present but checkable has command_endpoint specified --- lib/icinga/apiactions.cpp | 10 ++++++++-- lib/icinga/clusterevents.cpp | 12 ++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/icinga/apiactions.cpp b/lib/icinga/apiactions.cpp index 2d35c466770..4a2759bb2a5 100644 --- a/lib/icinga/apiactions.cpp +++ b/lib/icinga/apiactions.cpp @@ -681,9 +681,15 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons if (!endpointPtr) return ApiActions::CreateResult(404, "Can't find a valid endpoint for '" + resolved_endpoint + "'."); - /* Check if the endpoint zone can access the checkable */ + /* Return an error when + * the endpoint is different from the command endpoint of the checkable + * and the endpoint zone can't access the checkable. + * The endpoints are checked to allow for the case where command_endpoint is specified in the checkable + * but checkable is not actually present in the agent. + */ Zone::Ptr endpointZone = endpointPtr->GetZone(); - if (!endpointZone->CanAccessObject(checkable)) { + Endpoint::Ptr commandEndpoint = checkable->GetCommandEndpoint(); + if (endpointPtr != commandEndpoint && !endpointZone->CanAccessObject(checkable)) { return ApiActions::CreateResult( 409, "Zone '" + endpointZone->GetName() + "' cannot access checkable '" + checkable->GetName() + "'." diff --git a/lib/icinga/clusterevents.cpp b/lib/icinga/clusterevents.cpp index d1e58c55af0..b76ed492305 100644 --- a/lib/icinga/clusterevents.cpp +++ b/lib/icinga/clusterevents.cpp @@ -817,7 +817,7 @@ Value ClusterEvents::ExecuteCommandAPIHandler(const MessageOrigin::Ptr& origin, Host::Ptr host = Host::GetByName(params->Get("host")); if (!host) { Log(LogWarning, "ClusterEvents") - << "Discarding 'execute command' message " << executionUuid + << "Discarding 'execute command' message " << executionUuid << ": host " << params->Get("host") << " does not exist"; return Empty; } @@ -833,12 +833,16 @@ Value ClusterEvents::ExecuteCommandAPIHandler(const MessageOrigin::Ptr& origin, checkableName += "!" + params->Get("service"); Log(LogWarning, "ClusterEvents") - << "Discarding 'execute command' message " << executionUuid + << "Discarding 'execute command' message " << executionUuid << ": " << checkableName << " does not exist"; return Empty; } - /* Check if the child zone can access the checkable, and if it's the same endpoint zone */ + /* Return an error when the endpointZone is different than the child zone and + * the child zone can't access the checkable. + * The zones are checked to allow for the case where command_endpoint is specified in the checkable + * but checkable is not actually present in the agent. + */ if (!zone->CanAccessObject(checkable) && zone != endpointZone) { double now = Utility::GetTime(); Dictionary::Ptr executedParams = new Dictionary(); @@ -1276,7 +1280,7 @@ Value ClusterEvents::ExecutedCommandAPIHandler(const MessageOrigin::Ptr& origin, return Empty; } - if (origin->FromZone && !origin->FromZone->CanAccessObject(command_endpoint->GetZone())) { + if (origin->FromZone && !command_endpoint->GetZone()->IsChildOf(origin->FromZone)) { Log(LogNotice, "ClusterEvents") << "Discarding 'update executions API handler' message for checkable '" << checkable->GetName() << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";