Skip to content

update db pooling to handle iam rds auth - BI-1306#2356

Open
mamundsen-specter wants to merge 13 commits intomainfrom
bi-1348-main
Open

update db pooling to handle iam rds auth - BI-1306#2356
mamundsen-specter wants to merge 13 commits intomainfrom
bi-1348-main

Conversation

@mamundsen-specter
Copy link

@mamundsen-specter mamundsen-specter commented Feb 10, 2026

https://specterops.atlassian.net/browse/BI-1348
https://specterops.atlassian.net/browse/BI-1306

Bloodhound changes to enable RDS IAM auth. Coincides with DAWGs changes

Updates PostgresConnectionString() to fetch an IAM auth token and encode it before adding it to the password of the return postgres connection string.

Updates NewPool() calls coinciding with DAWGs newpool change

Updates OpenDatabase() to pass pgxpool to Gorm.

Motivation and Context

Enabling IAM auth allows us to get away from basic password authentication to the database. This frees us up from a infrastructure resource perspective and can move us towards better density in the cluster.

How Has This Been Tested?

PoC tenants have been created. These are in the process of being updated and recreated.

  • Chore (a change that does not modify the application functionality)
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Database Migrations

Checklist:

Summary by CodeRabbit

  • New Features

    • Added DisableTimeoutLimit configuration option for database connections.
  • Refactor

    • Unified database configuration usage across services, tooling, and tests for consistent connection and pool initialization.
  • Chores

    • Updated dependencies to newer versions.
    • Minor logging precision improvements for cache metrics.

@github-actions
Copy link

github-actions bot commented Feb 10, 2026

Howdy! Thank you for opening this pull request 🙇

It looks like your pull request title needs some adjustment.
We require pull request titles to follow the Conventional Commits specification as outlined in our documentation.
Please review the required format and update your pull request title accordingly.
Thank you!

Details:

No release type found in pull request title "update db pooling to handle iam rds auth - BI-1306". Add a prefix to indicate what kind of release this pull request corresponds to. For reference, see https://www.conventionalcommits.org/

Available types:
 - feat
 - fix
 - docs
 - refactor
 - test
 - chore

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Database and pool initialization now accept and propagate full configuration objects (Dawgs.DatabaseConfiguration / config.Configuration) instead of raw connection strings; function signatures, imports, and call sites were updated to use the new types.

Changes

Cohort / File(s) Summary
Configuration types
cmd/api/src/config/config.go, cmd/api/src/config/default.go
Replaced local DatabaseConfiguration with Dawgs.DatabaseConfiguration; removed connection-string helper methods; added DisableTimeoutLimit and dawgs import.
DB open & pool creation
cmd/api/src/database/db.go, cmd/api/src/api/tools/pg.go, cmd/api/src/bootstrap/util.go
Pool creation switched to pg.NewPool(cfg.Database) (pass config object); use stdlib.OpenDBFromPool() and postgres.New() to build GORM DB; OpenDatabase signature updated to accept config.Configuration.
Call sites & CLI harness
cmd/api/src/services/entrypoint.go, cmd/api/src/cmd/dawgs-harness/main.go
Callers updated to pass new config types; RunTestSuite signature now accepts drivers.DatabaseConfiguration; CLI main constructs and forwards config.
Graphify integration
packages/go/graphify/graph/graph.go
GraphService.InitializeService and initializeGraphDatabase updated to accept config.Configuration; Run flow now creates default config and passes it into graph DB init.
Defaults & imports
cmd/api/src/config/default.go
Default Configuration literal now uses Dawgs.DatabaseConfiguration; added Dawgs import alias.
Minor logging change
packages/go/analysis/ad/local_groups.go
Adjusted cache-stat logging to use cacheStats.Size() and cacheStats.Hits() casts.
Dependencies
go.mod
Bumped github.com/specterops/dawgs pseudo-version and added several indirect AWS SDK v2-related modules.

Sequence Diagram(s)

sequenceDiagram
    participant App as Application
    participant Config as config.Configuration
    participant PoolFactory as dawgs/pg PoolFactory
    participant Stdlib as pgx stdlib
    participant GORM as GORM (postgres driver)

    App->>Config: obtain cfg (includes Dawgs.DatabaseConfiguration)
    App->>PoolFactory: pg.NewPool(cfg.Database)
    PoolFactory-->>Stdlib: provide *sql.DB (OpenDBFromPool)
    Stdlib-->>GORM: provide Conn to postgres.New
    GORM-->>App: return initialized *gorm.DB
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • superlinkx
  • elikmiller
  • mvlipka
🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly refers to the main objective of updating database pooling to support IAM RDS authentication, which is directly reflected in the file changes across the codebase.
Description check ✅ Passed The description includes a solid summary of changes, clear motivation for IAM auth adoption, and notes testing with PoC tenants, but checklist items remain uncompleted and some sections lack detail.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bi-1348-main

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.

@coderabbitai coderabbitai bot added the api A pull request containing changes affecting the API code. label Feb 11, 2026
Copy link
Contributor

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
cmd/api/src/cmd/dawgs-harness/main.go (1)

150-153: ⚠️ Potential issue | 🔴 Critical

Critical: Missing cfg argument in neo4j RunTestSuite call.

RunTestSuite now requires 4 arguments, but the neo4j call on line 152 only passes 3. This is a compile error.

Proposed fix
 	n4jTestSuite := execSuite(neo4j.DriverName, func() tests.TestSuite {
-		return RunTestSuite(ctx, neo4jConnectionStr, neo4j.DriverName)
+		return RunTestSuite(ctx, neo4jConnectionStr, neo4j.DriverName, cfg.Database)
 	})

Note: The exact argument depends on resolving the type issue in RunTestSuite's signature (line 48).

packages/go/graphify/graph/graph.go (1)

412-423: ⚠️ Potential issue | 🟠 Major

Use cfg.Database.PostgreSQLConnectionString() instead of the raw postgresConnection variable for consistency with the rest of the codebase.

The initializeGraphDatabase function creates a pool from cfg.Database (which only has MaxConcurrentSessions: 10 set) while bypassing the connection string that should be retrieved from cfg.Database.PostgreSQLConnectionString(). This deviates from the pattern in cmd/api/src/api/tools/pg.go and cmd/api/src/bootstrap/util.go, where pg.NewPool(cfg.Database) is followed by cfg.Database.PostgreSQLConnectionString() for the connection string.

Either populate cfg.Database with connection details before calling initializeGraphDatabase, or refactor this function to use the standard pattern of calling pg.NewPool() with a fully-configured cfg.Database.

cmd/api/src/database/db.go (1)

243-263: ⚠️ Potential issue | 🔴 Critical

Critical resource leak: pgxpool.Pool is never closed. The pool created by pg.NewPool() at line 251 is wrapped with stdlib.OpenDBFromPool() but the underlying pool reference is discarded. Per pgx documentation, stdlib.OpenDBFromPool does not take ownership of pool closure—calling sql.DB.Close() only stops the database/sql wrapper, leaving the pool's connections permanently open. When BloodhoundDB.Close() calls sqlDBRef.Close(), the pgxpool remains active and unreleased, preventing graceful shutdown and exhausting connection limits.

Store the *pgxpool.Pool reference in the BloodhoundDB struct and call pool.Close() during shutdown in addition to sqlDBRef.Close().

🤖 Fix all issues with AI agents
In `@cmd/api/src/cmd/dawgs-harness/main.go`:
- Around line 145-148: The snippet uses invalid Go syntax and undefined
identifiers; replace the malformed line with a proper assignment and error
check: call config.NewDefaultConfiguration() as cfg, err :=
config.NewDefaultConfiguration(); then test if err != nil and handle it inside
main (e.g., log.Fatalf or fmt.Fprintf(os.Stderr, ...) followed by os.Exit(1))
instead of returning a non-existent configuration variable; ensure only cfg is
used thereafter.
- Line 48: The function RunTestSuite currently references the removed type
config.DatabaseConfiguration; change its parameter to use the new type from the
dawgs drivers package (e.g. import github.com/specterops/dawgs/drivers as dawgs
and update the signature to accept dawgs.DatabaseConfiguration), and update any
other unqualified usages (e.g. DatabaseConfiguration{} in
cmd/api/src/config/default.go) to the fully-qualified
dawgs.DatabaseConfiguration or switch those callers to pass config.Configuration
and read cfg.Database internally; ensure you add the dawgs import alias so
symbols resolve.

