From 9f2694bdc1ac9ae00e6b22aa3bd0571be475e6db Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Fri, 6 Apr 2018 19:18:19 +0200 Subject: [PATCH] Unify setting the local and parent zone names for node wizard/setup --- lib/cli/nodesetupcommand.cpp | 77 +++++++++++++++++++++++------------ lib/cli/nodeutility.cpp | 77 ++++++++++++++++++----------------- lib/cli/nodeutility.hpp | 7 +++- lib/cli/nodewizardcommand.cpp | 30 +++++++++++++- 4 files changed, 124 insertions(+), 67 deletions(-) diff --git a/lib/cli/nodesetupcommand.cpp b/lib/cli/nodesetupcommand.cpp index dca96ff29..128c2bdac 100644 --- a/lib/cli/nodesetupcommand.cpp +++ b/lib/cli/nodesetupcommand.cpp @@ -56,8 +56,9 @@ void NodeSetupCommand::InitParameters(boost::program_options::options_descriptio { visibleDesc.add_options() ("zone", po::value(), "The name of the local zone") - ("master_host", po::value(), "The name of the master host for auto-signing the csr; syntax: host[,port]") ("endpoint", po::value >(), "Connect to remote endpoint; syntax: cn[,host,port]") + ("parent_host", po::value(), "The name of the parent host for auto-signing the csr; syntax: host[,port]") + ("parent_zone", po::value(), "The name of the parent zone") ("listen", po::value(), "Listen on host,port") ("ticket", po::value(), "Generated ticket number for this request (optional)") ("trustedcert", po::value(), "Trusted master certificate file") @@ -68,7 +69,8 @@ void NodeSetupCommand::InitParameters(boost::program_options::options_descriptio ("global_zones", po::value >(), "The names of the additional global zones."); hiddenDesc.add_options() - ("master_zone", po::value(), "The name of the master zone"); + ("master_zone", po::value(), "DEPRECATED: The name of the master zone") + ("master_host", po::value(), "DEPRECATED: The name of the master host for auto-signing the csr; syntax: host[,port]"); } std::vector NodeSetupCommand::GetArgumentSuggestions(const String& argument, const String& word) const @@ -262,6 +264,12 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, return 1; } + /* Deprecation warnings. TODO: Remove in 2.10.0. */ + if (vm.count("master_zone")) + Log(LogWarning, "cli", "The 'master_zone' parameter has been deprecated. Use 'parent_zone' instead."); + if (vm.count("master_host")) + Log(LogWarning, "cli", "The 'master_host' parameter has been deprecated. Use 'parent_host' instead."); + String ticket; if (vm.count("ticket")) @@ -277,31 +285,38 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, /* require master host information for auto-signing requests */ - if (!vm.count("master_host")) { - Log(LogCritical, "cli", "Please pass the master host connection information for auto-signing using '--master_host '. This can also be a direct parent satellite since 2.8."); - + /* 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; } - std::vector tokens = String(vm["master_host"].as()).Split(","); - String master_host; - String master_port = "5665"; + String parentHostInfo; + + 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(); + + std::vector tokens = parentHostInfo.Split(","); + String parentHost; + String parentPort = "5665"; if (tokens.size() == 1 || tokens.size() == 2) - master_host = tokens[0]; + parentHost = tokens[0]; if (tokens.size() == 2) - master_port = tokens[1]; + parentPort = tokens[1]; Log(LogInformation, "cli") - << "Verifying parent host connection information: host '" << master_host << "', port '" << master_port << "'."; + << "Verifying parent host connection information: host '" << parentHost << "', port '" << parentPort << "'."; /* trusted cert must be passed (retrieved by the user with 'pki save-cert' before) */ 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 master.crt')."; + << "(Hint: 'icinga2 pki save-cert --host --port <5665> --key local.key --cert local.crt --trustedcert parent.crt')."; return 1; } @@ -320,21 +335,20 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, << "Using the following CN (defaults to FQDN): '" << cn << "'."; /* pki request a signed certificate from the master */ - - String pki_path = ApiListener::GetCertsDir(); - Utility::MkDirP(pki_path, 0700); + String certsDir = ApiListener::GetCertsDir(); + Utility::MkDirP(certsDir, 0700); String user = ScriptGlobal::Get("RunAsUser"); String group = ScriptGlobal::Get("RunAsGroup"); - if (!Utility::SetFileOwnership(pki_path, user, group)) { + if (!Utility::SetFileOwnership(certsDir, user, group)) { Log(LogWarning, "cli") - << "Cannot set ownership for user '" << user << "' group '" << group << "' on file '" << pki_path << "'. Verify it yourself!"; + << "Cannot set ownership for user '" << user << "' group '" << group << "' on file '" << certsDir << "'. Verify it yourself!"; } - String key = pki_path + "/" + cn + ".key"; - String cert = pki_path + "/" + cn + ".crt"; - String ca = pki_path + "/ca.crt"; + String key = certsDir + "/" + cn + ".key"; + String cert = certsDir + "/" + cn + ".crt"; + String ca = certsDir + "/ca.crt"; if (Utility::PathExists(key)) NodeUtility::CreateBackupFile(key, true); @@ -354,11 +368,11 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, Log(LogInformation, "cli", "Requesting a signed certificate from the parent Icinga node."); - if (PkiUtility::RequestCertificate(master_host, master_port, key, cert, ca, trustedcert, ticket) > 0) { + if (PkiUtility::RequestCertificate(parentHost, parentPort, key, cert, ca, trustedcert, ticket) > 0) { Log(LogCritical, "cli") << "Failed to fetch signed certificate from parent Icinga node '" - << master_host << ", " - << master_port << "'. Please try again."; + << parentHost << ", " + << parentPort << "'. Please try again."; return 1; } @@ -432,10 +446,22 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, << boost::errinfo_file_name(tempApiPath)); } - /* generate local zones.conf with zone+endpoint */ + /* Generate zones configuration. */ Log(LogInformation, "cli", "Generating zone and object configuration."); + /* Setup command hardcodes this as FQDN */ + String endpointName = cn; + + /* Allow to specify zone name. */ + String zoneName = vm["zone"].as(); + + /* Allow to specify the parent zone name. */ + String parentZoneName = "master"; + + if (vm.count("parent_zone")) + parentZoneName = vm["parent_zone"].as(); + std::vector globalZones { "global-templates", "director-global" }; std::vector setupGlobalZones; @@ -452,7 +478,8 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm, globalZones.insert(globalZones.end(), setupGlobalZones.begin(), setupGlobalZones.end()); - NodeUtility::GenerateNodeIcingaConfig(vm["endpoint"].as >(), globalZones); + /* Generate node configuration. */ + NodeUtility::GenerateNodeIcingaConfig(endpointName, zoneName, parentZoneName, vm["endpoint"].as >(), globalZones); /* update constants.conf with NodeName = CN */ if (cn != Utility::GetFQDN()) { diff --git a/lib/cli/nodeutility.cpp b/lib/cli/nodeutility.cpp index 5d4c6c90a..645e19d94 100644 --- a/lib/cli/nodeutility.cpp +++ b/lib/cli/nodeutility.cpp @@ -46,80 +46,83 @@ String NodeUtility::GetConstantsConfPath() return Application::GetSysconfDir() + "/icinga2/constants.conf"; } +String NodeUtility::GetZonesConfPath() +{ + return Application::GetSysconfDir() + "/icinga2/zones.conf"; +} + /* * Node Setup helpers */ -int NodeUtility::GenerateNodeIcingaConfig(const std::vector& endpoints, const std::vector& globalZones) +int NodeUtility::GenerateNodeIcingaConfig(const String& endpointName, const String& zoneName, + const String& parentZoneName, const std::vector& endpoints, + const std::vector& globalZones) { - Array::Ptr my_config = new Array(); + Array::Ptr config = new Array(); - Array::Ptr my_master_zone_members = new Array(); - - String master_zone_name = "master"; //TODO: Find a better name. + Array::Ptr myParentZoneMembers = new Array(); for (const String& endpoint : endpoints) { /* extract all --endpoint arguments and store host,port info */ std::vector tokens = endpoint.Split(","); - Dictionary::Ptr my_master_endpoint = new Dictionary(); + Dictionary::Ptr myParentEndpoint = new Dictionary(); if (tokens.size() > 1) { String host = tokens[1].Trim(); if (!host.IsEmpty()) - my_master_endpoint->Set("host", host); + myParentEndpoint->Set("host", host); } if (tokens.size() > 2) { String port = tokens[2].Trim(); if (!port.IsEmpty()) - my_master_endpoint->Set("port", port); + myParentEndpoint->Set("port", port); } - String cn = tokens[0].Trim(); - my_master_endpoint->Set("__name", cn); - my_master_endpoint->Set("__type", "Endpoint"); + String myEndpointName = tokens[0].Trim(); + myParentEndpoint->Set("__name", myEndpointName); + myParentEndpoint->Set("__type", "Endpoint"); /* save endpoint in master zone */ - my_master_zone_members->Add(cn); + myParentZoneMembers->Add(myEndpointName); - my_config->Add(my_master_endpoint); + config->Add(myParentEndpoint); } - /* add the master zone to the config */ - my_config->Add(new Dictionary({ - { "__name", master_zone_name }, + /* add the parent zone to the config */ + config->Add(new Dictionary({ + { "__name", parentZoneName }, { "__type", "Zone" }, - { "endpoints", my_master_zone_members } + { "endpoints", myParentZoneMembers } })); /* store the local generated node configuration */ - my_config->Add(new Dictionary({ - { "__name", new ConfigIdentifier("NodeName") }, + config->Add(new Dictionary({ + { "__name", endpointName }, { "__type", "Endpoint" } })); - my_config->Add(new Dictionary({ - { "__name", new ConfigIdentifier("ZoneName") }, + config->Add(new Dictionary({ + { "__name", zoneName }, { "__type", "Zone" }, - { "parent", master_zone_name }, //set the master zone as parent - { "endpoints", new Array({ new ConfigIdentifier("ZoneName") }) } + { "parent", parentZoneName }, + { "endpoints", new Array({ endpointName }) } })); for (const String& globalzone : globalZones) { - my_config->Add(new Dictionary({ + config->Add(new Dictionary({ { "__name", globalzone }, { "__type", "Zone" }, { "global", true } })); } - /* write the newly generated configuration */ - String zones_path = Application::GetSysconfDir() + "/icinga2/zones.conf"; - - NodeUtility::WriteNodeConfigObjects(zones_path, my_config); + /* Write the newly generated configuration. */ + NodeUtility::WriteNodeConfigObjects(GetZonesConfPath(), config); return 0; } @@ -127,32 +130,30 @@ int NodeUtility::GenerateNodeIcingaConfig(const std::vector& endpoi int NodeUtility::GenerateNodeMasterIcingaConfig(const String& endpointName, const String& zoneName, const std::vector& globalZones) { - Array::Ptr my_config = new Array(); + Array::Ptr config = new Array(); /* store the local generated node master configuration */ - my_config->Add(new Dictionary({ + config->Add(new Dictionary({ { "__name", endpointName }, { "__type", "Endpoint" } })); - my_config->Add(new Dictionary({ + config->Add(new Dictionary({ { "__name", zoneName }, { "__type", "Zone" }, { "endpoints", new Array({ endpointName }) } })); for (const String& globalzone : globalZones) { - my_config->Add(new Dictionary({ + config->Add(new Dictionary({ { "__name", globalzone }, { "__type", "Zone" }, { "global", true } })); } - /* write the newly generated configuration */ - String zones_path = Application::GetSysconfDir() + "/icinga2/zones.conf"; - - NodeUtility::WriteNodeConfigObjects(zones_path, my_config); + /* Write the newly generated configuration. */ + NodeUtility::WriteNodeConfigObjects(GetZonesConfPath(), config); return 0; } @@ -215,7 +216,7 @@ bool NodeUtility::WriteNodeConfigObjects(const String& filename, const Array::Pt /* * We generally don't overwrite files without backup before */ -bool NodeUtility::CreateBackupFile(const String& target, bool is_private) +bool NodeUtility::CreateBackupFile(const String& target, bool isPrivate) { if (!Utility::PathExists(target)) return false; @@ -231,7 +232,7 @@ bool NodeUtility::CreateBackupFile(const String& target, bool is_private) Utility::CopyFile(target, backup); #ifndef _WIN32 - if (is_private) + if (isPrivate) chmod(backup.CStr(), 0600); #endif /* _WIN32 */ diff --git a/lib/cli/nodeutility.hpp b/lib/cli/nodeutility.hpp index b9c66ff64..2ba33c2f3 100644 --- a/lib/cli/nodeutility.hpp +++ b/lib/cli/nodeutility.hpp @@ -38,15 +38,18 @@ class NodeUtility { public: static String GetConstantsConfPath(); + static String GetZonesConfPath(); - static bool CreateBackupFile(const String& target, bool is_private = false); + static bool CreateBackupFile(const String& target, bool isPrivate = false); static bool WriteNodeConfigObjects(const String& filename, const Array::Ptr& objects); static void UpdateConstant(const String& name, const String& value); /* node setup helpers */ - static int GenerateNodeIcingaConfig(const std::vector& endpoints, const std::vector& globalZones); + static int GenerateNodeIcingaConfig(const String& endpointName, const String& zoneName, + const String& parentZoneName, const std::vector& endpoints, + const std::vector& globalZones); static int GenerateNodeMasterIcingaConfig(const String& endpointName, const String& zoneName, const std::vector& globalZones); diff --git a/lib/cli/nodewizardcommand.cpp b/lib/cli/nodewizardcommand.cpp index 384d8e5f2..31fdfe00f 100644 --- a/lib/cli/nodewizardcommand.cpp +++ b/lib/cli/nodewizardcommand.cpp @@ -254,6 +254,7 @@ wizard_endpoint_loop_start: if (choice.Contains("y")) goto wizard_endpoint_loop_start; + /* Extract parent node information. */ String parentHost, parentPort; for (const String& endpoint : endpoints) { @@ -496,9 +497,33 @@ wizard_ticket: << boost::errinfo_file_name(tempApiConfPath)); } - /* apilistener config */ + /* Zones configuration. */ Log(LogInformation, "cli", "Generating local zones.conf."); + /* Setup command hardcodes this as FQDN */ + String endpointName = cn; + + /* Different local zone name. */ + std::cout << "\nLocal zone name [" + endpointName + "]: "; + std::getline(std::cin, answer); + + if (answer.empty()) + answer = endpointName; + + String zoneName = answer; + zoneName = zoneName.Trim(); + + /* Different parent zone name. */ + std::cout << "Parent zone name [master]: "; + std::getline(std::cin, answer); + + if (answer.empty()) + answer = "master"; + + String parentZoneName = answer; + parentZoneName = parentZoneName.Trim(); + + /* Global zones. */ std::vector globalZones { "global-templates", "director-global" }; std::cout << "\nDo you want to specify additional global zones? [y/N]: "; @@ -540,7 +565,8 @@ wizard_global_zone_loop_start: } else Log(LogInformation, "cli", "No additional global Zones have been specified"); - NodeUtility::GenerateNodeIcingaConfig(endpoints, globalZones); + /* Generate node configuration. */ + NodeUtility::GenerateNodeIcingaConfig(endpointName, zoneName, parentZoneName, endpoints, globalZones); if (cn != Utility::GetFQDN()) { Log(LogWarning, "cli")