diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ee94b93a..72529f02b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,10 @@ Build, CI/CD: * Bump pinned `linuxfabrik-lib` to 5.1.0 +Icinga Director: + +* the shipped Service and Host templates default to the master zone, so host and service configuration, including credentials on those objects, stays on the master instead of being distributed to every agent. Single-node and flat master to agent setups are unaffected; distributed setups with satellite- or agent-authoritative hosts must unset the zone on the two base templates and accept that configuration is then distributed to every agent (see ICINGA.md) ([#721](https://github.com/Linuxfabrik/monitoring-plugins/issues/721)) + Monitoring Plugins: * about-me: recognizes an installed Apache Tomcat when guessing Icinga Director tags @@ -718,7 +722,7 @@ Icinga Director: * [atlassian-statuspage](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/atlassian-statuspage/): Increase timeout from 8 to 30 secs * [uptimerobot](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/uptimerobot/): Increase timeout from 8 to 30 secs -* Path to notification plugins changed back to `/usr/lib64/nagios/plugins` +* Path to notification plugins changed back to `/usr/lib64/nagios/plugins` Monitoring Plugins: @@ -1532,7 +1536,7 @@ Monitoring Plugins: * about-me3: Add Maker and Model ([#637](https://github.com/Linuxfabrik/monitoring-plugins/issues/637)) * about-me3: Improve detection of coturn * about-me3: Improve psutil error handling -* about-me3: Make external IP search configurable with 3rd party providers (and disabled by default) ([#645](https://github.com/Linuxfabrik/monitoring-plugins/issues/645)) +* about-me3: Make external IP search configurable with 3rd party providers (and disabled by default) ([#645](https://github.com/Linuxfabrik/monitoring-plugins/issues/645)) * about-me3: Re-written from scratch, now also recommends tags for our Icinga Director Basket. New parameter `--tags`. * about-me3: Remove unstable bonding detection * [disk-usage](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/disk-usage/): Move state output to usage column @@ -1679,7 +1683,7 @@ Monitoring Plugins: * [about-me](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/about-me/): Add swanctl ([#575](https://github.com/Linuxfabrik/monitoring-plugins/issues/575)) * [about-me](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/about-me/): Print its own version ([#439](https://github.com/Linuxfabrik/monitoring-plugins/issues/439)) * [about-me](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/about-me/): Report active tuned-Profile in first line if tuned.service is found and running ([#374](https://github.com/Linuxfabrik/monitoring-plugins/issues/374)) -* [about-me](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/about-me/): Report Boot Mode ([#562](https://github.com/Linuxfabrik/monitoring-plugins/issues/562)) +* [about-me](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/about-me/): Report Boot Mode ([#562](https://github.com/Linuxfabrik/monitoring-plugins/issues/562)) * [about-me](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/about-me/): Show key features of the Machine ([#561](https://github.com/Linuxfabrik/monitoring-plugins/issues/561)) * All checks using SQLite databases: More unique sqlite db names ([#333](https://github.com/Linuxfabrik/monitoring-plugins/issues/333)) * [apache-httpd-status](https://linuxfabrik.github.io/monitoring-plugins/check-plugins/apache-httpd-status/): New parameter `--insecure` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3a94d5e2e..aeb2b1c05 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -181,6 +181,14 @@ Use: Ship the Service Template in `build-basket` either way. Add a Service Set entry to `all-the-rest.json` only if the check fits the generic or bundled shape. +### Icinga Director: Cluster Zones + +The shipped base templates `tpl-host-generic` and `tpl-service-generic` pin `"zone": "master"` in `all-the-rest.json`. Every other host and service template, including the per-plugin and `-no-agent` templates, sets no zone and inherits master through the template imports, so those two base templates are the single control point for the zone of the whole shipped configuration. This is a deliberate security default: it keeps host and service configuration, and any credentials on a host or service object, on the master and its HA peers instead of on every agent. When editing templates: + +* Keep the two base templates pinned to `master` and leave every other template's zone unset, so the whole tree inherits from that single control point. A distributed site that needs the checks on satellite- or agent-authoritative hosts unsets the zone on the two base templates (moving them to the global zone), accepting that host and service configuration is then distributed to every agent. That trade-off is documented in ICINGA.md. +* Never put a credential (password, SNMP community, API token) on a template or on a Service Set. A Service Set renders as an `apply` rule, which always goes to the global zone, so a secret on it reaches every agent regardless of the `master` pin. A secret on a shared template applies to every service that imports it and is distributed to every agent as soon as a distributed site unsets the base-template zone. Keep secrets on the concrete host or service object, which is deployed only to the zone that runs the check. + + ### Rules of Thumb * Be brief by default. Report what needs to be reported to fix a problem. If there is more information that might help the admin, support a `--lengthy` parameter. If the default output still grows unbounded on large systems (thousands of disk mounts, DHCP scopes, backends, services), also support a `--brief` parameter that hides rows within the thresholds. See "Verbosity parameter convention" below. diff --git a/ICINGA.md b/ICINGA.md index f098b7e96..2b43a0c0d 100644 --- a/ICINGA.md +++ b/ICINGA.md @@ -169,17 +169,22 @@ Most checks run on the Icinga Agent of the monitored host (the plugin files are In a distributed Icinga 2 setup the checks execute on satellites or agents, not on the master. Icinga validates that a checkable's `command_endpoint` is in the same zone as the checkable or in a *direct child zone*; otherwise it rejects the configuration with: ```text -Error: ... Attribute 'command_endpoint': Command endpoint must be in zone 'X' or in a direct child zone thereof. +critical/config: Error: Validation failed for object 'host.example.com!Load' of type 'Service'; Attribute 'command_endpoint': Command endpoint must be in zone 'master' or in a direct child zone thereof. ``` -The templates are built so this works in any topology: +The shipped base templates `tpl-service-generic` and `tpl-host-generic` pin `"zone": "master"`. Every other host and service template, including the per-plugin and `-no-agent` templates, sets no zone and inherits master through the template imports, so those two base templates are the single control point for the zone of the whole shipped configuration. This is a deliberate security default: it keeps host and service configuration, and any credentials set on a host or service object, on the master and its HA peers instead of on every agent. -* **Check commands** must exist on every endpoint that runs a check. Deploy them through a global zone (`director-global`), which the Icinga config sync distributes to all endpoints. -* **Hosts** carry their own zone and `command_endpoint`. Set them per host in Director (enable the *Icinga Agent* and pick the host's cluster zone); the host then lives in its agent or satellite zone. -* **Service templates do not pin a zone.** `tpl-service-generic` has no zone, so every service inherits the host's zone and `command_endpoint` and runs on the host's agent, no matter how many tiers sit between master and agent (master → agent, master → satellite → agent, and deeper). -* Only the agentless `-no-agent` variants (`tpl-service-cert-no-agent`, `tpl-service-url-no-agent`) pin `"zone": "master"`, because they run centrally from the master. +Icinga's config sync pushes only global zones and a node's own child zones downwards; a satellite or agent never receives the master zone. That shapes what works: -Do **not** force an agent-based service into a fixed zone or a global zone. A service that sets a `command_endpoint` can never satisfy the zone rule from a global zone (global zones have no child zones), and pinning it to `master` breaks every setup where the agent is not a direct child of the master, such as a three-tier master → satellite → agent topology. +* **Single node and flat master → agent.** Works out of the box and stays secure. The agent zone is a direct child of the master, so the `command_endpoint` rule holds: the check runs on the agent via `command_endpoint`, while its configuration and credentials stay on the master. The plugin files still have to be deployed on the agent. +* **Distributed with satellite- or agent-authoritative hosts.** The master-zoned templates are never synced to those nodes, so a host that lives in a satellite or agent zone cannot import them. The deploy is rejected on that node with `Import references unknown template: 'tpl-service-generic'` (or the `command_endpoint` error above, depending on which check Icinga reaches first). This is intentional: the default refuses to ship the configuration, and any credentials on it, out to every tier. + +To run the checks on satellite- or agent-authoritative hosts, unset the zone on `tpl-service-generic` and `tpl-host-generic`. Director then places them in the global zone, the config sync distributes them everywhere, and the imports resolve in every zone. Be aware of the trade-off you are accepting: host and service configuration, including credentials on those objects, is then copied to every agent's disk. + +Two more things to keep in mind: + +* **Check commands** always live in a global zone (`director-global`), because every endpoint that runs a check needs them. They carry no secrets. +* **Service Sets never protect secrets.** A Service Set is rendered as an `apply` rule, and apply rules always go to the global zone, so a credential set on a Service Set reaches every agent regardless of the master default. Put secrets on the concrete host or service object, never on a Service Set or a template. ### Notes URL @@ -364,7 +369,7 @@ Trade-off: without UUIDs, Director falls back to name-based object matching, whi ### Master zone is not named `master` -The agentless central Service Templates (`tpl-service-cert-no-agent`, `tpl-service-url-no-agent`) carry `"zone": "master"` because they run on the master. The agent-based templates do not pin a zone (they inherit the host's zone, see the "Distributed Monitoring" section under Core Concepts). If your Icinga 2 master zone has a different name, replace the literal before importing so the agentless checks still target your master: +The shipped base templates `tpl-service-generic` and `tpl-host-generic` carry `"zone": "master"`, and every other template inherits it (see the "Distributed Monitoring" section under Core Concepts for the reasoning). If your Icinga 2 master zone has a different name, replace the literal before importing so the checks still target your master: ```bash sed --in-place 's/"zone": "master"/"zone": "icinga-master-zone"/g' \ diff --git a/assets/icingaweb2-module-director/all-the-rest.json b/assets/icingaweb2-module-director/all-the-rest.json index 79589904c..5b8b89599 100644 --- a/assets/icingaweb2-module-director/all-the-rest.json +++ b/assets/icingaweb2-module-director/all-the-rest.json @@ -1686,7 +1686,7 @@ "ping_timeout": "5" }, "volatile": null, - "zone": null + "zone": "master" }, "tpl-host-hardware-server": { "accept_config": true, @@ -47153,7 +47153,7 @@ "uuid": "ed9802cd-54f2-4c55-8f7a-5c5ddb92c27f", "vars": {}, "volatile": null, - "zone": "master" + "zone": null }, "tpl-service-generic": { "action_url": null, @@ -47200,7 +47200,7 @@ "uuid": "b60279bb-147a-4f65-a4b2-c7adef4305c2", "vars": {}, "volatile": null, - "zone": null + "zone": "master" }, "tpl-service-icinga": { "action_url": null, @@ -47343,7 +47343,7 @@ "uuid": "51704073-9a28-41d4-9cb1-846fd5697f37", "vars": {}, "volatile": null, - "zone": "master" + "zone": null } }, "TimePeriod": {