Skip to content

Secret Store

Since 4.5

The Secret Store keeps the passwords, tokens and certificates the Syncer needs, encrypted, in one place for every module. An entry is either global or bound to a host, and rules read it with a Jinja function instead of carrying the secret themselves.

You find it under Modules > Secret Store (at the bottom of the Modules menu, next to the Lookup Tables).

Formerly the Checkmk Password Store

Up to version 4.4 this was the Checkmk Password Store (Modules > Checkmk > Manage Password Store). It is the same data: every existing entry keeps its name, its value and its Checkmk ident cmdbsyncer_<id>, nothing is migrated. {{ cmk_password("name") }} and checkmk export_passwords work as before, and rule exports made with an older version still import (the rule type is still called cmk_passwords). The Checkmk side of the store is described in Password Store.

How values are stored

Values are encrypted in the database with the CRYPTOGRAPHY_KEY from your local_config.py. If you change this key, the stored values have to be entered again. The list and the host overview never show a value; showing one needs a role of its own (see Access).

An entry

Field Description
Name Unique name of the entry. A global entry is reached by this name. For a host-bound entry it is set to <hostname>:<key> automatically
Documentation Free text for your own notes
Enabled Only enabled entries are exported to Checkmk
Kind Password, Token or Certificate
Value The secret. Leave it empty when editing to keep the stored value
Bound to host Empty for a global entry. With a hostname the entry belongs to that host
Key Name of the secret on the host, e.g. api_token. Required for a host-bound entry
Export to Checkmk Write the entry into the Checkmk password store (see below)
Title, Comment, Documentation URL, Owner, Shared How the entry is described in the Checkmk password store

Global entries

A global entry belongs to no host. Rules reach it by its Name, with {{ cmk_password("name") }} or {{ secret('name') }}.

Host-bound entries

A host-bound entry belongs to one host and is found by host and Key. Every host can have its own api_token, and a rule rendered for a host gets the entry of exactly that host. The usual way to create them is the host import, which can send chosen columns into the Secret Store instead of turning them into labels.

The host overview (the detail page of a host) has a Secrets row listing the entries bound to the host: key, kind, the reference to use in rules, the value masked as ******, a link to the entry and, with the matching role, a link to show the value.

Orphaned entries

When a host is archived or deleted, its entries are not removed. They are flagged orphaned in the list (there is a filter for it) and are no longer found by secret(). To reuse such an entry, edit it and put another hostname into Bound to host: the entry is bound to that host and the flag is cleared. When the archived host is restored, the flag goes away by itself.

Certificates

An entry of the kind Certificate is not exported to Checkmk, because Checkmk cannot create one in its password store over the REST API. Use the eye icon in the list (Show value) to display it and copy it by hand. A value containing a PEM block (BEGIN CERTIFICATE) that comes in through the host import is stored as a certificate automatically.

Using entries in rules

Function Result
{{ secret('key') }} The Checkmk password store ident (cmdbsyncer_<id>) of the entry bound to the current host under key, or of the global entry named key if the host has none
{{ secret_value('key') }} The plaintext value of the same entry
{{ cmk_password("name") }} The Checkmk ident of the global entry name. Host-bound entries are never resolved by name

The host always comes from the host the rule is rendered for. A template cannot switch to another host's secret, not even by setting HOSTNAME itself.

A Checkmk Setup Rule that needs a per host token, e.g. in the value of a special agent:

{
    'url': 'https://{{ api }}',
    'token': ('cmk_postprocessed', 'stored_password', ('{{ secret("api_token") }}', '')),
}

secret() only gives the ident, so the token itself has to be in the Checkmk password store: run ./cmdbsyncer checkmk export_passwords <account> first, as for global entries. See Passwords in Setup Rules.

secret_value() puts the plaintext into the result, use it only where a target really needs the value itself. Inside the web interface and the API (previews, host debug) the value is shown as ****** unless the user may show values of that entry. Exports run from the command line or cron get the real value.

A key that has neither a host-bound nor a global entry is logged as an error. secret() then gives the placeholder cmdbsyncer_missing_<key>, which Checkmk rejects, secret_value() gives an empty string.

Export to Checkmk

./cmdbsyncer checkmk export_passwords ACCOUNTNAME

writes every enabled entry with Export to Checkmk ticked into the Checkmk password store of that account, global and host-bound entries alike. Certificates are left out. Details in Password Store.

Access

Two roles under Settings > User:

Role Grants
Secret Store List, create, edit and bind entries. The Checkmk role still opens the store as well, as it did for the Password Store
Secret Store: show plaintext values Show the value of an entry (the eye icon in the list and on the host overview)

A user restricted to accounts or templates only reaches entries bound to hosts inside that limit, global admins included. Such a user:

  • sees, edits, switches, reveals and binds only entries of their own hosts,
  • cannot create or see global entries,
  • can only bind entries to hosts they can see,
  • cannot export or import the Secret Store through the rule export/import, the REST API or the MCP server,
  • only stores secrets for their own hosts through the host import.

Showing a value is written to the log with the user and the entry.