A configurable Kubernetes mutating admission webhook, written using Python's FastAPI.
The Docker image for this service is publicly accessible at:
TAG='20260707-1'
gcr.io/cloudkite-public/custom-mutating-webhook:20260707-1
The FastAPI service handles admission requests through the /mutate path. Upon receiving a request, it performs various checks, such as the namespace of the resource. Subsequently, it generates an admission response containing the patch to be applied to the resource. The charts directory holds the necessary Helm templates for deploying the mutating admission webhook within a Kubernetes cluster.
Run the generate-cert.sh script. The script will create a self signed SSL certificate and save the base64 encoded certificate and key to the chart/secrets.yaml file.
| VARIABLE NAME | DESCRIPTION | REQUIRED? | DEFAULT VALUE |
|---|---|---|---|
| PATCH_DICT | This is a JSON which contains key-value pairs, where the keys represent the patch path, and the values represent the patch values. The patch path acts as a field selector, indicating the resource path to the field you wish to patch, starting from the root. The specific path varies depending on the resource type. For example, the path to labels in a pod is /metadata/labels. The patch value is the new value you intend to apply using the mutating webhook. See example in ./charts/values.yaml. |
Yes | None |
| PATCH_OPERATION | The patch operation to be used. See the docs | No | "add" |
| MATCH_NAMESPACES | A comma separated string of namespaces in which resources should be patched. If not set, it defaults to all namespaces. | No | None |
| IMAGE_PULL_SECRET | The name of a kubernetes.io/dockerconfigjson secret to inject into the pod's imagePullSecrets. It is only injected when at least one container, init container, or ephemeral container uses an image from a matched registry (see MATCH_REGISTRIES). The secret is appended without clobbering existing pull secrets and is skipped if already present. The referenced secret must exist in each matched namespace. |
No | None |
| MATCH_REGISTRIES | A comma separated list of registry hosts whose images should receive the injected IMAGE_PULL_SECRET (e.g. docker.io,ghcr.io). Trailing slashes are optional. The special value * matches every image regardless of registry. When Docker Hub (docker.io, index.docker.io, or registry-1.docker.io) is in the list, images with no registry host such as nginx are also matched, since they implicitly pull from Docker Hub. Only used when IMAGE_PULL_SECRET is set. |
No | "docker.io,index.docker.io,registry-1.docker.io" |
| METRICS_PORT | The port on which Prometheus metrics are served (plaintext, separate from the TLS webhook port). Exposes counters for admission requests, patch operations, and imagePullSecret injections, plus a request-latency histogram. | No | 8080 |
Set IMAGE_PULL_SECRET to a kubernetes.io/dockerconfigjson secret holding authenticated Docker Hub credentials. Any pod pulling a Docker Hub image (e.g. nginx:1.29, bitnamilegacy/nginx:1.2.4) automatically gets the secret injected, so pulls use your authenticated (higher) rate limit instead of the anonymous one.
IMAGE_PULL_SECRET: "dockerhub-pull-secret"
# MATCH_REGISTRIES defaults to Docker Hub, so no further config is needed.
Point MATCH_REGISTRIES at any registries you want covered. Store multi-registry credentials in a single dockerconfigjson secret and inject it everywhere it's needed.
IMAGE_PULL_SECRET: "registry-creds"
MATCH_REGISTRIES: "ghcr.io,quay.io" # inject only for these registries
# or MATCH_REGISTRIES: "*" to inject for every image regardless of registry.
Use PATCH_DICT to attach a standard probe to matched pods, enforcing a health-check convention across teams without editing every manifest.
PATCH_DICT: |
{
"/spec/containers/0/livenessProbe": {
"exec": { "command": ["sh", "-c", "if timeout 4 cat /proc/1/fd/1 | grep .; then exit 0; else exit 1; fi"] },
"initialDelaySeconds": 10, "periodSeconds": 10, "timeoutSeconds": 5, "failureThreshold": 3
}
}
Add organizational metadata (cost-center labels, ownership annotations, sidecar-injection flags) to every matched resource.
PATCH_DICT: |
{
"/metadata/labels/managed-by": "platform-team",
"/metadata/annotations/example.com~1injected": "true"
}
Combine MATCH_NAMESPACES with any of the above to limit changes to a subset of namespaces (e.g. only staging and dev), leaving production untouched.
MATCH_NAMESPACES: "staging,dev"
Scrape the Prometheus metrics on METRICS_PORT to alert on admission errors, track patch volume, and monitor how often pull secrets are injected — useful for verifying rollout and catching regressions.