feat(auth): gate pihole UI with per-app oauth2-proxy sidecar (canary)

Close the un-gated-UI security finding for forward-auth apps (R-IDP-02) by
rendering the Option-B per-app oauth2-proxy reverse-proxy sidecar that crafty
proves working. catalog/render.py now emits, for any forward-auth app with an
exposed UI: the oauth2-proxy sidecar (upstream http://127.0.0.1:<uiport>,
:4180, --allowed-group per auth.group), an authproxy :4180 Service port, an
HTTPRoute backendRef -> :4180, and a gateway-ingress CiliumNetworkPolicy that
allows the Gateway to reach ONLY :4180 (fail-closed: the bare UI is never
served un-authenticated). oidc/native/none apps render byte-identical.

This is the CANARY: only pihole's golden carries the sidecar and is verified
fail-closed in-cluster first. jackett/qbittorrent/radarr/sonarr are deferred to
the rollout commit (temporarily listed in ci/render-golden.sh) so their UIs
keep serving exactly as today until their clients+secrets land.

- keycloak: confidential pihole client (realm-import + realm-clients mirror),
  provisioned live via kcadm (groups membership mapper, bare names).
- secret: SOPS/age pihole-oauth2-proxy-credentials (client-id/secret/cookie),
  wired into apps/wave-0 via the renderer's new sidecar-creds wave rule.
- L1 render goldens regenerated for the sidecar (forward-auth fixtures).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
jakman85andClaude Opus 4.8 committed 2026-08-31 08:36:03 -05:00
1 parent a04251bbc8
commit 72d4720d58
10 files changed
+584 -22

No files matched your search

@@ -61,6 +61,70 @@ spec:
image: nginx:1.27
ports:
- containerPort: 8080
- name: oauth2-proxy
image: quay.io/oauth2-proxy/oauth2-proxy:v7.8.1
imagePullPolicy: IfNotPresent
args:
- --http-address=0.0.0.0:4180
- --reverse-proxy=true
- --provider=oidc
- --oidc-issuer-url=https://keycloak.home.keithjackson.dev/realms/homelab
- --upstream=http://127.0.0.1:8080
- --email-domain=*
- --scope=openid email profile
- --oidc-groups-claim=groups
- --allowed-group=platform-admins
- --skip-provider-button=true
- --redirect-url=https://paas-demo.home.keithjackson.dev/oauth2/callback
- --cookie-domain=.home.keithjackson.dev
- --whitelist-domain=.home.keithjackson.dev
- --cookie-secure=true
- --pass-access-token=true
- --set-xauthrequest=true
env:
- name: OAUTH2_PROXY_CLIENT_ID
valueFrom:
secretKeyRef:
name: paas-demo-oauth2-proxy
key: client-id
- name: OAUTH2_PROXY_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: paas-demo-oauth2-proxy
key: client-secret
- name: OAUTH2_PROXY_COOKIE_SECRET
valueFrom:
secretKeyRef:
name: paas-demo-oauth2-proxy
key: cookie-secret
ports:
- name: http
containerPort: 4180
protocol: TCP
resources:
requests:
cpu: 25m
memory: 64Mi
limits:
memory: 128Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
livenessProbe:
httpGet:
path: /ping
port: http
initialDelaySeconds: 5
periodSeconds: 15
readinessProbe:
httpGet:
path: /ping
port: http
initialDelaySeconds: 5
periodSeconds: 15
---
# Service
apiVersion: v1
@@ -77,6 +141,9 @@ spec:
- name: port-8080
port: 8080
targetPort: 8080
- name: authproxy
port: 4180
targetPort: 4180
---
# CiliumNetworkPolicy gateway-ingress allow (R-NET-01/02): paas-demo-allow-gateway-ingress
apiVersion: cilium.io/v2
@@ -95,7 +162,7 @@ spec:
- ingress
toPorts:
- ports:
- port: '8080'
- port: '4180'
protocol: TCP
---
# CiliumNetworkPolicy world egress allow (egress class governs the path; R-NET-05): paas-demo-allow-internet-egress
@@ -143,7 +210,7 @@ spec:
value: /
backendRefs:
- name: paas-demo
port: 8080
port: 4180
---
# ServiceMonitor (R-OBS-01)
apiVersion: monitoring.coreos.com/v1