Mastering the CKS Kubernetes Exam — 5/6 — Cluster Hardening
As you prepare for the Certified Kubernetes Security Specialist (CKS) exam, it’s crucial to focus on securing your Kubernetes cluster effectively.
This is part 5 of the 6-post series, showing all the exam’s domains and competencies.
Today’s competency is Supply Chain Security, which constitutes 20% of the exam:
Table of Contents
1. Minimize Base Image Footprint
2. Secure Your Supply Chain: Whitelist Allowed Registries, Sign and Validate Images
1. Minimize Base Image Footprint
Recommended Lab:
Minimizing the footprint of your base images is one of the most effective ways to reduce the attack surface of your containers. Smaller images have fewer components and, therefore, fewer vulnerabilities.
Example: Using Minimal Base Images
Instead of using a full-featured base image like ubuntu
, consider using a minimal base image such as alpine
. Here’s a sample Dockerfile that uses an Alpine base image:
# Use a minimal base image
FROM alpine:latest
# Install only necessary packages
RUN apk add --no-cache curl
# Copy application files
COPY my-app /usr/local/bin/my-app
USER myuser
# Set the entrypoint for the container
ENTRYPOINT ["/usr/local/bin/my-app"]
Exam tips:
Remove root users whenever possible;
Reduce image size and attack surface by using alpine images;
Run the update and install commands in the same RUN instructions (e.g. apt update && apt install curl);
Layers that copy secrets are not secure, even if the next instruction is to delete them, because layers will persist the data;
2. Secure Your Supply Chain: Whitelist Allowed Registries, Sign and Validate Images
Recommended Lab:
Securing your supply chain involves controlling which registries are allowed and ensuring that the images you use are trusted. This can be achieved through image signing and validation.
OPA Gatekeeper is an open-source policy enforcement tool that integrates with Kubernetes to help manage and enforce policies on your Kubernetes cluster. One critical policy is to control which container image registries are allowed, ensuring that only trusted sources are used for container deployments.
Example Policy: Image Registry Whitelist
Here’s an example of a Gatekeeper policy that restricts the use of container images to those from specific registries. This helps in mitigating risks associated with using images from untrusted or potentially compromised sources.
To use this policy, you need to create a ConstraintTemplate
and Constraint
in OPA Gatekeeper that references this Rego policy. Here’s how you can do it:
- Create a ConstraintTemplate:
It defines the policy logic and is applied as a CRD in Kubernetes. This CRD defines the schema and logic for the constraints that will use it:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8simagewhitelist
spec:
crd:
spec:
names:
kind: K8sImageRegistry
listKind: K8sImageRegistryList
singular: k8simageregistry
plural: k8simageregistries
validation:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
match:
type: object
properties:
kinds:
type: array
items:
type: object
properties:
apiGroups:
type: array
items:
type: string
kinds:
type: array
items:
type: string
parameters:
type: object
properties:
allowedRegistries:
type: array
items:
type: string
rego: |
package k8simagewhitelist
allowed_registries = [
"trusted-registry.example.com",
"another-trusted-registry.example.com"
]
deny[msg] {
container_image := input.review.object.spec.containers[_].image
image_registry := split(container_image, "/")[0]
not allowed_registries[image_registry]
msg := sprintf("Image from registry '%s' is not allowed.", [image_registry])
}
Create the Constraint CRD
Once the ConstraintTemplate is in place, you create a Constraint that uses this template. The Constraint specifies which resources the policy applies to and any parameters for the policy.
apiVersion: templates.gatekeeper.sh/v1beta1
kind: K8sImageRegistry
metadata:
name: image-registry-whitelist
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
allowedRegistries:
- "trusted-registry.example.com"
- "another-trusted-registry.example.com"
Apply these YAML manifests to your Kubernetes cluster to enforce the registry whitelist policy. The Gatekeeper controller will then evaluate all Pod creations and updates against this policy, denying any Pods that use images from unauthorized registries.
You can read more about OPA constraint templates here:
3. Use Static Analysis of User Workloads
Static analysis of your Kubernetes resources and Dockerfiles helps to identify potential security issues before deployment.
Recommended labs:
Static Analysis of Dockerfiles
Common Issues to Look For:
- Use of Untrusted Base Images: Ensure that you use official and well-maintained base images. Avoid using
latest
tags. - Unnecessary Privileges: Check for
USER
instructions and avoid running containers as root. Use theUSER
directive to specify a non-root user. - Package Management: Ensure packages are updated to their latest versions to avoid known vulnerabilities.
- Hardcoded Secrets: Avoid hardcoding sensitive data like passwords or API keys in Dockerfiles.
Misconfigured Dockerfile Example
Issue: Running as root and not using any tag in the image:
# Dockerfile
FROM ubuntu:latest
# Install packages without updating first
RUN apt-get install -y curl
# Expose port
EXPOSE 80
# Run as root user
CMD ["curl", "http://example.com"]
Fix it with the following:
# Dockerfile
# Use the Alpine base image
FROM alpine:latest
# Install curl securely
RUN apk update && apk add --no-cache curl
# Create a non-root user
RUN adduser -D myuser
# Switch to the non-root user
USER myuser
# Expose port
EXPOSE 80
# Run as the non-root user
CMD ["curl", "http://example.com"]
Base Image:
- FROM alpine:latest: Changed the base image to Alpine Linux.
Security Context:
- USER myuser: Switches to the non-root user.
This Dockerfile is now optimized for Alpine Linux, a lightweight base image, which helps in creating smaller and more secure container images.
Static Analysis of Kubernetes Resources
Common Issues to Look For:
- Pod Security Policies: Ensure that pods are not running with excessive privileges. Look for
privileged
containers, like allowPrivilegeEscalation being true, host network usage, and root user privileges. - ConfigMaps and Secrets: Ensure that sensitive data is properly managed using Kubernetes Secrets rather than ConfigMaps.
- Sensitive Data: Ensure sensitive data is not stored in insecure volumes; use Kubernetes Secrets or ConfigMaps appropriately.
Misconfigured Deployment Example
Issues:
- Running as Root: The container runs as the root user.
- Privileged Escalation: No restrictions on privilege escalation.
- Secrets as Environment Variables: Secrets are hardcoded directly in the deployment manifest.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-registry/my-app:latest
ports:
- containerPort: 80
# Hardcoded secrets (not secure)
env:
- name: MY_SECRET
value: "supersecretvalue"
# No resource limits specified
# Running as root (default behavior)
securityContext:
allowPrivilegeEscalation: true
Fixed Example
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-container
image: my-registry/my-app:latest
ports:
- containerPort: 80
# Use environment variable from Kubernetes Secret
env:
- name: MY_SECRET
valueFrom:
secretKeyRef:
name: my-secret
key: secret-key
# Set resource requests and limits
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
# Run as non-root user and restrict privilege escalation
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
---
apiVersion: v1
kind: Secret
metadata:
name: my-secret
type: Opaque
data:
secret-key: c3VwZXJzZWNyZXQ= # base64 encoded value of "supersecretvalue"
4. Scan Images for Known Vulnerabilities
Regularly scanning container images for known vulnerabilities is crucial to maintaining security.
Example: Static Analysis Tools
Tools like trivy
can scan Dockerfiles for vulnerabilities. Here’s how you might use it to scan your Dockerfile:
# Scan Dockerfile with Trivy
trivy image --severity HIGH,CRITICAL nginx
This way you filter only by HIGH and CRITICAL vulnerabilities, which is most likely what they will ask in the exam. Then you have the following result:
Exam tips:
You may be tasked to find the less vulnerable image among the options and write to a file, or delete the pod with more vulnerabilities found, be prepared for any kind of task that involves finding the vulnerabilities and quickly scan them.
Conclusion
Good luck with your CKS exam prep!
Stay tuned for Part 6/6, which will be out soon.
If you have any questions or need a hand with anything, just let me know. Let’s tackle this certification journey together!
Follow me on: Linkedin