Learn: Runtime Security — reference
A lookup table for the runtime-security controls, with the orientation for the model behind them. Verified against code and both live clusters. No account IDs, keys, or secret values appear here.
The defense-in-depth stack
Section titled “The defense-in-depth stack”Admission → network-identity → encryption → cryptographic-identity → behavioral-detection. The last three operate at runtime, and this module owns them. The first two live in Policy and Foundations.
| Layer | Control | Mechanism | Status |
|---|---|---|---|
| encryption-in-transit | WireGuard | Cilium transparent encryption (in-kernel WG, pod-to-pod) | LIVE both clusters |
| host encryption | node-to-node | node_encryption |
designed (off) |
| cryptographic identity | mTLS + SPIRE | Cilium mutual auth, embedded SPIRE, per-path authentication.mode: required |
LIVE — preprod showcase, 1 pair |
| fleet/tier mTLS enforcement | per-regulated-tier |
auth-policies wired into the Environment Composition | designed, not built (no regulated tenant) |
| behavioral detection | Falco | eBPF syscall monitoring, per-node DaemonSet | LIVE both — detecting; routing deferred |
Falco — runtime threat detection
Section titled “Falco — runtime threat detection”- Idea: Kyverno gates config at admission; cosign gates the image; Falco watches runtime behavior — a
shell in a container, a read of
/etc/shadow, a write below a binary dir, priv-esc, an unexpected connection. It detects, it does not block: there’s no Audit→Enforce flip, it always alerts. - Mechanism: taps the syscall boundary via modern eBPF (CO-RE) (
driver_kind = "modern_ebpf"— no kernel-module build, portable across the AL2023 6.x kernels, coexists with Cilium’s eBPF at different hooks). A privileged DaemonSet, one per node, tolerates all taints so it runs cluster-wide, in thefalconamespace. Each event is matched against the default upstream ruleset (rules-as-code, priority + MITRE ATT&CK tags); no custom rules are wired.json_output: truekeeps downstream fields clean. - Versions/live: chart
9.0.0, Falco0.44.0, falcoctl0.13.0. DaemonSet 3/3 on the hub, streaming real events (e.g. ruleContact K8S API Server From Container, priorityNotice, tagT1565). - falcosidekick — routing (DEFERRED): deployed (2 replicas) but
Enabled Outputs: [], so it logs to stdout only and nobody is paged. SNS/Slack/observability outputs are a one-var change (falcosidekick_config = { sns = { topicarn = … } }). Theaws/sns-notificationsmodule names Falco as a future publisher; no Falco alert reaches the observability stack yet. - Tuning is the real cost: the stock ruleset is noisy — it flags the Tailscale operator, Beyla, and external-dns legitimately contacting the K8s API as “unexpected”. The sequence is detect-to-stdout, observe, tune, then wire outputs. Tuning means adding an exception or allowlist macro via a custom-rules ConfigMap, a module extension that isn’t wired today.
- Deployed: preprod + platform (2026-07-06).
East-west zero-trust
Section titled “East-west zero-trust”Two layers sit on top of the Cilium default-deny NetworkPolicy floor, both Cilium-native with no sidecar mesh. A mesh is only justified by L7 east-west traffic management, which isn’t needed here.
WireGuard transparent encryption — LIVE both clusters
Section titled “WireGuard transparent encryption — LIVE both clusters”- In-kernel WireGuard encrypts all pod-to-pod traffic transparently, with no app change, sitting under the
overlay tunnel (MTU auto-adjusted). It’s a fleet default, not tier-gated.
node_encryption(host-to-host) stays off — that’s a later, more invasive step. - Module (
infra/modules/cilium/):encryption_enabled(default off),encryption_type(wireguard|ipsec),node_encryption. Live units setencryption_enabled = trueon both clusters. - Gotcha:
enable-wireguardis read only at Cilium agent startup, so a running fleet needskubectl rollout restart ds/cilium -n kube-system, else agents logMismatch: enable-wireguard actual=false expectedValue=true. Verify with per-nodenetwork.cilium.io/wg-pub-keyandcilium-dbg status → Encryption: Wireguard.
mTLS mutual auth (Cilium + embedded SPIRE) — LIVE preprod showcase (1 pair), not platform
Section titled “mTLS mutual auth (Cilium + embedded SPIRE) — LIVE preprod showcase (1 pair), not platform”- Cilium mutual authentication uses an embedded SPIRE (SPIFFE) as the identity source. SPIRE attests workloads
(k8s PSAT) and issues SVIDs; a workload opts into enforcement per-path with a
CiliumNetworkPolicyauthentication.mode: required; Cilium does a SPIRE-backed handshake before allowing the connection (cached in a BPF auth-cache,cilium-dbg bpf auth list → AUTH TYPE: spire). The bytes are still WireGuard-encrypted — mTLS adds identity, not encryption. - Module:
mutual_auth_enabled(→authentication.enabled+authentication.mutual.spire.enabled),spire_install(embedded vs external),spire_persistence,spire_storage_class. Live on preprod only (mutual_auth_enabled = true); platform has nocilium-spirenamespace. - Proof (preprod): the real
storefront → checkoutcall is SPIRE-mutually-authenticated; a cross-team impostor is DROPPED at checkout’s ingress. The auth-required CNP lives in thealpha-shopapp repo, notgitops/. - Embedded SPIRE, not standalone: attests via k8s PSAT and stays clean on the overlay+WireGuard stack. Standalone SPIRE only earns its keep if identity is needed beyond Cilium — app-level mTLS or cross-cluster federation.
- Status: a live showcase, one pair, preprod. Fleet-wide,
regulated-tier-gated enforcement (wiring auth-policies into the Environment Composition per tier) is designed, not built — parked until a regulated tenant exists. - Gotchas: (1)
authentication.enabled: trueis mandatory; off denies auth-required traffic. (2) it needs a rolling Cilium restart, since the config is read at startup. (3) cross-namespace needs both netpol halves — env namespaces default-deny egress too, and a k8sipBlockdoesn’t cover in-cluster identities. (4) the delivery AppProject must permit tenant(Cilium)NetworkPolicy. (5) SPIRE’s PVC datastore hits the EBS-encryption SCP, so it needs an encrypted StorageClass (the preprod encrypted-gp3 default);spire_persistence=falseis ephemeral, fine for a spike but not a showcase.
Where the runtime hardening also comes from (cross-refs)
Section titled “Where the runtime hardening also comes from (cross-refs)”- Kyverno securityContext auto-injection (
mutate-pod-defaults):allowPrivilegeEscalation:false,capabilities.drop:[ALL],seccompProfile:RuntimeDefault,automountServiceAccountToken:false— live and Enforce (see Policy). - Regulated-tier hardening (
runAsNonRoot,readOnlyRootFilesystem) — live for the tier, unexercised because there’s no regulated tenant.
Gotchas (quick)
Section titled “Gotchas (quick)”- WireGuard needs a Cilium DS restart to activate (startup-read config).
authentication.enabledoff denies auth-required traffic; it doesn’t bypass it.- Falco detects, never blocks — and today it pages no one (
Enabled Outputs: []). - An untuned Falco is a false-positive firehose; tune before wiring outputs.
- mTLS is a preprod one-pair showcase — not platform, not fleet-wide.
Go deeper
Section titled “Go deeper”Deep dives: Falco · east-west zero-trust. Related: Policy & admission · Supply chain · Foundations → the cluster. External: Falco · Cilium transparent encryption · Cilium mutual authentication · SPIFFE/SPIRE · MITRE ATT&CK.