Portefaix docs GitHub

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)
Kyverno (deprecated v2.0.0) YAML-native policies Enforce, Audit Kyverno controller
OPA / Gatekeeper (deprecated v2.0.0) 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