realshuting/kyverno-policies

★ 1Forks 0GitHub ↗Compare

README

Kyverno CEL Policies for Confidential Containers (CoCo)

This repository contains Kyverno CEL policies for managing Confidential Containers workloads on Kubernetes/OpenShift clusters.

Prerequisites

  • Kubernetes/OpenShift cluster with Kata Containers runtime configured
  • Kyverno v1.18.0+ installed in the cluster (required for CEL compression/decompression support)

Install Kyverno

kubectl create -f https://raw.githubusercontent.com/kyverno/kyverno/refs/heads/main/config/install-latest-testing.yaml

Policies

Mutating Policies

Policy File Description
Inject Kata RuntimeClass policies/mutate/add-runtimeclass-mpol/inject-kata-cc-runtime.yaml Automatically adds runtimeClassName: kata-cc to pods with label coco: enabled
Inject InitData policies/mutate/inject-initdata-mpol/inject-coco-initdata.yaml Injects CoCo initdata annotation from a ConfigMap
Inject Sidecar policies/mutate/inject-sidecar-mpol/inject-coco-mtls-sidecar.yaml Injects secure mTLS sidecar for attestation API
Inject Init Container policies/mutate/inject-init-container-mpol/inject-coco-attestation-init.yaml Injects attestation verification init container
Inject Sealed Secret Config policies/mutate/inject-sealed-secret-mpol/inject-sealed-secret-config.yaml Injects sealed secret references (secretKeyRef + volume + volumeMount) from ConfigMap settings

Validation Policies

Policy File Description
Validate InitData ConfigMap policies/validate/validate-initdata-configmap-vpol/validate-initdata-configmap.yaml Validates structure of initdata ConfigMaps

Usage

1. Runtime Class Assignment

Add the label coco: enabled to your pods to automatically assign the kata-cc runtime class:

apiVersion: v1
kind: Pod
metadata:
  name: my-coco-pod
  labels:
    coco: enabled
spec:
  containers:
    - name: app
      image: myapp:latest

2. InitData Injection

  1. Create a ConfigMap with base64-gzip encoded initdata:
# Encode your initdata TOML
echo '<your-initdata-toml>' | gzip | base64
  1. Create the ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-initdata
data:
  data: <base64-gzip-encoded-content>
  1. Reference it in your pod:
metadata:
  labels:
    coco: enabled
  annotations:
    coco.io/initdata-configmap: my-initdata

3. Sidecar Injection

  1. Create a sidecar configuration ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-sidecar-config
data:
  sidecar_image: "ghcr.io/confidential-containers/secure-sidecar:latest"
  tls_cert_uri: "kbs:///default/sidecar-tls/app/cert.pem"
  https_port: "8443"
  forward_port: "8080"
  1. Reference it in your pod:
metadata:
  annotations:
    coco.io/sidecar-config: my-sidecar-config

4. Init Container Injection

  1. Create an init container configuration ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-init-config
data:
  init_image: "ghcr.io/confidential-containers/attestation-init:latest"
  kbs_url: "https://kbs.example.com:8080"
  timeout: "60"
  1. Reference it in your pod:
metadata:
  annotations:
    coco.io/init-config: my-init-config

5. Sealed Secrets Injection

The sealed secret configuration flow:

  1. Create a sealed secret envelope JSON, for example: {"version":"0.1.0","type":"vault","name":"kbs:///default/mysecret/secret","provider":"kbs","provider_settings":{},"annotations":{}}
  2. Encode and pack it as sealed.<header>.<base64url(json)>.<signature>
  3. Store the sealed value in a regular Kubernetes Secret
  4. Create a ConfigMap defining how to inject secretKeyRef and volumeMount
  5. Pod gets injected env var, volume, and volumeMount from that ConfigMap
  6. Kata agent unwraps the sealed value inside TEE via KBS at runtime

Steps:

  1. Create the sealed secret payload Secret:
apiVersion: v1
kind: Secret
metadata:
  name: sealed-secret
type: Opaque
stringData:
  secret: "sealed.<header>.<base64url(json)>.<signature>"
  1. Create the injection ConfigMap that maps env var + volume to that Secret:
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-secret-config
data:
  env_name: PROTECTED_SECRET
  secret_name: sealed-secret
  secret_key: secret
  volume_name: sealed-secret-volume
  mount_path: /sealed/myvalue
  1. Reference the ConfigMap in your pod:
metadata:
  labels:
    coco: enabled
  annotations:
    coco.io/sealed-secret-config: my-secret-config

6. Validate InitData ConfigMap

ConfigMaps with label coco.io/type: initdata are validated to ensure they contain required fields:

apiVersion: v1
kind: ConfigMap
metadata:
  name: my-initdata
  labels:
    coco.io/type: initdata
data:
  version: "0.1.0"
  algorithm: "sha384"  # sha256, sha384, or sha512
  policy.rego: |
    package agent_policy
    default allow = true
  aa.toml: |
    [token_configs.kbs]
    url = "https://kbs.example.com:8080"
  cdh.toml: |
    [kbc]
    name = "cc_kbc"
    url = "https://kbs.example.com:8080"

Folder Structure

.
├── configmaps/           # Example ConfigMaps for testing
├── policies/
│   ├── mutate/           # Mutating policies
│   │   ├── *-mpol/       # CEL MutatingPolicy
│   │   └── *.yaml        # Legacy ClusterPolicy
│   └── validate/         # Validation policies
│       ├── *-vpol/       # CEL ValidatingPolicy
│       └── *.yaml        # Legacy ClusterPolicy
└── tests/                # Test manifests

References

Contributors

realshutingbpradipt

Issues