Skip to content

feat: export admission violations from validation webhook - #4716

Open
JaydipGabani wants to merge 6 commits into
masterfrom
issue-2798-validation-webhook-export
Open

feat: export admission violations from validation webhook#4716
JaydipGabani wants to merge 6 commits into
masterfrom
issue-2798-validation-webhook-export

Conversation

@JaydipGabani

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

Exports valid constraint violations produced by the validating webhook, including denied requests that are never persisted and request identity unavailable to audit.

Admission handling marshals each violation and attempts a non-blocking enqueue into a per-pod queue bounded at 1,024 messages and 16 MiB. A manager runnable publishes queued records asynchronously through the existing export system, so backend latency and failure cannot change the admission decision. Delivery is best-effort: each publish is attempted once, overload and shutdown loss are reported through metrics and rate-limited logs, and complete encoded JSON records over 64 KiB are dropped rather than truncated.

The supported alpha backend is disk. Admission records use separately prefixed JSONL segments with bounded rotation, retention, free-space protection, file locking, and recovery of complete records from abandoned segments. Audit and admission reuse one Connection, channel, path, and volume while their files and cleanup remain isolated.

This also changes the alpha ConnectionPodStatus shape: aggregate active and errors fields are replaced by connectionErrors and a source-keyed publishStatuses list for audit and webhook. Each publisher updates only its own entry, so one source cannot clear the other source's failures. Error arrays and in-memory publish error classes are bounded at 500 entries.

Helm generator source, staging manifests, the demonstration disk reader, end-to-end coverage, metrics, user documentation, and a design document are included.

