diff --git a/lib/icinga/apiactions.cpp b/lib/icinga/apiactions.cpp index e7c2e3510..f6cb229c5 100644 --- a/lib/icinga/apiactions.cpp +++ b/lib/icinga/apiactions.cpp @@ -53,8 +53,11 @@ Dictionary::Ptr ApiActions::CreateResult(int code, const String& status, return result; } -Dictionary::Ptr ApiActions::ProcessCheckResult(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::ProcessCheckResult( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { using Result = Checkable::ProcessingResult; @@ -140,8 +143,11 @@ Dictionary::Ptr ApiActions::ProcessCheckResult(const ConfigObject::Ptr& object, return ApiActions::CreateResult(500, "Unexpected result (" + std::to_string(static_cast(result)) + ") for object '" + checkable->GetName() + "'. Please submit a bug report at https://github.com/Icinga/icinga2"); } -Dictionary::Ptr ApiActions::RescheduleCheck(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::RescheduleCheck( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { Checkable::Ptr checkable = static_pointer_cast(object); @@ -165,8 +171,11 @@ Dictionary::Ptr ApiActions::RescheduleCheck(const ConfigObject::Ptr& object, return ApiActions::CreateResult(200, "Successfully rescheduled check for object '" + checkable->GetName() + "'."); } -Dictionary::Ptr ApiActions::SendCustomNotification(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::SendCustomNotification( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { Checkable::Ptr checkable = static_pointer_cast(object); @@ -188,8 +197,11 @@ Dictionary::Ptr ApiActions::SendCustomNotification(const ConfigObject::Ptr& obje return ApiActions::CreateResult(200, "Successfully sent custom notification for object '" + checkable->GetName() + "'."); } -Dictionary::Ptr ApiActions::DelayNotification(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::DelayNotification( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { Checkable::Ptr checkable = static_pointer_cast(object); @@ -206,8 +218,11 @@ Dictionary::Ptr ApiActions::DelayNotification(const ConfigObject::Ptr& object, return ApiActions::CreateResult(200, "Successfully delayed notifications for object '" + checkable->GetName() + "'."); } -Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::AcknowledgeProblem( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { Checkable::Ptr checkable = static_pointer_cast(object); @@ -268,8 +283,11 @@ Dictionary::Ptr ApiActions::AcknowledgeProblem(const ConfigObject::Ptr& object, return ApiActions::CreateResult(200, "Successfully acknowledged problem for object '" + checkable->GetName() + "'."); } -Dictionary::Ptr ApiActions::RemoveAcknowledgement(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::RemoveAcknowledgement( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { Checkable::Ptr checkable = static_pointer_cast(object); @@ -292,8 +310,11 @@ Dictionary::Ptr ApiActions::RemoveAcknowledgement(const ConfigObject::Ptr& objec return ApiActions::CreateResult(200, "Successfully removed acknowledgement for object '" + checkable->GetName() + "'."); } -Dictionary::Ptr ApiActions::AddComment(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::AddComment( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { Checkable::Ptr checkable = static_pointer_cast(object); @@ -331,8 +352,11 @@ Dictionary::Ptr ApiActions::AddComment(const ConfigObject::Ptr& object, + "'.", additional); } -Dictionary::Ptr ApiActions::RemoveComment(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::RemoveComment( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { ConfigObjectsSharedLock lock (std::try_to_lock); @@ -365,8 +389,11 @@ Dictionary::Ptr ApiActions::RemoveComment(const ConfigObject::Ptr& object, return ApiActions::CreateResult(200, "Successfully removed comment '" + commentName + "'."); } -Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::ScheduleDowntime( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { Checkable::Ptr checkable = static_pointer_cast(object); @@ -535,8 +562,11 @@ Dictionary::Ptr ApiActions::ScheduleDowntime(const ConfigObject::Ptr& object, downtimeName + "' for object '" + checkable->GetName() + "'.", additional); } -Dictionary::Ptr ApiActions::RemoveDowntime(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::RemoveDowntime( + const ConfigObject::Ptr& object, + const ApiUser::Ptr&, + const Dictionary::Ptr& params +) { ConfigObjectsSharedLock lock (std::try_to_lock); @@ -588,24 +618,21 @@ Dictionary::Ptr ApiActions::RemoveDowntime(const ConfigObject::Ptr& object, } } -Dictionary::Ptr ApiActions::ShutdownProcess(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::ShutdownProcess(const ConfigObject::Ptr&, const ApiUser::Ptr&, const Dictionary::Ptr&) { Application::RequestShutdown(); return ApiActions::CreateResult(200, "Shutting down Icinga 2."); } -Dictionary::Ptr ApiActions::RestartProcess(const ConfigObject::Ptr& object, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::RestartProcess(const ConfigObject::Ptr&, const ApiUser::Ptr&, const Dictionary::Ptr&) { Application::RequestRestart(); return ApiActions::CreateResult(200, "Restarting Icinga 2."); } -Dictionary::Ptr ApiActions::GenerateTicket(const ConfigObject::Ptr&, - const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::GenerateTicket(const ConfigObject::Ptr&, const ApiUser::Ptr&, const Dictionary::Ptr& params) { if (!params->Contains("cn")) return ApiActions::CreateResult(400, "Option 'cn' is required"); @@ -653,7 +680,11 @@ Value ApiActions::GetSingleObjectByNameUsingPermissions(const String& type, cons return objs.at(0); }; -Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, const Dictionary::Ptr& params) +Dictionary::Ptr ApiActions::ExecuteCommand( + const ConfigObject::Ptr& object, + const ApiUser::Ptr& apiUser, + const Dictionary::Ptr& params +) { ApiListener::Ptr listener = ApiListener::GetInstance(); @@ -717,11 +748,11 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons nullptr, MacroProcessor::EscapeCallback(), nullptr, false ); - if (!ActionsHandler::AuthenticatedApiUser) + if (!apiUser) BOOST_THROW_EXCEPTION(std::invalid_argument("Can't find API user.")); /* Get endpoint */ - Endpoint::Ptr endpointPtr = GetSingleObjectByNameUsingPermissions(Endpoint::GetTypeName(), resolved_endpoint, ActionsHandler::AuthenticatedApiUser); + Endpoint::Ptr endpointPtr = GetSingleObjectByNameUsingPermissions(Endpoint::GetTypeName(), resolved_endpoint, apiUser); if (!endpointPtr) return ApiActions::CreateResult(404, "Can't find a valid endpoint for '" + resolved_endpoint + "'."); @@ -779,7 +810,7 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons Dictionary::Ptr execParams = new Dictionary(); if (command_type == "CheckCommand") { - CheckCommand::Ptr cmd = GetSingleObjectByNameUsingPermissions(CheckCommand::GetTypeName(), resolved_command, ActionsHandler::AuthenticatedApiUser); + CheckCommand::Ptr cmd = GetSingleObjectByNameUsingPermissions(CheckCommand::GetTypeName(), resolved_command, apiUser); if (!cmd) return ApiActions::CreateResult(404, "Can't find a valid " + command_type + " for '" + resolved_command + "'."); @@ -791,7 +822,7 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons cmd->Execute(checkable, cr, listener->GetWaitGroup(), execMacros, false); } } else if (command_type == "EventCommand") { - EventCommand::Ptr cmd = GetSingleObjectByNameUsingPermissions(EventCommand::GetTypeName(), resolved_command, ActionsHandler::AuthenticatedApiUser); + EventCommand::Ptr cmd = GetSingleObjectByNameUsingPermissions(EventCommand::GetTypeName(), resolved_command, apiUser); if (!cmd) return ApiActions::CreateResult(404, "Can't find a valid " + command_type + " for '" + resolved_command + "'."); @@ -803,7 +834,7 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons cmd->Execute(checkable, execMacros, false); } } else if (command_type == "NotificationCommand") { - NotificationCommand::Ptr cmd = GetSingleObjectByNameUsingPermissions(NotificationCommand::GetTypeName(), resolved_command, ActionsHandler::AuthenticatedApiUser); + NotificationCommand::Ptr cmd = GetSingleObjectByNameUsingPermissions(NotificationCommand::GetTypeName(), resolved_command, apiUser); if (!cmd) return ApiActions::CreateResult(404, "Can't find a valid " + command_type + " for '" + resolved_command + "'."); @@ -820,7 +851,7 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons MacroProcessor::EscapeCallback(), nullptr, false ); - User::Ptr user = GetSingleObjectByNameUsingPermissions(User::GetTypeName(), resolved_user, ActionsHandler::AuthenticatedApiUser); + User::Ptr user = GetSingleObjectByNameUsingPermissions(User::GetTypeName(), resolved_user, apiUser); if (!user) return ApiActions::CreateResult(404, "Can't find a valid user for '" + resolved_user + "'."); @@ -839,7 +870,7 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons MacroProcessor::EscapeCallback(), nullptr, false ); - Notification::Ptr notification = GetSingleObjectByNameUsingPermissions(Notification::GetTypeName(), resolved_notification, ActionsHandler::AuthenticatedApiUser); + Notification::Ptr notification = GetSingleObjectByNameUsingPermissions(Notification::GetTypeName(), resolved_notification, apiUser); if (!notification) return ApiActions::CreateResult(404, "Can't find a valid notification for '" + resolved_notification + "'."); @@ -852,7 +883,7 @@ Dictionary::Ptr ApiActions::ExecuteCommand(const ConfigObject::Ptr& object, cons }); cmd->Execute(notification, user, cr, NotificationType::NotificationCustom, - ActionsHandler::AuthenticatedApiUser->GetName(), "", execMacros, false); + apiUser->GetName(), "", execMacros, false); } } diff --git a/lib/icinga/apiactions.hpp b/lib/icinga/apiactions.hpp index b6ba83500..cc5bafe83 100644 --- a/lib/icinga/apiactions.hpp +++ b/lib/icinga/apiactions.hpp @@ -17,20 +17,20 @@ namespace icinga class ApiActions { public: - static Dictionary::Ptr ProcessCheckResult(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr RescheduleCheck(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr SendCustomNotification(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr DelayNotification(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr AcknowledgeProblem(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr RemoveAcknowledgement(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr AddComment(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr RemoveComment(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr ScheduleDowntime(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr RemoveDowntime(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr ShutdownProcess(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr RestartProcess(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr GenerateTicket(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); - static Dictionary::Ptr ExecuteCommand(const ConfigObject::Ptr& object, const Dictionary::Ptr& params); + static Dictionary::Ptr ProcessCheckResult(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr RescheduleCheck(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr SendCustomNotification(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr DelayNotification(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr AcknowledgeProblem(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr RemoveAcknowledgement(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr AddComment(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr RemoveComment(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr ScheduleDowntime(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr RemoveDowntime(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr ShutdownProcess(const ConfigObject::Ptr&, const ApiUser::Ptr&, const Dictionary::Ptr&); + static Dictionary::Ptr RestartProcess(const ConfigObject::Ptr&, const ApiUser::Ptr&, const Dictionary::Ptr&); + static Dictionary::Ptr GenerateTicket(const ConfigObject::Ptr& object, const ApiUser::Ptr&, const Dictionary::Ptr& params); + static Dictionary::Ptr ExecuteCommand(const ConfigObject::Ptr& object, const ApiUser::Ptr& apiUser, const Dictionary::Ptr& params); private: static Dictionary::Ptr CreateResult(int code, const String& status, const Dictionary::Ptr& additional = nullptr); diff --git a/lib/remote/actionshandler.cpp b/lib/remote/actionshandler.cpp index b9853945b..442c2ccae 100644 --- a/lib/remote/actionshandler.cpp +++ b/lib/remote/actionshandler.cpp @@ -11,8 +11,6 @@ using namespace icinga; -thread_local ApiUser::Ptr ActionsHandler::AuthenticatedApiUser; - REGISTER_URLHANDLER("/v1/actions", ActionsHandler); bool ActionsHandler::HandleRequest( @@ -79,11 +77,6 @@ bool ActionsHandler::HandleRequest( bool verbose = false; - ActionsHandler::AuthenticatedApiUser = user; - Defer a ([]() { - ActionsHandler::AuthenticatedApiUser = nullptr; - }); - if (params) verbose = HttpUtility::GetLastParameter(params, "verbose"); @@ -110,7 +103,7 @@ bool ActionsHandler::HandleRequest( } try { - results.emplace_back(action->Invoke(obj, params)); + results.emplace_back(action->Invoke(obj, user, params)); } catch (const std::exception& ex) { Dictionary::Ptr fail = new Dictionary({ { "code", 500 }, diff --git a/lib/remote/actionshandler.hpp b/lib/remote/actionshandler.hpp index 3ba856f69..4d837cd77 100644 --- a/lib/remote/actionshandler.hpp +++ b/lib/remote/actionshandler.hpp @@ -13,8 +13,6 @@ class ActionsHandler final : public HttpHandler public: DECLARE_PTR_TYPEDEFS(ActionsHandler); - static thread_local ApiUser::Ptr AuthenticatedApiUser; - bool HandleRequest( const WaitGroup::Ptr& waitGroup, const HttpRequest& request, diff --git a/lib/remote/apiaction.cpp b/lib/remote/apiaction.cpp index ccde28190..6f7dc2da3 100644 --- a/lib/remote/apiaction.cpp +++ b/lib/remote/apiaction.cpp @@ -9,9 +9,9 @@ ApiAction::ApiAction(std::vector types, Callback action) : m_Types(std::move(types)), m_Callback(std::move(action)) { } -Value ApiAction::Invoke(const ConfigObject::Ptr& target, const Dictionary::Ptr& params) +Value ApiAction::Invoke(const ConfigObject::Ptr& target, const ApiUser::Ptr& user, const Dictionary::Ptr& params) { - return m_Callback(target, params); + return m_Callback(target, user, params); } const std::vector& ApiAction::GetTypes() const diff --git a/lib/remote/apiaction.hpp b/lib/remote/apiaction.hpp index 2bb98b1b6..f96aa32fd 100644 --- a/lib/remote/apiaction.hpp +++ b/lib/remote/apiaction.hpp @@ -8,6 +8,7 @@ #include "base/value.hpp" #include "base/dictionary.hpp" #include "base/configobject.hpp" +#include "remote/apiuser.hpp" #include #include @@ -24,11 +25,11 @@ class ApiAction final : public Object public: DECLARE_PTR_TYPEDEFS(ApiAction); - typedef std::function Callback; + typedef std::function Callback; ApiAction(std::vector registerTypes, Callback function); - Value Invoke(const ConfigObject::Ptr& target, const Dictionary::Ptr& params); + Value Invoke(const ConfigObject::Ptr& target, const ApiUser::Ptr& user, const Dictionary::Ptr& params); const std::vector& GetTypes() const;