Implemented message-based authorisation checks.

This commit is contained in:
Gunnar Beutner 2012-05-09 10:15:51 +02:00
parent 36eb5e1cf3
commit 18bffce0ed
24 changed files with 575 additions and 125 deletions

View File

@ -2,6 +2,7 @@
## Created by Anjuta ## Created by Anjuta
SUBDIRS = ltdl \ SUBDIRS = ltdl \
mmatch \
base \ base \
cJSON \ cJSON \
jsonrpc \ jsonrpc \

View File

@ -93,7 +93,12 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup /> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(SolutionDir)\mmatch;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(SolutionDir)\mmatch;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<PrecompiledHeader> <PrecompiledHeader>

View File

@ -38,14 +38,7 @@ void ConfigCollection::AddObject(const ConfigObject::Ptr& object)
RemoveObject(object); RemoveObject(object);
Objects[object->GetName()] = object; Objects[object->GetName()] = object;
object->Commit();
EventArgs ea;
ea.Source = object;
OnObjectCreated(ea);
ConfigHive::Ptr hive = m_Hive.lock();
if (hive)
hive->OnObjectCreated(ea);
} }
/** /**

View File

@ -28,9 +28,8 @@ public:
void ForEachObject(function<int (const EventArgs&)> callback); void ForEachObject(function<int (const EventArgs&)> callback);
Event<EventArgs> OnObjectCreated; Event<EventArgs> OnObjectCommitted;
Event<EventArgs> OnObjectRemoved; Event<EventArgs> OnObjectRemoved;
Event<PropertyChangedEventArgs> OnPropertyChanged;
}; };
} }

View File

@ -23,9 +23,8 @@ public:
void ForEachObject(const string& type, void ForEachObject(const string& type,
function<int (const EventArgs&)> callback); function<int (const EventArgs&)> callback);
Event<EventArgs> OnObjectCreated; Event<EventArgs> OnObjectCommitted;
Event<EventArgs> OnObjectRemoved; Event<EventArgs> OnObjectRemoved;
Event<PropertyChangedEventArgs> OnPropertyChanged;
}; };
} }

View File

@ -30,7 +30,6 @@ void ConfigObject::SetHive(const ConfigHive::WeakPtr& hive)
throw InvalidArgumentException("Config object already has a parent hive."); throw InvalidArgumentException("Config object already has a parent hive.");
m_Hive = hive; m_Hive = hive;
OnPropertyChanged += bind_weak(&ConfigObject::PropertyChangedHandler, shared_from_this());
} }
/** /**
@ -118,21 +117,19 @@ bool ConfigObject::GetReplicated(void) const
} }
/** /**
* PropertyChangedHandler * Commit
* *
* Handles changed properties by propagating them to the hive * Handles changed properties by propagating them to the hive
* and collection this object is contained in. * and collection this object is contained in.
* *
* @param dpcea The event arguments.
* @returns 0.
*/ */
int ConfigObject::PropertyChangedHandler(const PropertyChangedEventArgs& dpcea) void ConfigObject::Commit(void)
{ {
ConfigHive::Ptr hive = m_Hive.lock(); ConfigHive::Ptr hive = m_Hive.lock();
if (hive) { if (hive) {
hive->GetCollection(m_Type)->OnPropertyChanged(dpcea); EventArgs ea;
hive->OnPropertyChanged(dpcea); ea.Source = shared_from_this();
hive->GetCollection(m_Type)->OnObjectCommitted(ea);
hive->OnObjectCommitted(ea);
} }
return 0;
} }

View File

@ -17,8 +17,6 @@ private:
string m_Type; string m_Type;
bool m_Replicated; bool m_Replicated;
int PropertyChangedHandler(const PropertyChangedEventArgs& dpcea);
public: public:
typedef shared_ptr<ConfigObject> Ptr; typedef shared_ptr<ConfigObject> Ptr;
typedef weak_ptr<ConfigObject> WeakPtr; typedef weak_ptr<ConfigObject> WeakPtr;
@ -36,6 +34,8 @@ public:
void SetReplicated(bool replicated); void SetReplicated(bool replicated);
bool GetReplicated(void) const; bool GetReplicated(void) const;
void Commit(void);
}; };
} }

View File

@ -1,4 +1,5 @@
#include "i2-base.h" #include "i2-base.h"
#include <mmatch.h>
using namespace icinga; using namespace icinga;
@ -137,3 +138,8 @@ shared_ptr<X509> Utility::GetX509Certificate(string pemfile)
return shared_ptr<X509>(cert, X509_free); return shared_ptr<X509>(cert, X509_free);
} }
bool Utility::Match(string pattern, string text)
{
return (match(pattern.c_str(), text.c_str()) != 0);
}

View File

