feat(db): allow a provider to supply the database password - #1606
Open
Moustafa-Moustafa wants to merge 1 commit into
Open
feat(db): allow a provider to supply the database password#1606Moustafa-Moustafa wants to merge 1 commit into
Moustafa-Moustafa wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds an optional hook for dynamically supplying PostgreSQL passwords at connection time, enabling Nebraska to use short-lived/rotating credentials (e.g., cloud IAM tokens) without requiring a process restart.
Changes:
- Extend the internal DB connection opener to optionally consult a password function before each physical connection (via pgx
BeforeConnect). - Introduce a public
api.DBPasswordProviderinterface plus a global setter used byapi.New(). - Add tests covering provider rotation, provider error propagation, and the no-provider default behavior; document the feature in the changelog.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| CHANGELOG.md | Documents the new pluggable DB password provider capability. |
| backend/pkg/api/internal/dbconn/conn.go | Adds optional provider-aware connection opening using pgx BeforeConnect. |
| backend/pkg/api/dbpassword.go | Introduces DBPasswordProvider and the global install hook used by api.New(). |
| backend/pkg/api/dbpassword_test.go | Adds tests for rotated credentials, error propagation, and default behavior. |
| backend/pkg/api/api.go | Wires dbPasswordFunc() into the shared DB connection initialization. |
Suppressed comments (1)
backend/pkg/api/dbpassword.go:36
- SetDBPasswordProvider accepts an interface, so it’s possible to pass a typed-nil implementation (e.g. var p *myProvider = nil; SetDBPasswordProvider(p)). In that case dbPasswordProvider != nil, and dbPasswordFunc will return a method value with a nil receiver, which can lead to a panic when Nebraska opens a connection. It would be safer to treat typed-nil providers as nil (typically via a small reflect-based nilability check) either here or in dbPasswordFunc().
// SetDBPasswordProvider installs the provider New authenticates with. Call it
// before New.
func SetDBPasswordProvider(provider DBPasswordProvider) {
dbPasswordMu.Lock()
defer dbPasswordMu.Unlock()
dbPasswordProvider = provider
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Moustafa-Moustafa
force-pushed
the
feat/db-password-provider
branch
from
August 22, 2026 17:54
525617d to
16718c5
Compare
Moustafa-Moustafa
force-pushed
the
feat/db-password-provider
branch
from
August 22, 2026 18:53
16718c5 to
ff1a0d2
Compare
Nebraska takes the database password from NEBRASKA_DB_URL. That string is fixed for the life of the process, so a deployment whose credential expires, such as an OAuth token from a cloud identity provider, has no in-process way to supply a new one: the first connection attempted after expiry fails, and so does every one after that. DBPasswordProvider is an optional hook consulted before each physical connection. When one is installed the handle is opened through pgx's BeforeConnect callback, which runs for every new connection and receives a fresh copy of the connection config, so the provider can return a credential renewed since startup. How that credential is obtained is not Nebraska's concern, and no cloud SDK is added; go.mod is unchanged. That callback runs before pgx applies connect_timeout, so when the URL carries one the provider call is bounded by it. The provider is given the user the connection authenticates as, so one provider can serve connections made as different roles. Both connections consult it: the serving one from NEBRASKA_DB_URL, and the short-lived migrations one from NEBRASKA_MIGRATIONS_DB_URL, which authenticates as a different role. Deployments that install no provider are untouched. Both connections take the plain sqlx.Open path exactly as before and the passwords keep coming from the URLs. Signed-off-by: Moustafa Moustafa <momousta@microsoft.com>
Moustafa-Moustafa
force-pushed
the
feat/db-password-provider
branch
from
August 24, 2026 18:36
ff1a0d2 to
397a263
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat(db): allow a provider to supply the database password
Nebraska takes the database password from
NEBRASKA_DB_URL. That string is fixed for the life of the process, so a deployment whose credential expires, such as an OAuth token from a cloud identity provider, has no in-process way to supply a new one: the first connection attempted after expiry fails, and so does every one after that.DBPasswordProvideris an optional hook consulted before each physical connection. When one is installed the handle is opened through pgx'sBeforeConnectcallback, which runs for every new connection and receives a fresh copy of the connection config, so the provider can return a credential renewed since startup. How that credential is obtained is not Nebraska's concern, and no cloud SDK is added;go.modis unchanged.The callback runs before pgx applies
connect_timeout, so the provider call is bounded by that same timeout. A provider that never answers fails the connection instead of holding up every one the pool is trying to open.The provider is given the user the connection authenticates as, so a single provider can serve connections made as different roles. That is what a deployment needs if it ever runs migrations under a separate role, as #1575 proposes.
Deployments that install no provider are untouched. The plain
sqlx.Openpath runs exactly as before and the password keeps coming fromNEBRASKA_DB_URL.How to use
No new behavior is introduced for anyone who does not install a provider, so the first thing to validate is that an existing deployment is not impacted at all.
To use it, implement the interface and install it in
cmd/nebraska/main.gobefore the database is created:func main() { conf, err := config.Parse() ... + db.SetDBPasswordProvider(tokenProvider{}) + if conf.RollbackDBTo != "" { db, err := db.New()It goes above the
RollbackDBTobranch so it covers both connectionsmaincan open, the down-migration one anddb.NewWithMigrations().The password in
NEBRASKA_DB_URLis then ignored; the user, host and database in it are still used.The same shape is used by netdata for Azure Entra ID and bytebase for AWS RDS IAM.
Testing done
Three tests cover the new path: that the provider is consulted for every connection and a rotated credential is picked up, that a provider error fails the connection, and that without a provider the URL password is still used.
changelog/directory (user-facing change, bug fix, security fix, update)/bootand/usrsize, packages, list files for any missing binaries, kernel modules, config files, kernel modules, etc.