From 4a5f4d94abc4a72c3911a890b5bafdfbd02d9b30 Mon Sep 17 00:00:00 2001 From: Mukul Sharma Date: Wed, 9 Sep 2026 12:35:35 +0530 Subject: [PATCH] Grant deployer Ingress rights in its own namespace, for custom domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Overdue: this belongs with toolshed's custom-domains feature, which has already merged and shipped. Without it, deployer gets "forbidden" the moment anyone actually adds a custom domain — the exact failure mode internal/deploy/kubernetes.go's own package doc warns about, since its resource list and this file are unsynchronised copies in two repositories. Scoped as a namespaced Role/RoleBinding rather than widening the ClusterRole above it. A custom domain's Ingress and TLS secret live in the gateway's own namespace and never in an app's, so this only ever targets one fixed namespace — unlike the per-app namespaces the ClusterRole necessarily spans. Secrets are get/list/watch/delete only: cert-manager writes them, deployer just reads readiness and cleans up on removal. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Wajog7nELA3i8JWTjxYGHF --- extra-manifests/toolshed-deployer-rbac.yaml | 44 +++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/extra-manifests/toolshed-deployer-rbac.yaml b/extra-manifests/toolshed-deployer-rbac.yaml index 8ee8ea2..d24a966 100644 --- a/extra-manifests/toolshed-deployer-rbac.yaml +++ b/extra-manifests/toolshed-deployer-rbac.yaml @@ -85,3 +85,47 @@ roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: toolshed-deployer +--- +# A custom domain's Ingress and TLS secret live in the gateway's own +# namespace (toolshed, same as above) — never an app's namespace. Scoped +# with a namespaced Role/RoleBinding rather than widening the ClusterRole +# above: Ingress management here only ever targets this one fixed +# namespace, unlike the per-app namespaces the ClusterRole necessarily +# spans. Added alongside toolshed's custom-domains feature — see +# internal/deploy.Client.EnsureDomainIngress/DomainCertReady/ +# RemoveDomainIngress and this file's own header comment about keeping it +# and deploy/helm/toolshed/templates/rbac.yaml in sync. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: toolshed-deployer-ingress + namespace: toolshed + labels: + app.kubernetes.io/part-of: toolshed +rules: + - apiGroups: ["networking.k8s.io"] + resources: ["ingresses"] + verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] + # Reads the TLS secret cert-manager's ingress-shim populates for a domain + # Ingress, and deletes it (and the Ingress above) when a domain is + # removed. Never create/update — cert-manager, not deployer, writes this + # secret. + - apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "list", "watch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: toolshed-deployer-ingress + namespace: toolshed + labels: + app.kubernetes.io/part-of: toolshed +subjects: + - kind: ServiceAccount + name: toolshed-deployer + namespace: toolshed +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: toolshed-deployer-ingress