mirror of https://github.com/Icinga/icinga2.git
Merge pull request #6209 from Icinga/feature/unify-master-zone-names
Unify zone name settings in node setup/wizard; add connection-less mode for node setup
This commit is contained in:
commit
026ce17fb6
|
@ -201,6 +201,7 @@ ensure to collect the required information:
|
|||
Parameter | Description
|
||||
--------------------|--------------------
|
||||
Common name (CN) | **Required.** By convention this should be the host's FQDN. Defaults to the FQDN.
|
||||
Master zone name | **Optional.** Allows to specify the master zone name. Defaults to `master`.
|
||||
Global zones | **Optional.** Allows to specify more global zones in addition to `global-templates` and `director-global`. Defaults to `n`.
|
||||
API bind host | **Optional.** Allows to specify the address the ApiListener is bound to. For advanced usage only.
|
||||
API bind port | **Optional.** Allows to specify the port the ApiListener is bound to. For advanced usage only (requires changing the default port 5665 everywhere).
|
||||
|
@ -233,6 +234,8 @@ Certificates not yet generated. Running 'api setup' now.
|
|||
Generating master configuration for Icinga 2.
|
||||
Enabling feature api. Make sure to restart Icinga 2 for these changes to take effect.
|
||||
|
||||
Master zone name [master]:
|
||||
|
||||
Do you want to specify additional global zones? [y/N]: N
|
||||
Please specify the API bind host/port (optional):
|
||||
Bind Host []:
|
||||
|
@ -336,10 +339,12 @@ Retrieve the ticket on the master node `icinga2-master1.localdomain` with `curl`
|
|||
|
||||
Store that ticket number for the satellite/client setup below.
|
||||
|
||||
**Note**: Never expose the ticket salt and/or ApiUser credentials to your client nodes.
|
||||
Example: Retrieve the ticket on the Puppet master node and send the compiled catalog
|
||||
to the authorized Puppet agent node which will invoke the
|
||||
[automated setup steps](06-distributed-monitoring.md#distributed-monitoring-automation-cli-node-setup).
|
||||
> **Note**
|
||||
>
|
||||
> Never expose the ticket salt and/or ApiUser credentials to your client nodes.
|
||||
> Example: Retrieve the ticket on the Puppet master node and send the compiled catalog
|
||||
> to the authorized Puppet agent node which will invoke the
|
||||
> [automated setup steps](06-distributed-monitoring.md#distributed-monitoring-automation-cli-node-setup).
|
||||
|
||||
### On-Demand CSR Signing <a id="distributed-monitoring-setup-on-demand-csr-signing"></a>
|
||||
|
||||
|
@ -522,7 +527,23 @@ Accept config from parent node? [y/N]: y
|
|||
Accept commands from parent node? [y/N]: y
|
||||
```
|
||||
|
||||
You can add more global zones in addition to `global-templates` and `director-global` if necessary. Press `Enter` or choose `n`, if you don't want to add any additional.
|
||||
Next you can optionally specify the local and parent zone names. This will be reflected
|
||||
in the generated zone configuration file.
|
||||
|
||||
Set the local zone name to something else, if you are installing a satellite or secondary master instance.
|
||||
|
||||
```
|
||||
Local zone name [icinga2-client1.localdomain]:
|
||||
```
|
||||
|
||||
Set the parent zone name to something else than `master` if this client connects to a satellite instance instead of the master.
|
||||
|
||||
```
|
||||
Parent zone name [master]:
|
||||
```
|
||||
|
||||
You can add more global zones in addition to `global-templates` and `director-global` if necessary.
|
||||
Press `Enter` or choose `n`, if you don't want to add any additional.
|
||||
|
||||
```
|
||||
Reconfiguring Icinga...
|
||||
|
@ -568,6 +589,8 @@ Here is an overview of all parameters in detail:
|
|||
API bind port | **Optional.** Allows to specify the port the ApiListener is bound to. For advanced usage only (requires changing the default port 5665 everywhere).
|
||||
Accept config | **Optional.** Whether this node accepts configuration sync from the master node (required for [config sync mode](06-distributed-monitoring.md#distributed-monitoring-top-down-config-sync)). For [security reasons](06-distributed-monitoring.md#distributed-monitoring-security) this defaults to `n`.
|
||||
Accept commands | **Optional.** Whether this node accepts command execution messages from the master node (required for [command endpoint mode](06-distributed-monitoring.md#distributed-monitoring-top-down-command-endpoint)). For [security reasons](06-distributed-monitoring.md#distributed-monitoring-security) this defaults to `n`.
|
||||
Local zone name | **Optional.** Allows to specify the name for the local zone. This comes in handy when this instance is a satellite, not a client. Defaults to the FQDN.
|
||||
Parent zone name | **Optional.** Allows to specify the name for the parent zone. This is important if the client has a satellite instance as parent, not the master. Defaults to `master`.
|
||||
Global zones | **Optional.** Allows to specify more global zones in addition to `global-templates` and `director-global`. Defaults to `n`.
|
||||
|
||||
The setup wizard will ensure that the following steps are taken:
|
||||
|
@ -2532,6 +2555,7 @@ be passed (defaults to the FQDN).
|
|||
Parameter | Description
|
||||
--------------------|--------------------
|
||||
Common name (CN) | **Optional.** Specified with the `--cn` parameter. By convention this should be the host's FQDN. Defaults to the FQDN.
|
||||
Zone name | **Optional.** Specified with the `--zone` parameter. Defaults to `master`.
|
||||
Listen on | **Optional.** Specified with the `--listen` parameter. Syntax is `host,port`.
|
||||
|
||||
Example:
|
||||
|
@ -2579,14 +2603,14 @@ Pass the following details to the `pki save-cert` CLI command:
|
|||
Parameter | Description
|
||||
--------------------|--------------------
|
||||
Client certificate files | **Required.** Pass the previously generated files using the `--key` and `--cert` parameters.
|
||||
Trusted master certificate | **Required.** Store the master's certificate file. Manually verify that you're trusting it.
|
||||
Master host | **Required.** FQDN or IP address of the master host.
|
||||
Trusted parent certificate | **Required.** Store the parent's certificate file. Manually verify that you're trusting it.
|
||||
Parent host | **Required.** FQDN or IP address of the parent host.
|
||||
|
||||
Example:
|
||||
|
||||
[root@icinga2-client1.localdomain /]# icinga2 pki save-cert --key /var/lib/icinga2/certs/icinga2-client1.localdomain.key \
|
||||
--cert /var/lib/icinga2/certs/icinga2-client1.localdomain.crt \
|
||||
--trustedcert /var/lib/icinga2/certs/trusted-master.crt \
|
||||
--trustedcert /var/lib/icinga2/certs/trusted-parent.crt \
|
||||
--host icinga2-master1.localdomain
|
||||
|
||||
Continue with the additional node setup step. Specify a local endpoint and zone name (`icinga2-client1.localdomain`)
|
||||
|
@ -2600,21 +2624,27 @@ Pass the following details to the `node setup` CLI command:
|
|||
Common name (CN) | **Optional.** Specified with the `--cn` parameter. By convention this should be the host's FQDN.
|
||||
Request ticket | **Required.** Add the previously generated [ticket number](06-distributed-monitoring.md#distributed-monitoring-setup-csr-auto-signing).
|
||||
Trusted master certificate | **Required.** Add the previously fetched trusted master certificate (this step means that you've verified its origin).
|
||||
Master endpoint | **Required.** Specify the master's endpoint name.
|
||||
Parent host | **Optional.** FQDN or IP address of the parent host. This is where the command connects for CSR signing. If not specified, you need to manually copy the parent's public CA certificate file into `/var/lib/icinga2/certs/ca.crt` in order to start Icinga 2.
|
||||
Parent endpoint | **Required.** Specify the parent's endpoint name.
|
||||
Client zone name | **Required.** Specify the client's zone name.
|
||||
Master host | **Required.** FQDN or IP address of the master host.
|
||||
Parent zone name | **Optional.** Specify the parent's zone name.
|
||||
Accept config | **Optional.** Whether this node accepts configuration sync from the master node (required for [config sync mode](06-distributed-monitoring.md#distributed-monitoring-top-down-config-sync)).
|
||||
Accept commands | **Optional.** Whether this node accepts command execution messages from the master node (required for [command endpoint mode](06-distributed-monitoring.md#distributed-monitoring-top-down-command-endpoint)).
|
||||
Global zones | **Optional.** Allows to specify more global zones in addition to `global-templates` and `director-global`.
|
||||
Global zones | **Optional.** Allows to specify more global zones in addition to `global-templates` and `director-global`.
|
||||
|
||||
Example for Icinga 2 v2.8:
|
||||
> **Note**
|
||||
>
|
||||
> The `master_host` parameter is deprecated and will be removed in 2.10.0. Please use `--parent_host` instead.
|
||||
|
||||
Example for Icinga 2 v2.9:
|
||||
|
||||
[root@icinga2-client1.localdomain /]# icinga2 node setup --ticket ead2d570e18c78abf285d6b85524970a0f69c22d \
|
||||
--cn icinga2-client1.localdomain \
|
||||
--endpoint icinga2-master1.localdomain \
|
||||
--zone icinga2-client1.localdomain \
|
||||
--master_host icinga2-master1.localdomain \
|
||||
--trustedcert /var/lib/icinga2/certs/trusted-master.crt \
|
||||
--parent_zone master \
|
||||
--parent_host icinga2-master1.localdomain \
|
||||
--trustedcert /var/lib/icinga2/certs/trusted-parent.crt \
|
||||
--accept-commands --accept-config
|
||||
|
||||
In case the client should connect to the master node, you'll
|
||||
|
@ -2622,14 +2652,25 @@ need to modify the `--endpoint` parameter using the format `cn,host,port`:
|
|||
|
||||
--endpoint icinga2-master1.localdomain,192.168.56.101,5665
|
||||
|
||||
Specify the parent zone using the `--parent_zone` parameter. This is useful
|
||||
if the client connects to a satellite, not the master instance.
|
||||
|
||||
--parent_zone satellite
|
||||
|
||||
In case the client should know the additional global zone `linux-templates`, you'll
|
||||
need to set the `--global-zones` parameter.
|
||||
|
||||
--global_zones linux-templates
|
||||
--global_zones linux-templates
|
||||
|
||||
Restart Icinga 2 afterwards:
|
||||
The `--parent-host` parameter is optional since v2.9 and allows you to perform a connection-less setup.
|
||||
You cannot restart Icinga 2 yet, the CLI command asked to to manually copy the parent's public CA
|
||||
certificate file in `/var/lib/icinga2/certs/ca.crt`. Once Icinga 2 is started, it sends
|
||||
a ticket signing request to the parent node. If you have provided a ticket, the master node
|
||||
signs the request and sends it back to the client which performs a certificate update in-memory.
|
||||
|
||||
In case you did not provide a ticket, you need to manually sign the CSR on the master node
|
||||
which holds the CA's key pair.
|
||||
|
||||
# service icinga2 restart
|
||||
|
||||
**You can find additional best practices below.**
|
||||
|
||||
|
|
|
@ -9,8 +9,14 @@ follow the instructions for v2.7 too.
|
|||
|
||||
## Upgrading to v2.9 <a id="upgrading-to-2-9"></a>
|
||||
|
||||
### Configuration Changes <a id="upgrading-to-2-9-config-changes"></a>
|
||||
|
||||
The CORS attributes `access_control_allow_credentials`, `access_control_allow_headers` and
|
||||
`access_control_allow_methods` are now controlled by Icinga 2 and are not changeable by config any more.
|
||||
`access_control_allow_methods` are now controlled by Icinga 2 and cannot be changed anymore.
|
||||
|
||||
### CLI Command Changes <a id="upgrading-to-2-9-cli-changes"></a>
|
||||
|
||||
The `node setup` parameter `--master_host` was deprecated and replaced with `--parent_host`. This parameter is now optional to allow connection-less client setups similar to the `node wizard` CLI command. The `parent_zone` parameter has been added to modify the parent zone name e.g. for client-to-satellite setups.
|
||||
|
||||
## Upgrading to v2.8.2 <a id="upgrading-to-2-8-2"></a>
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -129,6 +131,15 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v
|
|||
if (vm.count("cn"))
|
||||
cn = vm["cn"].as<std::string>();
|
||||
|
||||
/* Setup command hardcodes this as FQDN */
|
||||
String endpointName = cn;
|
||||
|
||||
/* Allow to specify zone name. */
|
||||
String zoneName = "master";
|
||||
|
||||
if (vm.count("zone"))
|
||||
zoneName = vm["zone"].as<std::string>();
|
||||
|
||||
/* check whether the user wants to generate a new certificate or not */
|
||||
String existingPath = ApiListener::GetCertsDir() + "/" + cn + ".crt";
|
||||
|
||||
|
@ -174,9 +185,10 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v
|
|||
|
||||
globalZones.insert(globalZones.end(), setupGlobalZones.begin(), setupGlobalZones.end());
|
||||
|
||||
NodeUtility::GenerateNodeMasterIcingaConfig(globalZones);
|
||||
/* Generate master configuration. */
|
||||
NodeUtility::GenerateNodeMasterIcingaConfig(endpointName, zoneName, globalZones);
|
||||
|
||||
/* update the ApiListener config - SetupMaster() will always enable it */
|
||||
/* Update the ApiListener config. */
|
||||
Log(LogInformation, "cli", "Updating the APIListener feature.");
|
||||
|
||||
String apipath = FeatureUtility::GetFeaturesAvailablePath() + "/api.conf";
|
||||
|
@ -252,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"))
|
||||
|
@ -265,41 +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<X509> trustedParentCert;
|
||||
|
||||
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: remove master_host in 2.10.0. */
|
||||
if (!vm.count("master_host") && !vm.count("parent_host")) {
|
||||
connectToParent = false;
|
||||
|
||||
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;
|
||||
|
||||
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(",");
|
||||
|
||||
if (tokens.size() == 1 || tokens.size() == 2)
|
||||
parentHost = tokens[0];
|
||||
|
||||
if (tokens.size() == 2)
|
||||
parentPort = tokens[1];
|
||||
|
||||
Log(LogInformation, "cli")
|
||||
<< "Verifying parent host connection information: host '" << parentHost << "', port '" << parentPort << "'.";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::vector<String> tokens = String(vm["master_host"].as<std::string>()).Split(",");
|
||||
String master_host;
|
||||
String master_port = "5665";
|
||||
|
||||
if (tokens.size() == 1 || tokens.size() == 2)
|
||||
master_host = tokens[0];
|
||||
|
||||
if (tokens.size() == 2)
|
||||
master_port = tokens[1];
|
||||
|
||||
Log(LogInformation, "cli")
|
||||
<< "Verifying parent host connection information: host '" << master_host << "', port '" << master_port << "'.";
|
||||
|
||||
/* 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').";
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::shared_ptr<X509> trustedcert = GetX509Certificate(vm["trustedcert"].as<std::string>());
|
||||
|
||||
Log(LogInformation, "cli")
|
||||
<< "Verifying trusted certificate file '" << vm["trustedcert"].as<std::string>() << "'.";
|
||||
|
||||
/* retrieve CN and pass it (defaults to FQDN) */
|
||||
String cn = Utility::GetFQDN();
|
||||
|
||||
|
@ -310,21 +329,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);
|
||||
|
@ -342,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 <masterhost> --port <5665> --key local.key --cert local.crt --trustedcert parent.crt').";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (PkiUtility::RequestCertificate(master_host, master_port, 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.";
|
||||
return 1;
|
||||
trustedParentCert = GetX509Certificate(vm["trustedcert"].as<std::string>());
|
||||
|
||||
Log(LogInformation, "cli")
|
||||
<< "Verifying trusted certificate file '" << vm["trustedcert"].as<std::string>() << "'.";
|
||||
|
||||
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)) {
|
||||
|
@ -422,10 +473,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;
|
||||
|
||||
|
@ -442,7 +505,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()) {
|
||||
|
@ -481,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;
|
||||
}
|
||||
|
|
|
@ -46,112 +46,114 @@ 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;
|
||||
}
|
||||
|
||||
int NodeUtility::GenerateNodeMasterIcingaConfig(const std::vector<String>& globalZones)
|
||||
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({
|
||||
{ "__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" },
|
||||
{ "endpoints", new Array({ new ConfigIdentifier("NodeName") }) }
|
||||
{ "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;
|
||||
}
|
||||
|
@ -214,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;
|
||||
|
@ -230,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,16 +38,20 @@ 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 GenerateNodeMasterIcingaConfig(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);
|
||||
|
||||
private:
|
||||
NodeUtility();
|
||||
|
|
|
@ -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")
|
||||
|
@ -579,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;
|
||||
}
|
||||
|
||||
|
@ -623,6 +659,7 @@ int NodeWizardCommand::MasterSetup() const
|
|||
std::cout << ConsoleColorTag(Console_Bold)
|
||||
<< "Generating master configuration for Icinga 2.\n"
|
||||
<< ConsoleColorTag(Console_Normal);
|
||||
|
||||
ApiSetupUtility::SetupMasterApiUser();
|
||||
|
||||
if (!FeatureUtility::CheckFeatureEnabled("api"))
|
||||
|
@ -630,6 +667,20 @@ int NodeWizardCommand::MasterSetup() const
|
|||
else
|
||||
std::cout << "'api' feature already enabled.\n";
|
||||
|
||||
/* Setup command hardcodes this as FQDN */
|
||||
String endpointName = cn;
|
||||
|
||||
/* Different zone name. */
|
||||
std::cout << "\nMaster zone name [master]: ";
|
||||
std::getline(std::cin, answer);
|
||||
|
||||
if (answer.empty())
|
||||
answer = "master";
|
||||
|
||||
String zoneName = answer;
|
||||
zoneName = zoneName.Trim();
|
||||
|
||||
/* Global zones. */
|
||||
std::vector<String> globalZones { "global-templates", "director-global" };
|
||||
|
||||
std::cout << "\nDo you want to specify additional global zones? [y/N]: ";
|
||||
|
@ -671,7 +722,8 @@ wizard_global_zone_loop_start:
|
|||
} else
|
||||
Log(LogInformation, "cli", "No additional global Zones have been specified");
|
||||
|
||||
NodeUtility::GenerateNodeMasterIcingaConfig(globalZones);
|
||||
/* Generate master configuration. */
|
||||
NodeUtility::GenerateNodeMasterIcingaConfig(endpointName, zoneName, globalZones);
|
||||
|
||||
/* apilistener config */
|
||||
std::cout << ConsoleColorTag(Console_Bold)
|
||||
|
|
Loading…
Reference in New Issue