@ -47,6 +47,8 @@ public:
static shared_ptr<SSL_CTX> MakeSSLContext(string pubkey, string privkey, string cakey); static shared_ptr<SSL_CTX> MakeSSLContext(string pubkey, string privkey, string cakey);
static string GetCertificateCN(const shared_ptr<X509>& certificate); static string GetCertificateCN(const shared_ptr<X509>& certificate);
static shared_ptr<X509> GetX509Certificate(string pemfile); static shared_ptr<X509> GetX509Certificate(string pemfile);
static bool Match(string pattern, string text);
}; };
} }

View File

@ -55,13 +55,23 @@ void ConfigFileComponent::Start(void)
for (cJSON *property = object->child; property != NULL; property = property->next) { for (cJSON *property = object->child; property != NULL; property = property->next) {
string key = property->string; string key = property->string;
if (property->type == cJSON_String) {
string value = property->valuestring;
if (property->type != cJSON_String) cfgobj->SetPropertyString(key, value);
continue; } else if (property->type == cJSON_Array) {
Dictionary::Ptr items = make_shared<Dictionary>();
string value = property->valuestring; for (cJSON *item = property->child; item != NULL; item = item->next) {
if (item->type != cJSON_String)
continue;
cfgobj->SetPropertyString(key, value); items->AddUnnamedPropertyString(item->valuestring);
}
cfgobj->SetPropertyDictionary(key, items);
}
} }
GetApplication()->GetConfigHive()->AddObject(cfgobj); GetApplication()->GetConfigHive()->AddObject(cfgobj);

View File

