From 623208d6176ca5b2fdc7c4377b82d698085111d3 Mon Sep 17 00:00:00 2001
From: Gunnar Beutner <gunnar.beutner@icinga.com>
Date: Mon, 4 Sep 2017 13:18:06 +0200
Subject: [PATCH] Implement support for forwarding certificate requests

refs #5450
---
 lib/remote/apilistener.cpp           |  2 ++
 lib/remote/jsonrpcconnection-pki.cpp | 31 ++++++++++++++++++++++++++++
 lib/remote/jsonrpcconnection.hpp     |  2 ++
 3 files changed, 35 insertions(+)

diff --git a/lib/remote/apilistener.cpp b/lib/remote/apilistener.cpp
index d298bbe1e..e7bee884c 100644
--- a/lib/remote/apilistener.cpp
+++ b/lib/remote/apilistener.cpp
@@ -498,6 +498,8 @@ void ApiListener::SyncClient(const JsonRpcConnection::Ptr& aclient, const Endpoi
 			    << "Requesting new certificate for this Icinga instance from endpoint '" << endpoint->GetName() << "'.";
 
 			aclient->SendCertificateRequest();
+
+			Utility::Glob(Application::GetLocalStateDir() + "/lib/icinga2/pki-requests/*.json", boost::bind(&JsonRpcConnection::SyncCertificateRequest, aclient, MessageOrigin::Ptr(), _1), GlobFile);
 		}
 
 		/* Make sure that the config updates are synced
diff --git a/lib/remote/jsonrpcconnection-pki.cpp b/lib/remote/jsonrpcconnection-pki.cpp
index 8c221ee7f..3110b53a4 100644
--- a/lib/remote/jsonrpcconnection-pki.cpp
+++ b/lib/remote/jsonrpcconnection-pki.cpp
@@ -151,6 +151,8 @@ delayed_request:
 
 	Utility::SaveJsonFile(requestPath, 0600, request);
 
+	JsonRpcConnection::SyncCertificateRequest(JsonRpcConnection::Ptr(), origin, requestPath);
+
 	result->Set("status_code", 2);
 	result->Set("error", "Certificate request is pending. Waiting for approval from the parent Icinga instance.");
 	return result;
@@ -260,3 +262,32 @@ void JsonRpcConnection::CertificateRequestResponseHandler(const Dictionary::Ptr&
 	Log(LogInformation, "JsonRpcConnection", "Updating the client certificate for the ApiListener object");
 	listener->UpdateSSLContext();
 }
+
+void JsonRpcConnection::SyncCertificateRequest(const JsonRpcConnection::Ptr& aclient, const MessageOrigin::Ptr& origin, const String& path)
+{
+	Dictionary::Ptr request = Utility::LoadJsonFile(path);
+
+	if (request->Contains("cert_response"))
+		return;
+
+	Dictionary::Ptr message = new Dictionary();
+	message->Set("jsonrpc", "2.0");
+	message->Set("method", "pki::RequestCertificate");
+
+	Dictionary::Ptr params = new Dictionary();
+	params->Set("cert_request", request->Get("cert_request"));
+	params->Set("ticket", request->Get("ticket"));
+
+	message->Set("params", params);
+
+	if (aclient)
+		JsonRpc::SendMessage(aclient->GetStream(), message);
+	else {
+		ApiListener::Ptr listener = ApiListener::GetInstance();
+
+		if (!listener)
+			return;
+
+		listener->RelayMessage(origin, Zone::GetLocalZone(), message, false);
+	}
+}
diff --git a/lib/remote/jsonrpcconnection.hpp b/lib/remote/jsonrpcconnection.hpp
index d8d2a863a..0ab1465af 100644
--- a/lib/remote/jsonrpcconnection.hpp
+++ b/lib/remote/jsonrpcconnection.hpp
@@ -85,6 +85,8 @@ public:
 
 	void SendCertificateRequest(void);
 
+	static void SyncCertificateRequest(const JsonRpcConnection::Ptr& aclient, const intrusive_ptr<MessageOrigin>& origin, const String& path);
+
 private:
 	int m_ID;
 	String m_Identity;