In `@packages/go/graphify/graph/graph.go`:
- Around line 206-214: The code calls config.NewDefaultConfiguration() and on
failure logs a message without the error and calls os.Exit(1), which prevents
deferred TeardownService from running; update the error handling in Run() so
that the slog/Error log includes the actual error value (err) and replace
os.Exit(1) with returning the error (e.g. return fmt.Errorf("creating default
configuration: %w", err)) so deferred s.service.TeardownService (and other
defers) can execute; modify the block around config.NewDefaultConfiguration()
accordingly.
🧹 Nitpick comments (1)
cmd/api/src/config/config.go (1)

34-34: Unconventional uppercase import alias Dawgs.

Go convention is to use lowercase import aliases (e.g., dawgsdrv or drivers). The uppercase Dawgs reads like an exported identifier rather than a package alias.

Suggested change
-	Dawgs "github.com/specterops/dawgs/drivers"
+	dawgsdrv "github.com/specterops/dawgs/drivers"

Then update usages accordingly (e.g., dawgsdrv.DatabaseConfiguration).

Comment on lines 145 to 148
cfg := config.NewDefaultConfiguration(); err != nil {
return configuration, fmt.Errorf("failed to create default configuration: %w", err)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: This code will not compile — broken syntax and undefined identifiers.

Lines 145–147 contain invalid Go syntax:

  1. config.NewDefaultConfiguration() returns (Configuration, error) but only one LHS variable is assigned.
  2. The ; pseudo-if pattern is malformed — it's not within an if block.
  3. return configuration, ... is invalid in main() (no return values, and configuration is undefined).
Proposed fix
-	cfg := config.NewDefaultConfiguration(); err != nil {
-		return configuration, fmt.Errorf("failed to create default configuration: %w", err)
-	}
+	cfg, err := config.NewDefaultConfiguration()
+	if err != nil {
+		fatalf("failed to create default configuration: %v", err)
+	}
🤖 Prompt for AI Agents
In `@cmd/api/src/cmd/dawgs-harness/main.go` around lines 145 - 148, The snippet
uses invalid Go syntax and undefined identifiers; replace the malformed line
with a proper assignment and error check: call config.NewDefaultConfiguration()
as cfg, err := config.NewDefaultConfiguration(); then test if err != nil and
handle it inside main (e.g., log.Fatalf or fmt.Fprintf(os.Stderr, ...) followed
by os.Exit(1)) instead of returning a non-existent configuration variable;
ensure only cfg is used thereafter.

Comment on lines +206 to +214
dbcfg, err := config.NewDefaultConfiguration()
if err != nil {
slog.Error("Error creating new default configuration")
os.Exit(1)
}

if graphDB, err := initializeGraphDatabase(ctx, s.env[environment.PostgresConnectionVarName], dbcfg); err != nil {
return fmt.Errorf("error connecting to graphDB: %w", err)
} else if err := s.service.InitializeService(ctx, s.env[environment.PostgresConnectionVarName], graphDB); err != nil {
} else if err := s.service.InitializeService(ctx, dbcfg, graphDB); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing error value in log message and abrupt os.Exit.

Line 208 logs "Error creating new default configuration" but does not include the actual error. Also, os.Exit(1) prevents the deferred TeardownService (line 202) from running. Consider returning the error from Run() instead.

Proposed fix
 	dbcfg, err := config.NewDefaultConfiguration()
 	if err != nil {
-		slog.Error("Error creating new default configuration")
-		os.Exit(1)
+		return fmt.Errorf("error creating default configuration: %w", err)
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
dbcfg, err := config.NewDefaultConfiguration()
if err != nil {
slog.Error("Error creating new default configuration")
os.Exit(1)
}
if graphDB, err := initializeGraphDatabase(ctx, s.env[environment.PostgresConnectionVarName], dbcfg); err != nil {
return fmt.Errorf("error connecting to graphDB: %w", err)
} else if err := s.service.InitializeService(ctx, s.env[environment.PostgresConnectionVarName], graphDB); err != nil {
} else if err := s.service.InitializeService(ctx, dbcfg, graphDB); err != nil {
dbcfg, err := config.NewDefaultConfiguration()
if err != nil {
return fmt.Errorf("error creating default configuration: %w", err)
}
if graphDB, err := initializeGraphDatabase(ctx, s.env[environment.PostgresConnectionVarName], dbcfg); err != nil {
return fmt.Errorf("error connecting to graphDB: %w", err)
} else if err := s.service.InitializeService(ctx, dbcfg, graphDB); err != nil {
🤖 Prompt for AI Agents
In `@packages/go/graphify/graph/graph.go` around lines 206 - 214, The code calls
config.NewDefaultConfiguration() and on failure logs a message without the error
and calls os.Exit(1), which prevents deferred TeardownService from running;
update the error handling in Run() so that the slog/Error log includes the
actual error value (err) and replace os.Exit(1) with returning the error (e.g.
return fmt.Errorf("creating default configuration: %w", err)) so deferred
s.service.TeardownService (and other defers) can execute; modify the block
around config.NewDefaultConfiguration() accordingly.

Copy link
Contributor

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cmd/api/src/cmd/dawgs-harness/main.go (1)

155-167: ⚠️ Potential issue | 🟠 Major

Bug: Neo4j test suite receives cfg.Database instead of cfg.Neo4J.

Line 150 sets cfg.Neo4J.Connection = neo4jConnectionStr, but on line 157 the neo4j RunTestSuite call passes cfg.Database — meaning the neo4j connection string configuration is unused and the wrong DatabaseConfiguration is passed. The same issue occurs on line 179.

Proposed fix
 	n4jTestSuite := execSuite(neo4j.DriverName, func() tests.TestSuite {
-		return RunTestSuite(ctx, neo4jConnectionStr, neo4j.DriverName, cfg.Database)
+		return RunTestSuite(ctx, neo4jConnectionStr, neo4j.DriverName, cfg.Neo4J)
 	})

And for the "neo4j" case (line 179):

 	execSuite(neo4j.DriverName, func() tests.TestSuite {
-		return RunTestSuite(ctx, neo4jConnectionStr, neo4j.DriverName, cfg.Database)
+		return RunTestSuite(ctx, neo4jConnectionStr, neo4j.DriverName, cfg.Neo4J)
 	})
🤖 Fix all issues with AI agents
In `@cmd/api/src/cmd/dawgs-harness/main.go`:
- Around line 146-149: The call to config.NewDefaultConfiguration() can fail but
the code currently creates an error value with fmt.Errorf and then continues
with a nil/zero cfg; replace that silent discard by checking err and terminating
with a fatal log (e.g., log.Fatalf or fmt.Fatalf or panic) so the program
doesn't continue with an invalid cfg; update the error handling right after cfg,
err := config.NewDefaultConfiguration() to log a descriptive message including
the wrapped err and exit (reference symbols: NewDefaultConfiguration, cfg, err).
🧹 Nitpick comments (3)
go.mod (1)

50-50: Pseudo-version dependency on dawgs — pin to a release tag before merging to main.

The dawgs dependency uses a pseudo-version (v0.4.8-0.20260211001809-7d3b4dd80186), which ties this repo to a specific unreleased commit. This is fine for development but should be updated to a proper tagged release before merging, to ensure reproducible builds and clear version tracking.

cmd/api/src/config/default.go (1)

22-22: Uppercase import alias Dawgs is unconventional.

Go convention uses lowercase import aliases (e.g., dawgsDrivers or just drivers). The uppercase Dawgs reads like an exported identifier rather than a package alias. Consider renaming for consistency with Go idioms.

Suggested rename
-	Dawgs "github.com/specterops/dawgs/drivers"
+	dawgsDrivers "github.com/specterops/dawgs/drivers"

Then update usages accordingly (e.g., dawgsDrivers.DatabaseConfiguration).

cmd/api/src/cmd/dawgs-harness/main.go (1)

49-60: connectionStr parameter is unused inside RunTestSuite for pg path — consider removing redundancy.

The connectionStr is passed separately but cfg already contains the connection string (set at line 151). For the pg path, pg.NewPool(cfg) uses cfg directly, making connectionStr redundant for that code path. It's still used for dawgs.Open on line 64, so this is more of a design observation — the connection string is duplicated in two places which could drift.

Comment on lines +146 to +149
cfg, err := config.NewDefaultConfiguration()
if err != nil {
fmt.Errorf("failed to create default configuration: %w", err)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical: Error from NewDefaultConfiguration() is silently discarded.

fmt.Errorf creates an error value but doesn't do anything with it — the program continues with a zero-value cfg on failure. This should use fatalf (or similar) to halt execution.

Proposed fix
 	cfg, err := config.NewDefaultConfiguration()
 	if err != nil {
-		fmt.Errorf("failed to create default configuration: %w", err)
+		fatalf("failed to create default configuration: %v", err)
 	}
🤖 Prompt for AI Agents
In `@cmd/api/src/cmd/dawgs-harness/main.go` around lines 146 - 149, The call to
config.NewDefaultConfiguration() can fail but the code currently creates an
error value with fmt.Errorf and then continues with a nil/zero cfg; replace that
silent discard by checking err and terminating with a fatal log (e.g.,
log.Fatalf or fmt.Fatalf or panic) so the program doesn't continue with an
invalid cfg; update the error handling right after cfg, err :=
config.NewDefaultConfiguration() to log a descriptive message including the
wrapped err and exit (reference symbols: NewDefaultConfiguration, cfg, err).

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

Labels

api A pull request containing changes affecting the API code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant