feat(constraints): scope excludedNamespaces by process#4637
feat(constraints): scope excludedNamespaces by process#4637amarkdotdev wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR implements issue #2161 by adding a new spec.match.processes field so that a constraint's excludedNamespaces can be scoped to specific Gatekeeper enforcement points. The motivating use case is excluding a namespace from admission (webhook) while still letting audit evaluate it, preserving violation metrics/logs for exempted namespaces. It threads an EnforcementPoint through the review pipeline (webhook + audit) down to the shared match package, where a new Processes list gates whether a namespace exclusion applies for the current process.
Changes:
- Added a
Processes []stringfield to the sharedmatch.Matchtype andexcludedNamespacesAppliesToProcesslogic so exclusions can be process-scoped (default/empty preserves existing behavior). - Propagated an
EnforcementPointvalue from the webhook and audit review entry points throughtargetreview structs into aprocess.Processused by the matcher. - Added a unit test for the process-scoped exclusion at the
matchpackage level.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
pkg/mutation/match/match_types.go |
Declares the new Processes match field (source for generated CRD schema/deepcopy). |
pkg/mutation/match/match.go |
Adds Process to Matchable and process-scoping logic in excludedNamespacesMatch. |
pkg/mutation/match/match_test.go |
Unit test covering webhook-excluded vs audit-enforced behavior. |
pkg/target/process.go |
New helper mapping an enforcement point string to a process.Process. |
pkg/target/matcher.go |
Passes enforcementPoint into matchAny and sets Matchable.Process. |
pkg/target/review.go |
Adds EnforcementPoint/enforcementPoint fields to review structs (gofmt alignment issue). |
pkg/target/data.go |
Adds EnforcementPoint to AugmentedUnstructured. |
pkg/target/target.go |
Wires EnforcementPoint into gkReview for all review inputs. |
pkg/webhook/policy.go |
Sets WebhookEnforcementPoint on admission reviews and resultants. |
pkg/audit/manager.go |
Sets AuditEnforcementPoint on audit reviews. |
Note: the generated pkg/target/matchcrd_constant.go (constraint match schema) and pkg/mutation/match/zz_generated.deepcopy.go were not regenerated, so the new field is not exposed/copied — this is the primary blocker (see inline comment).
| // Processes scopes excludedNamespaces to specific Gatekeeper processes. | ||
| // Accepts `audit`, `webhook`, `sync`, `mutation-webhook`, or `*`. | ||
| // When omitted or set to `*`, excludedNamespaces applies to all processes. | ||
| Processes []string `json:"processes,omitempty"` |
There was a problem hiding this comment.
Good catch — regenerated the manifests via controller-gen so processes is now present in the match schema (pkg/target/matchcrd_constant.go and the mutation CRDs that embed Match). Without it the API server would have pruned spec.match.processes as you noted.
| // Processes scopes excludedNamespaces to specific Gatekeeper processes. | ||
| // Accepts `audit`, `webhook`, `sync`, `mutation-webhook`, or `*`. | ||
| // When omitted or set to `*`, excludedNamespaces applies to all processes. | ||
| Processes []string `json:"processes,omitempty"` |
There was a problem hiding this comment.
Added +kubebuilder:validation:Enum=audit;webhook;sync;mutation-webhook;* so invalid/typo'd process names are rejected at admission instead of silently matching nothing. Regenerated the schema accordingly.
| namespace *corev1.Namespace | ||
| source types.SourceType | ||
| isAdmission bool | ||
| enforcementPoint string |
There was a problem hiding this comment.
Fixed — ran gofmt; the gkReview field alignment is now correct.
| func processFromEnforcementPoint(enforcementPoint string) process.Process { | ||
| switch enforcementPoint { | ||
| case util.AuditEnforcementPoint: | ||
| return process.Audit | ||
| default: | ||
| return process.Webhook | ||
| } | ||
| } |
There was a problem hiding this comment.
The core process-scoped matching is covered by TestExcludedNamespacesProcessScoped in the match package. I've also added TestProcessFromEnforcementPoint in pkg/target to cover the enforcement-point-to-process mapping directly.
21454ec to
f6732aa
Compare
f6732aa to
4c7cec6
Compare
|
Rebased on latest Would appreciate a re-review when you have a moment. Thanks! |
| // Processes scopes excludedNamespaces to specific Gatekeeper processes. | ||
| // Accepts `audit`, `webhook`, `sync`, `mutation-webhook`, or `*`. | ||
| // When omitted or set to `*`, excludedNamespaces applies to all processes. | ||
| // +kubebuilder:validation:Enum=audit;webhook;sync;mutation-webhook;* | ||
| Processes []string `json:"processes,omitempty"` |
There was a problem hiding this comment.
Fixed — switched to +kubebuilder:validation:items:Enum=... (same pattern as MutationApplyTo.Operations) and regenerated the match/mutation CRD schemas plus matchcrd_constant.go. The enum now lives on array items, not the array itself.
| // Matchable represent an object to be matched along with its metadata. | ||
| // +kubebuilder:object:generate=false | ||
| type Matchable struct { | ||
| Object client.Object | ||
| Namespace *corev1.Namespace | ||
| Source types.SourceType | ||
| Process process.Process | ||
| } |
There was a problem hiding this comment.
Good catch — MatchWithApplyTo and the assignmetadata mutator now set Matchable.Process to process.Mutation so spec.match.processes scoping works on the mutation webhook path instead of silently no-oping with a zero value.
|
Pushed follow-up addressing Copilot's latest review: item-level enum for |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4637 +/- ##
==========================================
- Coverage 54.49% 44.90% -9.59%
==========================================
Files 134 285 +151
Lines 12329 21067 +8738
==========================================
+ Hits 6719 9461 +2742
- Misses 5116 10799 +5683
- Partials 494 807 +313
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Add spec.match.processes so constraint-level namespace exclusions can apply only to selected enforcement points such as webhook, while audit continues to evaluate excluded namespaces. Fixes open-policy-agent#2161. Signed-off-by: amarkdotdev <amarkdotdev@users.noreply.github.com>
- Add +kubebuilder:validation:Enum to spec.match.processes so invalid process names are rejected instead of silently matching nothing - Regenerate manifests so the processes field is present in the match schema (otherwise the API server prunes spec.match.processes) - Add unit test for processFromEnforcementPoint - gofmt alignment fix in gkReview Signed-off-by: amarkdotdev <amarkdotdev@users.noreply.github.com>
Use items-level kubebuilder enum for processes arrays so the API server accepts spec.match.processes values. Set Matchable.Process to mutation-webhook in mutation mutator match paths. Signed-off-by: amarkdotdev <amarkdotdev@users.noreply.github.com>
Signed-off-by: amarkdotdev <amarkdotdev@users.noreply.github.com>
1af0339 to
36cf50e
Compare
Summary
Fixes #2161.
Adds
spec.match.processesso constraint-levelexcludedNamespacescan be scoped to specific enforcement points (for examplewebhookonly), allowing admission to skip excluded namespaces while audit continues to evaluate them.Testing
go test ./pkg/mutation/match/... -run TestExcludedNamespacesProcessScoped