Skip to content

Instantly share code, notes, and snippets.

@tirumaraiselvan
Last active October 25, 2023 15:05
  • Star 11 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save tirumaraiselvan/b7eb1831d25dd9d59a785c11bd46c84b to your computer and use it in GitHub Desktop.
Setup admission webhooks in Kubernetes

This gist gives instructions to setup a Validating Admission Webhook or Mutating Admission Webhook in Kubernetes.

Heavy credits to

  1. https://coreos.com/os/docs/latest/generate-self-signed-certificates.html
  2. https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/04-certificate-authority.md

Install cfssl PKI

OS X

brew install cfssl

Linux

wget -q --show-progress --https-only --timestamping \
  https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \
  https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
sudo mv cfssl_linux-amd64 /usr/local/bin/cfssl
sudo mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

Create CA cert

{

cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "8760h"
    },
    "profiles": {
      "server": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "8760h"
      }
    }
  }
}
EOF

cat > ca-csr.json <<EOF
{
  "CN": "Kubernetes",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "US",
      "L": "Portland",
      "O": "Kubernetes",
      "OU": "CA",
      "ST": "Oregon"
    }
  ]
}
EOF

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

}

Results:

ca-key.pem
ca.pem

Create Server Cert

cat > server-csr.json <<EOF
{
  "CN": "admission",
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "US",
      "L": "Portland",
      "O": "Kubernetes",
      "OU": "Kubernetes",
      "ST": "Oregon"
    }
  ]
}
EOF

cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -hostname=mutationwebhook.default.svc \
  -profile=server \
  server-csr.json | cfssljson -bare server

}

NOTE: The most important value is -hostname above which should be set to {service-name}.{service-namespace}.svc of your webhook service.

Results:

server-key.pem
server.pem

Create WebhookConfiguration

Encode and trim the ca cert.

cat ca.pem | base64 - | tr -d '\n' 

Results:

LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR0akNDQXA2Z0F3SUJBZ0lVQVkzSmtWdGxtVjdEMlBHa2ZoU2NCbjZMSk9Jd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1lURUxNQWtHQTFVRUJoTUNWVk14RmpBVUJnTlZCQWdURFZOaGJpQkdjbUZ1WTJselkyOHhDekFKQmdOVgpCQWNUQWtOQk1ROHdEUVlEVlFRS0V3WklZWE4xY21FeEN6QUpCZ05WQkFzVEFrTkJNUTh3RFFZRFZRUURFd1pJCllYTjFjbUV3SGhjTk1UZ3dOakU1TVRNeU5EQXdXaGNOTWpNd05qRTRNVE15TkRBd1dqQmhNUXN3Q1FZRFZRUUcKRXdKVlV6RVdNQlFHQTFVRUNCTU5VMkZ1SUVaeVlXNWphWE5qYnpFTE1Ba0dBMVVFQnhNQ1EwRXhEekFOQmdOVgpCQW9UQmtoaGMzVnlZVEVMTUFrR0ExVUVDeE1DUTBFeER6QU5CZ05WQkFNVEJraGhjM1Z5WVRDQ0FTSXdEUVlKCktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUtybkhrdE8yS0kycjFqbE9NbVdYYkk3dkVCeEFaM0cKOUZvSUErMjdUV2xyR1JpOHFmRlJNZDV6czdMd2RGZTJTeTVFeHdFZ3BOMEJGcEdtSE1qb0c2ajV5SFZZbTRySgphemJrd0J0d3pEdURlQUcrZmVRVjlXRkR1NFQ2OXp4YkZnanpZMEVBdnFjTEgwOXpOSHVkZ3UxUk0xdmtkNE5WCnVkcHl3L3dlMFlGZTBmZlVoK0V4VWhHZDNGeGI0R1ZUUjdQckc4dnN6WlJoSTFPVEUxN2prcUdVSlNZcndDaGcKdC9rbnRHMFhrTU5nRzRHa0owb1JPN2hNUXljRjVqdWowdVA3SFFSODI3cFlGTXhWcENHRmRZcSt5UFlKblNzMAp5eVAxbkFGSWl6Q01hb2c5NHk1MDA3MnNGM1p4eEZlbHVpbnhZUU5Ydyt0d0xLWGlaZkt4WncwQ0F3RUFBYU5tCk1HUXdEZ1lEVlIwUEFRSC9CQVFEQWdFR01CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRSXdIUVlEVlIwT0JCWUUKRkZnb3BrUlNCcHpVaE13bjhMNjFKTnhIZjd6Tk1COEdBMVVkSXdRWU1CYUFGRmdvcGtSU0JwelVoTXduOEw2MQpKTnhIZjd6Tk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQUNFcWxLTnA1L1NFSmVVc2FoRWM2RDhJUDZRQkc2CkVwVFFHTmcyUHBxTmFzcmxIblM2TkNTV3VjdW9mTUlQNjZHK2RPQzVmelpjVFJKUXdBVS9VUEJkaHRFcUJKZG8KczdGZXVzcTRWUldSTms4WUxhaGFsWHdKWDdDV01aZW9xYlpZeU9pbmh2czFHOWtkY2toL1Z3OFkzeTdRNWs1MQpqeGpUMUlESkxITkZCRHpMR3VDSHd4YWJZSWxlSTRGMzNtQ2RUQ2JhanBBVSs0dklEYzNVbDI5WFoyQjVEUVVOCnMxWDh1MFBvN2xteTFRZlkyeXBsZ01HSFFXZy9HT3pQSzh3ZFBxRnppWVZOTGp3aUtCZDBxeWRQakJQM2R3dUkKWHRLOTVBS3Z0ZjRCblVycDdFS0x3ZGV1SmtHTG4zelZpWWwrRGZXYXBYbU9Wb2ZzOFN6Ymo2N0EKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=

