mirror of https://github.com/Icinga/icinga2.git
Unify setting the local and parent zone names for node wizard/setup
This commit is contained in:
parent
abdc479d6a
commit
9f2694bdc1
|
@ -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()) {
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue