# PostSync Job to grant schema permissions after Database CRs reconcile # # ROOT CAUSE: CNPG Database CR creates databases but doesn't grant schema # permissions to the specified owner role. The bootstrap database owner # (app) retains CREATE privilege on public schema, blocking other roles. # # SOLUTION: After Database CRs reconcile, connect as 'app' (DB owner) and # grant ALL on schema public to each Database's owner role. # # This runs every sync (BeforeHookCreation policy), ensuring permissions # survive CNPG database recreation or cluster rebuilds. apiVersion: v1 kind: ServiceAccount metadata: name: grant-schema-permissions namespace: ddb --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: grant-schema-permissions namespace: ddb rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get"] - apiGroups: ["postgresql.cnpg.io"] resources: ["databases"] verbs: ["list", "get"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: grant-schema-permissions namespace: ddb subjects: - kind: ServiceAccount name: grant-schema-permissions namespace: ddb roleRef: kind: Role name: grant-schema-permissions apiGroup: rbac.authorization.k8s.io --- apiVersion: batch/v1 kind: Job metadata: name: grant-schema-permissions namespace: ddb annotations: argocd.argoproj.io/hook: PostSync argocd.argoproj.io/hook-delete-policy: BeforeHookCreation spec: backoffLimit: 5 template: spec: serviceAccountName: grant-schema-permissions restartPolicy: Never containers: - name: grant-permissions image: postgres:16-alpine command: - /bin/sh - -c - | set -e echo "Granting schema permissions to database owners..." # Get app user password (owns all databases) export PGPASSWORD=$(cat /app-secret/password) PGHOST=ddb-cluster-rw.ddb.svc.cluster.local PGUSER=app # Grant for authentik database echo "Granting to authentik role in authentik database..." psql -h "$PGHOST" -U "$PGUSER" -d authentik << 'SQL' GRANT ALL ON SCHEMA public TO authentik; GRANT ALL ON ALL TABLES IN SCHEMA public TO authentik; GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO authentik; ALTER DEFAULT PRIVILEGES FOR ROLE app IN SCHEMA public GRANT ALL ON TABLES TO authentik; ALTER DEFAULT PRIVILEGES FOR ROLE app IN SCHEMA public GRANT ALL ON SEQUENCES TO authentik; SQL # Grant for temporal database echo "Granting to temporal role in temporal database..." psql -h "$PGHOST" -U "$PGUSER" -d temporal << 'SQL' GRANT ALL ON SCHEMA public TO temporal; GRANT ALL ON ALL TABLES IN SCHEMA public TO temporal; GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO temporal; ALTER DEFAULT PRIVILEGES FOR ROLE app IN SCHEMA public GRANT ALL ON TABLES TO temporal; ALTER DEFAULT PRIVILEGES FOR ROLE app IN SCHEMA public GRANT ALL ON SEQUENCES TO temporal; SQL # Grant for temporal_visibility database echo "Granting to temporal role in temporal_visibility database..." psql -h "$PGHOST" -U "$PGUSER" -d temporal_visibility << 'SQL' GRANT ALL ON SCHEMA public TO temporal; GRANT ALL ON ALL TABLES IN SCHEMA public TO temporal; GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO temporal; ALTER DEFAULT PRIVILEGES FOR ROLE app IN SCHEMA public GRANT ALL ON TABLES TO temporal; ALTER DEFAULT PRIVILEGES FOR ROLE app IN SCHEMA public GRANT ALL ON SEQUENCES TO temporal; SQL echo "✅ Schema permissions granted successfully" volumeMounts: - name: app-secret mountPath: /app-secret readOnly: true volumes: - name: app-secret secret: secretName: ddb-cluster-app