Improve PostgreSQL role separation, provisioning, and connection management - #1752
Jeremy Alvis (iplay88keys) wants to merge 18 commits into
Conversation
…s-runtime-ddl-roles
…s-runtime-ddl-roles
Eitan Yarmush (EItanya)
left a comment
There was a problem hiding this comment.
🤖 AI-generated review.
I found three reproducible configuration issues, detailed inline. The five affected package suites passed, and an additional PostgreSQL 18 probe passed the actual OpenFGA migrations and initialization with the restricted roles. Cluster E2E was not run locally.
|
I have local changes that add a second Cloud SQL Auth Proxy sidecar to This provides separate PostgreSQL logins for runtime operations and owner operations, although it is not a hard security boundary still because the runtime identity retains permission to impersonate the owner GSA. I also considered the other way around and having the pod's KSA be the owner, which would impersonate the runtime GSA, but that would make the more privileged owner GSA the pod's ambient identity. The least-privileged option there was to have the runtime KSA. Achieving stronger separation would require moving owner operations out of Julian Gutierrez Oschmann (@juli4n) Eitan Yarmush (@EItanya) Joe Betz (@jpbetz), I’m happy to include the two-proxy approach in this PR, but I think the broader separation should be handled in a follow-up PR with an agreed-upon design and scope. |
…s-runtime-ddl-roles # Conflicts: # cmd/ateapi/internal/authz/authz_util.go # cmd/ateapi/internal/store/atepg/atepg.go # cmd/ateapi/main.go # internal/authz/server_test.go
…s-runtime-ddl-roles # Conflicts: # cmd/ate-setup/internal/config/config.go # cmd/ate-setup/internal/steps/deploy.go # cmd/ate-setup/internal/steps/postgres.go # cmd/ate-setup/internal/steps/postgres_test.go
…s-runtime-ddl-roles # Conflicts: # cmd/ateapi/main_test.go
Fixes #997
Summary
Note
See
docs/postgres.mdfor information about how this works in practice.ateapiseparate PostgreSQL owner and read/write connections. Migrations and owner maintenance use the owner pool; application reads and writes use the read/write pool. Each connection assumes its configured group role, so an operator can replace a login without changing object ownership.ateapiruns default to bootstrap disabled.@file:/absolute/pathfor both owner and read/write connection strings. Substrate rereads each projected Secret file when opening a new physical connection, so rotated credentials can take effect without restarting the process. The--postgres-max-conn-lifetimeCLI flag sets the maximum connection lifetime, bounding how long old connections remain in use; endpoint or database changes still require a restart.ate-setupand the installation manifests. The shell installer now delegates toate-setup. Its previous single-connection environment variable still supplies both pools when used alone and remains the owner connection when a separate read/write DSN is added. Bundled PostgreSQL requires password authentication plus its existing client certificate check.substrateschema, following best practices to not use thepublicschema from the Postgres Wiki.Scope
This identity layout requires a fresh PostgreSQL database. The PR does not migrate existing users, grants, or tables into it.
The bundled-database installers enable bootstrap to provision Substrate's fixed identities.
ateapialso accepts explicit administrator and application connections for a managed shared database; it has no way to infer which deployment owns PostgreSQL. Deployments using operator-managed users disable bootstrap and provide precreated roles, memberships, schema, and grants.Cloud SQL intentionally uses one IAM database login by default. The owner connection defaults to the read/write connection, and each pool assumes its configured role. Separate logins remain supported through separate connection strings, but requiring two IAM logins would add proxy identity setup. Two logins limit exposure if only the read/write credential leaks; because
ateapiholds both pools, they do not isolate a compromisedateapipod. Stronger isolation would require moving owner operations out of that pod.The bootstrap usernames and passwords are fixed, published development credentials. Do not enable fixed-identity bootstrap against a production database. For production, provision unique logins and permissions outside
ateapi, supply their connection strings, and leave bootstrap disabled.Reviewer Notes
ateapi. The current implementation has a single iam account which has both roles. Each pool does aSET ROLEto the appropriate role (owner for migrations and outbox partition management or read/write for runtime access).