From d55965c070d8609654315564713878983e551b99 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Fri, 27 Apr 2012 13:12:06 +0200 Subject: [PATCH] Made SSL cert paths configurable. --- base/configobject.h | 3 - icinga-app/icinga.conf | 7 ++ icinga/endpointmanager.cpp | 16 +++- icinga/endpointmanager.h | 6 +- icinga/icingaapplication.cpp | 147 ++++++++++++++++++++++++++--------- icinga/icingaapplication.h | 17 ++++ 6 files changed, 153 insertions(+), 43 deletions(-) diff --git a/base/configobject.h b/base/configobject.h index bea58f0d9..1caee2eb3 100644 --- a/base/configobject.h +++ b/base/configobject.h @@ -23,9 +23,6 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - typedef map::iterator ParameterIterator; - map Properties; - ConfigObject(const string& type, const string& name); void SetHive(const weak_ptr& hive); diff --git a/icinga-app/icinga.conf b/icinga-app/icinga.conf index 621a96513..04916d95f 100644 --- a/icinga-app/icinga.conf +++ b/icinga-app/icinga.conf @@ -1,4 +1,11 @@ { + "icinga": { + "icinga": { + "privkey": "icinga-c1.key", + "pubkey": "icinga-c1.crt", + "cakey": "ca.crt" + } + }, "component": { "configrpc": { "replicate": "0", "configSource": "1" }, "demo": { "replicate": "0" } diff --git a/icinga/endpointmanager.cpp b/icinga/endpointmanager.cpp index 76d094da9..dd05c96e7 100644 --- a/icinga/endpointmanager.cpp +++ b/icinga/endpointmanager.cpp @@ -2,10 +2,9 @@ using namespace icinga; -EndpointManager::EndpointManager(string identity, shared_ptr sslContext) +void EndpointManager::SetIdentity(string identity) { m_Identity = identity; - m_SSLContext = sslContext; } string EndpointManager::GetIdentity(void) const @@ -13,6 +12,16 @@ string EndpointManager::GetIdentity(void) const return m_Identity; } +void EndpointManager::SetSSLContext(shared_ptr sslContext) +{ + m_SSLContext = sslContext; +} + +shared_ptr EndpointManager::GetSSLContext(void) const +{ + return m_SSLContext; +} + void EndpointManager::AddListener(unsigned short port) { stringstream s; @@ -64,6 +73,9 @@ void EndpointManager::UnregisterServer(JsonRpcServer::Ptr server) void EndpointManager::RegisterEndpoint(Endpoint::Ptr endpoint) { + if (!endpoint->IsLocal() && endpoint->GetIdentity() != "") + throw InvalidArgumentException("Identity must be empty."); + endpoint->SetEndpointManager(static_pointer_cast(shared_from_this())); m_Endpoints.push_front(endpoint); diff --git a/icinga/endpointmanager.h b/icinga/endpointmanager.h index 864d31246..a51459dd7 100644 --- a/icinga/endpointmanager.h +++ b/icinga/endpointmanager.h @@ -29,10 +29,12 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; - EndpointManager(string identity, shared_ptr sslContext); - + void SetIdentity(string identity); string GetIdentity(void) const; + void SetSSLContext(shared_ptr sslContext); + shared_ptr GetSSLContext(void) const; + void AddListener(unsigned short port); void AddConnection(string host, unsigned short port); diff --git a/icinga/icingaapplication.cpp b/icinga/icingaapplication.cpp index ff1408607..567dd8f1b 100644 --- a/icinga/icingaapplication.cpp +++ b/icinga/icingaapplication.cpp @@ -22,54 +22,70 @@ int IcingaApplication::Main(const vector& args) return EXIT_FAILURE; } - shared_ptr cert = Utility::GetX509Certificate("icinga-c1.crt"); - string identity = Utility::GetCertificateCN(cert); - - Application::Log("My identity: " + identity); - - shared_ptr sslContext = Utility::MakeSSLContext("icinga-c1.crt", "icinga-c1.key", "ca.crt"); - - m_EndpointManager = make_shared(identity, sslContext); + m_EndpointManager = make_shared(); string componentDirectory = GetExeDirectory() + "/../lib/icinga"; AddComponentSearchDir(componentDirectory); + /* register handler for 'component' config objects */ ConfigCollection::Ptr componentCollection = GetConfigHive()->GetCollection("component"); - function NewComponentHandler = bind_weak(&IcingaApplication::NewComponentHandler, shared_from_this()); componentCollection->OnObjectCreated += NewComponentHandler; componentCollection->ForEachObject(NewComponentHandler); - componentCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedComponentHandler, shared_from_this()); - ConfigCollection::Ptr listenerCollection = GetConfigHive()->GetCollection("rpclistener"); - - function NewRpcListenerHandler = bind_weak(&IcingaApplication::NewRpcListenerHandler, shared_from_this()); - listenerCollection->OnObjectCreated += NewRpcListenerHandler; - listenerCollection->ForEachObject(NewRpcListenerHandler); - - listenerCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedRpcListenerHandler, shared_from_this()); - - ConfigCollection::Ptr connectionCollection = GetConfigHive()->GetCollection("rpcconnection"); - - function NewRpcConnectionHandler = bind_weak(&IcingaApplication::NewRpcConnectionHandler, shared_from_this()); - connectionCollection->OnObjectCreated += NewRpcConnectionHandler; - connectionCollection->ForEachObject(NewRpcConnectionHandler); - - connectionCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedRpcConnectionHandler, shared_from_this()); - - SubscriptionComponent::Ptr subscriptionComponent = make_shared(); - RegisterComponent(subscriptionComponent); - - DiscoveryComponent::Ptr discoveryComponent = make_shared(); - RegisterComponent(discoveryComponent); + /* register handler for 'icinga' config objects */ + ConfigCollection::Ptr icingaCollection = GetConfigHive()->GetCollection("icinga"); + function NewIcingaConfigHandler = bind_weak(&IcingaApplication::NewIcingaConfigHandler, shared_from_this()); + icingaCollection->OnObjectCreated += NewIcingaConfigHandler; + icingaCollection->ForEachObject(NewIcingaConfigHandler); + icingaCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedIcingaConfigHandler, shared_from_this()); + /* load config file */ ConfigObject::Ptr fileComponentConfig = make_shared("component", "configfile"); fileComponentConfig->SetPropertyString("configFilename", args[1]); fileComponentConfig->SetPropertyInteger("replicate", 0); GetConfigHive()->AddObject(fileComponentConfig); - ConfigCollection::Ptr collection = GetConfigHive()->GetCollection("rpclistener"); + if (GetPrivateKeyFile().empty()) + throw InvalidArgumentException("No private key was specified."); + + if (GetPublicKeyFile().empty()) + throw InvalidArgumentException("No public certificate was specified."); + + if (GetCAKeyFile().empty()) + throw InvalidArgumentException("No CA certificate was specified."); + + /* set up SSL context */ + shared_ptr cert = Utility::GetX509Certificate(GetPublicKeyFile()); + string identity = Utility::GetCertificateCN(cert); + Application::Log("My identity: " + identity); + m_EndpointManager->SetIdentity(identity); + + shared_ptr sslContext = Utility::MakeSSLContext(GetPublicKeyFile(), GetPrivateKeyFile(), GetCAKeyFile()); + m_EndpointManager->SetSSLContext(sslContext); + + /* register handler for 'rpclistener' config objects */ + ConfigCollection::Ptr listenerCollection = GetConfigHive()->GetCollection("rpclistener"); + function NewRpcListenerHandler = bind_weak(&IcingaApplication::NewRpcListenerHandler, shared_from_this()); + listenerCollection->OnObjectCreated += NewRpcListenerHandler; + listenerCollection->ForEachObject(NewRpcListenerHandler); + listenerCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedRpcListenerHandler, shared_from_this()); + + /* register handle for 'rpcconnection' config objects */ + ConfigCollection::Ptr connectionCollection = GetConfigHive()->GetCollection("rpcconnection"); + function NewRpcConnectionHandler = bind_weak(&IcingaApplication::NewRpcConnectionHandler, shared_from_this()); + connectionCollection->OnObjectCreated += NewRpcConnectionHandler; + connectionCollection->ForEachObject(NewRpcConnectionHandler); + connectionCollection->OnObjectRemoved += bind_weak(&IcingaApplication::DeletedRpcConnectionHandler, shared_from_this()); + + /* load the subscription component */ + SubscriptionComponent::Ptr subscriptionComponent = make_shared(); + RegisterComponent(subscriptionComponent); + + /* load the discovery component */ + DiscoveryComponent::Ptr discoveryComponent = make_shared(); + RegisterComponent(discoveryComponent); RunEventLoop(); @@ -88,13 +104,13 @@ EndpointManager::Ptr IcingaApplication::GetEndpointManager(void) int IcingaApplication::NewComponentHandler(const EventArgs& ea) { - string path; ConfigObject::Ptr object = static_pointer_cast(ea.Source); /* don't allow replicated config objects */ if (object->GetReplicated()) return 0; + string path; if (!object->GetPropertyString("path", &path)) { #ifdef _WIN32 path = object->GetName() + ".dll"; @@ -118,23 +134,52 @@ int IcingaApplication::DeletedComponentHandler(const EventArgs& ea) return 0; } +int IcingaApplication::NewIcingaConfigHandler(const EventArgs& ea) +{ + ConfigObject::Ptr object = static_pointer_cast(ea.Source); + + /* don't allow replicated config objects */ + if (object->GetReplicated()) + return 0; + + string privkey; + if (object->GetPropertyString("privkey", &privkey)) + SetPrivateKeyFile(privkey); + + string pubkey; + if (object->GetPropertyString("pubkey", &pubkey)) + SetPublicKeyFile(pubkey); + + string cakey; + if (object->GetPropertyString("cakey", &cakey)) + SetCAKeyFile(cakey); + + return 0; +} + +int IcingaApplication::DeletedIcingaConfigHandler(const EventArgs& ea) +{ + throw Exception("Unsupported operation."); + + return 0; +} + int IcingaApplication::NewRpcListenerHandler(const EventArgs& ea) { ConfigObject::Ptr object = static_pointer_cast(ea.Source); - long portValue; - unsigned short port; /* don't allow replicated config objects */ if (object->GetReplicated()) return 0; + long portValue; if (!object->GetPropertyInteger("port", &portValue)) throw InvalidArgumentException("Parameter 'port' is required for 'rpclistener' objects."); if (portValue < 0 || portValue > USHRT_MAX) throw InvalidArgumentException("Parameter 'port' contains an invalid value."); - port = (unsigned short)portValue; + unsigned short port = (unsigned short)portValue; GetEndpointManager()->AddListener(port); @@ -181,3 +226,33 @@ int IcingaApplication::DeletedRpcConnectionHandler(const EventArgs& ea) return 0; } + +void IcingaApplication::SetPrivateKeyFile(string privkey) +{ + m_PrivateKeyFile = privkey; +} + +string IcingaApplication::GetPrivateKeyFile(void) const +{ + return m_PrivateKeyFile; +} + +void IcingaApplication::SetPublicKeyFile(string pubkey) +{ + m_PublicKeyFile = pubkey; +} + +string IcingaApplication::GetPublicKeyFile(void) const +{ + return m_PublicKeyFile; +} + +void IcingaApplication::SetCAKeyFile(string cakey) +{ + m_CAKeyFile = cakey; +} + +string IcingaApplication::GetCAKeyFile(void) const +{ + return m_CAKeyFile; +} diff --git a/icinga/icingaapplication.h b/icinga/icingaapplication.h index 6904e3dac..49a2f6b6d 100644 --- a/icinga/icingaapplication.h +++ b/icinga/icingaapplication.h @@ -9,9 +9,16 @@ class I2_ICINGA_API IcingaApplication : public Application private: EndpointManager::Ptr m_EndpointManager; + string m_PrivateKeyFile; + string m_PublicKeyFile; + string m_CAKeyFile; + int NewComponentHandler(const EventArgs& ea); int DeletedComponentHandler(const EventArgs& ea); + int NewIcingaConfigHandler(const EventArgs& ea); + int DeletedIcingaConfigHandler(const EventArgs& ea); + int NewRpcListenerHandler(const EventArgs& ea); int DeletedRpcListenerHandler(const EventArgs& ea); @@ -19,6 +26,7 @@ private: int DeletedRpcConnectionHandler(const EventArgs& ea); int TestTimerHandler(const TimerEventArgs& tea); + public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; @@ -28,6 +36,15 @@ public: void PrintUsage(const string& programPath); EndpointManager::Ptr GetEndpointManager(void); + + void SetPrivateKeyFile(string privkey); + string GetPrivateKeyFile(void) const; + + void SetPublicKeyFile(string pubkey); + string GetPublicKeyFile(void) const; + + void SetCAKeyFile(string cakey); + string GetCAKeyFile(void) const; }; }