The module lifecycle stageGeneral Availability
The module has requirements for installation

Viewing resources that failed CIS compliance checks

d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson |
  jq '.status.detailReport.results | map(select(.checks | map(.success) | all | not))'

Viewing resources that have not passed a specific CIS compliance check

By id:

check_id="5.7.3"
d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson |
  jq --arg check_id "$check_id" '.status.detailReport.results | map(select(.id == $check_id))'

By description:

check_desc="Apply Security Context to Your Pods and Containers"
d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson |
  jq --arg check_desc "$check_desc" '.status.detailReport.results | map(select(.description == $check_desc))'

Manual rescan of a resource

The module rescans resources every 24 hours according to the following algorithm:

  1. A VulnerabilityReport object is created in the namespace with each scanned resource.
  2. This object contains the annotation trivy-operator.aquasecurity.github.io/report-ttl, which specifies the report lifetime (the default is 24h).
  3. After the lifetime expires, the object is deleted, which triggers a rescan of the resource.

You can force a resource rescan in one of the following ways:

  • Overwrite the annotation trivy-operator.aquasecurity.github.io/report-ttl, specifying a short report lifetime.
  • Delete the VulnerabilityReport object from the namespace where the scanned resource is located.

Example command for overwriting the annotation trivy-operator.aquasecurity.github.io/report-ttl:

d8 k annotate VulnerabilityReport -n <namespace> <reportName> trivy-operator.aquasecurity.github.io/report-ttl=1h --overwrite

Who has access to scan results

Access to scan results (including the ability to view resources with results) is granted to users with the following access roles:

  • d8:manage:networking:viewer or higher;
  • d8:manage:permission:module:operator-trivy:view.

These roles are from the experimental DKP role model.

  • To grant access to reports within a specific namespace (VulnerabilityReport, ConfigAuditReport, etc.), use a RoleBinding with the use-role d8:use:role:viewer (or higher) in that namespace.
  • To grant access to cluster-wide reports (ClusterComplianceReport, etc.), use a ClusterRoleBinding with d8:manage:permission:module:operator-trivy:view (or the broader d8:manage:security:viewer or higher).

In the current DKP role model (resources AuthorizationRule / ClusterAuthorizationRule), the following access levels are typically used:

  • Namespace scope (AuthorizationRule in a specific namespace): User, PrivilegedUser, Editor, Admin.
  • Cluster scope (ClusterAuthorizationRule for cluster-wide reports and/or system namespaces access): ClusterEditor, ClusterAdmin, SuperAdmin.

You can also grant access directly via standard Kubernetes RBAC (Role/ClusterRole + RoleBinding/ClusterRoleBinding):

Kubernetes RBAC example to view Trivy Operator reports

Namespaced reports (in a specific namespace):

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: trivy-reports-view
  namespace: <namespace>
rules:
- apiGroups: ["aquasecurity.github.io"]
  resources:
  - vulnerabilityreports
  - configauditreports
  - exposedsecretreports
  - sbomreports
  - infraassessmentreports
  - rbacassessmentreports
  verbs: ["get", "list", "watch"]

Cluster-wide reports:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: trivy-cluster-reports-view
rules:
- apiGroups: ["aquasecurity.github.io"]
  resources:
  - clustercompliancereports
  - clustervulnerabilityreports
  - clusterconfigauditreports
  - clusterinfraassessmentreports
  - clusterrbacassessmentreports
  - clustersbomreports
  verbs: ["get", "list", "watch"]

How to limit the list of resources scanned in a namespace

The current version does not support limiting the list of scanned resources within a namespace.
The operator scans all workloads in a namespace labeled with security-scanning.deckhouse.io/enabled="".

How to view the scan report for your application

To view the scan results of your application, use the Grafana dashboard Security / Trivy Image Vulnerability Overview.
You can filter the results by the desired namespace and resource.

You can also directly view the resources that contain scan results created for each scanned object.
Details about naming structure and resource location are available in the documentation.

How do CIS checks in DKP relate to kube-bench?

What is kube-bench?

kube-bench is a standalone utility from Aqua Security that checks Kubernetes cluster compliance with CIS Benchmark requirements. It runs shell commands on nodes to analyze configuration.

