From a525a5258031d472fb69711f3f1b119f3d263f8c Mon Sep 17 00:00:00 2001 From: rock Date: Tue, 27 Oct 2026 12:12:22 -0700 Subject: [PATCH] Revert "feat(gotify): put the Gotify UI behind ZITADEL single sign-on" This reverts commit 03cebb0aebc05f14ce3d1d08a44c245beef61d1b. --- k8s/apps/gotify/ingress.yaml | 6 -- k8s/apps/gotify/kustomization.yaml | 3 - k8s/apps/gotify/oauth2-proxy-deployment.yaml | 82 ------------------- k8s/apps/gotify/oauth2-proxy-ingress.yaml | 22 ----- k8s/apps/gotify/oauth2-proxy-service.yaml | 15 ---- .../gotify-oauth2-proxy-secrets.enc.yaml | 30 ------- k8s/argocd/secrets/secret-generator.yaml | 1 - scripts/iam/zitadel-provision.py | 19 ----- 8 files changed, 178 deletions(-) delete mode 100644 k8s/apps/gotify/oauth2-proxy-deployment.yaml delete mode 100644 k8s/apps/gotify/oauth2-proxy-ingress.yaml delete mode 100644 k8s/apps/gotify/oauth2-proxy-service.yaml delete mode 100644 k8s/argocd/secrets/gotify-oauth2-proxy-secrets.enc.yaml diff --git a/k8s/apps/gotify/ingress.yaml b/k8s/apps/gotify/ingress.yaml index 5ae2324..d140765 100644 --- a/k8s/apps/gotify/ingress.yaml +++ b/k8s/apps/gotify/ingress.yaml @@ -9,12 +9,6 @@ metadata: # WebSocket support for Gotify client connections (/stream endpoint) # nginx-ingress handles Upgrade/Connection headers natively with http/1.1 nginx.ingress.kubernetes.io/proxy-http-version: "1.1" - # Single sign-on. Gotify has no OIDC, so every request is handed to - # oauth2-proxy for an allow or deny decision. oauth2-proxy skips the token - # API paths itself, so /message keeps Gotify's own X-Gotify-Key check. - nginx.ingress.kubernetes.io/auth-url: "http://gotify-oauth2-proxy.notifications.svc.cluster.local:4180/oauth2/auth" - nginx.ingress.kubernetes.io/auth-signin: "https://gotify.riotpiao.com/oauth2/start?rd=$scheme://$host$request_uri" - nginx.ingress.kubernetes.io/auth-response-headers: "x-auth-request-user,x-auth-request-email" spec: ingressClassName: nginx rules: diff --git a/k8s/apps/gotify/kustomization.yaml b/k8s/apps/gotify/kustomization.yaml index 5c1ba7c..4c7e0b6 100644 --- a/k8s/apps/gotify/kustomization.yaml +++ b/k8s/apps/gotify/kustomization.yaml @@ -5,9 +5,6 @@ resources: - db.yaml - deployment.yaml - service.yaml - - oauth2-proxy-deployment.yaml - - oauth2-proxy-service.yaml - - oauth2-proxy-ingress.yaml - ingress.yaml - igotify-pvc.yaml - igotify-deployment.yaml diff --git a/k8s/apps/gotify/oauth2-proxy-deployment.yaml b/k8s/apps/gotify/oauth2-proxy-deployment.yaml deleted file mode 100644 index efc7346..0000000 --- a/k8s/apps/gotify/oauth2-proxy-deployment.yaml +++ /dev/null @@ -1,82 +0,0 @@ -# oauth2-proxy in front of Gotify. Gotify has no OIDC support of its own, so it -# cannot validate a ZITADEL token. This proxy is the front door: nginx asks it -# for an auth decision on every request (auth_request), and it answers from a -# ZITADEL session cookie. -# -# The Gotify REST API keeps its own client-token auth (X-Gotify-Key) and must -# stay reachable without a browser session, or every push sender breaks: -# Forgejo webhooks, the harness, poimen-sender and the ntfy-style relays all post -# to /message. skip-auth-route leaves those paths to Gotify's own token check. -# -# Gotify's own login still exists behind the proxy. ZITADEL decides who may -# reach the service; Gotify decides what that person may do inside it. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: gotify-oauth2-proxy - namespace: notifications - labels: - app: gotify-oauth2-proxy -spec: - replicas: 1 - selector: - matchLabels: - app: gotify-oauth2-proxy - template: - metadata: - labels: - app: gotify-oauth2-proxy - spec: - securityContext: - runAsNonRoot: true - runAsUser: 65534 - seccompProfile: - type: RuntimeDefault - containers: - - name: oauth2-proxy - image: quay.io/oauth2-proxy/oauth2-proxy:v7.7.1 - args: - - --provider=oidc - - --oidc-issuer-url=https://zitadel.riotpiao.com - - --email-domain=* - - --upstream=static://202 - - --reverse-proxy=true - - --set-xauthrequest=true - - --cookie-secure=true - - --cookie-expire=12h - - --cookie-refresh=1h - - --skip-provider-button=true - - --redirect-url=https://gotify.riotpiao.com/oauth2/callback - - --http-address=0.0.0.0:4180 - # Browser paths keep SSO. API paths fall through to Gotify's own - # client-token check, so existing senders and the Android client - # keep working without a browser session. - - --skip-auth-route=^/(message|application|client|user|version|stream|health)(/.*)?$ - env: - - name: OAUTH2_PROXY_CLIENT_ID - valueFrom: - secretKeyRef: {name: gotify-oauth2-proxy, key: client-id} - - name: OAUTH2_PROXY_CLIENT_SECRET - valueFrom: - secretKeyRef: {name: gotify-oauth2-proxy, key: client-secret} - - name: OAUTH2_PROXY_COOKIE_SECRET - valueFrom: - secretKeyRef: {name: gotify-oauth2-proxy, key: cookie-secret} - ports: - - name: http - containerPort: 4180 - readinessProbe: - httpGet: {path: /ping, port: http} - initialDelaySeconds: 5 - periodSeconds: 10 - livenessProbe: - httpGet: {path: /ping, port: http} - initialDelaySeconds: 15 - periodSeconds: 20 - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: ["ALL"] - resources: - requests: {cpu: 10m, memory: 32Mi} - limits: {cpu: 200m, memory: 128Mi} diff --git a/k8s/apps/gotify/oauth2-proxy-ingress.yaml b/k8s/apps/gotify/oauth2-proxy-ingress.yaml deleted file mode 100644 index c484b86..0000000 --- a/k8s/apps/gotify/oauth2-proxy-ingress.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# The proxy needs its own ingress path. nginx auth_request also guards -# /oauth2/start and /oauth2/callback, which would loop: the login entry point -# would itself require a login. A longer path match sends /oauth2 to the proxy -# directly, and the prefix rule on the gotify ingress handles everything else. -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: gotify-oauth2 - namespace: notifications -spec: - ingressClassName: nginx - rules: - - host: gotify.riotpiao.com - http: - paths: - - path: /oauth2 - pathType: Prefix - backend: - service: - name: gotify-oauth2-proxy - port: - number: 4180 diff --git a/k8s/apps/gotify/oauth2-proxy-service.yaml b/k8s/apps/gotify/oauth2-proxy-service.yaml deleted file mode 100644 index baf4965..0000000 --- a/k8s/apps/gotify/oauth2-proxy-service.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: gotify-oauth2-proxy - namespace: notifications - labels: - app: gotify-oauth2-proxy -spec: - type: ClusterIP - selector: - app: gotify-oauth2-proxy - ports: - - name: http - port: 4180 - targetPort: http diff --git a/k8s/argocd/secrets/gotify-oauth2-proxy-secrets.enc.yaml b/k8s/argocd/secrets/gotify-oauth2-proxy-secrets.enc.yaml deleted file mode 100644 index cdae31f..0000000 --- a/k8s/argocd/secrets/gotify-oauth2-proxy-secrets.enc.yaml +++ /dev/null @@ -1,30 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: gotify-oauth2-proxy - namespace: notifications -type: Opaque -data: - client-id: ENC[AES256_GCM,data:Q+XQAR6cfHKoiuxhPZs6khTvqT0A/JG6,iv:LqhfuhXOYPVB6FQpPpERzWRQ+nxgxHZo4qdJO/g52y8=,tag:V2eK2fyscQKmM3/MmDnNtg==,type:str] - client-secret: ENC[AES256_GCM,data:P7F+83CLDhHnTN+Qx3SeCFbCjVH4JHb2rSteCr3Dywcb1ysMSNvC+3HyBXzsfJJ/EErUrCPWuwlRmV5ySts1oIrWhKyWMJxNrUTzv4eoclat4RyV6SaNDg==,iv:ESO1OUIqZbZPEVUuHrqjskA4tuTX/sc5m+K6Eo319kI=,tag:2isdxjFbtosov88FHZdeaQ==,type:str] - cookie-secret: ENC[AES256_GCM,data:WoWiANSdju+Ep5MuZQNeT0BQdKf5cFvrDUZpe+4B0VeUmQqnvblFi3dciJOeBFom9xYYzUCAI2tUSmX+a6tdAObyoGvjdFmLh+WTfw==,iv:41gYYRkyDIqC3GPuZkoob81Wl2njFTY07j4Puzaq0s4=,tag:x6z33zZnFwvmWUQIVPcxdQ==,type:str] -sops: - kms: [] - gcp_kms: [] - azure_kv: [] - hc_vault: [] - age: - - recipient: age1e5fq3hwxy78psus2nfvmtmua36g0u3suk78ephw6246l974d2utsvn0hla - enc: | - -----BEGIN AGE ENCRYPTED FILE----- - YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2UURWblY4aTBOQjFSNDRL - YkRXVjVHK1QvYW1iR2o0UWVmdE94c2lkWDJjCnlXK1k3cnZBNEExbDU3eDhQZ3FT - TVcyckFiWHdRSjZHQ201Nnl6UFdTN28KLS0tIExQeE90VnM1WHRCYkpycjJtR0ht - ZHFDNWhKeENSQzljZUNmdktDYWloUDQK/fOG8AjTb2TNqLbqNfArOs0mzInYNJVd - iaYxnjH6AjhbLKdnmCpecTQpgx8GeFGIkefV/x5pgrdSUwn0lcvpSQ== - -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-10-27T19:05:35Z" - mac: ENC[AES256_GCM,data:KZV3JNebQ+DbZZZ+e3fvtOGckwC9fmkIchh8DBJ0DMq9lbrPEhP4Juordmnrrs9vJvGxuFJ/KwUv9EELqBsuSy8c47+z7flEAXJiJCJkvVPL/jMidABsFqMALvNNrCqBPWvMHLZUj762DwxB2gKhSx3GLfRUXhm+ZiNcD+39EVw=,iv:ifUlEq/GhBc/QomJApkCaWc3f4ggXoLsvqjzZElO0fU=,tag:fMo+HBDUZdRXgfck+8AJbA==,type:str] - pgp: [] - encrypted_regex: ^(data|stringData)$ - version: 3.9.3 diff --git a/k8s/argocd/secrets/secret-generator.yaml b/k8s/argocd/secrets/secret-generator.yaml index 60574ec..77211d2 100644 --- a/k8s/argocd/secrets/secret-generator.yaml +++ b/k8s/argocd/secrets/secret-generator.yaml @@ -36,7 +36,6 @@ files: - etcd-defrag-creds.enc.yaml - zitadel-masterkey.enc.yaml - smtp-gotify-secrets.enc.yaml - - gotify-oauth2-proxy-secrets.enc.yaml # Login UI RSA keypair, adopted from the chart-generated Secret so ArgoCD # owns it. Without this, the chart re-generates the keypair on every render, # which changes checksum/secret-login-service-key and leaves both Zitadel diff --git a/scripts/iam/zitadel-provision.py b/scripts/iam/zitadel-provision.py index 4cd967f..d39861e 100755 --- a/scripts/iam/zitadel-provision.py +++ b/scripts/iam/zitadel-provision.py @@ -88,20 +88,6 @@ ROLES = { # permission string, so consumer manifests did not change. "llm:inference": "LLM inference access (api-gw)", "llm-inference": "LLM inference access (dash alias)", - # Per-service capabilities. The gateway derives the required capability from - # the verb: GET/HEAD/OPTIONS -> ":read", anything else -> - # ":write" (internal/serviceadapter/router.go:142). The role key - # must match that string exactly, colon included. - "memory:read": "Poimen memory read (api-gw)", - "memory:write": "Poimen memory write (api-gw)", - "workflow:read": "Temporal workflow read (api-gw)", - "workflow:execute": "Temporal workflow execute (api-gw)", - "s3:read": "Object store read (api-gw)", - "s3:write": "Object store write (api-gw)", - "iam:read": "Identity read (api-gw)", - "iam:write": "Identity write (api-gw)", - "sqs:read": "Queue read (api-gw)", - "sqs:write": "Queue write (api-gw)", } _WEB = {"app_type_id": "OIDC_APP_TYPE_WEB", "auth_method_id": "OIDC_AUTH_METHOD_TYPE_BASIC"} @@ -122,11 +108,6 @@ OIDC_APPS = { "https://forgejo.riotpiao.com/user/oauth2/zitadel/callback", "http://localhost:3000/user/oauth2/authentik/callback", "https://forgejo.riotpiao.com/user/oauth2/authentik/callback"]}, - # Gotify has no native OIDC, so oauth2-proxy sits in front of it and this app - # is the proxy's client. The callback path is the proxy's, not Gotify's. - "gotify": {**_WEB, "redirect_uris": [ - "http://localhost:4180/oauth2/callback", - "https://gotify.riotpiao.com/oauth2/callback"]}, "grafana": {**_WEB, "redirect_uris": [ "http://localhost:3000/login/generic_oauth", "https://grafana.riotpiao.com/login/generic_oauth"]},