Skip to content

ENG-3566: Add DBCredentialProvider for dynamic credential resolution#8175

Merged
erosselli merged 7 commits into
mainfrom
erosselli/ENG-3566-db-cred-provider
May 14, 2026
Merged

ENG-3566: Add DBCredentialProvider for dynamic credential resolution#8175
erosselli merged 7 commits into
mainfrom
erosselli/ENG-3566-db-cred-provider

Conversation

@erosselli
Copy link
Copy Markdown
Contributor

Ticket ENG-3566

Description Of Changes

Adds DBCredentialProvider, the layer between SQLAlchemy engine creators and the SecretProvider abstraction. This is the foundation for dynamic database credentials via AWS Secrets Manager — it resolves credentials, handles auth-failure retry during rotation, and sanitizes connection exceptions to prevent credential leakage.

This PR adds the class and all supporting config/provider changes but does not wire it into the engine creators yet. The wiring will follow in a separate PR.

Code Changes

  • DBCredentialProvider class with get_credentials(), connect_with_retry(), auth error detection (SQLSTATE + psycopg2 string fallback), and SanitizedConnectionError
  • StaticSecretProvider refactored to read and cache DB credentials from CONFIG at construction time
  • get_secret_provider() singleton in config/secrets/__init__.py for shared provider cache
  • credential_secret_id and readonly_credential_secret_id fields added to DatabaseSettings
  • @model_validator on FidesConfig for cross-section config validation (static + secret_id, aws + missing secret_id)
  • aws_secrets_manager made Optional on SecretsSettings with its own validator
  • create_secret_provider factory simplified (no more static_secrets param)
  • INFO logs added to AWSSecretsManagerProvider for fetch/cache events

Steps to Confirm

  1. Run nox -s "pytest(misc-unit)" — all config, secrets, and db_credential_provider tests pass
  2. Run nox -s "pytest(lib)" — engine creator tests pass
  3. Verify static provider behavior unchanged: start Fides normally (no secrets config), confirm GET /health/database returns healthy

Pre-Merge Checklist

  • Issue requirements met
  • All CI pipelines succeeded
  • CHANGELOG.md updated
    • Updates unreleased work already in Changelog, no new entry necessary
  • UX feedback:
    • No UX review needed
  • Followup issues:
    • Followup issues created
  • Database migrations:
    • No migrations
  • Documentation:
    • No documentation updates required

Add DBCredentialProvider class that sits between SQLAlchemy engine
creators and the SecretProvider abstraction. Resolves credentials
from static config or AWS Secrets Manager, retries once on auth
failure during credential rotation, and sanitizes all connection
exceptions to prevent credential leakage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
fides-plus-nightly Ignored Ignored Preview May 13, 2026 8:43pm
fides-privacy-center Ignored Ignored May 13, 2026 8:43pm

Request Review

erosselli and others added 2 commits May 13, 2026 15:22
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The build_field_documentation function assumed every anyOf entry
has a "type" key, but Pydantic uses "$ref" for nested models.
Skip $ref entries to avoid KeyError.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.54%. Comparing base (545fd9a) to head (e9fb993).
⚠️ Report is 9 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8175      +/-   ##
==========================================
+ Coverage   85.45%   85.54%   +0.09%     
==========================================
  Files         650      654       +4     
  Lines       42363    42636     +273     
  Branches     4971     5008      +37     
==========================================
+ Hits        36200    36475     +275     
- Misses       5054     5055       +1     
+ Partials     1109     1106       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

erosselli and others added 3 commits May 13, 2026 16:04
- aws_secrets_manager is None when provider is static
- region is required (no default) when AWS is configured
- Before-validator constructs from env vars when needed
- Fix config doc generator for Optional nested model $ref

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace asserts with explicit raises for cases where upstream
validators should prevent None but callers may bypass validation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@erosselli erosselli requested a review from JadeCara May 13, 2026 20:03
@erosselli erosselli marked this pull request as ready for review May 13, 2026 20:03
@erosselli erosselli requested a review from a team as a code owner May 13, 2026 20:03
- Add reset_secret_provider() for test isolation
- Preserve original ValidationError with raise...from exc
- Add comment explaining time.sleep safety in greenlet context
- Add string fallback test coverage for _is_auth_error
- Demote fetch log to DEBUG, keep success at INFO
- Remove unused Any import from static_provider
- Add __all__ to db_credential_provider

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@JadeCara JadeCara left a comment

Choose a reason for hiding this comment

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

Only one note on some drift between the plan and implementation. Looks clean!

Comment on lines +112 to +119
else:
if not self.database.credential_secret_id:
raise ValueError(
f"secrets.provider is {self.secrets.provider!r} but "
"database.credential_secret_id is not set. "
"Provide the secret name/ARN containing database credentials."
)
return self
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think I remember this being a warning to not block start up in the design doc. Did that change?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ah maybe, but if something is misconfigured I think I'd rather fail noisly than log a silent warning. This should only scream if you've set FIDES__SECRETS__PROVIDER to aws but haven't configured the credential_secret_id for the DB

@erosselli erosselli added this pull request to the merge queue May 14, 2026
Merged via the queue into main with commit 8dce46e May 14, 2026
68 of 69 checks passed
@erosselli erosselli deleted the erosselli/ENG-3566-db-cred-provider branch May 14, 2026 14:02
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