@ -19,24 +19,20 @@ void ConfigRpcComponent::Start(void)
m_ConfigRpcEndpoint->RegisterMethodHandler("config::FetchObjects", m_ConfigRpcEndpoint->RegisterMethodHandler("config::FetchObjects",
bind_weak(&ConfigRpcComponent::FetchObjectsHandler, shared_from_this())); bind_weak(&ConfigRpcComponent::FetchObjectsHandler, shared_from_this()));
configHive->OnObjectCreated += bind_weak(&ConfigRpcComponent::LocalObjectCreatedHandler, shared_from_this()); configHive->OnObjectCommitted += bind_weak(&ConfigRpcComponent::LocalObjectCommittedHandler, shared_from_this());
configHive->OnObjectRemoved += bind_weak(&ConfigRpcComponent::LocalObjectRemovedHandler, shared_from_this()); configHive->OnObjectRemoved += bind_weak(&ConfigRpcComponent::LocalObjectRemovedHandler, shared_from_this());
configHive->OnPropertyChanged += bind_weak(&ConfigRpcComponent::LocalPropertyChangedHandler, shared_from_this());
m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectCreated"); m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectCommitted");
m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectRemoved"); m_ConfigRpcEndpoint->RegisterMethodSource("config::ObjectRemoved");
m_ConfigRpcEndpoint->RegisterMethodSource("config::PropertyChanged");
} }
endpointManager->OnNewEndpoint += bind_weak(&ConfigRpcComponent::NewEndpointHandler, shared_from_this()); endpointManager->OnNewEndpoint += bind_weak(&ConfigRpcComponent::NewEndpointHandler, shared_from_this());
m_ConfigRpcEndpoint->RegisterMethodSource("config::FetchObjects"); m_ConfigRpcEndpoint->RegisterMethodSource("config::FetchObjects");
m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectCreated", m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectCommitted",
bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this())); bind_weak(&ConfigRpcComponent::RemoteObjectCommittedHandler, shared_from_this()));
m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectRemoved", m_ConfigRpcEndpoint->RegisterMethodHandler("config::ObjectRemoved",
bind_weak(&ConfigRpcComponent::RemoteObjectRemovedHandler, shared_from_this())); bind_weak(&ConfigRpcComponent::RemoteObjectRemovedHandler, shared_from_this()));
m_ConfigRpcEndpoint->RegisterMethodHandler("config::PropertyChanged",
bind_weak(&ConfigRpcComponent::RemoteObjectUpdatedHandler, shared_from_this()));
endpointManager->RegisterEndpoint(m_ConfigRpcEndpoint); endpointManager->RegisterEndpoint(m_ConfigRpcEndpoint);
} }
@ -115,7 +111,7 @@ int ConfigRpcComponent::FetchObjectsHandler(const NewRequestEventArgs& ea)
return 0; return 0;
} }
int ConfigRpcComponent::LocalObjectCreatedHandler(const EventArgs& ea) int ConfigRpcComponent::LocalObjectCommittedHandler(const EventArgs& ea)
{ {
ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source); ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
@ -141,32 +137,7 @@ int ConfigRpcComponent::LocalObjectRemovedHandler(const EventArgs& ea)
return 0; return 0;
} }
int ConfigRpcComponent::LocalPropertyChangedHandler(const PropertyChangedEventArgs& ea) int ConfigRpcComponent::RemoteObjectCommittedHandler(const NewRequestEventArgs& ea)
{
ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
if (!ShouldReplicateObject(object))
return 0;
JsonRpcRequest msg = MakeObjectMessage(object, "config::PropertyChanged", false);
Message params;
msg.SetParams(params);
Message properties;
params.GetDictionary()->SetPropertyDictionary("properties", properties.GetDictionary());
string value;
if (!object->GetPropertyString(ea.Property, &value))
return 0;
properties.GetDictionary()->SetPropertyString(ea.Property, value);
GetEndpointManager()->SendMulticastRequest(m_ConfigRpcEndpoint, msg);
return 0;
}
int ConfigRpcComponent::RemoteObjectUpdatedHandler(const NewRequestEventArgs& ea)
{ {
JsonRpcRequest message = ea.Request; JsonRpcRequest message = ea.Request;
bool was_null = false; bool was_null = false;

View File

@ -12,12 +12,11 @@ private:
int NewEndpointHandler(const NewEndpointEventArgs& ea); int NewEndpointHandler(const NewEndpointEventArgs& ea);
int SessionEstablishedHandler(const EventArgs& ea); int SessionEstablishedHandler(const EventArgs& ea);
int LocalObjectCreatedHandler(const EventArgs& ea); int LocalObjectCommittedHandler(const EventArgs& ea);
int LocalObjectRemovedHandler(const EventArgs& ea); int LocalObjectRemovedHandler(const EventArgs& ea);
int LocalPropertyChangedHandler(const PropertyChangedEventArgs& ea);
int FetchObjectsHandler(const NewRequestEventArgs& ea); int FetchObjectsHandler(const NewRequestEventArgs& ea);
int RemoteObjectUpdatedHandler(const NewRequestEventArgs& ea); int RemoteObjectCommittedHandler(const NewRequestEventArgs& ea);
int RemoteObjectRemovedHandler(const NewRequestEventArgs& ea); int RemoteObjectRemovedHandler(const NewRequestEventArgs& ea);
static JsonRpcRequest MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties); static JsonRpcRequest MakeObjectMessage(const ConfigObject::Ptr& object, string method, bool includeProperties);

View File

@ -27,15 +27,16 @@ void DiscoveryComponent::Start(void)
GetConfig()->GetPropertyInteger("broker", &isBroker); GetConfig()->GetPropertyInteger("broker", &isBroker);
m_Broker = (isBroker != 0); m_Broker = (isBroker != 0);
if (IsBroker()) {
m_DiscoveryEndpoint->RegisterMethodSource("discovery::NewComponent");
m_DiscoveryEndpoint->RegisterMethodHandler("discovery::RegisterComponent",
bind_weak(&DiscoveryComponent::RegisterComponentMessageHandler, shared_from_this()));
}
m_DiscoveryEndpoint->RegisterMethodSource("discovery::RegisterComponent"); m_DiscoveryEndpoint->RegisterMethodSource("discovery::RegisterComponent");
m_DiscoveryEndpoint->RegisterMethodHandler("discovery::RegisterComponent",
bind_weak(&DiscoveryComponent::RegisterComponentMessageHandler, shared_from_this()));
if (IsBroker())
m_DiscoveryEndpoint->RegisterMethodSource("discovery::NewComponent");
m_DiscoveryEndpoint->RegisterMethodHandler("discovery::NewComponent", m_DiscoveryEndpoint->RegisterMethodHandler("discovery::NewComponent",
bind_weak(&DiscoveryComponent::NewComponentMessageHandler, shared_from_this())); bind_weak(&DiscoveryComponent::NewComponentMessageHandler, shared_from_this()));
m_DiscoveryEndpoint->RegisterMethodHandler("discovery::Welcome", m_DiscoveryEndpoint->RegisterMethodHandler("discovery::Welcome",
bind_weak(&DiscoveryComponent::WelcomeMessageHandler, shared_from_this())); bind_weak(&DiscoveryComponent::WelcomeMessageHandler, shared_from_this()));
@ -49,6 +50,9 @@ void DiscoveryComponent::Start(void)
m_DiscoveryTimer->SetInterval(30); m_DiscoveryTimer->SetInterval(30);
m_DiscoveryTimer->OnTimerExpired += bind_weak(&DiscoveryComponent::DiscoveryTimerHandler, shared_from_this()); m_DiscoveryTimer->OnTimerExpired += bind_weak(&DiscoveryComponent::DiscoveryTimerHandler, shared_from_this());
m_DiscoveryTimer->Start(); m_DiscoveryTimer->Start();
/* call the timer as soon as possible */
m_DiscoveryTimer->Reschedule(0);
} }
/** /**
@ -104,10 +108,8 @@ int DiscoveryComponent::NewEndpointHandler(const NewEndpointEventArgs& neea)
{ {
neea.Endpoint->OnIdentityChanged += bind_weak(&DiscoveryComponent::NewIdentityHandler, shared_from_this()); neea.Endpoint->OnIdentityChanged += bind_weak(&DiscoveryComponent::NewIdentityHandler, shared_from_this());
if (IsBroker()) { /* accept discovery::RegisterComponent messages from any endpoint */
/* accept discovery::RegisterComponent messages from any endpoint */ neea.Endpoint->RegisterMethodSource("discovery::RegisterComponent");
neea.Endpoint->RegisterMethodSource("discovery::RegisterComponent");
}
/* accept discovery::Welcome messages from any endpoint */ /* accept discovery::Welcome messages from any endpoint */
neea.Endpoint->RegisterMethodSource("discovery::Welcome"); neea.Endpoint->RegisterMethodSource("discovery::Welcome");
@ -231,12 +233,6 @@ int DiscoveryComponent::NewIdentityHandler(const EventArgs& ea)
GetEndpointManager()->ForEachEndpoint(bind(&DiscoveryComponent::CheckExistingEndpoint, this, endpoint, _1)); GetEndpointManager()->ForEachEndpoint(bind(&DiscoveryComponent::CheckExistingEndpoint, this, endpoint, _1));
ConfigCollection::Ptr brokerCollection = GetApplication()->GetConfigHive()->GetCollection("broker");
if (brokerCollection->GetObject(identity)) {
/* accept discovery::NewComponent messages from brokers */
endpoint->RegisterMethodSource("discovery::NewComponent");
}
// we assume the other component _always_ wants // we assume the other component _always_ wants
// discovery::RegisterComponent messages from us // discovery::RegisterComponent messages from us
endpoint->RegisterMethodSink("discovery::RegisterComponent"); endpoint->RegisterMethodSink("discovery::RegisterComponent");
@ -394,6 +390,30 @@ void DiscoveryComponent::SendDiscoveryMessage(string method, string identity, En
GetEndpointManager()->SendMulticastRequest(m_DiscoveryEndpoint, request); GetEndpointManager()->SendMulticastRequest(m_DiscoveryEndpoint, request);
} }
bool DiscoveryComponent::HasMessagePermission(Dictionary::Ptr roles, string messageType, string message)
{
ConfigHive::Ptr configHive = GetApplication()->GetConfigHive();
ConfigCollection::Ptr roleCollection = configHive->GetCollection("role");
for (DictionaryIterator ip = roles->Begin(); ip != roles->End(); ip++) {
ConfigObject::Ptr role = roleCollection->GetObject(ip->second);
if (!role)
continue;
Dictionary::Ptr permissions;
if (!role->GetPropertyDictionary(messageType, &permissions))
continue;
for (DictionaryIterator is = permissions->Begin(); is != permissions->End(); is++) {
if (Utility::Match(is->second.GetString(), message))
return true;
}
}
return false;
}
/** /**
* ProcessDiscoveryMessage * ProcessDiscoveryMessage
* *
@ -402,8 +422,9 @@ void DiscoveryComponent::SendDiscoveryMessage(string method, string identity, En
* *
* @param identity The authorative identity of the component. * @param identity The authorative identity of the component.
* @param message The discovery message. * @param message The discovery message.
* @param trusted Whether the message comes from a trusted source (i.e. a broker).
*/ */
void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessage message) void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessage message, bool trusted)
{ {
/* ignore discovery messages that are about ourselves */ /* ignore discovery messages that are about ourselves */
if (identity == GetEndpointManager()->GetIdentity()) if (identity == GetEndpointManager()->GetIdentity())
@ -416,14 +437,20 @@ void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessa
message.GetNode(&info->Node); message.GetNode(&info->Node);
message.GetService(&info->Service); message.GetService(&info->Service);
ConfigHive::Ptr configHive = GetApplication()->GetConfigHive();
ConfigCollection::Ptr endpointCollection = configHive->GetCollection("endpoint");
ConfigObject::Ptr endpointConfig = endpointCollection->GetObject(identity);
Dictionary::Ptr roles;
if (endpointConfig)
endpointConfig->GetPropertyDictionary("roles", &roles);
Message provides; Message provides;
if (message.GetProvides(&provides)) { if (message.GetProvides(&provides)) {
DictionaryIterator i; DictionaryIterator i;
for (i = provides.GetDictionary()->Begin(); i != provides.GetDictionary()->End(); i++) { for (i = provides.GetDictionary()->Begin(); i != provides.GetDictionary()->End(); i++) {
if (IsBroker()) { if (trusted || HasMessagePermission(roles, "publish", i->second))
/* TODO: Add authorisation checks here */ info->PublishedMethods.insert(i->second);
}
info->PublishedMethods.insert(i->second);
} }
} }
@ -431,16 +458,14 @@ void DiscoveryComponent::ProcessDiscoveryMessage(string identity, DiscoveryMessa
if (message.GetSubscribes(&subscribes)) { if (message.GetSubscribes(&subscribes)) {
DictionaryIterator i; DictionaryIterator i;
for (i = subscribes.GetDictionary()->Begin(); i != subscribes.GetDictionary()->End(); i++) { for (i = subscribes.GetDictionary()->Begin(); i != subscribes.GetDictionary()->End(); i++) {
if (IsBroker()) { if (trusted || HasMessagePermission(roles, "subscribe", i->second))
/* TODO: Add authorisation checks here */ info->SubscribedMethods.insert(i->second);
}
info->SubscribedMethods.insert(i->second);
} }
} }
map<string, ComponentDiscoveryInfo::Ptr>::iterator i; map<string, ComponentDiscoveryInfo::Ptr>::iterator i;
i = m_Components.find(identity); i = m_Components.find(identity);
if (i != m_Components.end()) if (i != m_Components.end())
m_Components.erase(i); m_Components.erase(i);
@ -472,7 +497,7 @@ int DiscoveryComponent::NewComponentMessageHandler(const NewRequestEventArgs& nr
if (!message.GetIdentity(&identity)) if (!message.GetIdentity(&identity))
return 0; return 0;
ProcessDiscoveryMessage(identity, message); ProcessDiscoveryMessage(identity, message, true);
return 0; return 0;
} }
@ -486,45 +511,36 @@ int DiscoveryComponent::NewComponentMessageHandler(const NewRequestEventArgs& nr
*/ */
int DiscoveryComponent::RegisterComponentMessageHandler(const NewRequestEventArgs& nrea) int DiscoveryComponent::RegisterComponentMessageHandler(const NewRequestEventArgs& nrea)
{ {
/* ignore discovery::RegisterComponent messages when we're not a broker */
if (!IsBroker())
return 0;
DiscoveryMessage message; DiscoveryMessage message;
nrea.Request.GetParams(&message); nrea.Request.GetParams(&message);
ProcessDiscoveryMessage(nrea.Sender->GetIdentity(), message); ProcessDiscoveryMessage(nrea.Sender->GetIdentity(), message, false);
return 0; return 0;
} }
/** /**
* BrokerConfigHandler * EndpointConfigHandler
* *
* Processes "broker" config objects. * Processes "endpoint" config objects.
* *
* @param ea Event arguments for the new config object. * @param ea Event arguments for the new config object.
* @returns 0 * @returns 0
*/ */
int DiscoveryComponent::BrokerConfigHandler(const EventArgs& ea) int DiscoveryComponent::EndpointConfigHandler(const EventArgs& ea)
{ {
ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source); ConfigObject::Ptr object = static_pointer_cast<ConfigObject>(ea.Source);
EndpointManager::Ptr endpointManager = GetEndpointManager(); EndpointManager::Ptr endpointManager = GetEndpointManager();
/* Check if we're already connected to this broker. */ /* Check if we're already connected to this endpoint. */
if (endpointManager->GetEndpointByIdentity(object->GetName())) if (endpointManager->GetEndpointByIdentity(object->GetName()))
return 0; return 0;
string node; string node, service;
if (!object->GetPropertyString("node", &node)) if (object->GetPropertyString("node", &node) && object->GetPropertyString("service", &service)) {
throw InvalidArgumentException("'node' property required for 'broker' config object."); /* reconnect to this endpoint */
endpointManager->AddConnection(node, service);
string service; }
if (!object->GetPropertyString("service", &service))
throw InvalidArgumentException("'service' property required for 'broker' config object.");
/* reconnect to this broker */
endpointManager->AddConnection(node, service);
return 0; return 0;
} }
@ -545,9 +561,9 @@ int DiscoveryComponent::DiscoveryTimerHandler(const TimerEventArgs& tea)
time_t now; time_t now;
time(&now); time(&now);
/* check whether we have to reconnect to one of our upstream brokers */ /* check whether we have to reconnect to one of our upstream endpoints */
ConfigCollection::Ptr brokerCollection = GetApplication()->GetConfigHive()->GetCollection("broker"); ConfigCollection::Ptr endpointCollection = GetApplication()->GetConfigHive()->GetCollection("endpoint");
brokerCollection->ForEachObject(bind(&DiscoveryComponent::BrokerConfigHandler, this, _1)); endpointCollection->ForEachObject(bind(&DiscoveryComponent::EndpointConfigHandler, this, _1));
map<string, ComponentDiscoveryInfo::Ptr>::iterator i; map<string, ComponentDiscoveryInfo::Ptr>::iterator i;
for (i = m_Components.begin(); i != m_Components.end(); ) { for (i = m_Components.begin(); i != m_Components.end(); ) {

View File

@ -36,7 +36,7 @@ private:
int WelcomeMessageHandler(const NewRequestEventArgs& nrea); int WelcomeMessageHandler(const NewRequestEventArgs& nrea);
void SendDiscoveryMessage(string method, string identity, Endpoint::Ptr recipient); void SendDiscoveryMessage(string method, string identity, Endpoint::Ptr recipient);
void ProcessDiscoveryMessage(string identity, DiscoveryMessage message); void ProcessDiscoveryMessage(string identity, DiscoveryMessage message, bool trusted);
bool GetComponentDiscoveryInfo(string component, ComponentDiscoveryInfo::Ptr *info) const; bool GetComponentDiscoveryInfo(string component, ComponentDiscoveryInfo::Ptr *info) const;
@ -51,7 +51,9 @@ private:
void FinishDiscoverySetup(Endpoint::Ptr endpoint); void FinishDiscoverySetup(Endpoint::Ptr endpoint);
int BrokerConfigHandler(const EventArgs& ea); int EndpointConfigHandler(const EventArgs& ea);
bool HasMessagePermission(Dictionary::Ptr roles, string messageType, string message);
static const int RegistrationTTL = 300; static const int RegistrationTTL = 300;

View File

@ -56,5 +56,5 @@ components/discovery/Makefile
icinga/Makefile icinga/Makefile
icinga-app/Makefile icinga-app/Makefile
jsonrpc/Makefile jsonrpc/Makefile
mmatch/Makefile
]) ])

