Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ track_codespace_created
--kubens-version v0.11.0 \
--k9s-version v0.50.18 \
--helm-version v4.1.4
"$REPO_ROOT/lib/kyverno/init.sh" --version 3.7.1 --cli-version v1.17.1
"$REPO_ROOT/lib/kyverno/init.sh" --version 3.8.1 --cli-version v1.18.1
2 changes: 1 addition & 1 deletion adventures/planned/00-lex-imperfecta/beginner/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ help:
@echo " make verify Run the verification script"

apply:
@kubectl delete pod compliant missing-labels privileged privileged-init-container --ignore-not-found > /dev/null 2>&1; true
@kubectl delete pod compliant missing-labels privileged privileged-init-container peregrinus --ignore-not-found > /dev/null 2>&1; true
@echo "Applied Policies:"; \
for f in manifests/policies/*.yaml; do \
name=$$(grep '^ name:' "$$f" | awk '{print $$2}'); \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
name: peregrinus
labels:
republic.rome/gens: forum-romanum
republic.rome/traveler: peregrinus
spec:
restartPolicy: Never
containers:
- name: app
image: busybox:stable
command: ["sleep", "infinity"]
securityContext:
privileged: false
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
name: no-privileged-containers
annotations:
Expand All @@ -12,23 +12,19 @@ metadata:
grants access to all Linux kernel capabilities and host resources, bypassing
namespace isolation.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: privileged-containers
match:
any:
- resources:
kinds:
- Pod
validate:
message: "The Senate forbids unchecked power: privileged containers seize full control of the host and are not permitted in the Republic."
# Privileged containers are forbidden — this applies to regular, ephemeral and init containers.
pattern:
spec:
"=(ephemeralContainers)":
- "=(securityContext)":
"=(privileged)": "false"
"=(initContainers)":
- "=(securityContext)":
"=(privileged)": "false"
validationActions:
- Deny
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
validations:
# Privileged containers are forbidden — this applies to regular, ephemeral and init containers.
- expression: |-
(
object.spec.?initContainers.orValue([]) +
object.spec.?ephemeralContainers.orValue([])
).all(c, !c.?securityContext.?privileged.orValue(false))
message: "The Senate forbids unchecked power: privileged containers seize full control of the host and are not permitted in the Republic."
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
apiVersion: kyverno.io/v1
kind: ClusterPolicy
apiVersion: policies.kyverno.io/v1
kind: ValidatingPolicy
metadata:
name: require-labels
annotations:
Expand All @@ -11,18 +11,14 @@ metadata:
Every citizen must declare their gens. Pods without the 'republic.rome/gens' label
are unregistered and cannot be admitted to the Republic's cluster.
spec:
validationFailureAction: Audit
background: true
rules:
- name: check-for-labels
match:
any:
- resources:
kinds:
- Pod
validate:
message: All workloads must declare their gens. Unregistered citizens are not permitted in the Republic.
pattern:
metadata:
labels:
republic.rome/gens: "?*"
validationActions:
- Audit
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["pods"]
validations:
- expression: "has(object.metadata.labels) && 'republic.rome/gens' in object.metadata.labels"
message: "All workloads must declare their gens. Unregistered citizens are not permitted in the Republic."
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
apiVersion: policies.kyverno.io/v1
kind: MutatingPolicy
metadata:
name: stamp-travel-permit
annotations:
policies.kyverno.io/title: Stamp Travel Permit
policies.kyverno.io/category: Admission Control
policies.kyverno.io/severity: low
policies.kyverno.io/subject: Pod, Label
policies.kyverno.io/description: >-
Peregrini — foreign travelers — must carry a travel permit to move freely through the Republic.
Any workload declaring itself as a peregrinus is automatically issued a travel permit upon arrival.
spec:
matchConstraints:
resourceRules:
- apiGroups: [""]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["pods"]
matchConditions:
- name: is-peregrinus
expression: >-
has(object.metadata.labels) &&
'republic.rome/traveler' in object.metadata.labels &&
object.metadata.labels['republic.rome/traveler'] == 'peregrinus'
mutations:
- patchType: ApplyConfiguration
applyConfiguration:
expression: |
Object{
metadata: Object.metadata{
}
}
53 changes: 51 additions & 2 deletions adventures/planned/00-lex-imperfecta/beginner/verify.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ OBJECTIVE="By the end of this level, you should have:

- All workloads missing the 'republic.rome/gens' label blocked at admission with a clear policy violation message
- All workloads running as privileged containers blocked at admission with a clear policy violation message
- All pods declaring 'republic.rome/traveler: peregrinus' automatically receiving the 'republic.rome/travel-permit: granted' label
- Confirmed that all other workloads deploy and run successfully in the cluster"

DOCS_URL="https://dynatrace-oss.github.io/open-ecosystem-challenges/00-lex-imperfecta/beginner"
Expand Down Expand Up @@ -139,10 +140,58 @@ EOF


# =============================================================================
# Objective 3: Compliant workloads deploy and run successfully
# Objective 3: Peregrini receive a travel permit via mutation
# =============================================================================
print_new_line
print_sub_header "3. Checking that compliant workloads are admitted..."
print_sub_header "3. Checking that peregrini receive a travel permit..."

check_label_exists \
"Peregrinus pod" \
"republic.rome/travel-permit" \
"granted" \
"Check the 'stamp-travel-permit' policy — what does the mutation expression add?" <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: verify-peregrinus
labels:
republic.rome/gens: forum-romanum
republic.rome/traveler: peregrinus
spec:
containers:
- name: app
image: busybox:stable
command: ["sleep", "1"]
securityContext:
privileged: false
EOF

check_label_not_exists \
"Non-peregrinus pod" \
"republic.rome/travel-permit" \
"Check the 'stamp-travel-permit' policy — does the matchCondition target only peregrini?" <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: verify-citizen
labels:
republic.rome/gens: forum-romanum
spec:
containers:
- name: app
image: busybox:stable
command: ["sleep", "1"]
securityContext:
privileged: false
EOF



# =============================================================================
# Objective 4: Compliant workloads deploy and run successfully
# =============================================================================
print_new_line
print_sub_header "4. Checking that compliant workloads are admitted..."

check_admission_allowed \
"Fully compliant pod (label + non-privileged)" \
Expand Down
32 changes: 19 additions & 13 deletions adventures/planned/00-lex-imperfecta/docs/beginner.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

The Republic's legal scholars have been busy — perhaps too busy. In their haste to codify the Twelve Tables, the foundation of the Republic's legal system, they introduced errors that now threaten the city's order. Workloads that should be blocked are running freely, and workloads that should be allowed are being turned away at the gates.

Another scholar left a note: "I tried to set up policies for privileged containers and required labels, but something's off — I can't figure out why the wrong things are getting through."
Another scholar left a note: "I tried to set up policies for privileged containers and required labels, but something's off — I can't figure out why the wrong things are getting through. There was also supposed to be a system for automatically issuing travel permits to foreign visitors, but that one is broken too."

Your mission: investigate the Kyverno policies and restore proper admission control before chaos reaches the city.

## 🏗️ Architecture

The defining principle of the Twelve Tables was that Roman law was enforced **at the gates** — before a citizen could act, not after the damage was done. Kubernetes admission control works exactly the same way: Kyverno intercepts every request to create or update a workload and checks it against your policies *before* it reaches the cluster. A misconfigured policy doesn't just fail to enforce — it fails silently, letting non-compliant workloads slip through unnoticed while you assume everything is fine.

That's the situation you've inherited. Your Codespace comes with a Kubernetes cluster and Kyverno pre-installed. Two `ClusterPolicy` resources are already deployed — but both are misconfigured. The policies live in `manifests/policies/`. You will edit them directly and re-apply with `kubectl`.
That's the situation you've inherited. Your Codespace comes with a Kubernetes cluster and Kyverno pre-installed. Three policies are already deployed — two `ValidatingPolicy` resources that validate workloads, and one `MutatingPolicy` that automatically stamps incoming pods with the right labels. All three are misconfigured. The policies live in `manifests/policies/`. You will edit them directly and re-apply with `kubectl`.

The pods in `manifests/pods/` are there for reference only — **you don't need to edit them**.

Expand All @@ -24,14 +24,15 @@ By the end of this level, you should have:

- All workloads **missing the `republic.rome/gens` label** blocked at admission with a clear policy violation message
- All workloads **running as privileged containers** blocked at admission with a clear policy violation message
- All pods declaring **`republic.rome/traveler: peregrinus`** automatically receiving the **`republic.rome/travel-permit: granted`** label
- Confirmed that **all other workloads** deploy and run successfully in the cluster

## 🧠 What You'll Learn

- How Kyverno [`ClusterPolicies`](https://kyverno.io/docs/writing-policies/) and [`validate`](https://kyverno.io/docs/writing-policies/validate/) rules work
- The difference between [`Audit` and `Enforce`](https://kyverno.io/docs/writing-policies/policy-settings/#validation-failure-action) enforcement modes
- How to write and interpret Kyverno [`deny` conditions](https://kyverno.io/docs/writing-policies/validate/#deny-rules)
- How Kyverno [`ValidatingPolicy`](https://kyverno.io/docs/policy-types/validating-policy/) resources and [CEL validation expressions](https://kubernetes.io/docs/reference/using-api/cel/) work
- The difference between [`Audit`, `Deny`, and `Warn`](https://kyverno.io/docs/policy-types/validating-policy/) validation actions
- How to use [custom label keys](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/) to enforce workload identity standards
- How Kyverno [`MutatingPolicy`](https://kyverno.io/docs/policy-types/mutating-policy/) resources automatically patch incoming workloads at admission

## 🧰 Toolbox

Expand Down Expand Up @@ -85,9 +86,12 @@ kubectl describe pod <pod-name>
Check the policies that are in place:

```bash
kubectl get clusterpolicies
kubectl get clusterpolicy require-labels -o yaml
kubectl get clusterpolicy no-privileged-containers -o yaml
kubectl get validatingpolicies
kubectl get validatingpolicy require-labels -o yaml
kubectl get validatingpolicy no-privileged-containers -o yaml

kubectl get mutatingpolicies
kubectl get mutatingpolicy stamp-travel-permit -o yaml
```

You can also launch **k9s** for a terminal UI view of all cluster resources:
Expand All @@ -96,13 +100,13 @@ You can also launch **k9s** for a terminal UI view of all cluster resources:
k9s
```

Navigate to `ClusterPolicy` resources with `:clusterpolicies` to inspect both policies.
Navigate to `ValidatingPolicy` resources with `:validatingpolicies` and `MutatingPolicy` resources with `:mutatingpolicies` to inspect all three policies.

### 3. Fix the Policies

Review the [🎯 Objective](#objective) and investigate what's wrong in `manifests/policies/`.

Both broken policies are in `manifests/policies/`. Read them carefully — each has a different kind of misconfiguration.
All three broken policies are in `manifests/policies/`. Read them carefully — each has a different kind of misconfiguration.

#### Test Locally with the Kyverno CLI

Expand All @@ -111,6 +115,7 @@ Before applying to the cluster, you can use the `kyverno` CLI to test your polic
```bash
kyverno apply manifests/policies/require-labels.yaml --resource manifests/pods/missing-labels.yaml
kyverno apply manifests/policies/no-privileged-containers.yaml --resource manifests/pods/privileged.yaml
kyverno apply manifests/policies/stamp-travel-permit.yaml --resource manifests/pods/peregrinus.yaml
```

This gives you fast feedback without touching the cluster.
Expand All @@ -127,9 +132,10 @@ This re-applies the policies and re-deploys all workloads so you immediately see

#### Helpful Documentation

- [Kyverno Policy Validation](https://kyverno.io/docs/writing-policies/validate/)
- [Kyverno Enforcement Modes](https://kyverno.io/docs/writing-policies/policy-settings/#validation-failure-action)
- [Kyverno Deny Rules](https://kyverno.io/docs/writing-policies/validate/#deny-rules)
- [Kyverno ValidatingPolicy](https://kyverno.io/docs/policy-types/validating-policy/)
- [Kyverno MutatingPolicy](https://kyverno.io/docs/policy-types/mutating-policy/)
- [CEL Validation Expressions](https://kubernetes.io/docs/reference/using-api/cel/)
- [Kyverno Playground](https://playground.kyverno.io/#/) — test your CEL expressions interactively against sample resources before applying them to the cluster

### 4. Verify Your Solution

Expand Down
16 changes: 8 additions & 8 deletions ideas/.implemented/lex-imperfecta.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ chaos takes hold.
- Manage and organize policies at scale across teams and environments
- Respond to runtime threats that bypass static policies

**Technologies:** Kyverno, Falco, Policy Reporter, Argo CD, Kubernetes
**Technologies:** Kyverno, Falco, Policy Reporter, OpenReports, Argo CD, Kubernetes

---

Expand All @@ -35,7 +35,7 @@ Your mission: investigate the Kyverno policies and restore proper admission cont

#### The Problem

Several Kyverno `ClusterPolicy` resources are misconfigured. They are intended to block non-compliant workloads and allow compliant ones through — but they are failing to do so correctly. Some policies are not enforcing when they should, others are rejecting workloads they should allow.
Several Kyverno `ValidatingPolicy` resources are misconfigured. They are intended to block non-compliant workloads and allow compliant ones through — but they are failing to do so correctly. Some policies are not enforcing when they should, others are rejecting workloads they should allow.

#### Objective

Expand All @@ -47,8 +47,8 @@ By the end of this level, the learner should:

#### What You'll Learn

- How Kyverno `ClusterPolicies` and `validate` rules work
- The difference between `Audit` and `Enforce` enforcement modes
- How Kyverno `ValidatingPolicy` resources and CEL validation expressions work
- The difference between `Audit`, `Deny`, and `Warn` validation actions
- How to read and interpret Kyverno policy violations

#### Tools & Infrastructure
Expand All @@ -62,7 +62,7 @@ By the end of this level, the learner should:

#### Description

Fix a misconfigured Kyverno policy setup and use Policy Reporter to restore proper governance across teams and namespaces.
Fix a misconfigured Kyverno policy setup and use Policy Reporter and the OpenReports format to restore proper governance across teams and namespaces.

#### Story

Expand All @@ -74,7 +74,7 @@ Your mission: investigate the policy estate, fix the scoping issues, and ensure

#### The Problem

Several Kyverno `ClusterPolicy` and `Policy` resources are misconfigured. They are intended to enforce specific rules across different teams and namespaces — but they are failing to do so correctly. Policies are applying to the wrong provinces, some namespaces are left ungoverned, and exceptions that were meant to be narrow are broader than intended.
Several Kyverno `ValidatingPolicy` and `NamespacedValidatingPolicy` resources are misconfigured. They are intended to enforce specific rules across different teams and namespaces — but they are failing to do so correctly. Policies are applying to the wrong provinces, some namespaces are left ungoverned, and exceptions that were meant to be narrow are broader than intended.

#### Objective

Expand All @@ -87,9 +87,9 @@ By the end of this level, the learner should:

#### What You'll Learn

- How to scope Kyverno policies to specific namespaces and teams
- How to scope policies using `ValidatingPolicy` (cluster-wide) and `NamespacedValidatingPolicy` (per-namespace)
- How to write and manage policy exceptions correctly
- How to use Policy Reporter to audit and debug the policy estate
- How to use Policy Reporter and the OpenReports format to audit and debug the policy estate

#### Tools & Infrastructure

Expand Down
Loading