diff --git a/agent/windows-setup-agent/SetupWizard.Designer.cs b/agent/windows-setup-agent/SetupWizard.Designer.cs
index 46dd421e4..258139224 100644
--- a/agent/windows-setup-agent/SetupWizard.Designer.cs
+++ b/agent/windows-setup-agent/SetupWizard.Designer.cs
@@ -87,6 +87,7 @@
this.txtError = new System.Windows.Forms.TextBox();
this.lblError = new System.Windows.Forms.Label();
this.picBanner = new System.Windows.Forms.PictureBox();
+ this.chkDisableConf = new System.Windows.Forms.CheckBox();
this.tabFinish.SuspendLayout();
this.tabConfigure.SuspendLayout();
this.tabParameters.SuspendLayout();
@@ -105,7 +106,7 @@
// btnBack
//
this.btnBack.Enabled = false;
- this.btnBack.Location = new System.Drawing.Point(376, 556);
+ this.btnBack.Location = new System.Drawing.Point(376, 587);
this.btnBack.Name = "btnBack";
this.btnBack.Size = new System.Drawing.Size(75, 23);
this.btnBack.TabIndex = 1;
@@ -115,7 +116,7 @@
//
// btnNext
//
- this.btnNext.Location = new System.Drawing.Point(457, 556);
+ this.btnNext.Location = new System.Drawing.Point(457, 587);
this.btnNext.Name = "btnNext";
this.btnNext.Size = new System.Drawing.Size(75, 23);
this.btnNext.TabIndex = 2;
@@ -126,7 +127,7 @@
// btnCancel
//
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.btnCancel.Location = new System.Drawing.Point(538, 556);
+ this.btnCancel.Location = new System.Drawing.Point(538, 587);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 3;
@@ -196,7 +197,7 @@
this.tabParameters.Location = new System.Drawing.Point(4, 5);
this.tabParameters.Name = "tabParameters";
this.tabParameters.Padding = new System.Windows.Forms.Padding(3);
- this.tabParameters.Size = new System.Drawing.Size(617, 471);
+ this.tabParameters.Size = new System.Drawing.Size(617, 495);
this.tabParameters.TabIndex = 3;
this.tabParameters.Text = "Agent Parameters";
this.tabParameters.UseVisualStyleBackColor = true;
@@ -275,6 +276,7 @@
//
// groupBox3
//
+ this.groupBox3.Controls.Add(this.chkDisableConf);
this.groupBox3.Controls.Add(this.txtUser);
this.groupBox3.Controls.Add(this.chkRunServiceAsThisUser);
this.groupBox3.Controls.Add(this.chkInstallNSCP);
@@ -282,7 +284,7 @@
this.groupBox3.Controls.Add(this.chkAcceptCommands);
this.groupBox3.Location = new System.Drawing.Point(308, 326);
this.groupBox3.Name = "groupBox3";
- this.groupBox3.Size = new System.Drawing.Size(301, 139);
+ this.groupBox3.Size = new System.Drawing.Size(301, 163);
this.groupBox3.TabIndex = 5;
this.groupBox3.TabStop = false;
this.groupBox3.Text = "Advanced Options";
@@ -377,7 +379,7 @@
this.groupBox2.Controls.Add(this.rdoListener);
this.groupBox2.Location = new System.Drawing.Point(8, 326);
this.groupBox2.Name = "groupBox2";
- this.groupBox2.Size = new System.Drawing.Size(298, 139);
+ this.groupBox2.Size = new System.Drawing.Size(298, 163);
this.groupBox2.TabIndex = 2;
this.groupBox2.TabStop = false;
this.groupBox2.Text = "TCP Listener";
@@ -513,7 +515,7 @@
this.tbcPages.Margin = new System.Windows.Forms.Padding(0);
this.tbcPages.Name = "tbcPages";
this.tbcPages.SelectedIndex = 0;
- this.tbcPages.Size = new System.Drawing.Size(625, 480);
+ this.tbcPages.Size = new System.Drawing.Size(625, 504);
this.tbcPages.SizeMode = System.Windows.Forms.TabSizeMode.Fixed;
this.tbcPages.TabIndex = 0;
this.tbcPages.SelectedIndexChanged += new System.EventHandler(this.tbcPages_SelectedIndexChanged);
@@ -691,13 +693,26 @@
this.picBanner.TabIndex = 1;
this.picBanner.TabStop = false;
//
+ // chkDisableConf
+ //
+ this.chkDisableConf.AutoSize = true;
+ this.chkDisableConf.Checked = true;
+ this.chkDisableConf.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.chkDisableConf.Location = new System.Drawing.Point(9, 137);
+ this.chkDisableConf.Name = "chkDisableConf";
+ this.chkDisableConf.Size = new System.Drawing.Size(138, 17);
+ this.chkDisableConf.TabIndex = 9;
+ this.chkDisableConf.Text = "Disable conf.d inclusion";
+ this.chkDisableConf.UseVisualStyleBackColor = true;
+ this.chkDisableConf.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
+ //
// SetupWizard
//
this.AcceptButton = this.btnNext;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.btnCancel;
- this.ClientSize = new System.Drawing.Size(625, 587);
+ this.ClientSize = new System.Drawing.Size(625, 622);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnNext);
this.Controls.Add(this.btnBack);
@@ -794,6 +809,7 @@
private System.Windows.Forms.Button btnAddGlobalZone;
private System.Windows.Forms.ListView lvwGlobalZones;
private System.Windows.Forms.ColumnHeader colGlobalZoneName;
+ private System.Windows.Forms.CheckBox chkDisableConf;
}
}
diff --git a/agent/windows-setup-agent/SetupWizard.cs b/agent/windows-setup-agent/SetupWizard.cs
index fc903fd91..6aceaf16b 100644
--- a/agent/windows-setup-agent/SetupWizard.cs
+++ b/agent/windows-setup-agent/SetupWizard.cs
@@ -229,6 +229,9 @@ namespace Icinga
args += " --global_zones " + lvi.SubItems[0].Text.Trim();
}
+ if (chkDisableConf.Checked)
+ args += " --disable-confd";
+
if (!RunProcess(Program.Icinga2InstallDir + "\\sbin\\icinga2.exe",
"node setup" + args,
out output)) {
@@ -568,6 +571,11 @@ namespace Icinga
lvwGlobalZones.Items.Add(lvi2);
}
+
+ private void checkBox1_CheckedChanged(object sender, EventArgs e)
+ {
+
+ }
}
}
diff --git a/doc/06-distributed-monitoring.md b/doc/06-distributed-monitoring.md
index 91b8e9748..491d2b5f7 100644
--- a/doc/06-distributed-monitoring.md
+++ b/doc/06-distributed-monitoring.md
@@ -205,6 +205,7 @@ ensure to collect the required information:
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).
+ Disable conf.d | **Optional.** Allows to disable the `include_recursive "conf.d"` directive except for the `api-users.conf` file in the `icinga2.conf` file. Defaults to `y`. Configuration on the master is discussed below.
The setup wizard will ensure that the following steps are taken:
@@ -213,6 +214,7 @@ The setup wizard will ensure that the following steps are taken:
* Create a certificate for this node signed by the CA key.
* Update the [zones.conf](04-configuring-icinga-2.md#zones-conf) file with the new zone hierarchy.
* Update the [ApiListener](06-distributed-monitoring.md#distributed-monitoring-apilistener) and [constants](04-configuring-icinga-2.md#constants-conf) configuration.
+* Update the [icinga2.conf](04-configuring-icinga-2.md#icinga2-conf) to disable the `conf.d` inclusion, and add the `api-users.conf` file inclusion.
Here is an example of a master setup for the `icinga2-master1.localdomain` node on CentOS 7:
@@ -236,11 +238,17 @@ Enabling feature api. Make sure to restart Icinga 2 for these changes to take ef
Master zone name [master]:
+Default global zones: global-templates director-global
Do you want to specify additional global zones? [y/N]: N
+
Please specify the API bind host/port (optional):
Bind Host []:
Bind Port []:
+Do you want to disable the inclusion of the conf.d directory [Y/n]:
+Disabling the inclusion of the conf.d directory...
+Checking if the api-users.conf file exists...
+
Done.
Now restart your Icinga 2 daemon to finish the installation!
@@ -335,7 +343,7 @@ object with at least the `actions/generate-ticket` permission.
Retrieve the ticket on the master node `icinga2-master1.localdomain` with `curl`, for example:
[root@icinga2-master1.localdomain /]# curl -k -s -u client-pki-ticket:bea11beb7b810ea9ce6ea -H 'Accept: application/json' \
- -X POST 'https://icinga2-master1.localdomain:5665/v1/actions/generate-ticket' -d '{ "cn": "icinga2-client1.localdomain" }'
+ -X POST 'https://localhost:5665/v1/actions/generate-ticket' -d '{ "cn": "icinga2-client1.localdomain" }'
Store that ticket number for the satellite/client setup below.
@@ -548,9 +556,20 @@ Press `Enter` or choose `n`, if you don't want to add any additional.
```
Reconfiguring Icinga...
+Default global zones: global-templates director-global
Do you want to specify additional global zones? [y/N]: N
```
+Last but not least the wizard asks you whether you want to disable the inclusion of the local configuration
+directory in `conf.d`, or not. Defaults to disabled, as clients either are checked via command endpoint, or
+they receive configuration synced from the parent zone.
+
+```
+Do you want to disable the inclusion of the conf.d directory [Y/n]: Y
+Disabling the inclusion of the conf.d directory...
+```
+
+
The wizard proceeds and you are good to go.
```
@@ -592,6 +611,7 @@ Here is an overview of all parameters in detail:
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`.
+ Disable conf.d | **Optional.** Allows to disable the inclusion of the `conf.d` directory which holds local example configuration. Clients should retrieve their configuration from the parent node, or act as command endpoint execution bridge. Defaults to `y`.
The setup wizard will ensure that the following steps are taken:
@@ -602,7 +622,7 @@ The setup wizard will ensure that the following steps are taken:
* Store the signed client certificate and ca.crt in `/var/lib/icinga2/certs`.
* Update the `zones.conf` file with the new zone hierarchy.
* Update `/etc/icinga2/features-enabled/api.conf` (`accept_config`, `accept_commands`) and `constants.conf`.
-
+* Update `/etc/icinga2/icinga2.conf` and comment out `include_recursive "conf.d"`.
You can verify that the certificate files are stored in the `/var/lib/icinga2/certs` directory.
@@ -779,11 +799,15 @@ Add a [global zone](06-distributed-monitoring.md#distributed-monitoring-global-z
for syncing check commands later. Navigate to `C:\ProgramData\icinga2\etc\icinga2` and open
the `zones.conf` file in your preferred editor. Add the following lines if not existing already:
- object Zone "global-templates" {
- global = true
- }
+```
+object Zone "global-templates" {
+ global = true
+}
+```
-Note: Packages >= 2.8 provide this configuration by default.
+> **Note:**
+>
+> Packages >= 2.8 provide this configuration by default.
You don't need any local configuration on the client except for
CheckCommand definitions which can be synced using the global zone
@@ -793,14 +817,23 @@ Navigate to `C:\ProgramData\icinga2\etc\icinga2` and open
the `icinga2.conf` file in your preferred editor. Remove or comment (`//`)
the following line:
- // Commented out, not required on a client with top down mode
- //include_recursive "conf.d"
+```
+// Commented out, not required on a client with top down mode
+//include_recursive "conf.d"
+```
+
+> **Note**
+>
+> Packages >= 2.9 provide an option in the setup wizard to disable this.
+> Defaults to disabled.
Validate the configuration on Windows open an administrator terminal
and run the following command:
- C:\WINDOWS\system32>cd "C:\Program Files\ICINGA2\sbin"
- C:\Program Files\ICINGA2\sbin>icinga2.exe daemon -C
+```
+C:\WINDOWS\system32>cd "C:\Program Files\ICINGA2\sbin"
+C:\Program Files\ICINGA2\sbin>icinga2.exe daemon -C
+```
**Note**: You have to run this command in a shell with `administrator` privileges.
@@ -918,23 +951,34 @@ The `master` zone is a parent of the `icinga2-client1.localdomain` zone:
In addition, add a [global zone](06-distributed-monitoring.md#distributed-monitoring-global-zone-config-sync)
for syncing check commands later:
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/zones.conf
- object Zone "global-templates" {
- global = true
- }
+object Zone "global-templates" {
+ global = true
+}
+```
-Note: Packages >= 2.8 provide this configuration by default.
+> **Note:**
+>
+> Packages >= 2.8 provide this configuration by default.
You don't need any local configuration on the client except for
CheckCommand definitions which can be synced using the global zone
above. Therefore disable the inclusion of the `conf.d` directory
in `/etc/icinga2/icinga2.conf`.
- [root@icinga2-client1.localdomain /]# vim /etc/icinga2/icinga2.conf
+```
+[root@icinga2-client1.localdomain /]# vim /etc/icinga2/icinga2.conf
- // Commented out, not required on a client as command endpoint
- //include_recursive "conf.d"
+// Commented out, not required on a client as command endpoint
+//include_recursive "conf.d"
+```
+
+> **Note**
+>
+> Packages >= 2.9 provide an option in the setup wizard to disable this.
+> Defaults to disabled.
Edit the `api` feature on the client `icinga2-client1.localdomain` in
the `/etc/icinga2/features-enabled/api.conf` file and make sure to set
@@ -2557,16 +2601,25 @@ be passed (defaults to the FQDN).
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`.
+ Disable conf.d | **Optional.** Specified with the `disable-confd` parameter. If provided, this disables the `include_recursive "conf.d"` directive and adds the `api-users.conf` file inclusion to `icinga2.conf`. Available since v2.9+. Not set by default for compatibility reasons with Puppet, Ansible, Chef, etc.
Example:
- [root@icinga2-master1.localdomain /]# icinga2 node setup --master
+```
+[root@icinga2-master1.localdomain /]# icinga2 node setup --master
+```
In case you want to bind the `ApiListener` object to a specific
host/port you can specify it like this:
--listen 192.68.56.101,5665
+In case you don't need anything in `conf.d`, use the following command line:
+
+```
+[root@icinga2-master1.localdomain /]# icinga2 node setup --master --disable-confd
+```
+
#### Node Setup with Satellites/Clients
@@ -2631,6 +2684,7 @@ Pass the following details to the `node setup` CLI command:
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`.
+ Disable conf.d | **Optional.** Specified with the `disable-confd` parameter. If provided, this disables the `include_recursive "conf.d"` directive in `icinga2.conf`. Available since v2.9+. Not set by default for compatibility reasons with Puppet, Ansible, Chef, etc.
> **Note**
>
@@ -2638,14 +2692,17 @@ Pass the following details to the `node setup` CLI command:
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 \
- --parent_zone master \
- --parent_host icinga2-master1.localdomain \
- --trustedcert /var/lib/icinga2/certs/trusted-parent.crt \
- --accept-commands --accept-config
+```
+[root@icinga2-client1.localdomain /]# icinga2 node setup --ticket ead2d570e18c78abf285d6b85524970a0f69c22d \
+--cn icinga2-client1.localdomain \
+--endpoint icinga2-master1.localdomain \
+--zone icinga2-client1.localdomain \
+--parent_zone master \
+--parent_host icinga2-master1.localdomain \
+--trustedcert /var/lib/icinga2/certs/trusted-parent.crt \
+--accept-commands --accept-config \
+--disable-confd
+```
In case the client should connect to the master node, you'll
need to modify the `--endpoint` parameter using the format `cn,host,port`:
diff --git a/lib/cli/apisetuputility.cpp b/lib/cli/apisetuputility.cpp
index 29983226c..070e78cff 100644
--- a/lib/cli/apisetuputility.cpp
+++ b/lib/cli/apisetuputility.cpp
@@ -40,7 +40,12 @@ using namespace icinga;
String ApiSetupUtility::GetConfdPath()
{
- return Application::GetSysconfDir() + "/icinga2/conf.d";
+ return Application::GetSysconfDir() + "/icinga2/conf.d";
+}
+
+String ApiSetupUtility::GetApiUsersConfPath()
+{
+ return ApiSetupUtility::GetConfdPath() + "/api-users.conf";
}
bool ApiSetupUtility::SetupMaster(const String& cn, bool prompt_restart)
diff --git a/lib/cli/apisetuputility.hpp b/lib/cli/apisetuputility.hpp
index eeacd8daa..9523ebffc 100644
--- a/lib/cli/apisetuputility.hpp
+++ b/lib/cli/apisetuputility.hpp
@@ -45,6 +45,7 @@ public:
static bool SetupMasterUpdateConstants(const String& cn);
static String GetConfdPath();
+ static String GetApiUsersConfPath();
private:
ApiSetupUtility();
diff --git a/lib/cli/nodesetupcommand.cpp b/lib/cli/nodesetupcommand.cpp
index 590b08fae..fa188e7f0 100644
--- a/lib/cli/nodesetupcommand.cpp
+++ b/lib/cli/nodesetupcommand.cpp
@@ -66,7 +66,8 @@ void NodeSetupCommand::InitParameters(boost::program_options::options_descriptio
("accept-config", "Accept config from master")
("accept-commands", "Accept commands from master")
("master", "Use setup for a master instance")
- ("global_zones", po::value >(), "The names of the additional global zones.");
+ ("global_zones", po::value >(), "The names of the additional global zones to 'global-templates' and 'director-global'.")
+ ("disable-confd", "Disables the conf.d directory during the setup");
hiddenDesc.add_options()
("master_zone", po::value(), "DEPRECATED: The name of the master zone")
@@ -244,8 +245,28 @@ int NodeSetupCommand::SetupMaster(const boost::program_options::variables_map& v
Log(LogInformation, "cli")
<< "Edit the api feature config file '" << apipath << "' and set a secure 'ticket_salt' attribute.";
- /* tell the user to reload icinga2 */
+ if (vm.count("disable-confd")) {
+ /* Disable conf.d inclusion */
+ if (NodeUtility::UpdateConfiguration("\"conf.d\"", false, true)) {
+ Log(LogInformation, "cli")
+ << "Disabled conf.d inclusion";
+ } else {
+ Log(LogWarning, "cli")
+ << "Tried to disable conf.d inclusion but failed, possibly it's already disabled.";
+ }
+ /* Include api-users.conf */
+ String apiUsersFilePath = ApiSetupUtility::GetApiUsersConfPath();
+
+ if (Utility::PathExists(apiUsersFilePath)) {
+ NodeUtility::UpdateConfiguration("\"conf.d/api-users.conf\"", true, false);
+ } else {
+ Log(LogWarning, "cli")
+ << "Included file dosen't exist " << apiUsersFilePath;
+ }
+ }
+
+ /* tell the user to reload icinga2 */
Log(LogInformation, "cli", "Make sure to restart Icinga 2.");
return 0;
@@ -555,5 +576,13 @@ int NodeSetupCommand::SetupNode(const boost::program_options::variables_map& vm,
Log(LogInformation, "cli", "Make sure to restart Icinga 2.");
}
+ if (vm.count("disable-confd")) {
+ /* Disable conf.d inclusion */
+ NodeUtility::UpdateConfiguration("\"conf.d\"", false, true);
+ }
+
+ /* tell the user to reload icinga2 */
+ Log(LogInformation, "cli", "Make sure to restart Icinga 2.");
+
return 0;
}
diff --git a/lib/cli/nodeutility.cpp b/lib/cli/nodeutility.cpp
index 645e19d94..38584a11e 100644
--- a/lib/cli/nodeutility.cpp
+++ b/lib/cli/nodeutility.cpp
@@ -265,6 +265,89 @@ void NodeUtility::SerializeObject(std::ostream& fp, const Dictionary::Ptr& objec
fp << "}\n\n";
}
+/*
+ * include = false, will comment out the include statement
+ * include = true, will add an include statement or uncomment a statement if one is existing
+ * resursive = false, will search for a non-resursive include statement
+ * recursive = true, will search for a resursive include statement
+ * Returns true on success, false if option was not found
+ */
+bool NodeUtility::UpdateConfiguration(const String& value, bool include, bool recursive)
+{
+ String configurationFile = Application::GetSysconfDir() + "/icinga2/icinga2.conf";
+
+ Log(LogInformation, "cli")
+ << "Updating ' " << value << "' include in '" << configurationFile << "'.";
+
+ NodeUtility::CreateBackupFile(configurationFile);
+
+ std::ifstream ifp(configurationFile.CStr());
+ std::fstream ofp;
+ String tempFile = Utility::CreateTempFile(configurationFile + ".XXXXXX", 0644, ofp);
+
+ String affectedInclude = value;
+
+ if (recursive)
+ affectedInclude = "include_recursive " + affectedInclude;
+ else
+ affectedInclude = "include " + affectedInclude;
+
+ bool found = false;
+
+ std::string line;
+
+ while (std::getline(ifp, line)) {
+ if (include) {
+ if (line.find("//" + affectedInclude) != std::string::npos || line.find("// " + affectedInclude) != std::string::npos) {
+ found = true;
+ ofp << "// Added by the node setup CLI command on "
+ << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", Utility::GetTime())
+ << "\n" + affectedInclude + "\n";
+ } else if (line.find(affectedInclude) != std::string::npos) {
+ found = true;
+
+ Log(LogInformation, "cli")
+ << "Include statement '" + affectedInclude + "' already set.";
+
+ ofp << line << "\n";
+ } else {
+ ofp << line << "\n";
+ }
+ } else {
+ if (line.find(affectedInclude) != std::string::npos) {
+ found = true;
+ ofp << "// Disabled by the node setup CLI command on "
+ << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", Utility::GetTime())
+ << "\n// " + affectedInclude + "\n";
+ } else {
+ ofp << line << "\n";
+ }
+ }
+ }
+
+ if (include && !found) {
+ ofp << "// Added by the node setup CLI command on "
+ << Utility::FormatDateTime("%Y-%m-%d %H:%M:%S %z", Utility::GetTime())
+ << "\n" + affectedInclude + "\n";
+ }
+
+ ifp.close();
+ ofp.close();
+
+#ifdef _WIN32
+ _unlink(configurationFile.CStr());
+#endif /* _WIN32 */
+
+ if (rename(tempFile.CStr(), configurationFile.CStr()) < 0) {
+ BOOST_THROW_EXCEPTION(posix_error()
+ << boost::errinfo_api_function("rename")
+ << boost::errinfo_errno(errno)
+ << boost::errinfo_file_name(configurationFile));
+ }
+
+ return (found || include);
+}
+
void NodeUtility::UpdateConstant(const String& name, const String& value)
{
String constantsConfPath = NodeUtility::GetConstantsConfPath();
diff --git a/lib/cli/nodeutility.hpp b/lib/cli/nodeutility.hpp
index 2ba33c2f3..3017a8ead 100644
--- a/lib/cli/nodeutility.hpp
+++ b/lib/cli/nodeutility.hpp
@@ -44,6 +44,7 @@ public:
static bool WriteNodeConfigObjects(const String& filename, const Array::Ptr& objects);
+ static bool UpdateConfiguration(const String& value, bool include, bool recursive);
static void UpdateConstant(const String& name, const String& value);
/* node setup helpers */
diff --git a/lib/cli/nodewizardcommand.cpp b/lib/cli/nodewizardcommand.cpp
index e6cdb827c..b5e143730 100644
--- a/lib/cli/nodewizardcommand.cpp
+++ b/lib/cli/nodewizardcommand.cpp
@@ -104,7 +104,8 @@ int NodeWizardCommand::Run(const boost::program_options::variables_map& vm,
* 9. enable ApiListener feature
* 10. generate zones.conf with endpoints and zone objects
* 11. set NodeName = cn in constants.conf
- * 12. reload icinga2, or tell the user to
+ * 12. disable conf.d directory?
+ * 13. reload icinga2, or tell the user to
*/
std::string answer;
@@ -526,6 +527,7 @@ wizard_ticket:
/* Global zones. */
std::vector globalZones { "global-templates", "director-global" };
+ std::cout << "\nDefault global zones: " << boost::algorithm::join(globalZones, " ");
std::cout << "\nDo you want to specify additional global zones? [y/N]: ";
std::getline(std::cin, answer);
@@ -615,6 +617,32 @@ wizard_global_zone_loop_start:
Log(LogInformation, "cli", "Make sure to restart Icinga 2.");
}
+ /* Disable conf.d inclusion */
+ std::cout << "\nDo you want to disable the inclusion of the conf.d directory [Y/n]: ";
+
+ std::getline(std::cin, answer);
+ boost::algorithm::to_lower(answer);
+ choice = answer;
+
+ if (choice.Contains("n"))
+ Log(LogInformation, "cli")
+ << "conf.d directory has not been disabled.";
+ else {
+ std::cout << ConsoleColorTag(Console_Bold | Console_ForegroundGreen)
+ << "Disabling the inclusion of the conf.d directory...\n"
+ << ConsoleColorTag(Console_Normal);
+
+ if (!NodeUtility::UpdateConfiguration("\"conf.d\"", false, true)) {
+ std::cout << ConsoleColorTag(Console_Bold | Console_ForegroundRed)
+ << "Failed to disable the conf.d inclusion, it may already have been disabled.\n"
+ << ConsoleColorTag(Console_Normal);
+ }
+
+ /* Satellite/Clients should not include the api-users.conf file.
+ * The configuration should instead be managed via config sync or automation tools.
+ */
+ }
+
return 0;
}
@@ -683,6 +711,7 @@ int NodeWizardCommand::MasterSetup() const
/* Global zones. */
std::vector globalZones { "global-templates", "director-global" };
+ std::cout << "\nDefault global zones: " << boost::algorithm::join(globalZones, " ");
std::cout << "\nDo you want to specify additional global zones? [y/N]: ";
std::getline(std::cin, answer);
@@ -788,6 +817,10 @@ wizard_global_zone_loop_start:
<< Utility::GetFQDN() << "'. Requires an update for the NodeName constant in constants.conf!";
}
+ Log(LogInformation, "cli", "Updating constants.conf.");
+
+ NodeUtility::CreateBackupFile(NodeUtility::GetConstantsConfPath());
+
NodeUtility::UpdateConstant("NodeName", cn);
NodeUtility::UpdateConstant("ZoneName", cn);
@@ -795,5 +828,41 @@ wizard_global_zone_loop_start:
NodeUtility::UpdateConstant("TicketSalt", salt);
+ /* Disable conf.d inclusion */
+ std::cout << "\nDo you want to disable the inclusion of the conf.d directory [Y/n]: ";
+
+ std::getline(std::cin, answer);
+ boost::algorithm::to_lower(answer);
+ choice = answer;
+
+ if (choice.Contains("n"))
+ Log(LogInformation, "cli")
+ << "conf.d directory has not been disabled.";
+ else {
+ std::cout << ConsoleColorTag(Console_Bold | Console_ForegroundGreen)
+ << "Disabling the inclusion of the conf.d directory...\n"
+ << ConsoleColorTag(Console_Normal);
+
+ if (!NodeUtility::UpdateConfiguration("\"conf.d\"", false, true)) {
+ std::cout << ConsoleColorTag(Console_Bold | Console_ForegroundRed)
+ << "Failed to disable the conf.d inclusion, it may already have been disabled.\n"
+ << ConsoleColorTag(Console_Normal);
+ }
+
+ /* Include api-users.conf */
+ String apiUsersFilePath = Application::GetSysconfDir() + "/icinga2/conf.d/api-users.conf";
+
+ std::cout << ConsoleColorTag(Console_Bold | Console_ForegroundGreen)
+ << "Checking if the api-users.conf file exists...\n"
+ << ConsoleColorTag(Console_Normal);
+
+ if (Utility::PathExists(apiUsersFilePath)) {
+ NodeUtility::UpdateConfiguration("\"conf.d/api-users.conf\"", true, false);
+ } else {
+ Log(LogWarning, "cli")
+ << "Included file '" << apiUsersFilePath << "' does not exist.";
+ }
+ }
+
return 0;
}