Skip to content

Commit

Permalink
Fix update execution message discarded
Browse files Browse the repository at this point in the history
refs #8616
  • Loading branch information
Mattia Codato committed Jul 30, 2021
1 parent 4c90709 commit 3c1835d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 8 deletions.
22 changes: 22 additions & 0 deletions lib/icinga/apiactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -806,6 +806,7 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons
Dictionary::Ptr pending_execution = new Dictionary();
pending_execution->Set("pending", true);
pending_execution->Set("deadline", deadline);
pending_execution->Set("endpoint", resolved_endpoint);
Dictionary::Ptr executions = checkable->GetExecutions();

if (!executions)
Expand Down Expand Up @@ -890,6 +891,27 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons
return ApiActions::CreateResult(202, "Accepted", result);
}
}

/* Check if the child zone can access the checkable */
if (!zone->CanAccessObject(checkable)) {
/* Update execution */
double now = Utility::GetTime();
pending_execution->Set("exit", 126);
pending_execution->Set(
"output",
"Zone '" + zone->GetName() + "' cannot access to checkable '" + checkable->GetName() + "'."
);
pending_execution->Set("start", now);
pending_execution->Set("end", now);
pending_execution->Remove("pending");

listener->RelayMessage(origin, checkable, updateMessage, true);

Dictionary::Ptr result = new Dictionary();
result->Set("checkable", checkable->GetName());
result->Set("execution", uuid);
return ApiActions::CreateResult(202, "Accepted", result);
}
}
}

Expand Down
65 changes: 57 additions & 8 deletions lib/icinga/clusterevents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,11 @@ Value ClusterEvents::ExecuteCommandAPIHandler(const MessageOrigin::Ptr& origin,
if (params->Contains("endpoint")) {
Endpoint::Ptr execEndpoint = Endpoint::GetByName(params->Get("endpoint"));

if (!execEndpoint) {
Log(LogWarning, "ClusterEvents") << "Endpoint " << params->Get("endpoint") << " does not exist";
return Empty;
}

if (execEndpoint != Endpoint::GetLocalEndpoint()) {
Zone::Ptr endpointZone = execEndpoint->GetZone();
Zone::Ptr localZone = Zone::GetLocalZone();
Expand Down Expand Up @@ -803,6 +808,41 @@ Value ClusterEvents::ExecuteCommandAPIHandler(const MessageOrigin::Ptr& origin,
return Empty;
}
}

Checkable::Ptr checkable;
Host::Ptr host = Host::GetByName(params->Get("host"));

if (params->Contains("service"))
checkable = host->GetServiceByShortName(params->Get("service"));
else
checkable = host;

/* Check if the child zone can access the checkable */
if (!checkable || !zone->CanAccessObject(checkable) && zone != endpointZone) {
double now = Utility::GetTime();
Dictionary::Ptr executedParams = new Dictionary();
executedParams->Set("execution", params->Get("source"));
executedParams->Set("host", params->Get("host"));

if (params->Contains("service"))
executedParams->Set("service", params->Get("service"));

executedParams->Set("exit", 126);
executedParams->Set(
"output",
"Zone '" + zone->GetName() + "' cannot access to checkable '" + checkable->GetName() + "'."
);
executedParams->Set("start", now);
executedParams->Set("end", now);

Dictionary::Ptr executedMessage = new Dictionary();
executedMessage->Set("jsonrpc", "2.0");
executedMessage->Set("method", "event::ExecutedCommand");
executedMessage->Set("params", executedParams);

listener->RelayMessage(nullptr, nullptr, executedMessage, true);
return Empty;
}
}
}

Expand Down Expand Up @@ -1179,13 +1219,6 @@ Value ClusterEvents::ExecutedCommandAPIHandler(const MessageOrigin::Ptr& origin,

ObjectLock oLock (checkable);

if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'update executions API handler' message for checkable '" << checkable->GetName()
<< "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
return Empty;
}

if (!params->Contains("execution")) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'update executions API handler' message for checkable '" << checkable->GetName()
Expand Down Expand Up @@ -1213,6 +1246,22 @@ Value ClusterEvents::ExecutedCommandAPIHandler(const MessageOrigin::Ptr& origin,
return Empty;
}

Endpoint::Ptr command_endpoint = Endpoint::GetByName(execution->Get("endpoint"));
if (!command_endpoint) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'update executions API handler' message from '" << origin->FromClient->GetIdentity()
<< "': Command endpoint does not exists.";

return Empty;
}

if (origin->FromZone && !origin->FromZone->CanAccessObject(command_endpoint->GetZone())) {
Log(LogNotice, "ClusterEvents")
<< "Discarding 'update executions API handler' message for checkable '" << checkable->GetName()
<< "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access.";
return Empty;
}

if (params->Contains("exit"))
execution->Set("exit", params->Get("exit"));

Expand Down Expand Up @@ -1303,7 +1352,7 @@ Value ClusterEvents::UpdateExecutionsAPIHandler(const MessageOrigin::Ptr& origin
updateMessage->Set("method", "event::UpdateExecutions");
updateMessage->Set("params", params);

listener->RelayMessage(origin, Zone::GetLocalZone(), updateMessage, true);
listener->RelayMessage(origin, checkable, updateMessage, true);

return Empty;
}

0 comments on commit 3c1835d

Please sign in to comment.