Skip to content

Room 47

ADMISSION WEBHOOKS


The Gatekeeper’s Code

  • Before any resource is persisted to etcd, it passes through admission controllers.
  • Webhooks let you intercept and modify (mutate) or reject (validate) requests.

📜 Mission Briefing

  1. Understand the admission flow: Authentication → Authorization → Admission.
  2. Study webhook-server.yaml - a simple validating webhook.
  3. Learn about mutating vs validating admission webhooks.
  4. Deploy the webhook and test that it rejects pods without labels.
  5. The rejection message contains the password: webhook9.

Key Commands
Command Purpose
kubectl get validatingwebhookconfigurations List validating webhooks
kubectl get mutatingwebhookconfigurations List mutating webhooks
kubectl api-resources --api-group=admissionregistration.k8s.io Admission resources

How Admission Webhooks Work
# Request Flow:
# API Request → Authentication → Authorization →
# Mutating Admission → Object Schema Validation →
# Validating Admission → Persisted to etcd

# Two types of webhooks:
# 1. MutatingAdmissionWebhook  - Can modify the object (runs first)
# 2. ValidatingAdmissionWebhook - Can only approve/reject (runs second)
# ValidatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: pod-label-validator
webhooks:
  - name: validate-labels.example.com
    admissionReviewVersions: ["v1"]
    sideEffects: None
    clientConfig:
      service:
        name: webhook-server
        namespace: webhook-system
        path: /validate
      caBundle: <base64-encoded-ca>
    rules:
      - operations: ["CREATE", "UPDATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
    failurePolicy: Fail         # Reject if webhook unavailable
    matchPolicy: Equivalent
    namespaceSelector:
      matchExpressions:
        - key: skip-validation
          operator: DoesNotExist
# MutatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: sidecar-injector
webhooks:
  - name: inject-sidecar.example.com
    admissionReviewVersions: ["v1"]
    sideEffects: None
    clientConfig:
      service:
        name: sidecar-injector
        namespace: sidecar-system
        path: /inject
    rules:
      - operations: ["CREATE"]
        apiGroups: [""]
        apiVersions: ["v1"]
        resources: ["pods"]
    reinvocationPolicy: IfNeeded  # Re-run if another webhook mutates
# Common use cases for admission webhooks:
# Mutating: inject sidecars, add labels/annotations, set defaults
# Validating: enforce naming conventions, require labels, deny privileged

# TLS is required for webhook servers
# The API server sends AdmissionReview objects to the webhook
# Webhook responds with AdmissionResponse (allowed: true/false)

Hints

Hint 1

kubectl apply -f webhook-server.yaml
kubectl create namespace webhook-system

Hint 2

Create a pod without the required label and check the error message:

kubectl run test --image=nginx 2>&1 | grep password

Hint 3

The password is webhook9.


🔓 Unlock Room 48

openssl enc -aes-256-cbc -d -a -pbkdf2 \
        -in ../room_48/README -out ../room_48/README.txt -pass pass:PASSWORD
cat ../room_48/README.txt