A self-contained, platform-agnostic Kubernetes admission audit service for KubeRocketCI: who changed what, recorded from Kubernetes admission events, without control-plane access and without ever blocking platform operations.
API server ──AdmissionReview──▶ kube-audit-rest (ValidatingWebhook, failurePolicy: Ignore)
│ logs raw payload + requestReceivedTimestamp
▼
Vector (sidecar): parse → filter → shape → postgres sink
▼
PostgreSQL audit_events (partitioned, append-only, deduped)This repository is the capture + store foundation. It ships:
- a
ValidatingWebhookConfiguration(wildcard-capable; default filter selects KRCI objects) that never blocks mutations (failurePolicy: Ignore,timeoutSeconds: 1); - a Vector pipeline that reshapes the
AdmissionReviewpayload into typed columns; - a PostgreSQL schema (
audit_events) — RANGE-partitioned by month, composite PK(event_uid, received_at),BEFORE INSERTdedup, least-privilege append-only writer, and a default read view that hides dry-run previews; - a migration runner (
krci-audit-migrate) and Helm chart to deploy it all.
cert-manager must already be installed in the cluster. Kubernetes admission webhooks are
only ever called over TLS, so kube-audit-rest's serving certificate and the webhook's
caBundle are issued and kept in sync by cert-manager (see deploy-templates/templates/ certificate.yaml). Without it, helm install will apply CRs cert-manager needs to reconcile
and the webhook will never become reachable.
- kube-audit-rest — the
ValidatingWebhookConfigurationtarget; logs the rawAdmissionReviewand always allows the request. - Vector — sidecar that tails the log and ships shaped rows to PostgreSQL.
- PostgreSQL — the append-only, partitioned
audit_eventsstore (BYO, or provisioned via Crunchydata's postgres-operator or a plain in-cluster Deployment — seedb.modebelow). - cert-manager — issues and rotates the webhook's TLS certificate (prerequisite, see above).
- golang-migrate — applies the embedded SQL
migrations via the
krci-audit-migraterunner.
| Column | Source (AdmissionReview) |
Notes |
|---|---|---|
event_uid |
request.uid |
logical event id + dedup key |
received_at |
object.metadata.creationTimestamp (CREATE) ‖ requestReceivedTimestamp |
partition key |
operation, api_group, api_version, resource, kind, sub_resource |
request.* |
|
namespace, name |
request.* (name falls back to object/oldObject) |
|
object_uid |
object/oldObject metadata.uid |
correlation column |
username, user_groups, user_extra |
request.userInfo.* |
human vs system:serviceaccount: |
dry_run |
request.dryRun |
stored, hidden from the default trail |
object, old_object, raw |
request.object/oldObject / whole payload |
configurable; not searchable in v1 |
See CLAUDE.md. make test runs unit tests, Docker-backed store integration
tests, and helm render tests; make build produces the migrator binary.
The stored event set is configuration (capture.filter / capture.rules in the chart) and
can be changed with a helm upgrade — no code change. The object-body capture level
(capture.level) toggles between metadata (default) and full. Retention is enforced by
dropping whole monthly partitions (scheduled by an external rotation job), never row-by-row deletes.
Choose how PostgreSQL is supplied at deploy time:
external(default) — bring your own DB: setdb.hostanddb.owner.secretName.pgo— provision a CrunchydataPostgresCluster(needs the postgres-operator add-on).simple— provision a single in-cluster PostgresDeployment(dev/small installs).
helm install krci-audit deploy-templates -n krci-audit --set db.mode=pgo
helm install krci-audit deploy-templates -n krci-audit --set db.mode=simple
helm install krci-audit deploy-templates -n krci-audit \
--set db.mode=external --set db.host=my-pg --set db.owner.secretName=my-pg-creds