View File

@ -5,7 +5,7 @@
"privkey": "icinga-c1.key", "privkey": "icinga-c1.key",
"pubkey": "icinga-c1.crt", "pubkey": "icinga-c1.crt",
"cakey": "ca.crt", "cakey": "ca.crt",
"node": "10.0.10.3", "node": "10.0.10.14",
"service": "7777" "service": "7777"
} }
}, },
@ -16,5 +16,8 @@
}, },
"host": { "host": {
"localhost": { "node": "127.0.0.1" } "localhost": { "node": "127.0.0.1" }
},
"include": {
"permissions.conf": { "test": [ "hello", "world" ] }
} }
} }

View File

@ -14,7 +14,21 @@
"demo": { "replicate": "0" }, "demo": { "replicate": "0" },
"discovery": { "replicate": "0", "broker": "0" } "discovery": { "replicate": "0", "broker": "0" }
}, },
"broker": { "endpoint": {
"icinga-c1": { "replicate": "0", "node": "10.0.10.3", "service": "7777" } "icinga-c1": {
"replicate": "0",
"node": "10.0.10.14",
"service": "7777",
"roles": [ "broker", "demo" ]
}
},
"role": {
"broker": {
"publish": [ "discovery::NewComponent" ]
},
"demo": {
"publish": [ "demo::*" ],
"subscribe": [ "demo::*" ]
}
} }
} }

