diff --git a/components/cluster/clustercomponent.cpp b/components/cluster/clustercomponent.cpp index d6e610021..14ef42119 100644 --- a/components/cluster/clustercomponent.cpp +++ b/components/cluster/clustercomponent.cpp @@ -19,6 +19,7 @@ #include "cluster/clustercomponent.h" #include "cluster/endpoint.h" +#include "icinga/domain.h" #include "base/netstring.h" #include "base/dynamictype.h" #include "base/logger_fwd.h" @@ -86,6 +87,33 @@ void ClusterComponent::Start(void) Service::OnAcknowledgementCleared.connect(boost::bind(&ClusterComponent::AcknowledgementClearedHandler, this, _1, _2)); Endpoint::OnMessageReceived.connect(boost::bind(&ClusterComponent::MessageHandler, this, _1, _2)); + + BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) { + BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) { + BOOST_FOREACH(const Endpoint::Ptr& endpoint, DynamicType::GetObjects()) { + int privs = 0; + + Array::Ptr domains = object->GetDomains(); + + if (domains) { + ObjectLock olock(domains); + BOOST_FOREACH(const String& domain, domains) { + Domain::Ptr domainObj = Domain::GetByName(domain); + + if (!domainObj) + BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid domain: " + domain)); + + privs |= domainObj->GetPrivileges(endpoint->GetName()); + } + } else { + privs = ~0; + } + + Log(LogInformation, "cluster", "Privileges for object '" + object->GetName() + "' of type '" + object->GetType()->GetName() + "' for instance '" + endpoint->GetName() + "' are '" + Convert::ToString(privs) + "'"); + object->SetPrivileges(endpoint->GetName(), privs); + } + } + } } /** @@ -209,7 +237,7 @@ void ClusterComponent::AddConnection(const String& node, const String& service) Utility::QueueAsyncCallback(boost::bind(&ClusterComponent::NewClientHandler, this, client, TlsRoleClient)); } -void ClusterComponent::RelayMessage(const Endpoint::Ptr& except, const Dictionary::Ptr& message, bool persistent) +void ClusterComponent::RelayMessage(const Endpoint::Ptr& source, const Dictionary::Ptr& message, bool persistent) { double ts = Utility::GetTime(); message->Set("ts", ts); @@ -218,8 +246,10 @@ void ClusterComponent::RelayMessage(const Endpoint::Ptr& except, const Dictionar Dictionary::Ptr pmessage = boost::make_shared(); pmessage->Set("timestamp", ts); - if (except) - pmessage->Set("except", except->GetName()); + if (source) + pmessage->Set("source", source->GetName()); + + pmessage->Set("security", message->Get("security")); pmessage->Set("message", Value(message).Serialize()); @@ -238,16 +268,45 @@ void ClusterComponent::RelayMessage(const Endpoint::Ptr& except, const Dictionar } } + Dictionary::Ptr security = message->Get("security"); + DynamicObject::Ptr secobj; + int privs; + + if (security) { + String type = security->Get("type"); + DynamicType::Ptr dtype = DynamicType::GetByName(type); + + if (!dtype) { + Log(LogWarning, "cluster", "Invalid type in security attribute: " + type); + return; + } + + String name = security->Get("name"); + secobj = dtype->GetObject(name); + + if (!secobj) { + Log(LogWarning, "cluster", "Invalid object name in security attribute: " + name + " (of type '" + type + "')"); + return; + } + + privs = security->Get("privs"); + } + BOOST_FOREACH(const Endpoint::Ptr& endpoint, DynamicType::GetObjects()) { if (!persistent && !endpoint->IsConnected()) continue; - if (endpoint == except) + if (endpoint == source) continue; if (endpoint->GetName() == GetIdentity()) continue; + if (secobj && !secobj->HasPrivileges(endpoint->GetName(), privs)) { + Log(LogDebug, "cluster", "Not sending message to endpoint '" + endpoint->GetName() + "': Insufficient privileges."); + continue; + } + { ObjectLock olock(endpoint); @@ -376,9 +435,38 @@ void ClusterComponent::ReplayLog(const Endpoint::Ptr& endpoint, const Stream::Pt if (pmessage->Get("timestamp") < peer_ts) continue; - if (pmessage->Get("except") == endpoint->GetName()) + if (pmessage->Get("source") == endpoint->GetName()) continue; + Dictionary::Ptr security = pmessage->Get("security"); + DynamicObject::Ptr secobj; + int privs; + + if (security) { + String type = security->Get("type"); + DynamicType::Ptr dtype = DynamicType::GetByName(type); + + if (!dtype) { + Log(LogWarning, "cluster", "Invalid type in security attribute: " + type); + return; + } + + String name = security->Get("name"); + secobj = dtype->GetObject(name); + + if (!secobj) { + Log(LogWarning, "cluster", "Invalid object name in security attribute: " + name + " (of type '" + type + "')"); + return; + } + + privs = security->Get("privs"); + } + + if (secobj && !secobj->HasPrivileges(endpoint->GetName(), privs)) { + Log(LogDebug, "cluster", "Not replaying message: Insufficient privileges."); + continue; + } + NetString::WriteStringToStream(stream, pmessage->Get("message")); count++; @@ -584,6 +672,18 @@ void ClusterComponent::ClusterTimerHandler(void) } } +void ClusterComponent::SetSecurityInfo(const Dictionary::Ptr& message, const DynamicObject::Ptr& object, int privs) +{ + ASSERT(object); + + Dictionary::Ptr security = boost::make_shared(); + security->Set("type", object->GetType()->GetName()); + security->Set("name", object->GetName()); + security->Set("privs", privs); + + message->Set("security", security); +} + void ClusterComponent::CheckResultHandler(const Service::Ptr& service, const Dictionary::Ptr& cr, const String& authority) { if (!authority.IsEmpty() && authority != GetIdentity()) @@ -598,6 +698,8 @@ void ClusterComponent::CheckResultHandler(const Service::Ptr& service, const Dic message->Set("method", "cluster::CheckResult"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -615,6 +717,8 @@ void ClusterComponent::NextCheckChangedHandler(const Service::Ptr& service, doub message->Set("method", "cluster::SetNextCheck"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -632,6 +736,8 @@ void ClusterComponent::NextNotificationChangedHandler(const Notification::Ptr& n message->Set("method", "cluster::SetNextNotification"); message->Set("params", params); + SetSecurityInfo(message, notification->GetService(), DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -649,6 +755,8 @@ void ClusterComponent::ForceNextCheckChangedHandler(const Service::Ptr& service, message->Set("method", "cluster::SetForceNextCheck"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -666,6 +774,8 @@ void ClusterComponent::ForceNextNotificationChangedHandler(const Service::Ptr& s message->Set("method", "cluster::SetForceNextNotification"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -683,6 +793,8 @@ void ClusterComponent::EnableActiveChecksChangedHandler(const Service::Ptr& serv message->Set("method", "cluster::SetEnableActiveChecks"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -700,6 +812,8 @@ void ClusterComponent::EnablePassiveChecksChangedHandler(const Service::Ptr& ser message->Set("method", "cluster::SetEnablePassiveChecks"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -717,6 +831,8 @@ void ClusterComponent::EnableNotificationsChangedHandler(const Service::Ptr& ser message->Set("method", "cluster::SetEnableNotifications"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -734,6 +850,8 @@ void ClusterComponent::EnableFlappingChangedHandler(const Service::Ptr& service, message->Set("method", "cluster::SetEnableFlapping"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -751,6 +869,8 @@ void ClusterComponent::CommentAddedHandler(const Service::Ptr& service, const Di message->Set("method", "cluster::AddComment"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -768,6 +888,8 @@ void ClusterComponent::CommentRemovedHandler(const Service::Ptr& service, const message->Set("method", "cluster::RemoveComment"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -785,6 +907,8 @@ void ClusterComponent::DowntimeAddedHandler(const Service::Ptr& service, const D message->Set("method", "cluster::AddDowntime"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -802,6 +926,8 @@ void ClusterComponent::DowntimeRemovedHandler(const Service::Ptr& service, const message->Set("method", "cluster::RemoveDowntime"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -822,6 +948,8 @@ void ClusterComponent::AcknowledgementSetHandler(const Service::Ptr& service, co message->Set("method", "cluster::SetAcknowledgement"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -838,6 +966,8 @@ void ClusterComponent::AcknowledgementClearedHandler(const Service::Ptr& service message->Set("method", "cluster::ClearAcknowledgement"); message->Set("params", params); + SetSecurityInfo(message, service, DomainPrivRead); + RelayMessage(Endpoint::Ptr(), message, true); } @@ -869,14 +999,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction } } - RelayMessage(sender, message, true); - Dictionary::Ptr params = message->Get("params"); - if (!params) - return; - if (message->Get("method") == "cluster::HeartBeat") { + if (!params) + return; + String identity = params->Get("identity"); Endpoint::Ptr endpoint = Endpoint::GetByName(identity); @@ -885,7 +1013,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction endpoint->SetSeen(Utility::GetTime()); endpoint->SetFeatures(params->Get("features")); } + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::CheckResult") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -899,7 +1032,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction return; service->ProcessCheckResult(cr, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetNextCheck") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -910,7 +1048,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction double nextCheck = params->Get("next_check"); service->SetNextCheck(nextCheck, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetForceNextCheck") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -921,7 +1064,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction bool forced = params->Get("forced"); service->SetForceNextCheck(forced, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetForceNextNotification") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -932,7 +1080,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction bool forced = params->Get("forced"); service->SetForceNextNotification(forced, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetEnableActiveChecks") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -943,7 +1096,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction bool enabled = params->Get("enabled"); service->SetEnableActiveChecks(enabled, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetEnablePassiveChecks") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -954,7 +1112,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction bool enabled = params->Get("enabled"); service->SetEnablePassiveChecks(enabled, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetEnableNotifications") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -965,7 +1128,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction bool enabled = params->Get("enabled"); service->SetEnableNotifications(enabled, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetEnableFlapping") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -976,7 +1144,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction bool enabled = params->Get("enabled"); service->SetEnableFlapping(enabled, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetNextNotification") { + if (!params) + return; + String nfc = params->Get("notification"); Notification::Ptr notification = Notification::GetByName(nfc); @@ -987,7 +1160,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction bool nextNotification = params->Get("next_notification"); notification->SetNextNotification(nextNotification, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::AddComment") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -1000,7 +1178,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction long type = static_cast(comment->Get("entry_type")); service->AddComment(static_cast(type), comment->Get("author"), comment->Get("text"), comment->Get("expire_time"), comment->Get("id"), sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::RemoveComment") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -1011,7 +1194,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction String id = params->Get("id"); service->RemoveComment(id, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::AddDowntime") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -1025,7 +1213,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction downtime->Get("start_time"), downtime->Get("end_time"), downtime->Get("fixed"), downtime->Get("triggered_by"), downtime->Get("duration"), downtime->Get("id"), sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::RemoveDowntime") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -1036,7 +1229,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction String id = params->Get("id"); service->RemoveDowntime(id, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetAcknowledgement") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -1050,7 +1248,12 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction double expiry = params->Get("expiry"); service->AcknowledgeProblem(author, comment, static_cast(type), expiry, sender->GetName()); + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::ClearAcknowledgement") { + if (!params) + return; + String svc = params->Get("service"); Service::Ptr service = Service::GetByName(svc); @@ -1058,11 +1261,21 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction if (!service) return; - ObjectLock olock(service); - service->ClearAcknowledgement(sender->GetName()); + { + ObjectLock olock(service); + service->ClearAcknowledgement(sender->GetName()); + } + + RelayMessage(sender, message, true); } else if (message->Get("method") == "cluster::SetLogPosition") { + if (!params) + return; + sender->SetLocalLogPosition(params->Get("log_position")); } else if (message->Get("method") == "cluster::Config") { + if (!params) + return; + Dictionary::Ptr remoteConfig = params->Get("config_files"); if (!remoteConfig) @@ -1155,6 +1368,8 @@ void ClusterComponent::MessageHandler(const Endpoint::Ptr& sender, const Diction Log(LogInformation, "cluster", "Restarting after configuration change."); Application::RequestRestart(); } + + RelayMessage(sender, message, true); } } diff --git a/components/cluster/clustercomponent.h b/components/cluster/clustercomponent.h index 8e5d4b289..97ddd617b 100644 --- a/components/cluster/clustercomponent.h +++ b/components/cluster/clustercomponent.h @@ -83,7 +83,7 @@ private: void NewClientHandler(const Socket::Ptr& client, TlsRole role); void ListenerThreadProc(const Socket::Ptr& server); - void RelayMessage(const Endpoint::Ptr& except, const Dictionary::Ptr& message, bool persistent); + void RelayMessage(const Endpoint::Ptr& source, const Dictionary::Ptr& message, bool persistent); void OpenLogFile(void); void RotateLogFile(void); @@ -117,6 +117,8 @@ private: static bool SupportsChecks(void); static bool SupportsNotifications(void); + + void SetSecurityInfo(const Dictionary::Ptr& message, const DynamicObject::Ptr& object, int privs); }; } diff --git a/itl/constants.conf b/itl/constants.conf index 5aba5be08..fe6f530db 100644 --- a/itl/constants.conf +++ b/itl/constants.conf @@ -55,3 +55,12 @@ set NotificationFilterRecovery = (1<Set("methods", m_Methods); bag->Set("custom", m_Custom); bag->Set("authorities", m_Authorities); + bag->Set("domains", m_Domains); } - bag->Set("extensions", m_Extensions); + if (attributeTypes & Attribute_State) + bag->Set("extensions", m_Extensions); /* This attribute is used by Serialize() to check that this * method was called. */ @@ -101,9 +103,11 @@ void DynamicObject::InternalDeserialize(const Dictionary::Ptr& bag, int attribut m_Methods = bag->Get("methods"); m_Custom = bag->Get("custom"); m_Authorities = bag->Get("authorities"); + m_Domains = bag->Get("domains"); } - m_Extensions = bag->Get("extensions"); + if (attributeTypes & Attribute_State) + m_Extensions = bag->Get("extensions"); } DynamicType::Ptr DynamicObject::GetType(void) const @@ -155,6 +159,27 @@ bool DynamicObject::HasAuthority(const String& type) const return m_Authority->Get(type); } +Array::Ptr DynamicObject::GetDomains(void) const +{ + return m_Domains; +} + +void DynamicObject::SetPrivileges(const String& instance, int privs) +{ + m_Privileges[instance] = privs; +} + +bool DynamicObject::HasPrivileges(const String& instance, int privs) const +{ + std::map::const_iterator it; + it = m_Privileges.find(instance); + + if (it == m_Privileges.end()) + return false; + + return (it->second & privs) == privs; +} + void DynamicObject::SetExtension(const String& key, const Object::Ptr& object) { Dictionary::Ptr extensions = m_Extensions; diff --git a/lib/base/dynamicobject.h b/lib/base/dynamicobject.h index 32b93f953..078937e8c 100644 --- a/lib/base/dynamicobject.h +++ b/lib/base/dynamicobject.h @@ -44,6 +44,13 @@ enum AttributeType Attribute_Config = 2, }; +enum DomainPriv +{ + DomainPrivRead = (1<<0), + DomainPrivCheckResult = (1<<1), + DomainPrivCommand = (1<<2) +}; + /** * A dynamic object that can be instantiated from the configuration file * and that supports attribute replication to remote application instances. @@ -77,6 +84,11 @@ public: void SetAuthority(const String& type, bool value); bool HasAuthority(const String& type) const; + Array::Ptr GetDomains(void) const; + + void SetPrivileges(const String& instance, int privs); + bool HasPrivileges(const String& instance, int privs) const; + void SetExtension(const String& key, const Object::Ptr& object); Object::Ptr GetExtension(const String& key); void ClearExtension(const String& key); @@ -119,6 +131,8 @@ private: Dictionary::Ptr m_Methods; Dictionary::Ptr m_Custom; Array::Ptr m_Authorities; + Array::Ptr m_Domains; + std::map m_Privileges; bool m_Active; Dictionary::Ptr m_Authority; diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index e8e49b4d9..4db16654a 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -555,7 +555,6 @@ String Utility::GetThreadName(void) unsigned long Utility::SDBM(const String& str) { unsigned long hash = 0; - int c; BOOST_FOREACH(char c, str) { hash = c + (hash << 6) + (hash << 16) - hash; diff --git a/lib/config/base-type.conf b/lib/config/base-type.conf index f2826eca1..5afa802bb 100644 --- a/lib/config/base-type.conf +++ b/lib/config/base-type.conf @@ -32,6 +32,10 @@ type DynamicObject { %attribute array "authorities" { %attribute string "*" + }, + + %attribute array "domains" { + %attribute string "*" } } diff --git a/lib/icinga/Makefile.am b/lib/icinga/Makefile.am index 1b1aedaa5..88654d862 100644 --- a/lib/icinga/Makefile.am +++ b/lib/icinga/Makefile.am @@ -21,6 +21,8 @@ libicinga_la_SOURCES = \ command.h \ compatutility.cpp \ compatutility.h \ + domain.cpp \ + domain.h \ eventcommand.cpp \ eventcommand.h \ externalcommandprocessor.cpp \ diff --git a/lib/icinga/domain.cpp b/lib/icinga/domain.cpp new file mode 100644 index 000000000..cd48c20a3 --- /dev/null +++ b/lib/icinga/domain.cpp @@ -0,0 +1,53 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#include "icinga/domain.h" +#include "base/dynamictype.h" + +using namespace icinga; + +REGISTER_TYPE(Domain); + +Dictionary::Ptr Domain::GetAcl(void) const +{ + return m_Acl; +} + +int Domain::GetPrivileges(const String& instance) const +{ + return m_Acl->Get(instance); +} + +void Domain::InternalSerialize(const Dictionary::Ptr& bag, int attributeTypes) const +{ + DynamicObject::InternalSerialize(bag, attributeTypes); + + if (attributeTypes & Attribute_Config) { + bag->Set("acl", m_Acl); + } +} + +void Domain::InternalDeserialize(const Dictionary::Ptr& bag, int attributeTypes) +{ + DynamicObject::InternalDeserialize(bag, attributeTypes); + + if (attributeTypes & Attribute_Config) { + m_Acl = bag->Get("acl"); + } +} diff --git a/lib/icinga/domain.h b/lib/icinga/domain.h new file mode 100644 index 000000000..19cc97760 --- /dev/null +++ b/lib/icinga/domain.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * Icinga 2 * + * Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software Foundation * + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ******************************************************************************/ + +#ifndef DOMAIN_H +#define DOMAIN_H + +#include "icinga/i2-icinga.h" +#include "base/dynamicobject.h" +#include "base/dictionary.h" + +namespace icinga +{ + +/** + * A domain. + * + * @ingroup icinga + */ +class I2_ICINGA_API Domain : public DynamicObject +{ +public: + DECLARE_PTR_TYPEDEFS(Domain); + DECLARE_TYPENAME(Domain); + + Dictionary::Ptr GetAcl(void) const; + int GetPrivileges(const String& instance) const; + +protected: + virtual void InternalSerialize(const Dictionary::Ptr& bag, int attributeTypes) const; + virtual void InternalDeserialize(const Dictionary::Ptr& bag, int attributeTypes); + +private: + Dictionary::Ptr m_Acl; +}; + +} + +#endif /* DOMAIN_H */ diff --git a/lib/icinga/host.cpp b/lib/icinga/host.cpp index a45c44cec..6f9a765c9 100644 --- a/lib/icinga/host.cpp +++ b/lib/icinga/host.cpp @@ -231,6 +231,7 @@ void Host::UpdateSlaveServices(void) keys.insert("servicedependencies"); keys.insert("hostdependencies"); keys.insert("authorities"); + keys.insert("domains"); ExpressionList::Ptr host_exprl = boost::make_shared(); item->GetLinkedExpressionList()->ExtractFiltered(keys, host_exprl); diff --git a/lib/icinga/icinga-type.conf b/lib/icinga/icinga-type.conf index 5685df4b7..ade463095 100644 --- a/lib/icinga/icinga-type.conf +++ b/lib/icinga/icinga-type.conf @@ -389,3 +389,9 @@ type NotificationCommand inherits Command { type EventCommand inherits Command { } + +type Domain { + %attribute dictionary "acl" { + %attribute number "*" + } +}