diff --git a/k8s/data/cluster/ddb-cluster.yaml b/k8s/data/cluster/ddb-cluster.yaml index 28da2ff..e2c2650 100644 --- a/k8s/data/cluster/ddb-cluster.yaml +++ b/k8s/data/cluster/ddb-cluster.yaml @@ -27,22 +27,10 @@ spec: - CREATE EXTENSION IF NOT EXISTS pgcrypto; - CREATE EXTENSION IF NOT EXISTS pg_trgm; - # Per-app login roles, passwords sourced from secrets (CNPG reconciles the - # role password to match the secret). Their databases are separate Database - # CRs (see authentik-database.yaml / temporal-database.yaml) owned by these - # roles. Replaces the old helmfile post-sync user-creation hook. - managed: - roles: - - name: authentik - ensure: present - login: true - passwordSecret: - name: authentik-db-role - - name: temporal - ensure: present - login: true - passwordSecret: - name: temporal-db-role + # Simple ownership model: all apps use 'app' bootstrap user. + # Isolation via separate database names, not separate roles. + # Aligns with CNPG design (single cluster, multiple databases). + # managed.roles removed - no per-app roles needed. # Disable superuser (security) enableSuperuserAccess: false diff --git a/k8s/data/schemas/authentik-database.yaml b/k8s/data/schemas/authentik-database.yaml index 63a3859..fb3d791 100644 --- a/k8s/data/schemas/authentik-database.yaml +++ b/k8s/data/schemas/authentik-database.yaml @@ -5,6 +5,6 @@ metadata: namespace: ddb spec: name: authentik - owner: authentik + owner: app # All apps use shared 'app' user (CNPG design pattern) cluster: name: ddb-cluster diff --git a/k8s/data/schemas/grant-schema-permissions-job.yaml b/k8s/data/schemas/grant-schema-permissions-job.yaml deleted file mode 100644 index 1813d5d..0000000 --- a/k8s/data/schemas/grant-schema-permissions-job.yaml +++ /dev/null @@ -1,122 +0,0 @@ -# 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' - -- Database-level permission (needed for CREATE SCHEMA) - GRANT CREATE ON DATABASE authentik TO authentik; - -- Schema-level permissions - 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' - -- Database-level permission - GRANT CREATE ON DATABASE temporal TO temporal; - -- Schema-level permissions - 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' - -- Database-level permission - GRANT CREATE ON DATABASE temporal_visibility TO temporal; - -- Schema-level permissions - 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 diff --git a/k8s/data/schemas/kustomization.yaml b/k8s/data/schemas/kustomization.yaml index d114433..415fabf 100644 --- a/k8s/data/schemas/kustomization.yaml +++ b/k8s/data/schemas/kustomization.yaml @@ -8,7 +8,6 @@ namespace: ddb # GitOps-managed database schemas (ArgoCD wave 6). # These depend on ddb-cluster existing (bootstrap wave 0). resources: - - grant-schema-permissions-job.yaml - authentik-database.yaml - temporal-database.yaml - temporal-visibility-database.yaml diff --git a/k8s/data/schemas/temporal-database.yaml b/k8s/data/schemas/temporal-database.yaml index 2559ace..10a61aa 100644 --- a/k8s/data/schemas/temporal-database.yaml +++ b/k8s/data/schemas/temporal-database.yaml @@ -5,6 +5,6 @@ metadata: namespace: ddb spec: name: temporal - owner: temporal + owner: app # All apps use shared 'app' user (CNPG design pattern) cluster: name: ddb-cluster diff --git a/k8s/data/schemas/temporal-visibility-database.yaml b/k8s/data/schemas/temporal-visibility-database.yaml index 4ec95c0..f7cb6b6 100644 --- a/k8s/data/schemas/temporal-visibility-database.yaml +++ b/k8s/data/schemas/temporal-visibility-database.yaml @@ -5,6 +5,6 @@ metadata: namespace: ddb spec: name: temporal_visibility - owner: temporal + owner: app # All apps use shared 'app' user (CNPG design pattern) cluster: name: ddb-cluster