Skip to content

Policy-as-Code: End-to-End Enforcement

Enforce security and operational policies across the entire SDLC: local development, CI pipelines, and runtime admission control.

Overview

Policy-as-Code ensures compliance through automated enforcement at three critical checkpoints:

graph LR
    A[Local Development] -->|Push Code| B[CI Pipeline]
    B -->|Deploy| C[Runtime Admission]

    A -->|policy-platform container| A1[Kyverno CLI]
    B -->|policy-platform container| B1[Kyverno CLI]
    C -->|Kyverno controller| C1[Admission Webhook]

    %% Ghostty Hardcore Theme
    style A fill:#a7e22e,color:#1b1d1e
    style B fill:#a7e22e,color:#1b1d1e
    style C fill:#65d9ef,color:#1b1d1e

The Core Principle: Same policies, three enforcement points. Zero gaps.


The Problem with Scattered Enforcement

Traditional approaches fail in predictable ways:

Approach Problem Result
Documentation only Nobody reads it Violations in production
CI-only checks Local testing incomplete Broken pipelines
Runtime-only admission control Issues caught too late Failed deployments

The Gap Problem

CI checks resource limits, but Kyverno policy doesn't match. Developer tests locally, CI passes, runtime rejects deployment. This gap causes production failures.

Solution: One policy source, distributed everywhere.


Architecture

Policy Sources

Policies originate from version-controlled repositories:

graph TD
    SP[security-policy repo] -->|OCI container| PP[policy-platform]
    DP[devops-policy repo] -->|OCI container| PP
    KC[Kyverno curated policies] -->|OCI container| PP

    PP -->|Container image| L[Local Dev]
    PP -->|Container image| CI[CI Pipeline]
    PP -->|Helm chart| RT[Runtime]

    %% Ghostty Hardcore Theme
    style SP fill:#f92572,color:#1b1d1e
    style DP fill:#fd971e,color:#1b1d1e
    style KC fill:#9e6ffe,color:#1b1d1e
    style PP fill:#65d9ef,color:#1b1d1e

Policy Aggregation

The policy-platform container aggregates policies from multiple sources:

Dockerfile (multi-stage build):

FROM security-policy-repo:main AS security_policy_repo
FROM devops-policy-repo:main AS devops_policy_repo

FROM alpine:3.22
RUN apk add helm kyverno pluto spectral

COPY --from=security_policy_repo /repos/security-policy/ /repos/security-policy/
COPY --from=devops_policy_repo /repos/devops-policy/ /repos/devops-policy/

Result: Single container with all policies, ready to run anywhere.


Three-Layer Enforcement

Layer 1: Local Development

Developer runs policy checks before commit:

docker run policy-platform:latest \
  kyverno apply /repos/security-policy/policies.yaml \
  --resource my-deployment.yaml

Benefits:

  • Instant feedback
  • No CI wait time
  • Same validation as CI

Layer 2: CI Pipeline

Automated validation in every pull request:

steps:
  - name: Validate Security Policy
    image: policy-platform:latest
    script:
      - kyverno apply security-policy.yaml --resource app.yaml
      - kyverno apply devops-policy.yaml --resource app.yaml

Benefits:

  • Blocks non-compliant merges
  • Generates policy reports
  • Environment-specific validation

Layer 3: Runtime Admission

Kyverno admission controller in Kubernetes:

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-resource-limits
spec:
  validationFailureAction: Enforce

Benefits:

  • Final safety net
  • Prevents misconfigured deployments
  • Continuous compliance monitoring

Enforcement Guarantees

Stage Enforcement Bypassable? Purpose
Local Developer-initiated Yes (developer choice) Fast feedback, early detection
CI Automated on PR No (blocks merge) Gate for code review
Runtime Admission webhook No (rejects pod) Production safety

Key Insight: Local and CI use same container, runtime uses same policies.


What You'll Learn

This section covers complete policy-as-code implementation:

  1. Local Development - Running policies in containers locally
  2. CI Integration - Automated validation in pipelines
  3. Runtime Deployment - Kyverno admission control
  4. Multi-Source Policies - Aggregating policy repositories
  5. Policy Packaging - Building the policy-platform container
  6. Operations - Day-to-day policy management

Prerequisites

  • Kubernetes cluster (for runtime deployment)
  • Container runtime (Docker/Podman for local dev)
  • CI platform (GitHub Actions, Bitbucket Pipelines, GitLab CI)
  • Basic Kyverno knowledge (see Kyverno guide)

Quick Start

Start Local, Scale Up

Test policies locally first. Fix violations in seconds, not hours. Only after local validation works should you move to CI integration and runtime deployment.

Step 1: Run policies locally

docker run policy-platform:latest \
  kyverno apply /repos/security-policy/ \
  --resource deployment.yaml

Step 2: Add to CI pipeline

- name: Policy Check
  image: policy-platform:latest
  script:
    - kyverno apply /repos/security-policy/ --resource app.yaml

Step 3: Deploy Kyverno to cluster

helm install kyverno kyverno/kyverno -f kyverno-values.yaml
helm install policy-reporter policy-reporter/policy-reporter

Real-World Impact

Before Policy-as-Code:

  • Pods deployed without resource limits → OOMKilled nodes
  • Secrets in ConfigMaps → Security incidents
  • Deprecated APIs → Failed upgrades

After Policy-as-Code:

  • 100% of deployments have resource limits
  • Zero secrets in clear text
  • Deprecated API usage blocked before merge

Key Metric: Issues caught in local dev (5 min fix) vs production (incident response).


Architecture Principles

1. Single Source of Truth

Policies live in Git repositories. Everything derives from there.

2. Container-Based Distribution

One container runs everywhere. No "works on my machine."

3. Progressive Enforcement

Local (warn) → CI (fail) → Runtime (block).

4. Separation of Concerns

  • Policy repos: Define rules
  • Policy-platform: Package and distribute
  • Kyverno: Enforce at runtime


Next Steps

Start with Local Development to run policies on your machine, then progress to CI and runtime deployment.

Comments