diff --git a/docs/cis-policy-mapping.md b/docs/cis-policy-mapping.md index c01c8f9..b399082 100644 --- a/docs/cis-policy-mapping.md +++ b/docs/cis-policy-mapping.md @@ -12,8 +12,8 @@ and avoids applying workload admission rules to platform namespaces. | 5.2.7 | `require-non-root` | A Pod without explicit non-root execution is rejected. | Does not prove the image cannot switch users internally. | | 5.5.1 | `restrict-image-registries` | Images outside the approved registry set are rejected. | Full provenance needs signing, verification, and trusted build controls. | | 5.7.3 supplemental | `require-resource-limits` | Pods must declare CPU and memory limits. | Resource limits are a defense-in-depth control, not a direct CIS test. | +| Supplemental | `disallow-default-namespace` | Common application resources in `default` are rejected. | Namespace hygiene is defense in depth, not a one-to-one CIS test. | The Kubernetes CIS Benchmark is broader than admission policy. kube-bench covers node, control-plane, RBAC, audit, network policy, and manual review areas that these Kyverno policies do not implement. - diff --git a/policies/README.md b/policies/README.md index b0ffe88..943169a 100644 --- a/policies/README.md +++ b/policies/README.md @@ -1,11 +1,12 @@ # Kyverno policy baseline -These policies are `ClusterPolicy` resources, but they intentionally select -only namespaces labeled `security-baseline/open: "true"`. That keeps the -portfolio demo enforceable without blocking Kyverno, Falco, ArgoCD, or other -platform components. Expand the label scope deliberately for a real cluster. +These policies are `ClusterPolicy` resources. The workload hardening policies +select only namespaces labeled `security-baseline/open: "true"`. The separate +`disallow-default-namespace` policy specifically protects the Kubernetes +`default` namespace. This keeps the portfolio demo enforceable without +blocking Kyverno, Falco, ArgoCD, or other platform components. -All five policies use `validationFailureAction: Enforce`, so a matching Pod is +All six policies use `validationFailureAction: Enforce`, so a matching resource is rejected at admission time. The policies use `background: false` because the goal is to demonstrate admission enforcement, not retroactively evaluate existing objects. @@ -16,9 +17,9 @@ existing objects. | `require-non-root` | 5.2.7 | Requires `runAsNonRoot: true` on containers and init containers. | | `require-resource-limits` | 5.7.3 supplemental | Requires CPU and memory limits. This is a supplemental control, not a one-to-one CIS test. | | `restrict-image-registries` | 5.5.1 supplemental | Allows only approved registries. Full image provenance requires signing and verification as well. | +| `disallow-default-namespace` | Supplemental | Blocks common application resources from being created in `default`, which makes namespace ownership explicit. | | `disallow-host-network` | 5.2.3 and 5.2.5 | Rejects host PID, host network, and host IPC access. | The CIS benchmark includes manual checks and platform-specific exceptions. The mapping above describes the control objective each policy supports, not a claim that one Kyverno rule implements the entire benchmark control. - diff --git a/policies/kyverno/disallow-default-namespace.yaml b/policies/kyverno/disallow-default-namespace.yaml new file mode 100644 index 0000000..dfcb8e9 --- /dev/null +++ b/policies/kyverno/disallow-default-namespace.yaml @@ -0,0 +1,41 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: disallow-default-namespace + annotations: + policies.kyverno.io/title: Disallow application workloads in default + policies.kyverno.io/category: Namespace hygiene + policies.kyverno.io/severity: medium + # Supplemental namespace-isolation control. This is not a one-to-one CIS control. + policies.kyverno.io/cis-control: "supplemental" +spec: + validationFailureAction: Enforce + background: false + failurePolicy: Fail + rules: + - name: application-resources-not-in-default + match: + any: + - resources: + kinds: + - Pod + - Deployment + - StatefulSet + - DaemonSet + - Job + - CronJob + - ReplicaSet + - ReplicationController + - Service + - Ingress + namespaceSelector: + matchLabels: + kubernetes.io/metadata.name: default + validate: + message: Application resources must be deployed into an explicitly named namespace. + deny: + conditions: + any: + - key: "{{ request.namespace }}" + operator: Equals + value: default diff --git a/policies/kyverno/kustomization.yaml b/policies/kyverno/kustomization.yaml index c98c436..76d91be 100644 --- a/policies/kyverno/kustomization.yaml +++ b/policies/kyverno/kustomization.yaml @@ -7,3 +7,4 @@ resources: - require-resource-limits.yaml - restrict-image-registries.yaml - disallow-host-network.yaml + - disallow-default-namespace.yaml