kube_bench_cache¶
Execution module: kube_bench_cache
Added in version 3.0.0.
Collect kube-bench results and write a validated JSON array to a minion-local
cache file. Every control SLS calls kube_bench_cache.ensure_fresh at Jinja
render time before reading the cache.
All cluster interaction goes through this extension’s own kubernetes
execution module (saltext.kubernetes.modules.kubernetesmod, loaded as
__salt__["kubernetes.*"]) rather than shelling out to kubectl. This
means connection/auth handling (kubeconfig file, inline kubeconfig data,
explicit host+credentials, in-cluster ServiceAccount) is inherited for free
from that module’s _setup_conn resolution instead of being reimplemented
here.
Two collection strategies are supported (selected via the collection_strategy
parameter or the kube_bench:collection_strategy pillar key):
job (default): creates a one-time Kubernetes Job from the suspended kube-bench CronJob template, waits for completion, collects JSON output from every pod (one per node), then deletes the Job. Use
run_assessment()to trigger this path on demand – it bypasses the TTL cache check and always runs a new Job. This matches howhelm/kube-bench-jobactually deploys kube-bench (a suspended CronJob, no standing pods), so it’s the default that works out of the box without any pillar configuration.daemonset (backward-compatible): reads logs from an existing long-running kube-bench DaemonSet. Only useful if you’ve deployed kube-bench that way yourself; set
collection_strategy: daemonsetexplicitly.
Because ensure_fresh is invoked via salt['kube_bench_cache.ensure_fresh']()
at Jinja render time it MUST NOT honour __opts__['test'] – doing so would
silently skip collection during every policy.assessment run (which uses
test=True) and leave all controls reading a stale or missing file.
- saltext.kubernetes.modules.kube_bench_cache.ensure_fresh(namespace=None, label=None, cache_path=None, ttl_seconds=None, kubeconfig=None, auth_mode=None, collection_strategy=None, cronjob_name=None, job_timeout=None)[source]¶
Return cache_path after guaranteeing it exists and is no older than ttl_seconds. If the file is missing or stale, collect kube-bench results using the selected collection_strategy and write them atomically to cache_path.
Any parameter left as None falls back to the
kube_benchpillar key of the same name, then to the module-level default constant. Explicit arguments always take precedence over pillar values.Parameters¶
- namespacestr or None
Kubernetes namespace where kube-bench resources live.
- labelstr or None
Label selector for kube-bench pods (DaemonSet strategy only).
- cache_pathstr or None
Absolute path where the JSON array is stored on the minion.
- ttl_secondsint or None
Maximum cache age in seconds before re-collection is triggered.
- kubeconfigstr or None
Path to a kubeconfig file. None falls back to pillar, then to
kubernetes.*’s own credential auto-detection.- auth_modestr or None
"in_cluster"or"kubeconfig". None falls back to pillar, then tokubernetes.*’s own auto-detection (kubeconfig file/env, then in-cluster ServiceAccount).- collection_strategystr or None
"job"or"daemonset". None falls back to pillar, then"job".- cronjob_namestr or None
Name of the suspended CronJob used as the Job template (Job strategy).
- job_timeoutint or None
Seconds to wait for the Job to complete before raising (Job strategy).
Returns¶
- str
cache_path (for use in Jinja
{%- set _ = salt['...']() %}).
CLI Example:
salt '*' kube_bench_cache.ensure_fresh
- saltext.kubernetes.modules.kube_bench_cache.run_assessment(namespace=None, cache_path=None, kubeconfig=None, auth_mode=None, cronjob_name=None, job_timeout=None)[source]¶
Trigger an on-demand kube-bench assessment using the Job strategy.
Unlike
ensure_fresh, this function always runs a new Job regardless of whether a fresh cache already exists. Results are written atomically to cache_path after the Job completes.Any parameter left as None falls back to the
kube_benchpillar key of the same name, then to the module-level default constant.Parameters¶
- namespacestr or None
Kubernetes namespace where the kube-bench CronJob lives.
- cache_pathstr or None
Absolute path where the JSON array is stored on the minion.
- kubeconfigstr or None
Path to a kubeconfig file. None falls back to pillar, then to
kubernetes.*’s own credential auto-detection.- auth_modestr or None
"in_cluster"or"kubeconfig". None falls back to pillar, then tokubernetes.*’s own auto-detection.- cronjob_namestr or None
Name of the suspended CronJob used as the Job template.
- job_timeoutint or None
Seconds to wait for the Job to complete before raising.
Returns¶
- dict
{"result": True, "message": "<cache_path>"}on success, or{"result": False, "message": "<error>"}on failure.
CLI Example:
salt '*' kube_bench_cache.run_assessment
- saltext.kubernetes.modules.kube_bench_cache.status_for_check(test_number, namespace=None, label=None, cache_path=None, ttl_seconds=None, kubeconfig=None, auth_mode=None, collection_strategy=None, cronjob_name=None, job_timeout=None)[source]¶
Return an aggregated status/comment for test_number across every node present in the merged kube-bench cache.
Added in version 2.2.0.
kube-bench runs the full CIS check set on every node regardless of its actual role (master/worker), so the cache can hold multiple results for the same test_number – one per node. Control SLS files that instead hand-parse the cache and stop at the first matching result silently ignore every other node – this is the correct replacement for that pattern, not just a convenience wrapper.
Aggregation policy is worst-status-wins:
FAILif any node FAILs,WARNif none FAIL but any node WARNs/INFOs,PASSonly if every node PASSes,ERRORif no node reports this check at all.Parameters mirror
ensure_fresh()(which this calls internally to guarantee freshness) with one addition:- test_numberstr
The kube-bench control ID to look up, e.g.
"1.1.11".
Returns¶
- dict
{"status": "PASS"|"WARN"|"FAIL"|"ERROR", "comment": str}. comment lists one line per node (via thenode_nametag each cached result carries) – the only place that detail can surface to a caller like RaaS, whose compliance-finding model has no per-node field of its own, only a single free-text comment per minion per check. Each line is"<node>: <status> [expected=<...>] actual=<...>";expectedis omitted when kube-bench doesn’t populateexpected_resultfor that check, andactualfalls back to kube-bench’sreason(the real audit-command error, e.g. “no such file or directory”) whenactual_valueitself is blank, which is common on FAILs where the audit command errored out rather than producing comparable output.
CLI Example:
salt '*' kube_bench_cache.status_for_check test_number=1.1.11