Skip to main content

Governing the Provinces

Fix a misconfigured Kyverno policy estate and use Policy Reporter to restore proper governance across the Republic's provinces.

Mission Objective

  • Empire-wide laws enforce across every province: no privileged containers, every workload carries a valid republic.rome/gens and republic.rome/province matching its namespace, scoped by namespace label rather than hardcoded names
  • Aegyptus's scribe law applies only within Aegyptus, admitting republic.rome/role: scribe workloads exclusively
  • The legacy exception is scoped to Aegyptus's grandfathered workload and cannot be claimed by any other province
  • The Tabularium's ledger is on file: policy reports exported in OpenReports format as estate-audit.yaml

Key Learnings

Best Suited For

Platform engineers and SREs who have some familiarity with Kyverno, ideally after completing the Beginner level. You should be comfortable reading Kubernetes YAML and basic kubectl commands.

The Story

The Republic has grown. What once was a single city is now a sprawling empire of provinces, each governed by different magistrates with different needs. The legal scholars decided to catalogue every law in a central archive (the Tabularium) so that each province's statutes could be tracked and audited in one place.

But cataloguing the laws introduced new chaos. Policies meant for one province are bleeding into another. Exceptions that were meant to be narrow have been written too broadly. And somewhere in the estate, a workload is slipping through that shouldn't be.

The Tabularium's auditors have handed you a report: Policy Reporter shows violations where there should be none, and silence where there should be enforcement. Your mission: investigate the policy estate, fix the scoping issues, and restore order before the provinces descend into chaos.

Architecture

Five namespaces span the estate: four provinces (gallia, hispania, britannia, aegyptus) with republic.rome/realm: province, and castra, the infra namespace, with republic.rome/realm: infra. These labels drive policy scoping; use kubectl get ns --show-labels to inspect them.

Two empire-wide policies cover all provinces: no-privileged-containers and require-census (every workload must declare a valid republic.rome/gens and a matching republic.rome/province). Aegyptus adds aegyptus-require-scribe-role for its local scribe requirement, and a PolicyException covers its single legacy workload.

The broken policies live in manifests/policies/ and manifests/exceptions/. After each change, run make apply to redeploy the workloads, then make verify to check your progress.

Ready to start?

Launch in a preconfigured devcontainer

Open in Codespaces (opens in new tab)

Free GitHub account required

Walkthrough
  1. Open in GitHub Codespaces. The devcontainer is pre-configured and starts automatically. When you push from Codespaces, GitHub forks the repository to your account automatically.

    Prefer working locally? Clone the repo and open it in any editor that supports the Dev Containers specification (VS Code, JetBrains IDEs, and others). The devcontainer config will be detected automatically.

  2. When your Codespace is ready, the policy estate is already deployed, but something is wrong. Open Policy Reporter at port 30110 (find it in the Ports tab) to get an overview of the estate:

    • Which namespaces have violations?
    • Which policies are generating results, and which are silent when they shouldn't be?

    Then dig into the cluster:

    # Inspect the namespace topology — the labels here drive policy scoping
    kubectl get ns --show-labels
    
    # List all policies — note which are cluster-wide and which are namespaced
    kubectl get validatingpolicies
    kubectl get namespacedvalidatingpolicies -A
    
    # Inspect any policy or exception in full
    kubectl get validatingpolicy <name> -o yaml
    kubectl get policyexceptions -A -o yaml
    
    # See the raw OpenReports data behind Policy Reporter
    kubectl get policyreports -A
    

    You can also launch k9s for a terminal UI view:

    k9s
    
  3. Review the Objective and investigate what is wrong in manifests/policies/ and manifests/exceptions/.

    Think about what each policy is supposed to cover, and compare that against what it is actually matching. The namespace labels you saw with kubectl get ns --show-labels are a key part of the picture.

    Test locally with the Kyverno CLI before applying:

    kyverno apply manifests/policies/require-census.yaml --resource manifests/workloads/citizens.yaml
    kyverno apply manifests/policies/aegyptus-require-scribe-role.yaml --resource manifests/workloads/aegyptus-legacy-scribe.yaml
    

    Apply your changes to the cluster:

    make apply
    

    Policies only act at admission, so make apply redeploys the workloads to re-evaluate the estate against your changes. Then check Policy Reporter again. The picture should improve as you fix each issue.

  4. Once the estate is in order, the Senate expects the Tabularium's ledger on file. Export the cluster's policy reports, the OpenReports data behind Policy Reporter, as the audit of record.

    kubectl get policyreports -A -o yaml > estate-audit.yaml
    

Complete Your Challenge

  • When you push from Codespaces, GitHub forks the repository to your account automatically. If you are working locally, fork the repository on GitHub before pushing.
  • Verify your solution:
    ./verify.sh
    If it passes, it generates a Certificate of Completion you can paste into the discussion.
  • Share your solutions in the challenge thread (opens in new tab) on community.offon.dev.

Completed the challenge? Share your achievement on LinkedIn (opens in new tab)

Toolbox

Know someone who'd enjoy this?