open-policy-agent / gatekeeper

🐊 Gatekeeper - Policy Controller for Kubernetes
https://open-policy-agent.github.io/gatekeeper/
Apache License 2.0
3.68k stars 754 forks source link

Resource violates rule but is created #3216

Closed danie1sullivan closed 6 months ago

danie1sullivan commented 9 months ago

What steps did you take and what happened: [A clear and concise description of what the bug is.]

I have created a rule to block webhook configurations that do not have namespace selectors, unless exempt.

Constraint ``` apiVersion: constraints.gatekeeper.sh/v1beta1 kind: K8sRequireWebhookNamespaces metadata: name: require-webhook-namespaces spec: enforcementAction: deny match: scope: "*" kinds: - apiGroups: ["admissionregistration.k8s.io"] kinds: ["ValidatingWebhookConfiguration", "MutatingWebhookConfiguration"] parameters: exemptWebhooks: [] ```
Template ``` apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: k8srequirewebhooknamespaces spec: crd: spec: names: kind: K8sRequireWebhookNamespaces validation: openAPIV3Schema: type: object properties: exemptWebhooks: type: array items: string targets: - target: admission.k8s.gatekeeper.sh rego: | package k8srequirewebhooknamespaces import future.keywords.if import future.keywords.in violation[{"msg": msg}] { not is_exempt(input.review.object.metadata.name) some webhook in input.review.object.webhooks not has_selectors(webhook) msg := sprintf("Webhook missing valid namespace selector: %v", [webhook.name]) } has_selectors(wh) if { wh.namespaceSelector count(wh.namespaceSelector.matchExpressions) > 0 some match in wh.namespaceSelector.matchExpressions required := {"key", "operator", "values"} found := object.keys(match) found == required } is_exempt(name) if { exempt := input.parameters.exemptWebhooks some webhook in exempt webhook == name } ```

This test resource is still able to be created:

Test Resource ``` apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: test-webhook-admission webhooks: - admissionReviewVersions: - v1 - v1beta1 clientConfig: service: name: test-webhook-service path: /validate-tests port: 443 failurePolicy: Fail matchPolicy: Equivalent namespaceSelector: {} name: testtrigger.example.com rules: - apiGroups: - tests.example.com apiVersions: - v1 operations: - CREATE - UPDATE resources: - testtriggers scope: '*' sideEffects: None timeoutSeconds: 10 ```

What did you expect to happen:

I expected the test resource to be denied. It is denied when testing locally with gator:

Gator ``` $ gator test -f resource.yaml -f constraint.yaml -f template.yaml admissionregistration.k8s.io/v1/ValidatingWebhookConfiguration test-webhook-admission: ["require-webhook-namespaces"] Message: "Webhook missing valid namespace selector: testtrigger.example.com" ```

The resource also shows in the Constraint as a violation:

Violation ``` $ kubectl get k8srequirewebhooknamespaces -o jsonpath='{.items[0].status.violations}' | jq . [ { "enforcementAction": "deny", "group": "admissionregistration.k8s.io", "kind": "ValidatingWebhookConfiguration", "message": "Webhook missing valid namespace selector: testtrigger.example.com", "name": "test-webhook-admission", "version": "v1" } ] ```

Anything else you would like to add: [Miscellaneous information that will assist in solving the issue.]

It seems that the creation event is never evaluated by Gatekeeper. We have several other rules that are correctly being enforced, so I assume it is not a general problem with our Gatekeeper deployment.

Gatekeeper is deployed using the Helm chart and is minimally altered. The rules for the validation webhook are default:

Webhook rules ``` $ kubectl get ValidatingWebhookConfiguration gatekeeper-validating-webhook-configuration -o jsonpath='{.webhooks[?(@.name=="validation.gatekeeper.sh")].rules}' | jq . [ { "apiGroups": [ "*" ], "apiVersions": [ "*" ], "operations": [ "CREATE", "UPDATE" ], "resources": [ "*", "pods/ephemeralcontainers", "pods/exec", "pods/log", "pods/eviction", "pods/portforward", "pods/proxy", "pods/attach", "pods/binding", "deployments/scale", "replicasets/scale", "statefulsets/scale", "replicationcontrollers/scale", "services/proxy", "nodes/proxy", "services/status" ], "scope": "*" } ] ```

It's entirely possible (or likely) that this is not a bug and I've missed something, but at this point I'm out of ideas.

Environment:

maxsmythe commented 9 months ago

Kubernetes webhooks cannot evaluate ValidatingWebhookConfiguration/MutatingWebhookConfiguration objects.

ValidatingAdmissionPolicy might be able to, but there is a similar problem there (VAP objects cannot validate other VAP objects).

Violations should show up in audit.

K8s doc source: see the docstring for the rules field here: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#validatingwebhook-v1-admissionregistration-k8s-io

danie1sullivan commented 9 months ago

Thanks @maxsmythe , I had suspected that but didn't know where to look. That answers my question, but should this issue then be considered a bug for gator?

soroushatarod commented 9 months ago

Thanks @maxsmythe , I had suspected that but didn't know where to look. That answers my question, but should this issue then be considered a bug for gator?

I have a similar issue which the policy is being flagged but Gatekeeper lets the resource to be created. https://github.com/open-policy-agent/gatekeeper/issues/3228

maxsmythe commented 9 months ago

Gatekeeper the webhook cannot/should not validate these resources. Gatekeeper audit and the gator CLI command should be able to validate them.

stale[bot] commented 6 months ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.