diff --git a/apps/base/bind-internal/authoritative/records.yaml b/apps/base/bind-internal/authoritative/records.yaml index 0f7fac8..e9be28c 100644 --- a/apps/base/bind-internal/authoritative/records.yaml +++ b/apps/base/bind-internal/authoritative/records.yaml @@ -147,3 +147,18 @@ spec: # traefik-internal gateway VIP; the cheeztv Gateway serves cheeztv.unkin.net # there. - 198.18.200.4 +--- +apiVersion: bind.unkin.net/v1alpha1 +kind: DNSRecord +metadata: + name: watchstate-dns-internal + namespace: bind-internal +spec: + zoneRef: unkin-net + name: watchstate + type: A + ttl: 600 + values: + # traefik-EXTERNAL (DMZ) gateway VIP; the watchstate-external Gateway serves + # the watchstate.unkin.net front door (oauth2-proxy) there. + - 198.18.199.0 diff --git a/apps/base/watchstate/gateway-external.yaml b/apps/base/watchstate/gateway-external.yaml new file mode 100644 index 0000000..7e87de3 --- /dev/null +++ b/apps/base/watchstate/gateway-external.yaml @@ -0,0 +1,40 @@ +--- +# External (DMZ) front for the WatchState admin UI, served on watchstate.unkin.net +# via the external Traefik (LB VIP 198.18.199.0). TLS is terminated with the real +# Let's Encrypt *.unkin.net wildcard (Certificate wildcard-unkin-net in the +# cert-manager namespace, reflected into this namespace as wildcard-unkin-net-tls +# by the emberstack reflector), so there is no cert-manager annotation here. The +# apex watchstate.unkin.net A record lives in the bind-operator unkin.net zone +# (bind-internal/authoritative), NOT external-dns, so no external-dns annotation +# either. The internal watchstate Gateway (watchstate.k8s.syd1.au.unkin.net) is +# untouched; oauth2-proxy fronts both hostnames. +apiVersion: gateway.networking.k8s.io/v1 +kind: Gateway +metadata: + labels: + traefik.io/instance: external + name: watchstate-external + namespace: watchstate +spec: + gatewayClassName: traefik-external + listeners: + - name: http + port: 80 + protocol: HTTP + hostname: watchstate.unkin.net + allowedRoutes: + namespaces: + from: Same + - name: https + port: 443 + protocol: HTTPS + hostname: watchstate.unkin.net + allowedRoutes: + namespaces: + from: Same + tls: + mode: Terminate + certificateRefs: + - group: "" + kind: Secret + name: wildcard-unkin-net-tls diff --git a/apps/base/watchstate/httproute-external.yaml b/apps/base/watchstate/httproute-external.yaml new file mode 100644 index 0000000..70b0a8a --- /dev/null +++ b/apps/base/watchstate/httproute-external.yaml @@ -0,0 +1,49 @@ +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: watchstate-external-http-redirect + namespace: watchstate +spec: + hostnames: + - watchstate.unkin.net + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: watchstate-external + sectionName: http + rules: + - filters: + - type: RequestRedirect + requestRedirect: + scheme: https + statusCode: 301 + matches: + - path: + type: PathPrefix + value: / +--- +apiVersion: gateway.networking.k8s.io/v1 +kind: HTTPRoute +metadata: + name: watchstate-external + namespace: watchstate +spec: + hostnames: + - watchstate.unkin.net + parentRefs: + - group: gateway.networking.k8s.io + kind: Gateway + name: watchstate-external + sectionName: https + rules: + - backendRefs: + - group: "" + kind: Service + name: watchstate-oauth2 + port: 80 + weight: 1 + matches: + - path: + type: PathPrefix + value: / diff --git a/apps/base/watchstate/kustomization.yaml b/apps/base/watchstate/kustomization.yaml index d0036e8..bc5cde3 100644 --- a/apps/base/watchstate/kustomization.yaml +++ b/apps/base/watchstate/kustomization.yaml @@ -13,3 +13,5 @@ resources: - service.yaml - gateway.yaml - httproute.yaml + - gateway-external.yaml + - httproute-external.yaml diff --git a/apps/base/watchstate/oauth2-proxy-configmap.yaml b/apps/base/watchstate/oauth2-proxy-configmap.yaml index ee514dd..d11d8ae 100644 --- a/apps/base/watchstate/oauth2-proxy-configmap.yaml +++ b/apps/base/watchstate/oauth2-proxy-configmap.yaml @@ -13,7 +13,12 @@ data: OAUTH2_PROXY_HTTP_ADDRESS: "0.0.0.0:4180" OAUTH2_PROXY_PROVIDER: "oidc" OAUTH2_PROXY_OIDC_ISSUER_URL: "https://identity.k8s.syd1.au.unkin.net/application/o/watchstate/" - OAUTH2_PROXY_REDIRECT_URL: "https://watchstate.k8s.syd1.au.unkin.net/oauth2/callback" + # Relative (host-less) redirect URL: with reverse-proxy mode on, oauth2-proxy + # derives scheme+host per request from X-Forwarded-Proto/Host, so the same + # deployment serves BOTH the external watchstate.unkin.net and internal + # watchstate.k8s.syd1.au.unkin.net callbacks. Both absolute callback URIs are + # registered on the Authentik provider (terraform-authentik, separate PR). + OAUTH2_PROXY_REDIRECT_URL: "/oauth2/callback" OAUTH2_PROXY_UPSTREAMS: "http://watchstate.watchstate.svc.cluster.local:8080/" OAUTH2_PROXY_SCOPE: "openid email profile ak_groups" OAUTH2_PROXY_OIDC_GROUPS_CLAIM: "ak_groups" @@ -23,8 +28,12 @@ data: # enforced Authentik-side, so accepting the unverified email is safe. OAUTH2_PROXY_INSECURE_OIDC_ALLOW_UNVERIFIED_EMAIL: "true" OAUTH2_PROXY_COOKIE_SECURE: "true" - OAUTH2_PROXY_COOKIE_DOMAINS: "watchstate.k8s.syd1.au.unkin.net" - OAUTH2_PROXY_WHITELIST_DOMAINS: "watchstate.k8s.syd1.au.unkin.net" + # One cookie domain per host (a single parent-domain cookie can't span + # unkin.net and k8s.syd1.au.unkin.net cleanly); oauth2-proxy picks the domain + # matching the request host. Whitelist both so post-auth `rd` redirects to + # either front door are honoured. + OAUTH2_PROXY_COOKIE_DOMAINS: "watchstate.unkin.net,watchstate.k8s.syd1.au.unkin.net" + OAUTH2_PROXY_WHITELIST_DOMAINS: "watchstate.unkin.net,watchstate.k8s.syd1.au.unkin.net" OAUTH2_PROXY_REVERSE_PROXY: "true" OAUTH2_PROXY_PROVIDER_CA_FILES: "/etc/ssl/combined/ca-certificates.crt" OAUTH2_PROXY_CODE_CHALLENGE_METHOD: "S256" diff --git a/apps/base/watchstate/vaultauth.yaml b/apps/base/watchstate/vaultauth.yaml index ee398eb..2e24e3e 100644 --- a/apps/base/watchstate/vaultauth.yaml +++ b/apps/base/watchstate/vaultauth.yaml @@ -4,8 +4,6 @@ kind: VaultAuth metadata: name: default namespace: watchstate - annotations: - argocd.argoproj.io/sync-wave: "0" spec: allowedNamespaces: - watchstate