prole/deploy/gcp/gke/knoe-db.yaml
chrisfu 872d715864 feat: Kerberos identity management — PROLE.LOCAL realm, cross-realm trust, user provisioning
Kerberos is now the single source of truth for all knoe-system accounts.

In-cluster KDC (PROLE.LOCAL):
- Rename in-cluster KDC realm PROLE.ORG → PROLE.LOCAL to avoid collision
  with the myrddin.prole.org Samba AD DC which owns PROLE.ORG
- Add [capaths] cross-realm trust block: PROLE.ORG (Samba AD) ↔ PROLE.LOCAL
- Create admin@PROLE.LOCAL on KDC startup (master password) for UI login
- Create guest@PROLE.LOCAL on KDC startup (read-only, PROLE_KDC_GUEST_PASSWORD)
- Update prole-kdc-secrets.example.yaml with trust_shared_password and guest_password
- Update prole-auth-kerberos ConfigMap realm/servicePrincipal to PROLE.LOCAL
- Add PROLE_AUTH_ADMIN_PRINCIPALS and PROLE_KDC_GUEST_PASSWORD to prole-auth Deployment

Database (knoe-db — k3s and GKE):
- Add spec.managed.roles: admin (superuser), guest (login), developer (group)
- Enable GSS pg_hba rules for both PROLE.ORG and PROLE.LOCAL realms
- Add krb_server_keyfile parameter for postgres service principal keytab
- Mount knoe-db-pg-keytab Secret via spec.additionalVolumes
- Add demo schema in postInitSQL with guest read-only grants

prole-auth (Spring Boot):
- SessionUser: add List<String> groups field
- AuthProperties: add adminPrincipals list (env: PROLE_AUTH_ADMIN_PRINCIPALS)
- LoginController: stamp groups=["admin"] for configured admin principals at login
- SessionTokenService: carry groups through TokenPayload; @JsonIgnoreProperties
  for backward compat with existing 2-field session cookies
- VerifyController: emit X-Prole-Groups header on /auth/verify
- grafana-proxy nginx: strip inbound X-Prole-Groups; capture and forward from auth

Services:
- ArgoCD (k3s + GKE): add g, admin, role:admin to argocd-rbac-cm policy.csv

etc/init_knoe_users.sh (new):
- Orchestrates full user provisioning: KDC principals, postgres keytab export,
  CNPG managed.roles patch, demo schema SQL, ArgoCD RBAC patch,
  Gitea and GitLab admin promotion via API
- Actions: initialize | status | cleanup
- Idempotent; sources prole_cfg.sh; follows existing init_*.sh style

Cross-realm trust activation (myrddin side):
  samba-tool user add krbtgt_PROLELOCAL --random-password
  samba-tool user setpassword krbtgt_PROLELOCAL --newpassword=<trust_shared_password>
  samba-tool spn add "krbtgt/PROLE.LOCAL" krbtgt_PROLELOCAL -U administrator
  samba-tool user setexpiry krbtgt_PROLELOCAL --noexpiry

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-01 20:38:57 -07:00

128 lines
3.8 KiB
YAML

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: knoe-db
namespace: ecosystem-0
spec:
instances: 3
# Image pulled from GCP Artifact Registry — set ARTIFACT_REGISTRY in conf/prod/gcp.cfg
# e.g. us-central1-docker.pkg.dev/<project>/prole/knoe-db:18-140
imageName: "${ARTIFACT_REGISTRY}/knoe-db:18-140"
postgresUID: 100
postgresGID: 101
maxSyncReplicas: 1
affinity:
enablePodAntiAffinity: true
podAntiAffinityType: preferred
topologyKey: topology.kubernetes.io/zone # GKE zone-aware spreading
postgresql:
parameters:
shared_buffers: 256MB
pg_stat_statements.max: '10000'
pg_stat_statements.track: all
shared_preload_libraries:
- pg_stat_statements
- pg_tde
pg_hba:
- local all postgres trust
- local all prole scram-sha-256
- host all postgres all scram-sha-256
- host prole knoe-db all scram-sha-256
- host all all all scram-sha-256
- hostssl prole knoe-db all scram-sha-256
bootstrap:
initdb:
database: knoe-db
owner: prole
localeCollate: 'en_US.utf8'
localeCType: 'en_US.utf8'
secret:
name: knoe-db-user
postInitTemplateSQL:
- CREATE EXTENSION IF NOT EXISTS pg_stat_statements;
postInitSQL:
- CREATE EXTENSION IF NOT EXISTS pg_tde;
- CREATE EXTENSION IF NOT EXISTS pgcrypto;
- GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO prole;
- CREATE EXTENSION IF NOT EXISTS postgis;
- CREATE EXTENSION IF NOT EXISTS postgis_topology;
- CREATE EXTENSION IF NOT EXISTS vector;
- CREATE EXTENSION IF NOT EXISTS tds_fdw;
- GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO prole;
- GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA topology TO prole;
- CREATE SCHEMA IF NOT EXISTS storage;
- CREATE SCHEMA IF NOT EXISTS graphql_public;
- CREATE ROLE anon NOLOGIN;
- CREATE ROLE authenticator LOGIN;
- GRANT USAGE ON SCHEMA public TO anon;
- GRANT USAGE ON SCHEMA storage TO anon;
- GRANT USAGE ON SCHEMA graphql_public TO anon;
- GRANT anon TO authenticator;
# demo schema for guest read-only access (evolves over time)
- CREATE SCHEMA IF NOT EXISTS demo;
- GRANT USAGE ON SCHEMA demo TO guest;
- ALTER DEFAULT PRIVILEGES IN SCHEMA demo GRANT SELECT ON TABLES TO guest;
managed:
roles:
- name: admin
ensure: present
login: true
superuser: true
comment: "Admin principal — full cluster database access"
- name: guest
ensure: present
login: true
superuser: false
comment: "Guest principal — read-only access to demo schema"
- name: developer
ensure: present
login: false
superuser: false
comment: "Developer group role — granted to knoe-system user accounts"
certificates:
serverTLSSecret: knoe-db-tls
serverCASecret: knoe-db-ca
enableSuperuserAccess: true
# GCS backup via Workload Identity — see knoe-db-backup-gcs.yaml
backup:
barmanObjectStore:
destinationPath: "gs://knoe-0-backups/"
googleCredentials:
applicationCredentials:
name: "" # empty = Workload Identity; no static key needed
wal:
compression: gzip
data:
compression: gzip
retentionPolicy: "14d"
storage:
size: 100Gi
pvcTemplate:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: premium-rwo # GCP SSD persistent disk (pd-ssd)
walStorage:
size: 20Gi
pvcTemplate:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
storageClassName: premium-rwo
monitoring:
enablePodMonitor: true # GKE managed Prometheus