Skip to content

feat: update db pooling to handle iam rds auth, move DatabaseConfiguration to dawgs#65

Merged
mamundsen-specter merged 4 commits intomainfrom
bi-1306
Apr 23, 2026
Merged

feat: update db pooling to handle iam rds auth, move DatabaseConfiguration to dawgs#65
mamundsen-specter merged 4 commits intomainfrom
bi-1306

Conversation

@mamundsen-specter
Copy link
Copy Markdown
Contributor

@mamundsen-specter mamundsen-specter commented Apr 22, 2026

…ation to dawgs

Description

Recreated from previous PR: #32
Didn't have commit signing enabled for this repo and figured it would be easier to create a new branch/PR instead of attempting to squash merge commits.

Updates pg pooling to enable IAM auth. Moves DatabaseConfiguation to DAWGs repo from the BHCE repo.

Resolves: <TICKET_OR_ISSUE_NUMBER>

Type of Change

  • Chore (a change that does not modify the application functionality)
  • Bug fix (a change that fixes an issue)
  • [X ] New feature / enhancement (a change that adds new functionality)
  • Refactor (no behaviour change)
  • Test coverage
  • Build / CI / tooling
  • Documentation

Testing

  • Unit tests added / updated
  • Integration tests added / updated
  • Manual integration tests run (go test -tags manual_integration ./integration/...)

Test tenant created with IAM enabled.

Screenshots (if appropriate):

Driver Impact

  • [X ] PostgreSQL driver (drivers/pg)
  • Neo4j driver (drivers/neo4j)

Checklist

  • Code is formatted
  • All existing tests pass
  • go.mod / go.sum are up to date if dependencies changed

Summary by CodeRabbit

  • New Features

    • Added AWS RDS IAM authentication support for PostgreSQL, enabling credential-free connections via AWS auth tokens.
    • Improved Neo4j connection configuration with more flexible centralized management.
  • Refactor

    • Unified and simplified database configuration and connection initialization for more consistent, reliable behavior across tools.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

Warning

Rate limit exceeded

@mamundsen-specter has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 31 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 10 minutes and 31 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: da68a51b-5ecf-4d75-8498-0e8fd778c175

📥 Commits

Reviewing files that changed from the base of the PR and between 45b752d and 53169ec.

📒 Files selected for processing (1)
  • drivers/config.go

Walkthrough

Adds a new drivers.DatabaseConfiguration type with connection-string builders (Postgres and Neo4j) including optional RDS IAM auth; updates pg.NewPool to accept that config; and changes CLI and integration code to construct and pass DatabaseConfiguration. go.mod adds AWS SDK v2 deps.

Changes

Cohort / File(s) Summary
Configuration Module
drivers/config.go
New DatabaseConfiguration type and methods: PostgreSQLConnectionString(), Neo4jConnectionString(), LookupEndpoint(), plus RDS IAM auth token flow and CNAME lookup with logging/fallback.
PostgreSQL Pool Driver
drivers/pg/pg.go
NewPool signature changed to accept drivers.DatabaseConfiguration; uses cfg.PostgreSQLConnectionString() and conditionally sets BeforeConnect to inject RDS IAM tokens and update endpoint.
CLI Commands
cmd/benchmark/main.go, cmd/export/main.go
Construct drivers.DatabaseConfiguration (setting Connection from resolved conn string) and pass it to pg.NewPool; added drivers import. Minor flag formatting alignment in benchmark.
Integration Testing
integration/harness.go
SetupDB now builds drivers.DatabaseConfiguration from CONNECTION_STRING and passes it to pg.NewPool; added drivers import.
Dependencies
go.mod
Adds AWS SDK v2 requirements for config and RDS IAM auth (aws-sdk-go-v2/config, aws-sdk-go-v2/feature/rds/auth) and associated transitive dependencies.

Sequence Diagram