Which issue(s) this PR fixes (optional, using fixes #<issue number>(, fixes #<issue_number>, ...) format, will close the issue(s) when the PR gets merged):
Fixes #2798

Special notes for your reviewer:

Start with docs/design/admission-violation-export.md, then review the commits in order:

  1. feat: separate export status by source
  2. feat: add admission export queue
  3. feat: add admission disk spool
  4. feat: wire admission violation export
  5. feat: deploy admission violation export
  6. docs: describe admission violation export

Alpha limitations and operator behavior:

  • Admission export supports only exportBackend: disk; Helm rejects other backends.
  • There is no individual publish retry or delivery guarantee.
  • The 64 KiB limit covers the complete encoded ExportMsg, including details, annotations, labels, and request metadata.
  • Spool count and byte limits can remove old segments before their 24-hour maximum age.
  • The default per-pod emptyDir survives a container restart but loses unconsumed records when the pod is replaced.
  • The demonstration reader logs each record and deletes successfully consumed segments; it is not a production archive.
  • Helm sources remain under cmd/build/helmify; generated review artifacts are under manifest_staging. Root charts and deploy outputs are unchanged.

Validation:

  • make native-test
  • go test -race ./pkg/webhook ./pkg/export/... ./pkg/controller/export ./pkg/audit -count=1
  • make lint
  • make manifests generate with a clean tree afterward
  • Helm lint for cmd/build/helmify/static and manifest_staging/charts/gatekeeper
  • Helm render checks for supported disk and rejected Dapr admission backends
  • Every commit compiled and passed its focused tests independently
  • Manual kind test: a denied pod was consumed by the admission reader, and audit/webhook publish status remained independently active without clobbering

Track audit and webhook publishing independently and bound status errors.

Signed-off-by: Jaydip Gabani <gabanijaydip@gmail.com>
Publish violations asynchronously with bounded memory, shutdown, and metrics.

Signed-off-by: Jaydip Gabani <gabanijaydip@gmail.com>
Store admission violations in bounded, recoverable JSONL segments.

Signed-off-by: Jaydip Gabani <gabanijaydip@gmail.com>
Export validated webhook results through the shared connection and channel.

Signed-off-by: Jaydip Gabani <gabanijaydip@gmail.com>
Add disk-only Helm wiring, reader support, and end-to-end coverage.

Signed-off-by: Jaydip Gabani <gabanijaydip@gmail.com>
Document delivery, limits, status, metrics, and disk lifecycle.

Signed-off-by: Jaydip Gabani <gabanijaydip@gmail.com>
Copilot AI review requested due to automatic review settings July 30, 2026 21:54
@JaydipGabani
JaydipGabani requested a review from a team as a code owner July 30, 2026 21:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds best-effort admission violation export through the existing export system, with asynchronous queuing, disk spooling, source-specific status, deployment support, and observability.

Changes:

  • Adds bounded asynchronous webhook export and disk-backed admission segments.
  • Separates audit and webhook publishing status.
  • Adds Helm wiring, metrics, documentation, and end-to-end coverage.

Reviewed changes

Copilot reviewed 56 out of 57 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
website/docs/metrics.md Documents export metrics.
website/docs/export.md Documents admission export behavior.
test/export/fake-reader/main.go Adds admission segment consumption.
test/export/fake-reader/main_test.go Tests reader selection and deletion.
test/export/denied_pod.yaml Adds denied-request fixture.
test/bats/test.bats Exercises admission export end-to-end.
test/bats/helpers.bash Adds export test helpers.
pkg/webhook/webhook.go Injects export dependencies.
pkg/webhook/stats_reporter.go Adds queue and publishing metrics.
pkg/webhook/stats_reporter_test.go Tests new metrics.
pkg/webhook/policy.go Exports validation results.
pkg/webhook/policy_test.go Tests admission payloads.
pkg/webhook/export.go Implements bounded asynchronous publishing.
pkg/webhook/export_test.go Tests queue and shutdown behavior.
pkg/export/util/util.go Extends messages and error aggregation.
pkg/export/util/util_test.go Tests flags and error bounds.
pkg/export/system_test.go Tests shared disk routing.
pkg/export/disk/admission_file.go Implements admission disk spooling.
pkg/export/disk/admission_file_test.go Tests spool lifecycle and recovery.
pkg/export/disk/test_helpers_test.go Updates disk test helpers.
pkg/export/disk/disk.go Integrates admission records into disk driver.
pkg/export/disk/connection_test.go Updates connection lifecycle tests.
pkg/export/disk/config.go Refactors connection configuration.
pkg/export/disk/config_test.go Tests admission defaults.
pkg/export/disk/cleanup.go Extends combined file cleanup.
pkg/export/disk/cleanup_test.go Tests bounded failed cleanup.
pkg/export/disk/audit_file.go Isolates audit retention.
pkg/export/disk/audit_file_test.go Tests admission-file exclusion.
pkg/controller/export/export_connection_controller.go Adds source-specific status updates.
pkg/controller/export/export_connection_controller_test.go Tests status merging and conflicts.
pkg/controller/connectionstatus/connectionstatus_controller_test.go Tests aggregated status shape.
pkg/audit/manager.go Reports audit-specific publishing status.
pkg/audit/manager_test.go Tests audit status reporting.
manifest_staging/deploy/gatekeeper.yaml Updates generated CRDs.
manifest_staging/charts/gatekeeper/values.yaml Adds admission chart settings.
manifest_staging/charts/gatekeeper/templates/gatekeeper-controller-manager-deployment.yaml Deploys exporter volume and reader.
manifest_staging/charts/gatekeeper/templates/gatekeeper-audit-violation-export-connection.yaml Creates shared disk connection.
manifest_staging/charts/gatekeeper/README.md Documents chart values.
manifest_staging/charts/gatekeeper/crds/connectionpodstatus-customresourcedefinition.yaml Updates pod-status schema.
manifest_staging/charts/gatekeeper/crds/connection-customresourcedefinition.yaml Updates connection status schema.
Makefile Adds admission export deployment options.
main.go Wires exporter dependencies.
go.mod Promotes filesystem dependency.
docs/design/README.md Links the design proposal.
docs/design/admission-violation-export.md Defines architecture and semantics.
config/crd/bases/status.gatekeeper.sh_connectionpodstatuses.yaml Updates source CRD schema.
config/crd/bases/connection.gatekeeper.sh_connections.yaml Updates connection CRD schema.
cmd/build/helmify/static/values.yaml Adds source Helm values.
cmd/build/helmify/static/templates/gatekeeper-audit-violation-export-connection.yaml Updates source connection template.
cmd/build/helmify/static/README.md Documents source chart values.
cmd/build/helmify/replacements.go Adds admission argument substitution.
cmd/build/helmify/main.go Generates volume and sidecar wiring.
cmd/build/helmify/kustomize-for-helm.yaml Adds Helm substitution marker.
apis/status/v1alpha1/zz_generated.deepcopy.go Updates generated deep copies.
apis/status/v1alpha1/connectionpodstatus_types.go Defines source-specific status API.
apis/status/v1alpha1/connectionpodstatus_types_test.go Tests status deep copying.
.github/workflows/disk-export.yaml Expands disk export CI coverage.
Files not reviewed (1)
  • apis/status/v1alpha1/zz_generated.deepcopy.go: Generated file

Comment thread pkg/export/disk/disk.go
Comment on lines +244 to +246
if conn.admission.cleanupTimer == nil {
if err := conn.recoverAdmissionFiles(); err != nil {
return fmt.Errorf("recovering admission files for connection %s: %w", connectionName, err)
Comment thread Makefile
$(HELM_EXPORT_ARGS) \
$(if $(filter disk,$(EXPORT_BACKEND)),$(HELM_DISK_EXPORT_ARGS)) \
$(if $(filter dapr,$(EXPORT_BACKEND)),$(HELM_DAPR_EXPORT_ARGS)) \
$(if $(and $(filter true,$(ENABLE_EXPORT)),$(filter disk,$(EXPORT_BACKEND))),$(HELM_DISK_EXPORT_ARGS)) \
Comment on lines +93 to +97
var auditErr error
if conn.File != nil {
auditErr = conn.unlockAndCloseFile()
}
return errors.Join(auditErr, conn.closeAdmissionStream(finalizeAdmission))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add export mechanism to validation webhook

2 participants