View File

@ -14,7 +14,21 @@
"demo": { "replicate": "0" }, "demo": { "replicate": "0" },
"discovery": { "replicate": "0", "broker": "0" } "discovery": { "replicate": "0", "broker": "0" }
}, },
"broker": { "endpoint": {
"icinga-c1": { "replicate": "0", "node": "10.0.10.3", "service": "7777" } "icinga-c1": {
"replicate": "0",
"node": "10.0.10.14",
"service": "7777",
"roles": [ "broker", "demo" ]
}
},
"role": {
"broker": {
"publish": [ "discovery::NewComponent" ]
},
"demo": {
"publish": [ "demo::*" ],
"subscribe": [ "demo::*" ]
}
} }
} }

View File

@ -2,6 +2,9 @@
Microsoft Visual Studio Solution File, Format Version 11.00 Microsoft Visual Studio Solution File, Format Version 11.00
# Visual C++ Express 2010 # Visual C++ Express 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base", "base\base.vcxproj", "{9C92DA90-FD53-43A9-A244-90F2E8AF9677}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "base", "base\base.vcxproj", "{9C92DA90-FD53-43A9-A244-90F2E8AF9677}"
ProjectSection(ProjectDependencies) = postProject
{19CBCE06-3F5C-479A-BD75-E2AB6215D345} = {19CBCE06-3F5C-479A-BD75-E2AB6215D345}
EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsonrpc", "jsonrpc\jsonrpc.vcxproj", "{8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsonrpc", "jsonrpc\jsonrpc.vcxproj", "{8DD52FAC-ECEE-48C2-B266-E7C47ED485F8}"
ProjectSection(ProjectDependencies) = postProject ProjectSection(ProjectDependencies) = postProject
@ -46,6 +49,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "discovery", "components\dis
{C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} = {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8} = {C1FC77E1-04A4-481B-A78B-2F7AF489C2F8}
EndProjectSection EndProjectSection
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mmatch", "mmatch\mmatch.vcxproj", "{19CBCE06-3F5C-479A-BD75-E2AB6215D345}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
@ -88,6 +93,10 @@ Global
{EAD41628-BB96-4F99-9070-8A9676801295}.Debug|Win32.Build.0 = Debug|Win32 {EAD41628-BB96-4F99-9070-8A9676801295}.Debug|Win32.Build.0 = Debug|Win32
{EAD41628-BB96-4F99-9070-8A9676801295}.Release|Win32.ActiveCfg = Release|Win32 {EAD41628-BB96-4F99-9070-8A9676801295}.Release|Win32.ActiveCfg = Release|Win32
{EAD41628-BB96-4F99-9070-8A9676801295}.Release|Win32.Build.0 = Release|Win32 {EAD41628-BB96-4F99-9070-8A9676801295}.Release|Win32.Build.0 = Release|Win32
{19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win32.ActiveCfg = Debug|Win32
{19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Debug|Win32.Build.0 = Debug|Win32
{19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win32.ActiveCfg = Release|Win32
{19CBCE06-3F5C-479A-BD75-E2AB6215D345}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@ -30,14 +30,14 @@ int IcingaApplication::Main(const vector<string>& args)
/* register handler for 'icinga' config objects */ /* register handler for 'icinga' config objects */
ConfigCollection::Ptr icingaCollection = GetConfigHive()->GetCollection("icinga"); ConfigCollection::Ptr icingaCollection = GetConfigHive()->GetCollection("icinga");
function<int (const EventArgs&)> NewIcingaConfigHandler = bind_weak(&IcingaApplication::NewIcingaConfigHandler, shared_from_this()); function<int (const EventArgs&)> NewIcingaConfigHandler = bind_weak(&IcingaApplication::NewIcingaConfigHandler, shared_from_this());
icingaCollection->OnObjectCreated += NewIcingaConfigHandler; icingaCollection->OnObjectCommitted += NewIcingaConfigHandler;
icingaCollection->ForEachObject(NewIcingaConfigHandler); icingaCollection->ForEachObject(NewIcingaConfigHandler);
icingaCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedIcingaConfigHandler, shared_from_this()); icingaCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedIcingaConfigHandler, shared_from_this());
/* register handler for 'component' config objects */ /* register handler for 'component' config objects */
ConfigCollection::Ptr componentCollection = GetConfigHive()->GetCollection("component"); ConfigCollection::Ptr componentCollection = GetConfigHive()->GetCollection("component");
function<int (const EventArgs&)> NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this()); function<int (const EventArgs&)> NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this());
componentCollection->OnObjectCreated += NewComponentHandler; componentCollection->OnObjectCommitted += NewComponentHandler;
componentCollection->ForEachObject(NewComponentHandler); componentCollection->ForEachObject(NewComponentHandler);
componentCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this()); componentCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this());

