This gist gives instructions to setup a Validating Admission Webhook or Mutating Admission Webhook in Kubernetes.
Heavy credits to
- https://coreos.com/os/docs/latest/generate-self-signed-certificates.html
- https://github.com/kelseyhightower/kubernetes-the-hard-way/blob/master/docs/04-certificate-authority.md
brew install cfssl
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
{
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
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
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
kubectl create secret tls mutating-certs --cert=path-to-server.pem --key=path-to-server-key.pem
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
apiVersion: v1
kind: Service
metadata:
name: mutationwebhook
namespace: default
spec:
selector:
app: mutation
ports:
- protocol: TCP
port: 443
targetPort: 443
And that's it