Create the webhook configuration resource

cat > mutating.yaml <<EOF
apiVersion: admissionregistration.k8s.io/v1beta1
kind: MutatingWebhookConfiguration
metadata:
  name: mutation
webhooks:
- name: sample.mutation.io
  rules:
  - apiGroups:
    - ""
    apiVersions:
    - v1
    operations:
    - CREATE
    resources:
    - pods
  clientConfig:
    service:
      namespace: default
      name: mutationwebhook
      path: /mutate
    caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR0akNDQXA2Z0F3SUJBZ0lVQVkzSmtWdGxtVjdEMlBHa2ZoU2NCbjZMSk9Jd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1lURUxNQWtHQTFVRUJoTUNWVk14RmpBVUJnTlZCQWdURFZOaGJpQkdjbUZ1WTJselkyOHhDekFKQmdOVgpCQWNUQWtOQk1ROHdEUVlEVlFRS0V3WklZWE4xY21FeEN6QUpCZ05WQkFzVEFrTkJNUTh3RFFZRFZRUURFd1pJCllYTjFjbUV3SGhjTk1UZ3dOakU1TVRNeU5EQXdXaGNOTWpNd05qRTRNVE15TkRBd1dqQmhNUXN3Q1FZRFZRUUcKRXdKVlV6RVdNQlFHQTFVRUNCTU5VMkZ1SUVaeVlXNWphWE5qYnpFTE1Ba0dBMVVFQnhNQ1EwRXhEekFOQmdOVgpCQW9UQmtoaGMzVnlZVEVMTUFrR0ExVUVDeE1DUTBFeER6QU5CZ05WQkFNVEJraGhjM1Z5WVRDQ0FTSXdEUVlKCktvWklodmNOQVFFQkJRQURnZ0VQQURDQ0FRb0NnZ0VCQUtybkhrdE8yS0kycjFqbE9NbVdYYkk3dkVCeEFaM0cKOUZvSUErMjdUV2xyR1JpOHFmRlJNZDV6czdMd2RGZTJTeTVFeHdFZ3BOMEJGcEdtSE1qb0c2ajV5SFZZbTRySgphemJrd0J0d3pEdURlQUcrZmVRVjlXRkR1NFQ2OXp4YkZnanpZMEVBdnFjTEgwOXpOSHVkZ3UxUk0xdmtkNE5WCnVkcHl3L3dlMFlGZTBmZlVoK0V4VWhHZDNGeGI0R1ZUUjdQckc4dnN6WlJoSTFPVEUxN2prcUdVSlNZcndDaGcKdC9rbnRHMFhrTU5nRzRHa0owb1JPN2hNUXljRjVqdWowdVA3SFFSODI3cFlGTXhWcENHRmRZcSt5UFlKblNzMAp5eVAxbkFGSWl6Q01hb2c5NHk1MDA3MnNGM1p4eEZlbHVpbnhZUU5Ydyt0d0xLWGlaZkt4WncwQ0F3RUFBYU5tCk1HUXdEZ1lEVlIwUEFRSC9CQVFEQWdFR01CSUdBMVVkRXdFQi93UUlNQVlCQWY4Q0FRSXdIUVlEVlIwT0JCWUUKRkZnb3BrUlNCcHpVaE13bjhMNjFKTnhIZjd6Tk1COEdBMVVkSXdRWU1CYUFGRmdvcGtSU0JwelVoTXduOEw2MQpKTnhIZjd6Tk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQUNFcWxLTnA1L1NFSmVVc2FoRWM2RDhJUDZRQkc2CkVwVFFHTmcyUHBxTmFzcmxIblM2TkNTV3VjdW9mTUlQNjZHK2RPQzVmelpjVFJKUXdBVS9VUEJkaHRFcUJKZG8KczdGZXVzcTRWUldSTms4WUxhaGFsWHdKWDdDV01aZW9xYlpZeU9pbmh2czFHOWtkY2toL1Z3OFkzeTdRNWs1MQpqeGpUMUlESkxITkZCRHpMR3VDSHd4YWJZSWxlSTRGMzNtQ2RUQ2JhanBBVSs0dklEYzNVbDI5WFoyQjVEUVVOCnMxWDh1MFBvN2xteTFRZlkyeXBsZ01HSFFXZy9HT3pQSzh3ZFBxRnppWVZOTGp3aUtCZDBxeWRQakJQM2R3dUkKWHRLOTVBS3Z0ZjRCblVycDdFS0x3ZGV1SmtHTG4zelZpWWwrRGZXYXBYbU9Wb2ZzOFN6Ymo2N0EKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
EOF
kubectl create -f mutating.yaml

Create TLS secret for server

kubectl create secret tls mutating-certs --cert=path-to-server.pem --key=path-to-server-key.pem

Mount the server TLS secret to webhook deployment

Mount the TLS secret as volumes so it can be used in the web service to start a HTTPS server.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mutation
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mutation
  template:
    metadata:
      labels:
        app: mutation
    spec:
      containers:
      - name: mutation
        image: tirumarai/mutation:v1.0.0
        command:
        - "/mutation"
        args:
        - "--tls-cert-file=/certs/tls.crt"
        - "--tls-private-key-file=/certs/tls.key"
        ports:
        - containerPort: 443
        volumeMounts:
        - name: certs
          mountPath: /certs
          readOnly: true
      volumes:
      - name: certs
        secret:
          secretName: mutating-certs

Create webhook service

apiVersion: v1
kind: Service
metadata:
  name: mutationwebhook
  namespace: default
spec:
  selector:
    app: mutation
  ports:
  - protocol: TCP
    port: 443
    targetPort: 443

And that's it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment