Architecture¶
Layer model¶
Portal sits across the API-server and control-plane layers:
- Layer 4 — Admission (
internal/admission): TLSValidatingWebhookConfiguration. Synchronous, pre-persistence. - Layer 5 — Audit (
internal/audit): informer-driven; events on persisted objects. - Layer 6 — Network (
internal/network): declarative NetworkPolicy graph analyser. Re-runs on informer events from layers shared with audit. - Layer 7 — Runtime (v2): K8s API-audit-log source. Not enabled in v1.
flowchart TB
subgraph K8s[Kubernetes cluster]
APIServer[kube-apiserver]
Etcd[(etcd)]
APIServer --- Etcd
end
subgraph Portal[Portal Deployment]
Admission[admission webhook<br/>internal/admission]
Audit[audit controller<br/>internal/audit]
Network[NP analyser<br/>internal/network]
Engine[rule engine<br/>internal/engine]
Dispatcher[action dispatcher<br/>internal/actions/engine]
Sinks[sinks<br/>alertmanager, policyreport,<br/>prometheus, stdout]
end
APIServer -- AdmissionReview --> Admission
APIServer -- watch --> Audit
APIServer -- watch --> Network
Admission --> Engine
Audit --> Engine
Network --> Engine
Engine --> Dispatcher
Engine --> Sinks
Dispatcher -- evict / label / patch / revoke --> APIServer
Module dependency graph¶
The repo enforces a one-way dependency on internal/api:
Every
internal/*package may depend oninternal/api. Nothing else may depend oninternal/{admission,audit,network,actions/...}.
internal/api contains pure interfaces and DTOs (internal/api/rule.go, engine.go, action.go, sink.go, source.go). Implementations register themselves at init() time via api.RegisterEngine, api.RegisterAction, api.RegisterSink.
Pipeline¶
Every event source feeds the same pipeline:
flowchart LR
Sources[admission / audit / network] --> CB[ContextBuilder]
CB --> Engine[RuleEngine.Evaluate]
Engine --> Violations[[]Violation]
Violations --> Dispatcher[ActionDispatcher]
Violations --> Sinks[OutputSink fan-out]
Dispatcher --> Actions[alertmanager, label,<br/>annotate, evict,<br/>patch-networkpolicy,<br/>revoke-sa-token]
- ContextBuilder (
internal/context/podand the generic builder embedded in admission) normalises the rawunstructured.Unstructuredinto the env map exposed to expr-lang. - RuleEngine (
internal/engine) indexes rules by GVK and produces[]Violation. - ActionDispatcher (
internal/actions/engine) applies idempotency + rate-limit + worker pool semantics. See actions-and-rate-limiting.md. - OutputSinks receive every violation: AlertManager, PolicyReport, Prometheus, stdout-JSON.
Per-layer toggles¶
Every layer is independently enable-able:
| Layer | CLI flag (portal run) |
Helm value |
|---|---|---|
| Admission | --admission (default true) |
webhook.enabled |
| Audit | --audit (default false) |
audit.enabled |
| Network | --network (default false, implies audit) |
network.enabled |
Portal in admission-only mode does not start informers; audit-only mode does not serve TLS. RBAC scope mirrors the toggles (see ../operator/rbac-scoping.md).