diff --git a/platform-config/kustomization.yaml b/platform-config/kustomization.yaml index ec38af9..c7c910f 100644 --- a/platform-config/kustomization.yaml +++ b/platform-config/kustomization.yaml @@ -50,9 +50,7 @@ resources: - ../platform/keycloak/httproute.yaml - ../platform/keycloak/servicemonitor.yaml # oauth2-proxy: forward-auth sign-in/callback ingress + ServiceMonitor (Gateway API / monitoring CRs) - # TEMP-DEFERRED with the oauth2-proxy HelmRelease (see platform/kustomization.yaml) — re-enable both - # together once the operator provisions oauth2-proxy-credentials. - # - ../platform/oauth2-proxy/httproute.yaml - # - ../platform/oauth2-proxy/servicemonitor.yaml + - ../platform/oauth2-proxy/httproute.yaml + - ../platform/oauth2-proxy/servicemonitor.yaml # monitoring SSO proof: Grafana native-OIDC login ingress (Gateway API CR) - ../platform/monitoring/grafana-httproute.yaml diff --git a/platform/keycloak/keycloak-realm-clients.sops.yaml b/platform/keycloak/keycloak-realm-clients.sops.yaml new file mode 100644 index 0000000..5dce5df --- /dev/null +++ b/platform/keycloak/keycloak-realm-clients.sops.yaml @@ -0,0 +1,29 @@ +apiVersion: v1 +kind: Secret +metadata: + name: keycloak-realm-clients + namespace: keycloak +type: Opaque +stringData: + grafana-client-secret: ENC[AES256_GCM,data:J6grYrkJVubGNS+z1WrcUuvjKu2Z/fETWNXsKkjQnk/RlitaMjDqkazglKgy8PkEymNLNuVao48gksnuNLQ6aA==,iv:9sw5IdW+7GuwsRjn4NSi2JVZh9mTE2hiWJQYQS7w2bA=,tag:2hOUFeFqcQJsPeC8e6U4RA==,type:str] + oauth2-proxy-client-secret: ENC[AES256_GCM,data:hE9mN6A6uTL3GpqOCGb3T0qVR9bcY4wcqNlgcrs9+uezSeci/Vs9uiXeFzfD57klHe8nEqxF1bCftD0GVFadhQ==,iv:rP2CbbGG4LWmGyV0adrlsmn2GtQLH8hSlqbioOAD824=,tag:p28vfuSZxYMs7XnAjslBWg==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age175l8mdpdfu7hq0aml3exs3gykarwjmuvr23sq56s3wjejnyk44wsp4mfzg + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvaU5Ba1Ztb2JydVQ5Q1cr + V3lOV2RwNVNjUFJ3MmRocEYyb0JibWRyTHpzCk5wNGRaNXVhcGNNS3RoN0VWRUdz + VHFtbS95c0RQajhUTmJPazdUTTRqZ3MKLS0tIHh0cXJsQ1k3azVHMWdZcWpQTjhP + YXJGUUJiTnFndFhDZDU1bmxXTENCbmsKuhb3RQ3LZmuTPAXEck8b6iuZ5vxLb9fV + +fQELmU4kOTbZrPSxy+kpttLG5Cy5d6X2ieZXBf6opzpLTUhlBOkHA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-08-25T03:06:30Z" + mac: ENC[AES256_GCM,data:wJ6Mf7yFXnnnuo/IhfGdDYcgNUzzNv2bFGN6wPwmVRr1To4rt3DGb1JZO19OxvloWYrGAyJaeXzC5NCLGDZOzS99TBmMy1TIeEYUqd6zEmFofEla0mZyLFGLsU/JUIVL3d1l4ECPmcHpUnEjJf4o4kE8BxkWAyHSMWktB69a1cc=,iv:7E7T7cFpAcT42ryTfqbDUoWr0d23a9rCI3n//LgBFS8=,tag:zVXOh/hjQNousg85TZw/Zg==,type:str] + pgp: [] + encrypted_regex: ^(data|stringData)$ + version: 3.9.4 diff --git a/platform/keycloak/kustomization.yaml b/platform/keycloak/kustomization.yaml index d07e761..4bfcae6 100644 --- a/platform/keycloak/kustomization.yaml +++ b/platform/keycloak/kustomization.yaml @@ -26,5 +26,7 @@ resources: - https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/26.0.6/kubernetes/kubernetes.yml # --- Admin (break-glass) credential — SOPS-encrypted, referenced by name (ADR-0007, R-IDP-04) --- - keycloak-admin-credentials.sops.yaml + # --- OIDC client secrets (grafana + oauth2-proxy) the realm import injects via placeholders --- + - keycloak-realm-clients.sops.yaml # --- Grafana dashboard for Keycloak health (plain ConfigMap; R-OBS-03) --- - grafana-dashboard.yaml diff --git a/platform/kustomization.yaml b/platform/kustomization.yaml index f692688..0a85f58 100644 --- a/platform/kustomization.yaml +++ b/platform/kustomization.yaml @@ -28,12 +28,7 @@ resources: # Cluster CRs + ServiceMonitors + HTTPRoutes are in platform-config (dependsOn platform). ---- - cnpg # CloudNativePG operator (DB backend for Keycloak) — ghcr.io images (not Bitnami) - keycloak # Keycloak Operator (quay.io images) + SOPS admin credential - # TEMP-DEFERRED (PM, pending operator SOPS hand-off): oauth2-proxy's HelmRelease mounts - # `existingSecret: oauth2-proxy-credentials`, which is not yet provisioned. Under the unified graph's - # `platform` wait:true, a not-ready HR here blocks platform → platform-config → the whole downstream - # graph (incl. KubeVirt). Re-enable this line (and the two oauth2-proxy entries in platform-config) - # the moment the operator fills platform/oauth2-proxy/oauth2-proxy-credentials.sops.yaml + wires it. - # - oauth2-proxy # forward-auth for non-OIDC UIs — needs SOPS `oauth2-proxy-credentials` (hand-off) + - oauth2-proxy # forward-auth for non-OIDC UIs — SOPS oauth2-proxy-credentials now provisioned # ---- Later phases: enabled when their phase opens ---- # - velero # Phase 4 (Backup/DR): BLOCKED on OQ-BKP (off-cluster backup target decision) # - image-automation # Phase 4 (Automated updates): Flux image-automation + Renovate diff --git a/platform/monitoring/grafana-oidc-credentials.sops.yaml b/platform/monitoring/grafana-oidc-credentials.sops.yaml new file mode 100644 index 0000000..8324da6 --- /dev/null +++ b/platform/monitoring/grafana-oidc-credentials.sops.yaml @@ -0,0 +1,28 @@ +apiVersion: v1 +kind: Secret +metadata: + name: grafana-oidc-credentials + namespace: monitoring +type: Opaque +stringData: + client-secret: ENC[AES256_GCM,data:yq81eILYDrasFchtD+375EYmKYc38NMblbvRdDVhRpmRO/4d6/QVzfVDG4WrrREjkOaDbj/7Qkw25EX2NEQTyg==,iv:m4pQdOR2VJMTRJ/TxWaLOUN3rLzoCuvlaLgoo2AU7os=,tag:scoKscvm2sA+zDLnN1ub7w==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age175l8mdpdfu7hq0aml3exs3gykarwjmuvr23sq56s3wjejnyk44wsp4mfzg + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWdy8wc25KdTZVQzV5YlBs + WDFDRHgwN0RpdlRiWGZsQUJDZGthcWI0cVZzCm0wUHc4Y1dwcEVFQ2U4c2o0ZWd5 + Y0htSm1laWt2ZmFBTkNMYjlKeUNyV0UKLS0tIHdwTDNWNWNhM2RseGd5SzVVdTVw + MTNHY2xiNTVFdkhobEp0MGFjOEJLYUUK8i5l3GQnxQlS9U53jOOsyqaVdqUA/jxv + Cmix6W9abwRntFwJYTQk3Hcl6HW0BcP1uUpPuOxaIzk8F52U1A4AOw== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-08-25T03:06:30Z" + mac: ENC[AES256_GCM,data:Y0f9W7IfJZf0VXHG9XYrxV7ueZ1RYKye/Z9smGUD+eUeY3c8QKaqc+SLsEH1BPxlUkZUTDHZzD2jtl0Rs+bL2N51uskQyeW/ksDBuCoZjHZGwAeTiQG/ZMoL9iJXjCDc74h5DTqqkL2aEBozux9kNw9MiiV1uKupT2JFlcA0srw=,iv:lveLPR61E41altRc9o4O52ThnLnMeU/8gqdS1WcWXmk=,tag:rH3/qsp8+GReQZKJpFqAfA==,type:str] + pgp: [] + encrypted_regex: ^(data|stringData)$ + version: 3.9.4 diff --git a/platform/monitoring/kustomization.yaml b/platform/monitoring/kustomization.yaml index 5a573be..4755db3 100644 --- a/platform/monitoring/kustomization.yaml +++ b/platform/monitoring/kustomization.yaml @@ -12,3 +12,4 @@ resources: # (dependsOn platform) so the CRDs exist first. File stays here for locality. - grafana-admin-credentials.sops.yaml - alertmanager-smtp.sops.yaml + - grafana-oidc-credentials.sops.yaml diff --git a/platform/oauth2-proxy/kustomization.yaml b/platform/oauth2-proxy/kustomization.yaml index 5704992..4a45056 100644 --- a/platform/oauth2-proxy/kustomization.yaml +++ b/platform/oauth2-proxy/kustomization.yaml @@ -5,3 +5,4 @@ resources: - namespace.yaml - helmrepository.yaml - helmrelease.yaml + - oauth2-proxy-credentials.sops.yaml diff --git a/platform/oauth2-proxy/oauth2-proxy-credentials.sops.yaml b/platform/oauth2-proxy/oauth2-proxy-credentials.sops.yaml index a0f6ac3..b714b61 100644 --- a/platform/oauth2-proxy/oauth2-proxy-credentials.sops.yaml +++ b/platform/oauth2-proxy/oauth2-proxy-credentials.sops.yaml @@ -1,32 +1,30 @@ -# ============================================================================= -# TEMPLATE — NOT APPLIED, NOT ENCRYPTED (.yaml.example is ignored by kustomize -# and never auto-encrypted by SOPS). Reference scaffold only. -# -# (a) Copy to: platform/oauth2-proxy/oauth2-proxy-credentials.sops.yaml -# (b) kustomization: add this line under `resources:` in -# platform/oauth2-proxy/kustomization.yaml -# - oauth2-proxy-credentials.sops.yaml -# (c) Encrypt: sops -e -i platform/oauth2-proxy/oauth2-proxy-credentials.sops.yaml -# (d) Consumed by: oauth2-proxy Helm chart -> existingSecret. [Phase 6] -# -# VALUE NOTES: -# - client-id / client-secret: come from the Keycloak OIDC client created for -# oauth2-proxy (Phase 6, after Keycloak is up). -# - cookie-secret: must be a 16, 24, or 32-byte value, base64-encoded. -# Generate with: openssl rand -base64 32 -# -# !! VERIFY KEY NAMES BEFORE ENCRYPTING !! -# Confirm the exact stringData key names against the pinned oauth2-proxy chart's -# existingSecret contract (common keys: client-id, client-secret, cookie-secret, -# but chart versions vary). Adjust below to match before running `sops -e -i`. -# ============================================================================= apiVersion: v1 kind: Secret metadata: - name: oauth2-proxy-credentials - namespace: oauth2-proxy + name: oauth2-proxy-credentials + namespace: oauth2-proxy type: Opaque stringData: - client-id: REPLACE-ME - client-secret: REPLACE-ME - cookie-secret: REPLACE-ME + client-id: ENC[AES256_GCM,data:YqWOatWC7SbM0yp4,iv:vMxhYu7PxLlTrjIcRMrWhN1r4cPiWAUtPrEyTeb3DiA=,tag:ZEVcSR8YaEVxiMj7IsRd8g==,type:str] + client-secret: ENC[AES256_GCM,data:DKxzn/nSQRWhKHzYqQNpmrnNmc0LzcIg+aUNODG6vd5TGMDkEQtsbR96j0PaS5MpNUraWKlo/GCKSPaZr/wqMA==,iv:IPRHbq0Nir90GZLjKPmqawdpRgzAf9mfs6mP5N0bwqI=,tag:Zuik7AN23lz408ikj67OtQ==,type:str] + cookie-secret: ENC[AES256_GCM,data:acF3v5BRojefjARfJB2udO2gaeffk64/0J+3YvOzvdHdtGk9lrXI/vuzC5A=,iv:EiloVBHhCWxgoGlbRruZUTgTB9/ekcQOHY7fmZPZu8I=,tag:+D4T7mNz1U8EnzErk98OyQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age175l8mdpdfu7hq0aml3exs3gykarwjmuvr23sq56s3wjejnyk44wsp4mfzg + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBac0gxeDFhbW8wNVY4SkNj + OWc2aVc3M1dzYmRxdkk3dWNJNkJKYk9qRUMwClBzVXBvUStKdW8wU3orWFlkTFFW + WkhyVGd4VVdMbmlMMUZ4VDA5M09lYmcKLS0tIGFXekE3ODFaNTlqR1RhS1N3SmhC + elUvK1l2Q1gvd0hFQXZrQUd1a29RQVEKQ/9keILThurYGEs5vbuRUghlyfpVpcDt + Gc0EGCN0ZZyV4zNmODX91Yubd7whUTl3WNs0n3TZfqXSeSP9bUFI+Q== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2026-08-25T03:06:30Z" + mac: ENC[AES256_GCM,data:Q5dzE84NWDdZo9qrgPMJghF823nNr57bhg4CURfZHCoc1hkpsBNy0XVdbKfOt4wqvsy9ebL2s/vAhBlUJjqIgrk742YA+oUDkksII+CsldlECBTmFrJQULgmSIJgrlctgGP06wycnCL6dYvB+bnEG7hitlP9isoAyW0rQ7dUNmc=,iv:nIKr1zerrY6FEaOlu+hIBJYxK58GrV0NOeFpTzUFny4=,tag:lrC82Nt7/gZTZ6R3BjigpQ==,type:str] + pgp: [] + encrypted_regex: ^(data|stringData)$ + version: 3.9.4