fix(db/migrate): preserve verify-ca/verify-full TLS mode in migration DSN#1360
Conversation
… DSN buildMigrateDSN inferred the migration sslmode solely from whether TLSConfig was nil, collapsing every TLS-enabled configuration to sslmode=require. This silently downgraded stricter modes (verify-ca, verify-full, both supported in internal/database/config.go) during migrations, dropping the certificate validation the application enforces in normal operation. Recover the exact mode from the parsed pgx TLSConfig via sslModeFromTLSConfig, which inverts pgx's sslmode -> *tls.Config mapping (nil -> disable; InsecureSkipVerify without a VerifyPeerCertificate callback -> require; InsecureSkipVerify with the callback -> verify-ca; InsecureSkipVerify=false -> verify-full). Add TestBuildMigrateDSN_PreservesSSLMode, which round-trips each mode DSN -> pgx TLSConfig -> migration DSN and pins the version-specific mapping; it fails on the pre-fix inference for verify-ca and verify-full.
|
Important Review skippedNo new commits to review since the last review. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughMigration DSN construction now derives PostgreSQL ChangesPostgreSQL migration TLS handling
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
internal/database/postgres/migrations/migrate.go (1)
532-544: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winPreserve the CA path for migration connections
internal/database/postgres/migrations/migrate.go:520-544only carriessslmode; it drops anysslrootcert/CA source, andinternal/database/config.godoesn’t expose one elsewhere.verify-ca/verify-fullwill only work if lib/pq can find its default trust anchor, so strict-TLS deployments can fail here. Thread the root cert through to the migration DSN as well.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/database/postgres/migrations/migrate.go` around lines 532 - 544, Update the migration DSN construction in the shown migration connection flow to preserve the TLS root certificate/CA source alongside sslmode. Thread the configured CA path into the generated postgres URL using lib/pq’s sslrootcert option, while retaining the existing behavior for connections without a configured CA.
🧹 Nitpick comments (2)
internal/database/postgres/migrations/migrate_security_test.go (1)
136-154: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider covering
require+sslrootcert.The table only exercises bare
sslmodevalues, so it can't catch that pgx mapsrequire+sslrootcerttoverify-ca(see thesslModeFromTLSConfigcomment), nor whether strict modes actually connect during migration. A subtest withsslrootcertset would pin that behavior.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/database/postgres/migrations/migrate_security_test.go` around lines 136 - 154, Extend TestBuildMigrateDSN_PreservesSSLMode with a subtest or table case combining sslmode=require and an sslrootcert value, then assert that buildMigrateDSN preserves the resulting pgx mapping as sslmode=verify-ca. Use a valid certificate path or test fixture accepted by pgxpool.ParseConfig, and retain the existing bare-mode coverage.internal/database/postgres/migrations/migrate.go (1)
547-578: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winClarify the
require + sslrootcertcase in the TLS mapping.
pgx treats that combination asverify-ca, so therequirebullet should be narrowed torequirewithout a root cert. Add a test case forsslmode=require&sslrootcert=...to pin the round-trip behavior.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/database/postgres/migrations/migrate.go` around lines 547 - 578, Clarify the sslModeFromTLSConfig mapping documentation so the require case explicitly excludes configurations with a root certificate, since pgx maps require plus sslrootcert to verify-ca. Add a focused test covering sslmode=require with sslrootcert and assert that the round-trip preserves the resulting verify-ca mode.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@internal/database/postgres/migrations/migrate.go`:
- Around line 532-544: Update the migration DSN construction in the shown
migration connection flow to preserve the TLS root certificate/CA source
alongside sslmode. Thread the configured CA path into the generated postgres URL
using lib/pq’s sslrootcert option, while retaining the existing behavior for
connections without a configured CA.
---
Nitpick comments:
In `@internal/database/postgres/migrations/migrate_security_test.go`:
- Around line 136-154: Extend TestBuildMigrateDSN_PreservesSSLMode with a
subtest or table case combining sslmode=require and an sslrootcert value, then
assert that buildMigrateDSN preserves the resulting pgx mapping as
sslmode=verify-ca. Use a valid certificate path or test fixture accepted by
pgxpool.ParseConfig, and retain the existing bare-mode coverage.
In `@internal/database/postgres/migrations/migrate.go`:
- Around line 547-578: Clarify the sslModeFromTLSConfig mapping documentation so
the require case explicitly excludes configurations with a root certificate,
since pgx maps require plus sslrootcert to verify-ca. Add a focused test
covering sslmode=require with sslrootcert and assert that the round-trip
preserves the resulting verify-ca mode.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d6016c00-ea3e-4329-b8ee-f33c90c70d75
📒 Files selected for processing (2)
internal/database/postgres/migrations/migrate.gointernal/database/postgres/migrations/migrate_security_test.go
What
buildMigrateDSN(used to build the golang-migrate connection string) inferred the migrationsslmodesolely from whether the pgxTLSConfigwas nil:This collapses every TLS-enabled configuration to
sslmode=require, silently downgrading stricter modes (verify-ca,verify-full, both supported ininternal/database/config.go). During migrations the connection then performs no certificate-chain or hostname verification that the application enforces in normal operation, so a deployment configured forverify-fullruns its migrations withrequire-level (no verification) TLS.Fix
Recover the exact mode from the parsed pgx
TLSConfigvia a newsslModeFromTLSConfig, inverting pgx v5'ssslmode -> *tls.Configmapping:disablerequireInsecureSkipVerify=true, noVerifyPeerCertificateverify-caInsecureSkipVerify=true+ aVerifyPeerCertificatecallbackverify-fullInsecureSkipVerify=false+ServerNameAdded
TestBuildMigrateDSN_PreservesSSLMode, which round-trips each modeDSN -> pgx TLSConfig -> migration DSNand pins the version-specific mapping. It fails on the pre-fix inference forverify-caandverify-full(both downgraded torequire) and passes after the fix.Provenance
Extracted from #1276, which is now closed as superseded by main's independent golangci-lint sweep (that branch reached the same lint-clean state via root-cause fixes, ~30 nolints, rather than #1276's ~291 suppressions). This TLS-mode preservation is the one unique, non-lint fix on that branch and does not belong to the lint theme, so it lands here on its own.
Verification
go build ./...passes.golangci-lintadds 0 new issues overorigin/main(--new-from-rev origin/mainclean); the pre-existing findings inmigrate.goare main's baseline, untouched..golangci.ymlbyte-identical toorigin/main.Summary by CodeRabbit
Bug Fixes
Tests