Checkmk can read this plugin’s Nagios output directly. You can run it as an active check on the Checkmk server or as a local check on an agent host. Choose the machine that can reach the instance from the network you want to test.
| Active check | Local check | |
|---|---|---|
| Runs on | the Checkmk server | a host with the Checkmk agent |
| Reaches the instance from | the monitoring network | wherever that host sits |
| Needs the plugin installed on | the Checkmk server | the agent host |
| Configured in | the web interface | a file the agent runs |
| Output format | nagios (the default) |
--format checkmk |
Use the active check unless the instance is unreachable from the Checkmk server. It is configured in one place, it needs nothing on any other machine, and Checkmk parses the plugin's ordinary output itself.
Everything below uses opencloud.example.com. Substitute your own, and scan
only instances you are responsible for.
1. An active check on the Checkmk server
Install the plugin on the Checkmk server, as the site user:
pipx install check-opencloud-security
Installing the plugin covers uv, pip and a checkout;
check-opencloud-security --version confirms which one you got.
Then, in the web interface: Setup > Services > Other services > Integrate Nagios plugins, and create a rule with
- Service description:
OpenCloud security opencloud.example.com - Command line:
check-opencloud-security --host opencloud.example.com --check-hardening
Assign it to the host you want the service to appear on. That host is a label
for where the service lives, not where the scan goes - the scan always goes
to --host.
Checkmk reads the state from the exit code, the summary from the first output
line, the rest of the output as the service's details, and everything after
the | as metrics. Nothing needs converting: the
performance data this plugin already writes -
rating, vulnerabilities, hardenings_missing, extra_checks_failed,
update_available, support_days_left, cert_days_left, upgrade_path_complete,
waiver_days_left, coverage_inconclusive, coverage_not_checked, time - is the
Nagios format Checkmk was built to read, thresholds and all.
One warning about scheduling: the default check interval is one minute, and a scan makes around twenty HTTP requests and five TCP connects to the instance. Set a sensible interval on the service - hourly is plenty for a rating that moves when somebody changes a configuration file - under Setup > Services > Service monitoring rules > Normal check interval for service checks.
2. A local check on an agent host
When the Checkmk server cannot reach the instance, the scan has to start somewhere that can. A local check is a script the agent runs; its output becomes a service on the agent's host.
--format checkmk writes exactly what the agent expects:
check-opencloud-security --host opencloud.example.com --format checkmk
0 "OpenCloud_Security_opencloud.example.com" rating=5|vulnerabilities=0|hardenings_missing=0|extra_checks_failed=0|update_available=0|support_days_left=284|cert_days_left=67|execution_time=4.120 OK: Server is up to date. No known vulnerabilities.
Four fields, separated by single spaces: the state, the quoted service name,
the metrics, and the detail text. With several hosts in --host you get
several lines, which is several services - one per instance.
Installing it
contrib/checkmk/opencloud_security
is that call wrapped in a script, configured by the same COS_ environment
variables as the cron and systemd examples beside it, so it
needs no editing to point at your instance:
sudo install -m 0755 contrib/checkmk/opencloud_security \
/usr/lib/check_mk_agent/local/3600/opencloud_security
The 3600 is the important part. A script in local/ itself runs every
time the agent is called - once a minute - and that is a scan a minute against
somebody's production instance. The numeric subdirectory is the agent's cache
interval in seconds: the scan then runs at most hourly, and every call in
between is answered from the cached line. Pick the interval you actually want;
3600 is a good default for a rating.
Installed from the .deb or .rpm, the same script is at
/usr/share/doc/check-opencloud-security/checkmk-local-check.sh - as an
example, deliberately not installed into the agent's directory by a package
that has no business writing there.
Set the target in the script, or in an environment file the agent reads:
COS_HOST=opencloud.example.com
# OpenCloud self-signs its certificate unless a proxy terminates TLS for it.
#COS_SCANNER_VERIFY_TLS=false
Then discover the new service on that host: Setup > Hosts, the host's Services page, Full service scan.
What the states mean
The state on the line is the plugin's, unchanged - the same 0/1/2/3
the exit code carries, decided by the same
rating thresholds, waivers and
end-of-life rules as everywhere else. Checkmk is not asked to judge anything:
0OK - the rating is above--warningand nothing new appeared1WARN - at or below--warning, or a finding is missing hardening2CRIT - at or below--critical, or a known vulnerability applies3UNKNOWN - the scan could not be completed at all
That last one is why the shipped script always prints a line, even when the plugin is missing or was killed by the agent's timeout. A local check that prints nothing does not go UNKNOWN - it removes its service from the host, which reads like a check somebody deliberately switched off rather than one that broke.
The metrics
The same measurements the Nagios performance data carries, under the same names, with two differences the format requires:
- No thresholds. A local check's levels are only evaluated when the state
field is
P, which hands the verdict to Checkmk. Deciding is this plugin's job, so it sends the state it reached and the metrics carry values alone. - No unit suffix. Every value has to parse as a number, so the Nagios
time=4.120sisexecution_time=4.120here.
| Metric | What it is |
|---|---|
rating |
0-5, where 5 is A+. Absent when no rating could be established |
vulnerabilities |
Known advisories matching the detected version |
hardenings_missing |
Measures the instance is missing. Absent without --check-hardening, because an empty list would otherwise be indistinguishable from a perfect one |
extra_checks_failed |
Failed additional checks - TLS, exposed paths, cookies, headers |
update_available |
1 when a newer release exists. Absent when the update check is off |
support_days_left |
Days until the release line stops receiving fixes; negative once it has |
cert_days_left |
Days until the certificate expires; negative once it has |
upgrade_path_complete |
1 when the recommended upgrade clears every known advisory, 0 when it does not; absent without advisories |
waiver_days_left |
Days until a --waive-until waiver ends and lets a failing check alert again; absent when no failing check depends on a deadline |
coverage_inconclusive |
Checks the scan ran and could not decide; absent without a coverage block |
coverage_not_checked |
Checks the scan did not run; absent without a coverage block |
execution_time |
How long the scan took, in seconds |
A metric that was not measured is left out rather than sent as a zero, so a graph never shows a confident zero for something nobody looked at.
Alerting on it
Both routes produce an ordinary Checkmk service, so notifications, downtimes and acknowledgements work as they do for anything else. Two rules worth setting up:
- Alert on CRIT immediately - a known vulnerability or an end-of-life release is not a tomorrow problem.
- Graph
support_days_leftand set a level on it. It is the one number that gets worse while nothing about the instance changes, and the day it goes negative the rating drops to F on its own.
--baseline and --warn-on-new (Reporting only what
changed) work under both routes and are worth having on a check
that runs unattended: the state then reflects what is new rather than
repeating a finding somebody has already decided to live with. An
end-of-life release and a rating that drops further are never forgiven by
that, so it cannot quieten the two findings that matter most.
See also
- Installing the plugin - and the Icinga2/Nagios object definitions, if Checkmk is not the only thing you run
- Machine-readable output - every
--formatvalue compared - Scheduling - the systemd timer and cron drop-in the local check's environment variables come from
- Prometheus and Grafana - the other pull-based route, if you would rather graph this outside Checkmk