1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "cli/casigncommand.hpp"
4 #include "remote/apilistener.hpp"
5 #include "base/logger.hpp"
6 #include "base/application.hpp"
7 #include "base/tlsutility.hpp"
9 using namespace icinga;
11 REGISTER_CLICOMMAND("ca/sign", CASignCommand);
13 String CASignCommand::GetDescription() const
15 return "Signs an outstanding certificate request.";
18 String CASignCommand::GetShortDescription() const
20 return "signs an outstanding certificate request";
23 int CASignCommand::GetMinArguments() const
28 ImpersonationLevel CASignCommand::GetImpersonationLevel() const
30 return ImpersonateIcinga;
34 * The entry point for the "ca sign" CLI command.
36 * @returns An exit status.
38 int CASignCommand::Run(const boost::program_options::variables_map& vm, const std::vector<std::string>& ap) const
40 String requestFile = ApiListener::GetCertificateRequestsDir() + "/" + ap[0] + ".json";
42 if (!Utility::PathExists(requestFile)) {
43 Log(LogCritical, "cli")
44 << "No request exists for fingerprint '" << ap[0] << "'.";
48 Dictionary::Ptr request = Utility::LoadJsonFile(requestFile);
53 String certRequestText = request->Get("cert_request");
55 std::shared_ptr<X509> certRequest = StringToCertificate(certRequestText);
58 Log(LogCritical, "cli", "Certificate request is invalid. Could not parse X.509 certificate for the 'cert_request' attribute.");
62 std::shared_ptr<X509> certResponse = CreateCertIcingaCA(certRequest);
64 BIO *out = BIO_new(BIO_s_mem());
65 X509_NAME_print_ex(out, X509_get_subject_name(certRequest.get()), 0, XN_FLAG_ONELINE & ~ASN1_STRFLGS_ESC_MSB);
69 length = BIO_get_mem_data(out, &data);
71 String subject = String(data, data + length);
75 Log(LogCritical, "cli")
76 << "Could not sign certificate for '" << subject << "'.";
80 request->Set("cert_response", CertificateToString(certResponse));
82 Utility::SaveJsonFile(requestFile, 0600, request);
84 Log(LogInformation, "cli")
85 << "Signed certificate for '" << subject << "'.";