From: Michael Friedrich Date: Fri, 6 Apr 2018 17:49:01 +0000 (+0200) Subject: Implement support for connection-less node setup (no csr auto-signing connect) X-Git-Tag: v2.9.0~97^2~2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7c0ef80279d75a77e4cc14bb71647ecb3fd9c86a;p=icinga2 Implement support for connection-less node setup (no csr auto-signing connect) --- diff --git a/lib/cli/nodesetupcommand.cpp b/lib/cli/nodesetupcommand.cpp index 128c2bdac..590b08fae 100644 --- a/lib/cli/nodesetupcommand.cpp +++ b/lib/cli/nodesetupcommand.cpp @@ -283,48 +283,42 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, << "Requesting certificate with ticket '" << ticket << "'."; } - /* require master host information for auto-signing requests */ + /* Decide whether to directly connect to the parent node for CSR signing, or leave it to the user. */ + bool connectToParent = false; + String parentHost; + String parentPort = "5665"; + std::shared_ptr trustedParentCert; - /* TODO: master_host is deprecated, remove it in 2.10.0. */ - if (!vm.count("master_host") && !vm.count("parent_host") ) { - Log(LogCritical, "cli", "Please pass the parent host connection information for auto-signing using '--parent_host '."); - return 1; - } + /* TODO: remove master_host in 2.10.0. */ + if (!vm.count("master_host") && !vm.count("parent_host")) { + connectToParent = false; - String parentHostInfo; + Log(LogWarning, "cli") + << "Node to master/satellite connection setup skipped. Please configure your parent node to\n" + << "connect to this node by setting the 'host' attribute for the node Endpoint object.\n"; + } else { + connectToParent = true; - if (vm.count("parent_host")) - parentHostInfo = vm["parent_host"].as(); - else if (vm.count("master_host")) /* TODO: Remove in 2.10.0. */ - parentHostInfo = vm["master_host"].as(); + String parentHostInfo; - std::vector tokens = parentHostInfo.Split(","); - String parentHost; - String parentPort = "5665"; + if (vm.count("parent_host")) + parentHostInfo = vm["parent_host"].as(); + else if (vm.count("master_host")) /* TODO: Remove in 2.10.0. */ + parentHostInfo = vm["master_host"].as(); - if (tokens.size() == 1 || tokens.size() == 2) - parentHost = tokens[0]; + std::vector tokens = parentHostInfo.Split(","); - if (tokens.size() == 2) - parentPort = tokens[1]; + if (tokens.size() == 1 || tokens.size() == 2) + parentHost = tokens[0]; - Log(LogInformation, "cli") - << "Verifying parent host connection information: host '" << parentHost << "', port '" << parentPort << "'."; + if (tokens.size() == 2) + parentPort = tokens[1]; - /* trusted cert must be passed (retrieved by the user with 'pki save-cert' before) */ + Log(LogInformation, "cli") + << "Verifying parent host connection information: host '" << parentHost << "', port '" << parentPort << "'."; - if (!vm.count("trustedcert")) { - Log(LogCritical, "cli") - << "Please pass the trusted cert retrieved from the parent node (master or satellite)\n" - << "(Hint: 'icinga2 pki save-cert --host --port <5665> --key local.key --cert local.crt --trustedcert parent.crt')."; - return 1; } - std::shared_ptr trustedcert = GetX509Certificate(vm["trustedcert"].as()); - - Log(LogInformation, "cli") - << "Verifying trusted certificate file '" << vm["trustedcert"].as() << "'."; - /* retrieve CN and pass it (defaults to FQDN) */ String cn = Utility::GetFQDN(); @@ -366,14 +360,47 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, << "Cannot set ownership for user '" << user << "' group '" << group << "' on file '" << key << "'. Verify it yourself!"; } - Log(LogInformation, "cli", "Requesting a signed certificate from the parent Icinga node."); + /* Send a signing request to the parent immediately, or leave it to the user. */ + if (connectToParent) { + /* In contrast to `node wizard` the user must manually fetch + * the trustedParentCert to prove the trust relationship (fetched with 'pki save-cert'). + */ + if (!vm.count("trustedcert")) { + Log(LogCritical, "cli") + << "Please pass the trusted cert retrieved from the parent node (master or satellite)\n" + << "(Hint: 'icinga2 pki save-cert --host --port <5665> --key local.key --cert local.crt --trustedcert parent.crt')."; + return 1; + } - if (PkiUtility::RequestCertificate(parentHost, parentPort, key, cert, ca, trustedcert, ticket) > 0) { - Log(LogCritical, "cli") - << "Failed to fetch signed certificate from parent Icinga node '" - << parentHost << ", " - << parentPort << "'. Please try again."; - return 1; + trustedParentCert = GetX509Certificate(vm["trustedcert"].as()); + + Log(LogInformation, "cli") + << "Verifying trusted certificate file '" << vm["trustedcert"].as() << "'."; + + Log(LogInformation, "cli", "Requesting a signed certificate from the parent Icinga node."); + + if (PkiUtility::RequestCertificate(parentHost, parentPort, key, cert, ca, trustedParentCert, ticket) > 0) { + Log(LogCritical, "cli") + << "Failed to fetch signed certificate from parent Icinga node '" + << parentHost << ", " + << parentPort << "'. Please try again."; + return 1; + } + } else { + /* We cannot retrieve the parent certificate. + * Tell the user to manually copy the ca.crt file + * into LocalStateDir + "/lib/icinga2/certs" + */ + Log(LogWarning, "cli") + << "\nNo connection to the parent node was specified.\n\n" + << "Please copy the public CA certificate from your master/satellite\n" + << "into '" << ca << "' before starting Icinga 2.\n"; + + if (Utility::PathExists(ca)) { + Log(LogInformation, "cli") + << "\nFound public CA certificate in '" << ca << "'.\n" + << "Please verify that it is the same as on your master/satellite.\n"; + } } if (!Utility::SetFileOwnership(ca, user, group)) { @@ -518,8 +545,15 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, } } - /* tell the user to reload icinga2 */ - Log(LogInformation, "cli", "Make sure to restart Icinga 2."); + /* If no parent connection was made, the user must supply the ca.crt before restarting Icinga 2.*/ + if (!connectToParent) { + Log(LogWarning, "cli") + << "No connection to the parent node was specified.\n\n" + << "Please copy the public CA certificate from your master/satellite\n" + << "into '" << ca << "' before starting Icinga 2.\n"; + } else { + Log(LogInformation, "cli", "Make sure to restart Icinga 2."); + } return 0; } diff --git a/lib/cli/nodewizardcommand.cpp b/lib/cli/nodewizardcommand.cpp index 31fdfe00f..e6cdb827c 100644 --- a/lib/cli/nodewizardcommand.cpp +++ b/lib/cli/nodewizardcommand.cpp @@ -605,6 +605,16 @@ wizard_global_zone_loop_start: } } + /* If no parent connection was made, the user must supply the ca.crt before restarting Icinga 2.*/ + if (!connectToParent) { + Log(LogWarning, "cli") + << "No connection to the parent node was specified.\n\n" + << "Please copy the public CA certificate from your master/satellite\n" + << "into '" << nodeCA << "' before starting Icinga 2.\n"; + } else { + Log(LogInformation, "cli", "Make sure to restart Icinga 2."); + } + return 0; }