9
mmatch/Makefile.am Normal file
View File

@ -0,0 +1,9 @@
## Process this file with automake to produce Makefile.in
noinst_LTLIBRARIES = \
libmmatch.la
libmmatch_la_SOURCES = \
mmatch.c \
mmatch.h

305
mmatch/mmatch.c Normal file
View File

@ -0,0 +1,305 @@
/*
* IRC - Internet Relay Chat, common/match.c
* Copyright (C) 1990 Jarkko Oikarinen
*
* 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: Match.cpp,v 1.2 2005/08/15 10:08:50 shroud23 Exp $
*/
#include <ctype.h>
#include "mmatch.h"
#define ToLower tolower
/*
* mmatch()
*
* Written by Run (carlo@runaway.xs4all.nl), 25-10-96
*
*
* From: Carlo Wood <carlo@runaway.xs4all.nl>
* Message-Id: <199609021026.MAA02393@runaway.xs4all.nl>
* Subject: [C-Com] Analysis for `mmatch' (was: gline4 problem)
* To: coder-com@mail.undernet.org (coder committee)
* Date: Mon, 2 Sep 1996 12:26:01 +0200 (MET DST)
*
* We need a new function `mmatch(const char *old_mask, const char *new_mask)'
* which returns `true' likewise the current `match' (start with copying it),
* but which treats '*' and '?' in `new_mask' differently (not "\*" and "\?" !)
* as follows: a '*' in `new_mask' does not match a '?' in `old_mask' and
* a '?' in `new_mask' does not match a '\?' in `old_mask'.
* And ofcourse... a '*' in `new_mask' does not match a '\*' in `old_mask'...
* And last but not least, '\?' and '\*' in `new_mask' now become one character.
*/
int mmatch(const char *old_mask, const char *new_mask)
{
const char *m = old_mask;
const char *n = new_mask;
const char *ma = m;
const char *na = n;
int wild = 0;
int mq = 0, nq = 0;
while (1)
{
if (*m == '*')
{
while (*m == '*')
m++;
wild = 1;
ma = m;
na = n;
}
if (!*m)
{
if (!*n)
return 0;
for (m--; (m > old_mask) && (*m == '?'); m--)
;
if ((*m == '*') && (m > old_mask) && (m[-1] != '\\'))
return 0;
if (!wild)
return 1;
m = ma;
/* Added to `mmatch' : Because '\?' and '\*' now is one character: */
if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
++na;
n = ++na;
}
else if (!*n)
{
while (*m == '*')
m++;
return (*m != 0);
}
if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
{
m++;
mq = 1;
}
else
mq = 0;
/* Added to `mmatch' : Because '\?' and '\*' now is one character: */
if ((*n == '\\') && ((n[1] == '*') || (n[1] == '?')))
{
n++;
nq = 1;
}
else
nq = 0;
/*
* This `if' has been changed compared to match() to do the following:
* Match when:
* old (m) new (n) boolean expression
* * any (*m == '*' && !mq) ||
* ? any except '*' (*m == '?' && !mq && (*n != '*' || nq)) ||
* any except * or ? same as m (!((*m == '*' || *m == '?') && !mq) &&
* ToLower(*m) == ToLower(*n) &&
* !((mq && !nq) || (!mq && nq)))
*
* Here `any' also includes \* and \? !
*
* After reworking the boolean expressions, we get:
* (Optimized to use boolean shortcircuits, with most frequently occuring
* cases upfront (which took 2 hours!)).
*/
if ((*m == '*' && !mq) ||
((!mq || nq) && ToLower(*m) == ToLower(*n)) ||
(*m == '?' && !mq && (*n != '*' || nq)))
{
if (*m)
m++;
if (*n)
n++;
}
else
{
if (!wild)
return 1;
m = ma;
/* Added to `mmatch' : Because '\?' and '\*' now is one character: */
if ((*na == '\\') && ((na[1] == '*') || (na[1] == '?')))
++na;
n = ++na;
}
}
}
/*
* Compare if a given string (name) matches the given
* mask (which can contain wild cards: '*' - match any
* number of chars, '?' - match any single character.
*
* return 0, if match
* 1, if no match
*/
/*
* match
*
* Rewritten by Andrea Cocito (Nemesi), November 1998.
*
*/
/****************** Nemesi's match() ***************/
int match(const char *mask, const char *string)
{
const char *m = mask, *s = string;
char ch;
const char *bm, *bs; /* Will be reg anyway on a decent CPU/compiler */
/* Process the "head" of the mask, if any */
while ((ch = *m++) && (ch != '*'))
switch (ch)
{
case '\\':
if (*m == '?' || *m == '*')
ch = *m++;
default:
if (ToLower(*s) != ToLower(ch))
return 1;
case '?':
if (!*s++)
return 1;
};
if (!ch)
return *s;
/* We got a star: quickly find if/where we match the next char */
got_star:
bm = m; /* Next try rollback here */
while ((ch = *m++))
switch (ch)
{
case '?':
if (!*s++)
return 1;
case '*':
bm = m;
continue; /* while */
case '\\':
if (*m == '?' || *m == '*')
ch = *m++;
default:
goto break_while; /* C is structured ? */
};
break_while:
if (!ch)
return 0; /* mask ends with '*', we got it */
ch = ToLower(ch);
if (!*s) /* String is already empty, don't continue */
return 1; /* This fixes the #quakenet access denied bug */
while (ToLower(*s++) != ch)
if (!*s)
return 1;
bs = s; /* Next try start from here */
/* Check the rest of the "chunk" */
while ((ch = *m++))
{
switch (ch)
{
case '*':
goto got_star;
case '\\':
if (*m == '?' || *m == '*')
ch = *m++;
default:
if (ToLower(*s) != ToLower(ch))
{
/* If we've run out of string, give up */
if (!*bs)
return 1;
m = bm;
s = bs;
goto got_star;
};
case '?':
if (!*s++)
return 1;
};
};
if (*s)
{
m = bm;
s = bs;
goto got_star;
};
return 0;
}
/*
* collapse()
* Collapse a pattern string into minimal components.
* This particular version is "in place", so that it changes the pattern
* which is to be reduced to a "minimal" size.
*
* (C) Carlo Wood - 6 Oct 1998
* Speedup rewrite by Andrea Cocito, December 1998.
* Note that this new optimized alghoritm can *only* work in place.
*/
char *collapse(char *mask)
{
int star = 0;
char *m = mask;
char *b;
if (m)
{
do
{
if ((*m == '*') && ((m[1] == '*') || (m[1] == '?')))
{
b = m;
do
{
if (*m == '*')
star = 1;
else
{
if (star && (*m != '?'))
{
*b++ = '*';
star = 0;
};
*b++ = *m;
if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
*b++ = *++m;
};
}
while (*m++);
break;
}
else
{
if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?')))
m++;
};
}
while (*m++);
};
return mask;
}

16
mmatch/mmatch.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef MMATCH_H
#define MMATCH_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
int mmatch(const char *old_mask, const char *new_mask);
int match(const char *ma, const char *na);
char *collapse(char *pattern);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* MMATCH_H */

80
mmatch/mmatch.vcxproj Normal file
View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<ClCompile Include="mmatch.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="mmatch.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{19CBCE06-3F5C-479A-BD75-E2AB6215D345}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>mmatch</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>