sequenceDiagram
    participant App as Application
    participant Cfg as DatabaseConfiguration
    participant AWS as AWS SDK
    participant DB as PostgreSQL Database

    App->>Cfg: Create DatabaseConfiguration (EnableRDSIAMAuth?)
    Cfg->>Cfg: PostgreSQLConnectionString()
    alt EnableRDSIAMAuth == true
        Cfg->>Cfg: LookupEndpoint() (CNAME resolution)
        Cfg->>AWS: LoadDefaultConfig()
        AWS-->>Cfg: AWS Config
        Cfg->>AWS: BuildAuthToken(endpoint, user)
        AWS-->>Cfg: IAM Auth Token
        Cfg->>Cfg: Return URI with token as password
    else
        Cfg->>Cfg: Return formatted PostgreSQL URI
    end
    App->>DB: Call pg.NewPool(cfg) -> pool init uses cfg.PostgreSQLConnectionString()
    DB-->>App: Pool ready
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐇 I hopped a patch of code today,
A config bundle led the way.
Tokens fetched and endpoints found,
Connection strings snugly bound.
Pools now hum — hip-hop hooray! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description includes motivation, change type selection, testing notes, and driver impact; however, the ticket reference placeholder remains unfilled and several checklist items (formatting, tests, go.mod status) are not marked despite being applicable.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title directly aligns with the primary changes: adding RDS IAM authentication support to database pooling and moving DatabaseConfiguration into the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bi-1306

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@drivers/config.go`:
- Around line 68-70: The Neo4jConnectionString function currently interpolates
s.Username and s.Secret directly into the URI userinfo, which can break when
those contain reserved chars; update Neo4jConnectionString to escape credentials
like PostgreSQLConnectionString does (use url.QueryEscape or equivalent) for
s.Username and s.Secret before formatting the connection string so the returned
string is a valid/parseable Neo4j URI.
- Around line 76-85: The LookupEndpoint logic must handle addresses that already
include a port and use the context-aware CNAME API: change
DatabaseConfiguration.LookupEndpoint to accept a context.Context, split
s.Address with net.SplitHostPort to separate host and port (use ":5432" only
when no explicit port present), call net.DefaultResolver.LookupCNAME(ctx, host)
instead of net.LookupCNAME, trim any trailing '.' from the resolved host and
reattach the explicit or default port, and update callers to pass context (use
context.TODO() where no context is available and pass the existing poolCtx from
the PostgreSQL pool creation site).
- Around line 35-57: The RDS IAM token function currently swallows
AWS/config/auth errors and falls back to static credentials; change
DatabaseConfiguration.RDSIAMAuthConnectionString to return (string, error) and
return explicit errors on AWS config load, endpoint lookup, or
auth.BuildAuthToken failures instead of calling
defaultPostgreSQLConnectionString; update PostgreSQLConnectionString (and any
wrapper that calls RDSIAMAuthConnectionString) to accept and propagate the
error, and modify pg.NewPool callers (the two places calling
PostgreSQLConnectionString) to pass poolCtx and handle/return the error so IAM
failures bubble up rather than silently falling back.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 794c115f-1511-428f-85fa-ee235edf2ed5

📥 Commits

Reviewing files that changed from the base of the PR and between dbdd47f and 017519e.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • cmd/benchmark/main.go
  • cmd/export/main.go
  • drivers/config.go
  • drivers/pg/pg.go
  • go.mod
  • integration/harness.go

Comment thread drivers/config.go
Comment thread drivers/config.go Outdated
Comment thread drivers/config.go Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (3)
drivers/config.go (3)

36-37: ⚠️ Potential issue | 🟠 Major

Fail closed when IAM token generation fails.

Line 56 falls back to the default/static PostgreSQL connection string after AWS config or token-generation errors. With EnableRDSIAMAuth, that can silently bypass IAM or hide misconfiguration until later. Return an error from the IAM/PostgreSQL connection-string path and propagate it through drivers/pg/pg.go instead. Based on learnings, DatabaseConfiguration.PostgreSQLConnectionString() intentionally ignores the Connection field when EnableRDSIAMAuth is true because IAM auth always takes precedence.

🛡️ Proposed direction
-func (s DatabaseConfiguration) RDSIAMAuthConnectionString() string {
-	if cfg, err := awsConfig.LoadDefaultConfig(context.TODO()); err != nil {
-		slog.Error("AWS Config Loading Error", slog.String("err", err.Error()))
+func (s DatabaseConfiguration) RDSIAMAuthConnectionString(ctx context.Context) (string, error) {
+	if cfg, err := awsConfig.LoadDefaultConfig(ctx); err != nil {
+		return "", fmt.Errorf("load AWS config for RDS IAM auth: %w", err)
 	} else {
 		// Must use instance endpoint with IAM auth
 		var endpoint string
 		if s.Endpoint != "" {
 			endpoint = s.Endpoint
 		} else {
-			endpoint = s.LookupEndpoint()
+			endpoint = s.LookupEndpoint(ctx)
 		}
 
 		slog.Info("Requesting RDS IAM Auth Token")
-		if authenticationToken, err := auth.BuildAuthToken(context.TODO(), endpoint, cfg.Region, s.Username, cfg.Credentials); err != nil {
-			slog.Error("RDS IAM Auth Token Request Error", slog.String("err", err.Error()))
+		if authenticationToken, err := auth.BuildAuthToken(ctx, endpoint, cfg.Region, s.Username, cfg.Credentials); err != nil {
+			return "", fmt.Errorf("build RDS IAM auth token: %w", err)
 		} else {
 			slog.Info("RDS IAM Auth Token Created")
-			return fmt.Sprintf("postgresql://%s:%s@%s/%s", s.Username, url.QueryEscape(authenticationToken), endpoint, s.Database)
+			return fmt.Sprintf("postgresql://%s:%s@%s/%s", s.Username, url.QueryEscape(authenticationToken), endpoint, s.Database), nil
 		}
 	}
-
-	slog.Warn("Failed to create IAM auth token. Falling back to default Postgres connection string")
-	return s.defaultPostgreSQLConnectionString()
 }

Also applies to: 48-49, 56-57

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@drivers/config.go` around lines 36 - 37, The current AWS IAM flow in
DatabaseConfiguration.PostgreSQLConnectionString falls back to the static
Connection string on AWS config or token-generation errors; instead fail closed
by returning an error from the IAM path when awsConfig.LoadDefaultConfig or the
RDS IAM token generation fails (do not silently return the default Connection),
and update callers to propagate that error (notably the drivers/pg package
entrypoint in drivers/pg/pg.go) so EnableRDSIAMAuth truly takes precedence;
locate and modify the blocks around awsConfig.LoadDefaultConfig and the
token-generation calls to return descriptive errors and ensure drivers/pg/pg.go
surfaces those errors to its caller.

