Available

Check compliance and apply the rules that close it

Score a cluster against published frameworks, see which workloads fail each control, and apply the rule that closes it with Kubernetes built-in admission or with Kyverno.

Once a cluster is connected, AuthFI scores it against published compliance frameworks. Every failing control names the workloads that fail it and the rule that would close it. Each rule comes in two forms, so you can apply it with what your cluster already has:

Apply withWhat it needs
Kubernetes built-in admission (no extra install)Kubernetes 1.30 or later. Nothing else to install.
KyvernoKyverno running in the cluster

Use this guide to read the score, and to turn a failing control into a rule in your cluster.

Before you begin

You need:

  • A cluster with Zero-Code installed. See Install Zero-Code on a cluster.
  • kubectl, with permission to create the rule: a ValidatingAdmissionPolicy and a ValidatingAdmissionPolicyBinding for built-in admission, or a ClusterPolicy for Kyverno.

Open the compliance score

In the AuthFI console, open Security > Compliance.

Choose the cluster in Cluster and the framework in Compliance framework. To score the cluster again, choose Score again.

The tiles Passing, Failing and We cannot decide count the controls. The table lists each control with the columns Control, Requires, Status, Objects scanned and Would refuse.

Find the failing controls

Choose the Fail chip above the table to show only failing controls. Each control has one of five statuses, and only Pass counts as a pass.

Would refuse shows how many workloads the rule would deny, before you apply it.

Read a failing control

Select a control's row. A drawer opens with four tabs.

TabShows
What failedThe workloads that fail, by namespace and name
The rule that closes itThe rule that closes the control
Already guardedWhat already guards the control
Why this mattersWhy the control matters

A control you already guard with your own Kyverno policy gets no suggestion. See How your own Kyverno policies are counted.

Choose how you will apply it

On The rule that closes it, under Apply with, choose Kubernetes built-in admission (no extra install) or Kyverno. The rule shown below changes to that form. The same choice sits above the table, beside the button that copies every rule at once.

Copy the rule and apply it

Choose Copy for built-in admission or Copy as Kyverno. The rule is copied to the clipboard as JSON, and the console confirms how many rules were copied.

Save it to a file and apply it to the cluster yourself:

kubectl apply -f authfi-privileged-container.json

A built-in admission rule is two objects: a ValidatingAdmissionPolicy that holds the check, and a ValidatingAdmissionPolicyBinding that puts it in force. They are copied together as one List. This is the rule for the privileged containers check:

{
  "apiVersion": "v1",
  "kind": "List",
  "items": [
    {
      "apiVersion": "admissionregistration.k8s.io/v1",
      "kind": "ValidatingAdmissionPolicy",
      "metadata": { "name": "authfi-privileged-container" },
      "spec": {
        "failurePolicy": "Fail",
        "matchConstraints": {
          "resourceRules": [
            { "apiGroups": [""], "apiVersions": ["*"], "operations": ["CREATE", "UPDATE"], "resources": ["pods"] },
            {
              "apiGroups": ["apps"],
              "apiVersions": ["*"],
              "operations": ["CREATE", "UPDATE"],
              "resources": ["deployments", "statefulsets", "daemonsets"]
            },
            {
              "apiGroups": ["batch"],
              "apiVersions": ["*"],
              "operations": ["CREATE", "UPDATE"],
              "resources": ["jobs", "cronjobs"]
            }
          ]
        },
        "variables": [
          {
            "name": "spec",
            "expression": "has(object.spec.jobTemplate) ? object.spec.jobTemplate.spec.template.spec : (has(object.spec.template) ? object.spec.template.spec : object.spec)"
          },
          {
            "name": "containers",
            "expression": "variables.spec.containers + (has(variables.spec.initContainers) ? variables.spec.initContainers : []) + (has(variables.spec.ephemeralContainers) ? variables.spec.ephemeralContainers : [])"
          }
        ],
        "validations": [
          {
            "expression": "variables.containers.all(c, !has(c.securityContext) || !has(c.securityContext.privileged) || !c.securityContext.privileged)",
            "message": "EADMIT001: Containers must not be privileged",
            "reason": "Forbidden"
          }
        ]
      }
    },
    {
      "apiVersion": "admissionregistration.k8s.io/v1",
      "kind": "ValidatingAdmissionPolicyBinding",
      "metadata": { "name": "authfi-privileged-container" },
      "spec": { "policyName": "authfi-privileged-container", "validationActions": ["Warn", "Audit"] }
    }
  ]
}

