Skip to content

Instantly share code, notes, and snippets.

@tsandall
Created February 21, 2018 17:26
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsandall/f328635433acc5beeb4cb9b36295ee89 to your computer and use it in GitHub Desktop.
Save tsandall/f328635433acc5beeb4cb9b36295ee89 to your computer and use it in GitHub Desktop.

MutatingAdmissionWebhook Example with OPA

This is a quick example of how to use OPA as a Mutating Admission Controller in Kubernetes 1.9.

Steps

  1. Register OPA as a MutatingAdmissionWebhook
  2. Load a policy to test mutation
  3. Exercise the policy

1. Register OPA as a MutatingAdmissionWebhook

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>

2. Load a policy to test mutation

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

3. Exercise the policy

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'
@aalmekhlafi0
Copy link

aalmekhlafi0 commented Sep 20, 2018

Thanks for the great example.
I've followed the steps but unfortunately the nginx metadata is not getting annotated with "foo:bar". Is there any missing step not mentioned in here. However, when i applied the validation webhook in this example Kubernetes Admission Control the validation works just fine.

@aalmekhlafi0
Copy link

Thanks for the great example.
I've followed the steps but unfortunately the nginx metadata is not getting annotated with "foo:bar". Is there any missing step not mentioned in here. However, when i applied the validation webhook in this example Kubernetes Admission Control the validation works just fine.

I got this working by removing the main section on the admission-controller.yaml file. this might be something very basic but i think it worth the mention if a beginner like me faced the same issue i had.

@rogeduardo
Copy link

Thanks for the great example.
I've followed the steps but unfortunately the nginx metadata is not getting annotated with "foo:bar". Is there any missing step not mentioned in here. However, when i applied the validation webhook in this example Kubernetes Admission Control the validation works just fine.

I got this working by removing the main section on the admission-controller.yaml file. this might be something very basic but i think it worth the mention if a beginner like me faced the same issue i had.

Excuse me, aalmekhlafi0, but I dont understand what remove from where. Could you put the files here?

@harshal-shah
Copy link

@rogeduardo the admission-controller.yaml is here

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