Skip to content

postgres: add Azure AD and GCP Cloud SQL IAM dynamic-auth backends - #262

Open
reyortiz3 wants to merge 1 commit into
mainfrom
postgres-azure-gcp-dynamic-auth
Open

postgres: add Azure AD and GCP Cloud SQL IAM dynamic-auth backends#262
reyortiz3 wants to merge 1 commit into
mainfrom
postgres-azure-gcp-dynamic-auth

Conversation

@reyortiz3

Copy link
Copy Markdown
Contributor

Closes #261.

Summary

Adds two dynamic-auth backends alongside the existing AWS RDS IAM one, and generalizes the backend-dispatch plumbing (Config.Validate, NewAuthToken, NewDynamicAuthFunc) to support three backends cleanly via singleDynamicAuthBackend/countDynamicAuthBackends, instead of a single hardcoded AWS check. This also newly rejects a config with more than one backend set — previously unreachable with only one backend to choose from, but a real ambiguity risk now that there are three.

  • DynamicAuthAzureAD — Entra ID (formerly Azure AD) tokens for Azure Database for PostgreSQL, via azidentity.DefaultAzureCredential's normal resolution chain (env vars, workload identity, managed identity, Azure CLI — AZURE_CLIENT_ID selects a user-assigned managed identity). Same BeforeConnect token-swap shape as AWS RDS IAM.
  • DynamicAuthGCPCloudSQLIAM — OAuth2 tokens for GCP Cloud SQL IAM database authentication, minted from ambient Application Default Credentials. This is the direct-TCP token-swap path, not the Cloud SQL Go connector (cloudsqlconn): it requires the instance to have a reachable IP and does not get Cloud SQL's automatic mTLS tunnel. The connector is a structurally different piece of work (needs a DialFunc-based extension point this package doesn't have, not a BeforeConnect password swap) — deliberately out of scope here, per postgres: add Azure AD and GCP Cloud SQL IAM dynamic-auth backends #261.

Testing notes (read before assuming symmetry between the two backends)

  • Azure: azidentity.NewDefaultAzureCredential's construction is credential-free — resolution is deferred to the first GetToken call — so azureADBeforeConnect is unit-tested the same way awsRDSIAMBeforeConnect already is (asserts a non-nil hook is returned; never invokes it, since invocation needs real credentials).
  • GCP: verified empirically (not assumed) that google.DefaultTokenSource resolves Application Default Credentials eagerly and errors immediately when none are found, unlike AWS/Azure. That makes even "does the constructor return a non-nil hook" environment-dependent — a machine with real GCP credentials configured would get a different result than this dev sandbox did. So there's deliberately no equivalent invocation-level test for the GCP backend; the comment at the bottom of azuread_test.go explains why, rather than silently omitting coverage with no trace of the decision.

Verification

  • go build ./..., go vet ./..., golangci-lint run ./... — all clean.
  • go test ./postgres/... — all pass, including new cases for both backends and the multi-backend-configured rejection.
  • govulncheck ./postgres/... — no vulnerabilities in code added by this PR (one pre-existing, already-tracked golang.org/x/crypto/openpgp finding unrelated to this change and not reachable from it — see issue Drop the GO-2026-5932 openpgp exclusion once rekor releases the migration #231).
  • go mod tidy run; azcore/azidentity promoted from indirect to direct deps; golang.org/x/oauth2/google needed no new module dependency (already required at v0.36.0).

Not in this PR

Adds two dynamic-auth backends alongside the existing AWS RDS IAM one,
plus generalizes the backend-dispatch plumbing to support three (and
future) backends cleanly instead of a single hardcoded check.

- DynamicAuthAzureAD: Entra ID (formerly Azure AD) tokens for Azure
  Database for PostgreSQL, via azidentity.DefaultAzureCredential's normal
  resolution chain (env vars, workload identity, managed identity, Azure
  CLI). Construction is credential-free (lazy resolution deferred to
  GetToken), so it's unit-tested the same way the AWS backend is.

- DynamicAuthGCPCloudSQLIAM: OAuth2 tokens for GCP Cloud SQL IAM database
  authentication, minted from ambient Application Default Credentials.
  This is the direct-TCP token-swap path, not the Cloud SQL Go connector
  (cloudsqlconn) — it requires the instance to have a reachable IP and
  does not get Cloud SQL's automatic mTLS tunnel; that's a deliberately
  separate, larger piece of work (a DialFunc-based extension point, not
  a BeforeConnect password swap), tracked in #261 as a follow-up.
  Unlike AWS/Azure, google.DefaultTokenSource resolves credentials
  eagerly rather than lazily, so its outcome is environment-dependent —
  this backend has no invocation-level unit test, and the comment at the
  bottom of azuread_test.go explains why, rather than silently omitting
  it.

- Config.Validate, NewAuthToken, and NewDynamicAuthFunc's per-backend
  dispatch is generalized via singleDynamicAuthBackend/
  countDynamicAuthBackends, which also newly rejects a config with more
  than one backend set (previously unreachable with only one backend to
  choose from).

Closes #261.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

postgres: add Azure AD and GCP Cloud SQL IAM dynamic-auth backends

1 participant