This is a quick example of how to use OPA as a Mutating Admission Controller in Kubernetes 1.9.
- Register OPA as a MutatingAdmissionWebhook
- Load a policy to test mutation
- Exercise the policy
The steps in Kubernetes Admission Control show how to deploy OPA as a Validating Admission Controller. To deploy OPA as a Mutating Admission Controller, follow steps 1-3. In step 3, instead of creating a ValidatingWebhookConfiguration, create a MutatingWebhookConfiguration:
kind: MutatingWebhookConfiguration
apiVersion: admissionregistration.k8s.io/v1beta1
metadata:
name: opa-mutating-webhook
webhooks:
- name: mutating-webhook.openpolicyagent.org
rules:
- operations: ["*"]
apiGroups: ["*"]
apiVersions: ["*"]
resources: ["*"]
clientConfig:
service:
namespace: opa
name: opa
caBundle: <CA-BUNDLE>
Define a policy to exercise mutation.
example.rego:
package system
main = {
"apiVersion": "admission.k8s.io/v1beta1",
"kind": "AdmissionReview",
"response": {
"allowed": true,
"patchType": "JSONPatch",
"patch": patch_bytes,
}
} {
# Only apply mutations to objects in create/update operations (not
# delete/connect operations.)
is_create_or_update
# If the resource has the "test-mutation" annotation key, the patch will be
# generated and applied to the resource.
input.request.object.metadata.annotations["test-mutation"]
# Construct JSON Patch for test purposes. kube-apiserver expects changes to
# be represented as JSON Patch operations against the resource. The JSON
# Patch must be JSON serialized and base64 encoded.
patch = [
{"op": "add", "path": "/metadata/annotations/foo", "value": "bar"},
]
patch_json = json.marshal(patch)
patch_bytes = base64url.encode(patch_json)
}
is_create_or_update { is_create }
is_create_or_update { is_update }
is_create { input.request.operation == "CREATE" }
is_update { input.request.operation == "UPDATE" }
This policy will mutate resources that define an annotation with the key "test-mutation"
. The resouces will be updated to include the annotation "foo": "bar"
.
Load the policy as a ConfigMap:
kubectl create configmap example --from-file example.rego
First create a Deployment:
kubectl run nginx --image nginx
Check that the Deployment was not mutated:
kubectl get deployment nginx -o json | jq '.metadata'
Annotate the Deployment to indicate that it should be mutated:
kubectl annotate deployment nginx test-mutation=true
Check that the Deployment was mutated:
kubectl get deployment nginx -o json | jq '.metadata'
Thanks for the great example, Torin.
We're currently finding OPA very useful as an admission controller for k8s.
In the above example, what would the 'main' function look like if we use OPA as both a validating and mutating admission controller?
Or would you recommend that we only use it as a mutating admission controller in that case?
Thanks.