From a0285769dd34a7986deb8556531b65d9a93911b3 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Tue, 8 Sep 2020 11:56:14 +0200 Subject: [PATCH] config::WantObjects: send the actual config objects refs #8210 --- lib/remote/apilistener-configsync.cpp | 66 +++++++++++++++++++++++++++ lib/remote/apilistener.hpp | 1 + 2 files changed, 67 insertions(+) diff --git a/lib/remote/apilistener-configsync.cpp b/lib/remote/apilistener-configsync.cpp index ab2adb82f..be7401b63 100644 --- a/lib/remote/apilistener-configsync.cpp +++ b/lib/remote/apilistener-configsync.cpp @@ -15,6 +15,7 @@ using namespace icinga; REGISTER_APIFUNCTION(UpdateObject, config, &ApiListener::ConfigUpdateObjectAPIHandler); REGISTER_APIFUNCTION(DeleteObject, config, &ApiListener::ConfigDeleteObjectAPIHandler); REGISTER_APIFUNCTION(HaveObjects, config, &ApiListener::ConfigHaveObjectsAPIHandler); +REGISTER_APIFUNCTION(WantObjects, config, &ApiListener::ConfigWantObjectsAPIHandler); INITIALIZE_ONCE([]() { ConfigObject::OnActiveChanged.connect(&ApiListener::ConfigUpdateObjectHandler); @@ -322,6 +323,71 @@ Value ApiListener::ConfigHaveObjectsAPIHandler(const MessageOrigin::Ptr& origin, return Empty; } +Value ApiListener::ConfigWantObjectsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) +{ + Log(LogNotice, "ApiListener") + << "Received request for runtime objects: " << JsonEncode(params); + + /* check permissions */ + ApiListener::Ptr listener = ApiListener::GetInstance(); + + if (!listener) + return Empty; + + Endpoint::Ptr endpoint = origin->FromClient->GetEndpoint(); + String identity = origin->FromClient->GetIdentity(); + + /* discard messages if the client is not configured on this node */ + if (!endpoint) { + Log(LogNotice, "ApiListener") + << "Discarding 'config want objects' message from '" << identity << "': Invalid endpoint origin (client not allowed)."; + return Empty; + } + + auto zone (endpoint->GetZone()); + Dictionary::Ptr objects (params->Get("objects")); + ObjectLock oLock (objects); + + for (auto& kv : objects) { + auto type (Type::GetByName(kv.first)); + + if (!type) { + Log(LogWarning, "ApiListener") + << "Bad object type in runtime objects request from '" + << identity << "': '" << kv.first << "'"; + continue; + } + + auto ctype (dynamic_cast(type.get())); + + if (!ctype) { + Log(LogWarning, "ApiListener") + << "Bad object type in runtime objects request from '" + << identity << "': '" << kv.first << "'"; + continue; + } + + Array::Ptr perType (kv.second); + ObjectLock oLock (perType); + + for (auto& name : perType) { + auto object (ctype->GetObject(name)); + + if (!object) { + Log(LogWarning, "ApiListener") + << "No such " << kv.first << " in runtime objects request from '" + << identity << "': '" << name << "'"; + continue; + } + + // UpdateConfigObject() checks access by itself + listener->UpdateConfigObject(object, nullptr, origin->FromClient); + } + } + + return Empty; +} + Value ApiListener::ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) { Log(LogNotice, "ApiListener") diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index d79f8f195..d1176ed2e 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -92,6 +92,7 @@ public: static Value ConfigUpdateObjectAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); static Value ConfigDeleteObjectAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); static Value ConfigHaveObjectsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); + static Value ConfigWantObjectsAPIHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); /* API config packages */ void SetActivePackageStage(const String& package, const String& stage);