Passwords in Setup Rules
Some Checkmk Setup Rules carry a secret — a special agent's password, an API token, an SNMP community. This page explains how to keep such rules deployable across several Checkmk instances (for example a test and a production site) without ever putting the real secret into the rule.
The problem: Checkmk masks passwords on read
When a rule stores a password inline (an "explicit" password), Checkmk returns
it masked as ****** on every read of that rule:
'secret': ('cmk_postprocessed', 'explicit_password', ('uuid…', '******'))
So a rule read from one Checkmk carries no usable secret. If you copied that rule
to another Checkmk as-is, you would overwrite its password with ******. This is
why rules imported from a Checkmk folder
can't simply be re-deployed with their inline password.
The solution: reference the Syncer Secret Store
Instead of inlining the secret, a rule references an entry in the Syncer's Secret Store (until 4.4 the Checkmk Password Store) with a Jinja macro:
{{ cmk_password("name") }}
nameis the Name of a global entry in the Syncer's Secret Store (Modules > Secret Store), not its title. Entries bound to a host are not found by name, see Per host secrets.- On rule export the macro resolves to that entry's Checkmk password-store ident,
cmdbsyncer_<id>, which is the same on every Checkmk instance you export the password to.
The real secret lives only in the Syncer (encrypted) and in each Checkmk's own password store — never inside the rule. A rule exported to test and to prod resolves each site's own stored secret through the same ident.
Imported rules are rewritten automatically
When you import Setup Rules from a Checkmk folder, every inline password is rewritten into such a reference:
# imported
'secret': ('cmk_postprocessed', 'explicit_password', ('uuid…', '******'))
# stored on the rule
'secret': ('cmk_postprocessed', 'stored_password', ('{{ cmk_password("secret") }}', ''))
- The default macro name is the value's field (here
secret). Rename it on the rule to match your chosen password entry — a re-import keeps your renamed macro instead of reverting it. - Non-password fields (e.g. an explicit proxy URL) are left untouched.
- After an import that found passwords, the Syncer tells you which names it used, in the import result and the log.
You decide when passwords are pushed
A macro only resolves on a Checkmk instance whose password store already contains the referenced entry. The Syncer does not push passwords automatically during a rule export — that stays a job you run, so the rule export is not slowed down by re-writing password-store entries on every run.
Populate a target Checkmk's password store with the password export:
./cmdbsyncer checkmk export_passwords <account>
This writes every enabled Secret Store entry with Export to Checkmk ticked into that account's Checkmk password store (creating or updating it). Certificates are left out.
Workflow: test → prod
- Create a global entry in the Syncer's Secret Store: a unique Name, the real secret, Enabled and Export to Checkmk ticked.
- Point the rule at it: make sure the rule's value uses
{{ cmk_password("<that name>") }}(imported rules already carry a macro you can rename). -
Push the password to each target Checkmk once (and again after a rotation):
./cmdbsyncer checkmk export_passwords test-cmk ./cmdbsyncer checkmk export_passwords prod-cmk -
Export the rules as usual:
./cmdbsyncer checkmk export_rules test-cmk ./cmdbsyncer checkmk export_rules prod-cmk
The rules resolve the macro to the ident that now exists in each site's password store.
To rotate a secret, edit the entry in the Syncer and re-run
export_passwords for each target — the ident stays the same, so the rules do
not need re-exporting.
Missing or disabled entries
If a referenced name has no global Secret Store entry (or the entry exists but is
disabled and was never exported), the macro resolves to a placeholder ident
that Checkmk rejects. Only that one rule fails to deploy (the failure is logged);
the rest of the export continues. Fix it by creating or enabling the entry and
running export_passwords for the target.
Per host secrets
Since 4.5
When every host has its own secret (an API token per cluster, for example), bind the entries to the hosts instead of creating one global entry per host. The host import does that for chosen columns. A rule rendered per host then references the entry of its host by key:
'token': ('cmk_postprocessed', 'stored_password', ('{{ secret("api_token") }}', ''))
secret('api_token') resolves to the ident of the entry bound to the current
host under the key api_token, or of a global entry named api_token when the
host has none. Host-bound entries are exported by export_passwords like the
global ones. See Secret Store.