The Kyverno form of the same rule is one ClusterPolicy:

{
  "apiVersion": "kyverno.io/v1",
  "kind": "ClusterPolicy",
  "metadata": { "name": "authfi-privileged-container" },
  "spec": {
    "validationFailureAction": "Audit",
    "background": true,
    "rules": [
      {
        "name": "privileged_container",
        "match": { "any": [{ "resources": { "kinds": ["Pod"] } }] },
        "validate": {
          "message": "EADMIT001: Containers must not be privileged",
          "pattern": {
            "spec": {
              "=(containers)": [{ "=(securityContext)": { "=(privileged)": false } }],
              "=(initContainers)": [{ "=(securityContext)": { "=(privileged)": false } }],
              "=(ephemeralContainers)": [{ "=(securityContext)": { "=(privileged)": false } }]
            }
          }
        }
      }
    ]
  }
}

Every rule's message starts with a stable code, such as EADMIT001, so you can search your logs for it whatever the wording.

Every exported rule only watches. A built-in admission binding is ["Warn", "Audit"]: whoever applies a failing object sees a warning, and the API server's audit log records it. A Kyverno policy is in Audit. Neither denies anything, so applying a rule cannot break a deployment.

To copy the rules for every control shown in the table at once, choose Copy the rules for built-in admission or Copy the rules as Kyverno above the table. One rule copies as one object, and several copy as one List.

Switch the rule to deny

When the warnings and reports are clean, switch the rule to deny yourself and apply it again:

  • Built-in admission: set the binding's validationActions to ["Deny"].
  • Kyverno: set validationFailureAction to Enforce.

AuthFI reads, scores and writes the rule. You apply it, and you decide what is admitted to your cluster.

Check that it works

For a built-in admission rule, list the rule, then ask the API server to admit a failing object without creating it:

kubectl get validatingadmissionpolicy authfi-privileged-container
kubectl run probe --image=busybox --privileged --dry-run=server

While the binding is ["Warn", "Audit"], the second command prints a warning carrying EADMIT001. Once the binding is ["Deny"], the same command is refused with that code.

For a Kyverno policy, open Security > Policy and choose the Admission chip. Your policy is listed beside every other rule in force, marked with whether it denies or only monitors. A policy in Audit is counted as monitoring. Once it is in Enforce, it is counted as a guard and the control is covered by you.

Frameworks

FrameworkVersion
CIS Kubernetes Benchmark1.9
SOC 2
ISO/IEC 270012022
NIST SP 800-207, Zero Trust
PCI DSS4.0
HIPAA Security Rule
OWASP Top 102021
OWASP API Security Top 102023
OWASP Top 10 for LLM Applications2025

Checks

CheckFails when
Privileged containersA container runs privileged
Privilege escalationA container may gain more privileges than its parent
Running as rootA container is not required to run as a non-root user
Host namespacesA pod shares the host's network, process or IPC namespace
Host pathsA pod mounts a path from the node
Wildcard RBACA role grants * on verbs or resources
Cluster-admin bindingsA subject is bound to cluster-admin
Service account tokensA token is mounted into a pod that does not need it
Calls across namespacesA workload was seen calling into another namespace

The last check comes from traffic the nodes observed, not from configuration. It tells you what is happening. The other checks tell you what is permitted.

Statuses

StatusValueMeaning
PasspassObjects were checked and none fails
FailfailAt least one object fails. The failing objects are listed.
Nothing of this kindno_objectsNothing in the cluster is in scope for this control
We cannot decideunanswerableThe control is about something a cluster cannot show, such as a staff policy
Cluster not reportingnot_syncedThe cluster has not reported recently enough to answer

A control that cannot be answered from the cluster is shown as We cannot decide. It is not counted as passing, so the score reflects only what was checked.

How your own Kyverno policies are counted

If the cluster runs Kyverno, AuthFI reads your ClusterPolicy and Policy objects.

Your policyCounted as
Validates the same thing, in EnforceA guard. The control is covered by you.
Validates the same thing, in AuditMonitoring. It reports and denies nothing.
Something elseListed on Security > Policy, with its mode

Your policies appear on Security > Policy beside every other rule in force. Each is marked with whether it denies or only monitors.

How current the score is

The score is computed from what the cluster last reported. The Store tile shows current or stale.

If a cluster has not reported for an hour, the page says the result is stale and shows when it was last complete.

Next steps