diff --git a/templates/serviceaccount.yaml b/templates/serviceaccount.yaml index b10066a..71601e1 100644 --- a/templates/serviceaccount.yaml +++ b/templates/serviceaccount.yaml @@ -29,6 +29,36 @@ rules: - apiGroups: ['metrics.k8s.io'] resources: ['nodes'] verbs: ['get', 'list'] + # Tenant-control surface: when the destination cluster IS the + # admin platform (in-cluster lab1), Tower acts on `tenants` ns + # resources directly using its own ServiceAccount. When the + # destination is a registered customer cluster (e.g. customer1), + # Tower uses that cluster's admin cert and these in-cluster + # rules don't apply. Without these, the in-cluster path of every + # backup/restore/migrate flow returned 403 from the K8s API + # service-proxy and `waitForOdooReady` looped to timeout. + # + # `services/proxy` is the specific subresource the probe needs; + # the rest (jobs/pods/STSes/Deployments/svc/secret/cm/pvc) cover + # spawn-Job + scaleDeployment + delete-cascade. + - apiGroups: [''] + resources: ['services/proxy'] + verbs: ['get', 'create'] + - apiGroups: [''] + resources: ['pods', 'pods/log', 'pods/exec'] + verbs: ['get', 'list', 'watch', 'create', 'delete'] + - apiGroups: ['apps'] + resources: ['deployments', 'deployments/scale', 'statefulsets', 'statefulsets/scale', 'replicasets'] + verbs: ['get', 'list', 'watch', 'patch', 'update', 'delete'] + - apiGroups: ['batch'] + resources: ['jobs', 'cronjobs'] + verbs: ['get', 'list', 'watch', 'create', 'patch', 'update', 'delete'] + - apiGroups: [''] + resources: ['services', 'secrets', 'configmaps', 'persistentvolumeclaims', 'events'] + verbs: ['get', 'list', 'watch', 'patch', 'update', 'delete'] + - apiGroups: ['traefik.io'] + resources: ['ingressroutes'] + verbs: ['get', 'list', 'delete'] # Read ArgoCD's cluster Secrets (the registered customer-cluster # creds) so Tower can build cross-cluster API clients for capacity # queries. Scoped to a single Role+RoleBinding in the argocd ns —