31-31: ⚠️ Potential issue | 🟡 Minor

Build connection URLs with url.URL and url.UserPassword.

url.QueryEscape is for query strings, not URI userinfo (Go net/url docs). These lines still leave Username unescaped and can mis-encode credentials containing spaces; use url.UserPassword so PostgreSQL, IAM, and Neo4j credentials are encoded consistently.

🔧 Proposed refactor
-	return fmt.Sprintf("postgresql://%s:%s@%s/%s", s.Username, url.QueryEscape(s.Secret), s.Address, s.Database)
+	postgresURL := url.URL{
+		Scheme: "postgresql",
+		User:   url.UserPassword(s.Username, s.Secret),
+		Host:   s.Address,
+		Path:   "/" + strings.TrimPrefix(s.Database, "/"),
+	}
+	return postgresURL.String()
-			return fmt.Sprintf("postgresql://%s:%s@%s/%s", s.Username, url.QueryEscape(authenticationToken), endpoint, s.Database)
+			postgresURL := url.URL{
+				Scheme: "postgresql",
+				User:   url.UserPassword(s.Username, authenticationToken),
+				Host:   endpoint,
+				Path:   "/" + strings.TrimPrefix(s.Database, "/"),
+			}
+			return postgresURL.String()
-		return fmt.Sprintf("neo4j://%s:%s@%s/%s", s.Username, url.QueryEscape(s.Secret), s.Address, s.Database)
+		neo4jURL := url.URL{
+			Scheme: "neo4j",
+			User:   url.UserPassword(s.Username, s.Secret),
+			Host:   s.Address,
+			Path:   "/" + strings.TrimPrefix(s.Database, "/"),
+		}
+		return neo4jURL.String()

