Unify setting the local and parent zone names for node wizard/setup

This commit is contained in:
Michael Friedrich 2018-04-06 19:18:19 +02:00
parent abdc479d6a
commit 9f2694bdc1
4 changed files with 124 additions and 67 deletions

View File

@ -56,8 +56,9 @@ void NodeSetupCommand::InitParameters(boost::program_options::options_descriptio
{
visibleDesc.add_options()
("zone", po::value<std::string>(), "The name of the local zone")
("master_host", po::value<std::string>(), "The name of the master host for auto-signing the csr; syntax: host[,port]")
("endpoint", po::value<std::vector<std::string> >(), "Connect to remote endpoint; syntax: cn[,host,port]")
("parent_host", po::value<std::string>(), "The name of the parent host for auto-signing the csr; syntax: host[,port]")
("parent_zone", po::value<std::string>(), "The name of the parent zone")
("listen", po::value<std::string>(), "Listen on host,port")
("ticket", po::value<std::string>(), "Generated ticket number for this request (optional)")
("trustedcert", po::value<std::string>(), "Trusted master certificate file")
@ -68,7 +69,8 @@ void NodeSetupCommand::InitParameters(boost::program_options::options_descriptio
("global_zones", po::value<std::vector<std::string> >(), "The names of the additional global zones.");
hiddenDesc.add_options()
("master_zone", po::value<std::string>(), "The name of the master zone");
("master_zone", po::value<std::string>(), "DEPRECATED: The name of the master zone")
("master_host", po::value<std::string>(), "DEPRECATED: The name of the master host for auto-signing the csr; syntax: host[,port]");
}
std::vector<String> 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 <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 <host>'.");
return 1;
}
std::vector<String> tokens = String(vm["master_host"].as<std::string>()).Split(",");
String master_host;
String master_port = "5665";
String parentHostInfo;
if (vm.count("parent_host"))
parentHostInfo = vm["parent_host"].as<std::string>();
else if (vm.count("master_host")) /* TODO: Remove in 2.10.0. */
parentHostInfo = vm["master_host"].as<std::string>();
std::vector<String> 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 <masterhost> --port <5665> --key local.key --cert local.crt --trustedcert master.crt').";
<< "(Hint: 'icinga2 pki save-cert --host <parenthost> --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<std::string>();
/* Allow to specify the parent zone name. */
String parentZoneName = "master";
if (vm.count("parent_zone"))
parentZoneName = vm["parent_zone"].as<std::string>();
std::vector<String> globalZones { "global-templates", "director-global" };
std::vector<std::string> 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<std::vector<std::string> >(), globalZones);
/* Generate node configuration. */
NodeUtility::GenerateNodeIcingaConfig(endpointName, zoneName, parentZoneName, vm["endpoint"].as<std::vector<std::string> >(), globalZones);
/* update constants.conf with NodeName = CN */
if (cn != Utility::GetFQDN()) {

View File

@ -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<std::string>& endpoints, const std::vector<String>& globalZones)
int NodeUtility::GenerateNodeIcingaConfig(const String& endpointName, const String& zoneName,
const String& parentZoneName, const std::vector<std::string>& endpoints,
const std::vector<String>& 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<String> 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<std::string>& endpoi
int NodeUtility::GenerateNodeMasterIcingaConfig(const String& endpointName, const String& zoneName,
const std::vector<String>& 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 */

View File

@ -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<std::string>& endpoints, const std::vector<String>& globalZones);
static int GenerateNodeIcingaConfig(const String& endpointName, const String& zoneName,
const String& parentZoneName, const std::vector<std::string>& endpoints,
const std::vector<String>& globalZones);
static int GenerateNodeMasterIcingaConfig(const String& endpointName, const String& zoneName,
const std::vector<String>& globalZones);

View File

@ -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<String> 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")