If you want to run kube-bench checks in a DKP cluster yourself, use the instructions in the deckhouse module FAQ.

How does DKP implement CIS checks?

DKP uses Trivy Operator — an integrated solution that:

  • Runs as a Kubernetes operator inside the cluster
  • Automatically scans all resources
  • Stores results in Custom Resources (ClusterComplianceReport)
  • Exports metrics to Prometheus

Identifier mapping

CIS Section Description kube-bench DKP
1.x API Server [PASS/FAIL] 1.2.1 ... AVD-KCV-*
2.x etcd [PASS/FAIL] 2.1 ... AVD-KCV-*
3.x Control Plane Manual Manual
4.x Worker Nodes [PASS/FAIL] 4.2.1 ... AVD-KCV-*
5.x Policies Partial AVD-KSV-* (full coverage)

How to compare results?

Use CIS Control ID (e.g., 1.2.1, 5.2.2) — it’s the same in both tools.

Example: If kube-bench shows [FAIL] 1.2.16 Ensure that the admission control plugin..., find it in DKP:

d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson | \
  jq '.status.detailReport.results | map(select(.id == "1.2.16"))'

You can read more in the CIS checks documentation section.

Why do some CIS checks always show PASS for system components?

Some checks are disabled for system namespaces (kube-system and d8-*) because system components require elevated privileges.

You can read the full list of disabled checks in the CIS checks documentation section.

Why are checks 5.1.2 and 5.1.3 not shown in the dashboard?

Checks 5.1.2 (Minimize access to secrets) and 5.1.3 (Minimize wildcard use in Roles and ClusterRoles) are excluded from metrics and the dashboard due to a high number of false positives for system components.

The checks are still performed, and results are available in the ClusterComplianceReport resource:

d8 k get clustercompliancereports.aquasecurity.github.io cis -ojson | \
  jq '.status.detailReport.results | map(select(.id == "5.1.2" or .id == "5.1.3"))'

What CIS Benchmark version is used?

The module implements checks according to CIS Kubernetes Benchmark v1.12 specification.

Component versions (external operator-trivy module, DKP 1.75+):

Component Version
Trivy v0.69.3
Trivy Operator v0.30.1
k8s-node-collector v0.3.1

DKP 1.74 and earlier used a built-in module with Trivy v0.55.2.

How often are CIS checks performed?

CIS Benchmark checks run:

  • every 6 hours (cron: 0 */6 * * *);
  • on operator startup.

How to expand the module’s disk (PVC)

The module stores data on several PVCs in the d8-operator-trivy namespace:

  • security-storage — runtime profile data (ApplicationProfile/NetworkNeighborhood, etc.);
  • data-trivy-server-0 — the Trivy vulnerability database cache;
  • data-trivy-provider-0 — the trivy-provider cache.

The size is set in the module templates and is not configurable. If a disk runs low, a PVC can be expanded manually, provided the StorageClass in use supports volume expansion.

  1. Make sure the StorageClass allows expansion (allowVolumeExpansion: true):

    kubectl get storageclass <storageClass> -o jsonpath='{.allowVolumeExpansion}'
  2. Increase the storage request on the PVC (expansion only — a PVC cannot be shrunk):

    kubectl -n d8-operator-trivy patch pvc security-storage --type merge \
      -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'
  3. Depending on the CSI driver, the volume expands online or after the consuming pod is restarted.

For PVCs created by StatefulSets (data-trivy-server-0, data-trivy-provider-0) the procedure is the same — patch the existing PVC. The volumeClaimTemplates field is immutable, so leave the template alone; the module never shrinks an already-expanded PVC back.

security-storage is an aggregated API server (spdx.softwarecomposition.kubescape.io). Restarting it briefly makes the runtime-profile API unavailable, so only restart the pod when necessary.

Disk usage is tracked automatically: the d8-operator-trivy namespace is labeled extended-monitoring.deckhouse.io/enabled, so the extended-monitoring module emits the standard PVC space-running-out alerts (such as KubernetesPersistentVolumeClaimBytesAvailable). No extra alert configuration is needed.