Also applies to: 52-52, 70-70

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@drivers/config.go` at line 31, The connection URL assembly is using
fmt.Sprintf with url.QueryEscape (which is for query strings) and leaves
s.Username unescaped; update the code that returns the DSN (the line using
fmt.Sprintf("postgresql://%s:%s@%s/%s", s.Username, url.QueryEscape(s.Secret),
s.Address, s.Database)) to build the URL via net/url: create a url.URL with
Scheme "postgresql", Host set to s.Address, Path set to "/"+s.Database, and set
User to url.UserPassword(s.Username, s.Secret) so both username and secret are
encoded correctly; apply the same pattern for the other similar return lines
that reference s.Username, s.Secret, s.Address, s.Database.

76-86: ⚠️ Potential issue | 🟠 Major

Default the endpoint port and use the context-aware DNS resolver.

Line 77 ignores SplitHostPort errors, so Address: "db.example.com" leaves both host and port empty and can return an IAM endpoint without :5432. AWS documents RDS auth token endpoints as <host>:<port> (AWS SDK for Go v2 RDS utilities); Line 78 also triggers the noctx lint because net.LookupCNAME uses context.Background internally (Go net docs).

🔧 Proposed fix
-func (s DatabaseConfiguration) LookupEndpoint() string {
-	host, port, _ := net.SplitHostPort(s.Address)
-	if hostCName, err := net.LookupCNAME(host); err != nil {
+func (s DatabaseConfiguration) LookupEndpoint(ctx context.Context) string {
+	host := s.Address
+	port := "5432"
+	if splitHost, splitPort, err := net.SplitHostPort(s.Address); err == nil {
+		host = splitHost
+		port = splitPort
+	}
+
+	if hostCName, err := net.DefaultResolver.LookupCNAME(ctx, host); err != nil {
 		slog.Warn("Error looking up CNAME for DB host. Using original address.", slog.String("err", err.Error()))
-		return s.Address
 	} else {
 		host = hostCName
 	}
 
 	// Instance endpoint always returns with a trailing '.'
-	return strings.TrimSuffix(host, ".") + ":" + port
+	return net.JoinHostPort(strings.TrimSuffix(host, "."), port)
 }

Update callers to pass the available context, especially drivers/pg/pg.go:75 and the BeforeConnect path.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@drivers/config.go`:
- Around line 36-37: The current AWS IAM flow in
DatabaseConfiguration.PostgreSQLConnectionString falls back to the static
Connection string on AWS config or token-generation errors; instead fail closed
by returning an error from the IAM path when awsConfig.LoadDefaultConfig or the
RDS IAM token generation fails (do not silently return the default Connection),
and update callers to propagate that error (notably the drivers/pg package
entrypoint in drivers/pg/pg.go) so EnableRDSIAMAuth truly takes precedence;
locate and modify the blocks around awsConfig.LoadDefaultConfig and the
token-generation calls to return descriptive errors and ensure drivers/pg/pg.go
surfaces those errors to its caller.
- Line 31: The connection URL assembly is using fmt.Sprintf with url.QueryEscape
(which is for query strings) and leaves s.Username unescaped; update the code
that returns the DSN (the line using fmt.Sprintf("postgresql://%s:%s@%s/%s",
s.Username, url.QueryEscape(s.Secret), s.Address, s.Database)) to build the URL
via net/url: create a url.URL with Scheme "postgresql", Host set to s.Address,
Path set to "/"+s.Database, and set User to url.UserPassword(s.Username,
s.Secret) so both username and secret are encoded correctly; apply the same
pattern for the other similar return lines that reference s.Username, s.Secret,
s.Address, s.Database.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 93cfcf78-53c8-408c-96ef-2ede50f700c1

📥 Commits

Reviewing files that changed from the base of the PR and between 017519e and 45b752d.

📒 Files selected for processing (1)
  • drivers/config.go

@mamundsen-specter mamundsen-specter changed the title feat: update db pooling to handle iam rds auth, move DatabaseConfigur… feat: update db pooling to handle iam rds auth, move DatabaseConfiguration to dawgs Apr 22, 2026
@mamundsen-specter
Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@mamundsen-specter mamundsen-specter merged commit ef67c9d into main Apr 23, 2026
4 checks passed
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.

2 participants