]> granicus.if.org Git - icinga2/commitdiff
Implement support for sending pki::RequestCertificate messages in the cluster
authorGunnar Beutner <gunnar.beutner@icinga.com>
Wed, 23 Aug 2017 13:11:32 +0000 (15:11 +0200)
committerGunnar Beutner <gunnar.beutner@icinga.com>
Tue, 12 Sep 2017 10:52:49 +0000 (12:52 +0200)
refs #5450

lib/cli/pkiutility.cpp
lib/remote/apilistener.cpp
lib/remote/apilistener.hpp
lib/remote/jsonrpcconnection-pki.cpp

index aeb385f9f6dee4652c18840a50cd093338ba9356..3dcae4cb2c188e63ba830b0cba447daf77af87ac 100644 (file)
@@ -258,10 +258,41 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const
 
        Dictionary::Ptr result = response->Get("result");
 
+       if (result->Contains("ca")) {
+               try {
+                       StringToCertificate(result->Get("ca"));
+               } catch (const std::exception& ex) {
+                       Log(LogCritical, "cli")
+                           << "Could not write CA file: " << DiagnosticInformation(ex, false);
+                       return 1;
+               }
+
+               Log(LogInformation, "cli")
+                   << "Writing CA certificate to file '" << cafile << "'.";
+
+               std::ofstream fpca;
+               fpca.open(cafile.CStr());
+               fpca << result->Get("ca");
+               fpca.close();
+
+               if (fpca.fail()) {
+                       Log(LogCritical, "cli")
+                           << "Could not open CA certificate file '" << cafile << "' for writing.";
+                       return 1;
+               }
+       }
+
        if (result->Contains("error")) {
                LogSeverity severity;
 
-               if (result->Get("status_code") == 1)
+               Value vstatus;
+
+               if (!result->Get("status_code", &vstatus))
+                       vstatus = 1;
+
+               int status = vstatus;
+
+               if (status == 1)
                        severity = LogCritical;
                else {
                        severity = LogInformation;
@@ -271,7 +302,7 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const
                Log(severity, "cli")
                    << "!!! " << result->Get("error");
 
-               if (result->Get("status_code") == 1)
+               if (status == 1)
                        return 1;
                else {
                        Log(severity, "cli", "!!!!!!");
@@ -287,13 +318,8 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const
                return 1;
        }
 
-       try {
-               StringToCertificate(result->Get("ca"));
-       } catch (const std::exception& ex) {
-               Log(LogCritical, "cli")
-                   << "Could not write CA file: " << DiagnosticInformation(ex, false);
-               return 1;
-       }
+       Log(LogInformation, "cli")
+           << "Writing signed certificate to file '" << certfile << "'.";
 
        std::ofstream fpcert;
        fpcert.open(certfile.CStr());
@@ -306,23 +332,6 @@ int PkiUtility::RequestCertificate(const String& host, const String& port, const
                return 1;
        }
 
-       Log(LogInformation, "cli")
-           << "Writing signed certificate to file '" << certfile << "'.";
-
-       std::ofstream fpca;
-       fpca.open(cafile.CStr());
-       fpca << result->Get("ca");
-       fpca.close();
-
-       if (fpca.fail()) {
-               Log(LogCritical, "cli")
-                   << "Could not open CA certificate file '" << cafile << "' for writing.";
-               return 1;
-       }
-
-       Log(LogInformation, "cli")
-           << "Writing CA certificate to file '" << cafile << "'.";
-
        return 0;
 }
 
index fd348edd909c73cf916441fcfa68dd1354103a3a..bd6630dce4aeca9a98b4509311eef03ecfcb48e9 100644 (file)
@@ -478,6 +478,15 @@ void ApiListener::SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoi
                        endpoint->SetSyncing(true);
                }
 
+               Zone::Ptr myZone = Zone::GetLocalZone();
+
+               if (myZone->GetParent() == eZone) {
+                       Log(LogInformation, "ApiListener")
+                           << "Requesting new certificate for this Icinga instance from endpoint '" << endpoint->GetName() << "'.";
+
+                       SendCertificateRequest(aclient);
+               }
+
                /* Make sure that the config updates are synced
                 * before the logs are replayed.
                 */
@@ -530,6 +539,19 @@ void ApiListener::SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoi
            << "Finished syncing endpoint '" << endpoint->GetName() << "' in zone '" << eZone->GetName() << "'.";
 }
 
+void ApiListener::SendCertificateRequest(const JsonRpcConnection::Ptr& aclient)
+{
+       Dictionary::Ptr message = new Dictionary();
+       message->Set("jsonrpc", "2.0");
+       message->Set("method", "pki::RequestCertificate");
+
+       Dictionary::Ptr params = new Dictionary();
+
+       message->Set("params", params);
+
+       JsonRpc::SendMessage(aclient->GetStream(), message);
+}
+
 void ApiListener::ApiTimerHandler(void)
 {
        double now = Utility::GetTime();
index 8e12f0dcae147c40eb8e4e8d9ec0b22c272f70fe..c16ed46c53bbe77c8b672ed9c0e72f7d8a9b5de9 100644 (file)
@@ -158,6 +158,7 @@ private:
 
        static void ConfigGlobHandler(ConfigDirInformation& config, const String& path, const String& file);
        void SendConfigUpdate(const JsonRpcConnection::Ptr& aclient);
+       void SendCertificateRequest(const JsonRpcConnection::Ptr& aclient);
 
        /* configsync */
        void UpdateConfigObject(const ConfigObject::Ptr& object, const MessageOrigin::Ptr& origin,
index 14470806e2a64c18ba7862d159fda616f7765e9d..a0df4fa0b86210b4155e66b0658f0b86c8475749 100644 (file)
@@ -94,10 +94,11 @@ Value RequestCertificateHandler(const MessageOrigin::Ptr& origin, const Dictiona
        if (!origin->FromClient->IsAuthenticated()) {
                String salt = listener->GetTicketSalt();
 
-               if (salt.IsEmpty())
+               String ticket = params->Get("ticket");
+
+               if (salt.IsEmpty() || ticket.IsEmpty())
                        goto delayed_request;
 
-               String ticket = params->Get("ticket");
                String realTicket = PBKDF2_SHA1(origin->FromClient->GetIdentity(), salt, 50000);
 
                if (ticket != realTicket) {