diff --git a/k8s/bases/infrastructure/controllers/auth-proxy/cilium-network-policy.yaml b/k8s/bases/infrastructure/controllers/auth-proxy/cilium-network-policy.yaml index f4fe46655..98e517658 100644 --- a/k8s/bases/infrastructure/controllers/auth-proxy/cilium-network-policy.yaml +++ b/k8s/bases/infrastructure/controllers/auth-proxy/cilium-network-policy.yaml @@ -79,6 +79,15 @@ spec: - ports: - port: "8080" protocol: TCP + # OpenBao UI/API upstream. The public HTTPRoute points at oauth2-proxy, + # then auth-proxy forwards only authenticated requests to OpenBao. + - toEndpoints: + - matchLabels: + k8s:io.kubernetes.pod.namespace: openbao + toPorts: + - ports: + - port: "8200" + protocol: TCP # DNS resolution - toEndpoints: - matchLabels: diff --git a/k8s/bases/infrastructure/controllers/auth-proxy/config-map.yaml b/k8s/bases/infrastructure/controllers/auth-proxy/config-map.yaml index 1a0b3fbbe..f310c8846 100644 --- a/k8s/bases/infrastructure/controllers/auth-proxy/config-map.yaml +++ b/k8s/bases/infrastructure/controllers/auth-proxy/config-map.yaml @@ -55,6 +55,10 @@ data: rule: "Host(`policy-reporter.${domain}`)" entryPoints: ["web"] service: policy-reporter + openbao: + rule: "Host(`vault.${domain}`)" + entryPoints: ["web"] + service: openbao services: homepage: loadBalancer: @@ -88,3 +92,9 @@ data: loadBalancer: servers: - url: "http://policy-reporter-ui.policy-reporter.svc.cluster.local:8080" + # OpenBao UI/API, routed only after oauth2-proxy SSO. Use the active + # Service to avoid sending UI/API requests to sealed standby pods. + openbao: + loadBalancer: + servers: + - url: "http://openbao-active.openbao.svc.cluster.local:8200" diff --git a/k8s/bases/infrastructure/controllers/openbao/cilium-network-policy.yaml b/k8s/bases/infrastructure/controllers/openbao/cilium-network-policy.yaml index de6e9fbb5..fadc9e155 100644 --- a/k8s/bases/infrastructure/controllers/openbao/cilium-network-policy.yaml +++ b/k8s/bases/infrastructure/controllers/openbao/cilium-network-policy.yaml @@ -24,9 +24,9 @@ spec: protocol: TCP - port: "8201" protocol: TCP - # Allow same-namespace clients (vault-config Jobs, UI), + # Allow same-namespace clients (vault-config Jobs, snapshots), # cross-namespace clients (ESO from external-secrets namespace), - # and Cilium Gateway envoy proxies for external ingress + # and authenticated UI/API traffic forwarded by auth-proxy. - fromEndpoints: - matchLabels: app: vault-config @@ -36,15 +36,9 @@ spec: k8s:io.kubernetes.pod.namespace: openbao - matchLabels: k8s:io.kubernetes.pod.namespace: external-secrets - toPorts: - - ports: - - port: "8200" - protocol: TCP - # Cilium Gateway / Ingress traffic (envoy runs with hostNetwork, - # so label-based matching doesn't work — use ingress + host entities) - - fromEntities: - - ingress - - host + - matchLabels: + app: auth-proxy + k8s:io.kubernetes.pod.namespace: oauth2-proxy toPorts: - ports: - port: "8200" diff --git a/k8s/bases/infrastructure/controllers/openbao/http-route.yaml b/k8s/bases/infrastructure/controllers/openbao/http-route.yaml index e2b624867..fa718d63e 100644 --- a/k8s/bases/infrastructure/controllers/openbao/http-route.yaml +++ b/k8s/bases/infrastructure/controllers/openbao/http-route.yaml @@ -19,18 +19,22 @@ spec: hostnames: - vault.${domain} rules: - - backendRefs: - # openbao-active routes only to the unsealed Raft leader. The chart's - # openbao-ui Service selects every server pod, including sealed-but-Ready - # standbys (readinessProbe sealedcode=204), so the UI would round-robin - # onto a sealed node. Trade-off: with NO active node (all sealed, DR), - # the UI is unreachable — recovery is CLI-driven anyway - # (docs/dr/openbao-raft-ha-migration.md). - - name: openbao-active - port: 8200 - filters: + - filters: + # Gate the public OpenBao UI/API route behind oauth2-proxy so + # unauthenticated Internet traffic cannot generate unbounded audit + # records on the fail-closed file audit PVC. After SSO, auth-proxy + # forwards vault.${domain} to the active OpenBao Service. + - type: RequestHeaderModifier + requestHeaderModifier: + set: + - name: X-Auth-Request-Redirect + value: https://vault.${domain}/ - type: ResponseHeaderModifier responseHeaderModifier: set: - name: Strict-Transport-Security value: max-age=63072000; includeSubDomains; preload + backendRefs: + - name: oauth2-proxy + namespace: oauth2-proxy + port: 80