diff --git a/lib/icinga/checkable-check.cpp b/lib/icinga/checkable-check.cpp index 68361fe17..cc32f09ee 100644 --- a/lib/icinga/checkable-check.cpp +++ b/lib/icinga/checkable-check.cpp @@ -492,7 +492,7 @@ void Checkable::ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrig } } -void Checkable::ExecuteRemoteCheck(const Dictionary::Ptr& resolvedMacros) +void Checkable::ExecuteRemoteCheck(const Dictionary::Ptr& resolvedMacros, const Checkable::Ptr& checkable) { CONTEXT("Executing remote check for object '" + GetName() + "'"); @@ -503,7 +503,11 @@ void Checkable::ExecuteRemoteCheck(const Dictionary::Ptr& resolvedMacros) cr->SetScheduleStart(scheduled_start); cr->SetExecutionStart(before_check); - GetCheckCommand()->Execute(this, cr, resolvedMacros, true); + if (!checkable) { + GetCheckCommand()->Execute(this, cr, resolvedMacros, true); + } else { + GetCheckCommand()->Execute(checkable, cr, resolvedMacros, true); + } } void Checkable::ExecuteCheck() diff --git a/lib/icinga/checkable.cpp b/lib/icinga/checkable.cpp index 0f4d1399b..3f31d5667 100644 --- a/lib/icinga/checkable.cpp +++ b/lib/icinga/checkable.cpp @@ -20,6 +20,7 @@ boost::signals2::signal Checkable::OnFlappingChange; static Timer::Ptr l_CheckablesFireSuppressedNotifications; +thread_local std::function Checkable::ExecuteCommandProcessFinishedHandler; void Checkable::StaticInitialize() { diff --git a/lib/icinga/checkable.hpp b/lib/icinga/checkable.hpp index 0eb1c5950..38ecf0106 100644 --- a/lib/icinga/checkable.hpp +++ b/lib/icinga/checkable.hpp @@ -5,6 +5,7 @@ #include "base/atomic.hpp" #include "base/timer.hpp" +#include "base/process.hpp" #include "icinga/i2-icinga.hpp" #include "icinga/checkable-ti.hpp" #include "icinga/timeperiod.hpp" @@ -14,6 +15,7 @@ #include "remote/endpoint.hpp" #include "remote/messageorigin.hpp" #include +#include namespace icinga { @@ -55,6 +57,7 @@ public: DECLARE_OBJECTNAME(Checkable); static void StaticInitialize(); + static thread_local std::function ExecuteCommandProcessFinishedHandler; Checkable(); @@ -94,7 +97,7 @@ public: static void UpdateStatistics(const CheckResult::Ptr& cr, CheckableType type); - void ExecuteRemoteCheck(const Dictionary::Ptr& resolvedMacros = nullptr); + void ExecuteRemoteCheck(const Dictionary::Ptr& resolvedMacros = nullptr, const Checkable::Ptr& checkbale = nullptr); void ExecuteCheck(); void ProcessCheckResult(const CheckResult::Ptr& cr, const MessageOrigin::Ptr& origin = nullptr); diff --git a/lib/icinga/clusterevents-check.cpp b/lib/icinga/clusterevents-check.cpp index 5db8c009b..8ab03f655 100644 --- a/lib/icinga/clusterevents-check.cpp +++ b/lib/icinga/clusterevents-check.cpp @@ -6,6 +6,7 @@ #include "base/configuration.hpp" #include "base/serializer.hpp" #include "base/exception.hpp" +#include "methods/executeactiontask.hpp" #include #include @@ -97,12 +98,38 @@ void ClusterEvents::ExecuteCheckFromQueue(const MessageOrigin::Ptr& origin, cons return; } + Checkable::Ptr checkable = nullptr; if (params->Contains("source")) { - Log(LogCritical, "ApiListener", "Not implemented."); - String uuid = params->Get("source"); - return; + Host::Ptr host = Host::GetByName(params->Get("host")); + if (!host) { + Log(LogCritical, "ApiListener", "Host not found."); + return; + } + + if (params->Contains("service")) + checkable = host->GetServiceByShortName(params->Get("service")); + else + checkable = host; + + if (!checkable) { + Log(LogCritical, "ApiListener", "Checkable not found."); + return; + } + + ObjectLock oLock (checkable); + + if (origin->FromZone && !origin->FromZone->CanAccessObject(checkable)) { + Log(LogNotice, "ApiListener") + << "Discarding 'ExecuteCheckFromQueue' event for checkable '" << checkable->GetName() + << "' from '" << origin->FromClient->GetIdentity() << "': Unauthorized access."; + return; + } + + Checkable::ExecuteCommandProcessFinishedHandler = ExecuteActionTask::ProcessFinishedHandler; + } else { + Checkable::ExecuteCommandProcessFinishedHandler = nullptr; } if (!listener->GetAcceptCommands()) { @@ -182,7 +209,7 @@ void ClusterEvents::ExecuteCheckFromQueue(const MessageOrigin::Ptr& origin, cons if (command_type == "check_command") { try { - host->ExecuteRemoteCheck(macros); + host->ExecuteRemoteCheck(macros, checkable); } catch (const std::exception& ex) { CheckResult::Ptr cr = new CheckResult(); cr->SetState(ServiceUnknown); diff --git a/lib/methods/executeactiontask.cpp b/lib/methods/executeactiontask.cpp index c40a7ba24..305bc3213 100644 --- a/lib/methods/executeactiontask.cpp +++ b/lib/methods/executeactiontask.cpp @@ -54,7 +54,7 @@ void ExecuteActionTask::ProcessFinishedHandler(const Checkable::Ptr& checkable, executedParams->Set("check_result", cr); - /* FIXME command endpoint was overwrite by macro? */ + /* FIXME command endpoint overwritten by macro? */ Endpoint::Ptr commandEndpoint = checkable->GetCommandEndpoint(); bool local = !commandEndpoint || commandEndpoint == Endpoint::GetLocalEndpoint(); if (local) { diff --git a/lib/methods/pluginchecktask.cpp b/lib/methods/pluginchecktask.cpp index 70523b49f..43851f31d 100644 --- a/lib/methods/pluginchecktask.cpp +++ b/lib/methods/pluginchecktask.cpp @@ -43,9 +43,16 @@ void PluginCheckTask::ScriptFunc(const Checkable::Ptr& checkable, const CheckRes if (!checkable->GetCheckTimeout().IsEmpty()) timeout = checkable->GetCheckTimeout(); - PluginUtility::ExecuteCommand(commandObj, checkable, checkable->GetLastCheckResult(), - resolvers, resolvedMacros, useResolvedMacros, timeout, - std::bind(&PluginCheckTask::ProcessFinishedHandler, checkable, cr, _1, _2)); + + if (Checkable::ExecuteCommandProcessFinishedHandler) { + PluginUtility::ExecuteCommand(commandObj, checkable, checkable->GetLastCheckResult(), + resolvers, resolvedMacros, useResolvedMacros, timeout, + std::bind(Checkable::ExecuteCommandProcessFinishedHandler, checkable, cr, _1, _2)); + } else { + PluginUtility::ExecuteCommand(commandObj, checkable, checkable->GetLastCheckResult(), + resolvers, resolvedMacros, useResolvedMacros, timeout, + std::bind(&PluginCheckTask::ProcessFinishedHandler, checkable, cr, _1, _2)); + } if (!resolvedMacros || useResolvedMacros) { Checkable::CurrentConcurrentChecks.fetch_add(1);