Lab: Disallowing the latest
Tag in Container Images Using Kyverno and CEL on Amazon EKS
Prerequisites
- Amazon EKS Cluster: Already running and
kubectl
is configured to interact with it. - kubectl: Installed and configured to connect to your EKS cluster.
- Helm: Installed on your local machine.
Part:1 Introduction to Common Expression Language (CEL)
-
What is CEL?
- CEL is a simple, readable expression language used to write conditions and validations in code and configurations. In Kubernetes, it's used to define rules for resource validation.
-
CEL Playground
- Practice writing CEL expressions using the online tool: CEL Playground.
Basic CEL Expressions
Here are four basic examples to illustrate how CEL works.
- Example 1: Arithmetic Operations
// Expression
1 + 2 * 3 - 4 / 2
// Evaluates to
5.0
- Example 2: String Operations
// Expression
"Hello, " + "World!"
// Evaluates to
"Hello, World!"
- Example 3: Logical Operations
// Expression
true && !false
// Evaluates to
true
- Example 4: Conditional Expressions
// Expression
size([1, 2, 3]) == 3 ? "Three elements" : "Not three"
// Evaluates to
"Three elements"
- Applying CEL in Kubernetes Policies
Here's how CEL is used in a Kyverno policy to disallow the use of the
latest
tag in container images.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Enforce
rules:
- name: disallow-latest-tag
match:
any:
- resources:
kinds:
- Pod
validate:
cel:
expressions:
- expression: "object.spec.containers.all(c, !c.image.matches('.*:latest$'))"
message: "Using the 'latest' tag is not allowed."
- Explanation
- object: The resource being evaluated (e.g., a Pod).
- object.spec.containers: List of containers in the Pod.
- all(c, condition): Checks that the condition is true for all containers
c
. - !c.image.matches('.*:latest$'): Ensures the image does not end with
:latest
.
Part:2 Hands on Lab
- Navigate to the EKS Directory:
cd /workspaces/ecr_eks_security_masterclass_public/eks/
- Ensure that
kubectl
can communicate with your EKS cluster.
# Verify cluster nodes
kubectl get nodes
- Install Kyverno in the
kyverno
Namespace using Helm.
# Add Kyverno Helm repository
helm repo add kyverno https://kyverno.github.io/kyverno/
# Update Helm repositories
helm repo update
# Create Kyverno Namespace
kubectl create namespace kyverno
# Install Kyverno using Helm
helm install kyverno kyverno/kyverno -n kyverno
- Check that the Kyverno pod is running.
# Check Kyverno pods
kubectl get pods -n kyverno
- Understand CEL Basics in Kyverno
Common Expression Language (CEL) allows you to write expressions for custom validations in Kyverno policies.
-
Variables:
object
: The resource being validated.namespaceObject
: The Namespace of the resource.
-
Expressions: Use CEL to define conditions that resources must meet.
-
Now, create a policy that blocks the creation of Pods using container images tagged with
latest
. -
Use the
cat << EOF > filename
method to create the policy file.
# Create the policy file
cat << EOF > disallow-latest-tag.yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
spec:
validationFailureAction: Enforce
background: false
rules:
- name: disallow-latest-tag
match:
any:
- resources:
kinds:
- Pod
validate:
cel:
expressions:
- expression: "object.spec.containers.all(c, !c.image.matches('.*:latest$'))"
message: "Using the 'latest' tag is not allowed."
EOF
- Apply the policy using
kubectl
.
# Apply the policy
kubectl apply -f disallow-latest-tag.yaml
- Now to validate, create a Pod definition file that uses the
latest
tag.
# Create the Pod definition file
cat << EOF > pod-with-latest.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod-latest
spec:
containers:
- name: nginx
image: nginx:latest
EOF
- Attempt to create the Pod.
# Apply the Pod definition
kubectl apply -f pod-with-latest.yaml
- Expected Result will be error message indicating that the Pod creation is blocked by the Kyverno policy.
Error from server: error when creating "pod-with-latest.yaml": admission webhook "validate.kyverno.svc-fail" denied the request:
resource Pod/default/test-pod-latest was blocked due to the following policies
disallow-latest-tag:
disallow-latest-tag: Using the 'latest' tag is not allowed.
- Create a Pod definition file that uses a specific version tag.
# Create the Pod definition file
cat << EOF > pod-with-version.yaml
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: nginx
image: nginx:1.19
EOF
- Apply the Pod definition.
# Apply the Pod definition
kubectl apply -f pod-with-version.yaml
- Expected Result will show that the Pod should be created successfully.
pod/test-pod created
- Verify the Pod is running:
# Get the list of Pods
kubectl get pods
Clean Up
- Delete the Pods and policy created during this lab.
# Delete the Kyverno policy
kubectl delete -f disallow-latest-tag.yaml
# Delete the Pods
kubectl delete -f pod-with-latest.yaml
kubectl delete -f pod-with-version.yaml
# (Optional) Delete the Kyverno Namespace and release
helm uninstall kyverno -n kyverno
kubectl delete namespace kyverno