Platform Policies
Deprecated in v2.0.0: Kyverno and OPA/Gatekeeper support are deprecated and will be removed in Portefaix v2.0.0. Policies are being migrated to Kubernetes Validating Admission Policy (VAP) with CEL expressions — a built-in admission control mechanism requiring no additional webhook controller. This page documents the new VAP-based policy model.
portefaix-policies
is a library of Kubernetes admission policies implemented as
ValidatingAdmissionPolicy
resources using
CEL (Common Expression Language).
Every policy has a unique code (e.g. PORTEFAIX-C0001) that appears in admission
rejections, audit logs, and CI reports.
Policy Engine
| Engine | Language | Mode | Requirement |
|---|---|---|---|
| Kubernetes VAP | CEL expressions | Deny, Audit, Warn | Kubernetes ≥ 1.28 (GA in 1.30) |
| YAML-native policies | Enforce, Audit | Kyverno controller | |
| Rego | Enforce, Audit | Gatekeeper controller |
Policies
All policy codes are preserved across the migration from Kyverno/OPA to VAP, ensuring consistent identifiers in audit logs and tooling.
| Code | Policy | Description |
|---|---|---|
PORTEFAIX-C0001 | Require labels | All resources must have the required Portefaix labels. |
PORTEFAIX-C0002 | Require team label | Resources must carry a team ownership label. |
PORTEFAIX-C0003 | Require app label | Pods must carry an app.kubernetes.io/name label. |
PORTEFAIX-C0004 | Require version label | Deployments must specify an app.kubernetes.io/version label. |
PORTEFAIX-C0005 | Require managed-by label | Resources must declare their management tool. |
PORTEFAIX-P0001 | No privileged containers | Containers must not run in privileged mode. |
PORTEFAIX-P0002 | Read-only root filesystem | Container root filesystems must be read-only. |
PORTEFAIX-P0003 | No host network | Pods must not use the host network namespace. |
PORTEFAIX-P0004 | Resource limits required | All containers must define CPU and memory limits. |
PORTEFAIX-P0005 | No latest image tag | Container images must not use the :latest tag. |
Example: Label Validation (VAP + CEL)
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: portefaix-require-labels
annotations:
portefaix.xyz/policy-code: PORTEFAIX-C0001
portefaix.xyz/severity: medium
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["apps"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["deployments", "statefulsets", "daemonsets"]
validations:
- expression: >
object.metadata.labels != null &&
"app.kubernetes.io/name" in object.metadata.labels
message: "PORTEFAIX-C0001: Label 'app.kubernetes.io/name' is required."
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: portefaix-require-labels-binding
spec:
policyName: portefaix-require-labels
validationActions: [Deny, Audit]
matchResources: {} Example: Security Policy (VAP + CEL)
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: portefaix-no-privileged
annotations:
portefaix.xyz/policy-code: PORTEFAIX-P0001
portefaix.xyz/severity: high
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
validations:
- expression: >
object.spec.containers.all(c,
!has(c.securityContext) ||
!has(c.securityContext.privileged) ||
c.securityContext.privileged == false
)
message: "PORTEFAIX-P0001: Privileged containers are not allowed." Policy Modes
ValidatingAdmissionPolicyBinding controls validation actions per binding:
- Deny — reject non-compliant resources at admission time. Use for critical security policies.
- Audit — allow resources but emit audit events. Use during rollout or for informational policies.
- Warn — allow resources but return a warning to the caller. Useful during migration.
Gradual rollout: Use Warn mode first to surface violations
without blocking workloads. Once all existing resources comply, switch to Deny.
Kubernetes 1.30+ supports all three modes simultaneously on a single binding.
CI Integration
All policies are tested in CI using kubectl --dry-run=server against a local
KinD cluster with
pass/fail YAML fixtures:
# Validate VAP policies with kubectl dry-run
kubectl apply --dry-run=server -f policies/vap/
# Run CEL expression unit tests (requires Kubernetes 1.30+)
kubectl alpha cel-policy test --policy policies/vap/ --test-dir policies/tests/
# Integration test against a local kind cluster
make policy-test ENV=local