Skip to content

Commit dc749e6

Browse files
authored
Merge pull request #67 from vicentefb/KyvernoExampleSABindingPrevention
feat: Added example of SA binding protection using Kyverno ClusterPolicy
2 parents 81193c7 + 1481090 commit dc749e6

File tree

2 files changed

+202
-0
lines changed

2 files changed

+202
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# User Guide: Protecting Sandboxes with Kyverno
2+
3+
## 1. Overview
4+
5+
This guide provides step-by-step instructions for configuring a Kyverno security policy on a Kubernetes cluster. The goal of this policy is to **prevent any user or process from granting new permissions to a ServiceAccount that is actively being used by a custom `Sandbox` resource.**
6+
7+
This acts as a critical security boundary, preventing accidental or malicious privilege escalation for sandboxed environments.
8+
9+
**How it Works:**
10+
The policy intercepts all `RoleBinding` and `ClusterRoleBinding` creation requests. If the request targets a `ServiceAccount` that is referenced by a running `Sandbox`, Kyverno will **block the request and return an error**.
11+
12+
---
13+
14+
## 2. Prerequisites
15+
16+
Before you begin, ensure you have the following:
17+
18+
- `kubectl` access to a Kubernetes cluster with permissions to install Helm charts and create `ClusterPolicy` resources.
19+
- Helm v3+ installed on your local machine.
20+
- The **Sandbox controller** must already be installed. This is crucial as it provides the `Sandbox` Custom Resource Definition (CRD) that the policy needs to recognize.
21+
22+
---
23+
24+
## 3. Configuration Steps
25+
26+
### Step 1: Install Kyverno
27+
28+
If you do not already have Kyverno installed, use the following Helm commands to deploy it to your cluster.
29+
30+
```bash
31+
# 1. Add the official Kyverno Helm repository
32+
helm repo add kyverno https://kyverno.github.io/kyverno/
33+
34+
# 2. Update your local Helm repositories
35+
helm repo update
36+
37+
# 3. Install Kyverno into its own namespace
38+
helm install kyverno kyverno/kyverno -n kyverno --create-namespace
39+
```
40+
41+
You can verify the installation by checking the pods and CRDs in the kyverno namespace:
42+
43+
```bash
44+
kubectl get pods -n kyverno
45+
```
46+
47+
All pods should be in the `Running` state.
48+
49+
### Step 2: Verify Custom Resource Definitions (CRDs)
50+
51+
Ensure that the Kyverno CRDs are present in your cluster:
52+
53+
```bash
54+
kubectl get crds | grep kyverno
55+
```
56+
57+
If either CRD is not found, stop and resolve that issue before proceeding.
58+
59+
### Step 3: Create and Apply the Kyverno Policy
60+
61+
Apply the policy:
62+
63+
```bash
64+
kubectl apply -f prevent-sandbox-binding-policy.yaml
65+
```
66+
67+
## Understanding the Policy Fields
68+
69+
* `spec.validationFailureAction`: Enforce
70+
Tells Kyverno to actively block any API request that violates the rule.
71+
72+
* `rules[].match`: Triggers on creation or update of any RoleBinding or ClusterRoleBinding.
73+
74+
* `rules[].validate.foreach`: Iterates over request.object.subjects, filtering for ServiceAccount types.
75+
76+
* `context.apiCall`: Calls the K8s API to check for Sandbox resources referencing the given ServiceAccount.
77+
78+
* `pattern`: The request is allowed only if the number of matching sandboxes is 0. If it’s 1 or more, the request is blocked.
79+
80+
81+
### Step 4: Verify the Policy is Active
82+
83+
Check that the policy was successfully created and is ready:
84+
85+
```bash
86+
kubectl get clusterpolicy prevent-sandbox-sa-binding
87+
88+
NAME ADMISSION BACKGROUND READY AGE MESSAGE
89+
prevent-sandbox-sa-binding true true True 36s Ready
90+
```
91+
92+
Ensure `READY` is `True`.
93+
94+
## 4. Testing and Verification
95+
96+
To confirm the policy is working, simulate an attempt to grant new permissions to a protected `ServiceAccount`.
97+
98+
### A. Set Up the Test Scenario
99+
100+
Apply the `ServiceAccount` and `Sandbox` resources to the cluster.
101+
102+
```bash
103+
kubectl apply -f - <<EOF
104+
apiVersion: v1
105+
kind: ServiceAccount
106+
metadata:
107+
name: sandbox-sa
108+
namespace: sandbox-ns
109+
---
110+
apiVersion: agents.x-k8s.io/v1alpha1
111+
kind: Sandbox
112+
metadata:
113+
name: sandbox-example
114+
namespace: sandbox-ns
115+
spec:
116+
podTemplate:
117+
metadata:
118+
labels:
119+
sandbox: my-sandbox
120+
annotations:
121+
test: "yes"
122+
spec:
123+
serviceAccountName: sandbox-sa
124+
containers:
125+
- name: my-container
126+
image: busybox
127+
command: ["/bin/sh", "-c", "sleep 3600"]
128+
EOF
129+
```
130+
131+
132+
### B. Trigger the Policy (Expected Failure)
133+
134+
Apply a `RoleBinding` that should fail
135+
136+
```bash
137+
kubectl apply -f - <<EOF
138+
apiVersion: rbac.authorization.k8s.io/v1
139+
kind: RoleBinding
140+
metadata:
141+
name: test-forbidden-binding
142+
namespace: sandbox-ns
143+
roleRef:
144+
apiGroup: rbac.authorization.k8s.io
145+
kind: Role
146+
name: view
147+
subjects:
148+
- kind: ServiceAccount
149+
name: sandbox-sa
150+
namespace: sandbox-ns
151+
EOF
152+
```
153+
154+
### C. Check the Expected Outcome
155+
You should see an error like:
156+
```bash
157+
Error from server: error when creating "role-binding-fail.yaml": admission webhook "validate.kyverno.svc-fail" denied the request:
158+
159+
resource RoleBinding/default/test-forbidden-binding was blocked due to the following policies
160+
161+
prevent-sandbox-sa-binding:
162+
block-sandbox-sa-bindings: 'validation failure: validation error: Binding to a ServiceAccount
163+
that is actively in use by a Sandbox is forbidden...'
164+
```
165+
166+
If you see this error, your security policy is successfully configured and enforced. ✅
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
apiVersion: kyverno.io/v1
2+
kind: ClusterPolicy
3+
metadata:
4+
name: prevent-sandbox-sa-binding
5+
annotations:
6+
policies.kyverno.io/title: Disallow RoleBindings to Sandbox SAs
7+
policies.kyverno.io/description: >-
8+
This policy prevents creating or updating RoleBindings
9+
and ClusterRoleBindings that grant new permissions to any
10+
ServiceAccount actively referenced by an Sandbox resource.
11+
spec:
12+
validationFailureAction: Enforce
13+
rules:
14+
- name: block-sandbox-sa-bindings
15+
match:
16+
any:
17+
- resources:
18+
kinds:
19+
- RoleBinding
20+
- ClusterRoleBinding
21+
validate:
22+
message: "Binding to a ServiceAccount that is actively in use by an Sandbox is forbidden."
23+
foreach:
24+
- list: "request.object.subjects"
25+
preconditions:
26+
all:
27+
- key: "{{element.kind}}"
28+
operator: Equals
29+
value: "ServiceAccount"
30+
context:
31+
- name: matchingSandboxes
32+
apiCall:
33+
urlPath: "/apis/karo.io/v1/namespaces/{{element.namespace}}/sandboxes"
34+
jmesPath: "items[?spec.serviceAccountRef.name == '{{element.name}}'] | length(@)"
35+
pattern:
36+
matchingSandboxes: 0

0 commit comments

Comments
 (0)