Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Aws Iam Rds Auth Bundle Laravel Package

macpaw/doctrine-aws-iam-rds-auth-bundle

Symfony bundle for Doctrine DBAL that enables Amazon RDS connections using AWS IAM authentication. It generates short-lived IAM auth tokens instead of static database passwords, helping PHP applications manage database credentials more securely.

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle does one job: mint a short-lived AWS RDS IAM authentication token and hand it to Doctrine DBAL as the connection password. In a Laravel app you will rarely use the bundle half (it registers a Symfony Bundle class and a DI extension); you will use the token provider class from src/ directly and wire it yourself. Read the token provider first, then the service definition in Resources/config/ to see exactly which DBAL params it overrides.

  1. composer require macpaw/doctrine-aws-iam-rds-auth-bundle — v1.1.0 requires doctrine/dbal ^3.0 || ^4.0, so Laravel 9+ (which ships with DBAL 3) is fine, older DBAL 2 stacks are not.
  2. Confirm credentials resolve in the runtime you actually deploy to, not just locally: aws sts get-caller-identity inside the container, or check AWS_ROLE_ARN / AWS_WEB_IDENTITY_TOKEN_FILE for IRSA.
  3. Grant the role rds-db:connect on arn:aws:rds-db:<region>:<account>:dbuser:<DbiResourceId>/<dbuser> — note it is the resource id, not the DB identifier.
  4. Create the DB user with the IAM plugin (CREATE USER app IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; on MySQL/Aurora MySQL) and require TLS.
  5. First use case: generate a token and open a one-off DBAL connection in a queued job or artisan command that talks to Aurora.
use Doctrine\DBAL\DriverManager;

$config = [
    'dbname'   => config('database.connections.aurora.database'),
    'host'     => config('database.connections.aurora.host'),
    'port'     => 3306,
    'user'     => 'app',
    'password' => app(TokenProvider::class)->getToken($host, $port, 'app', $region),
    'driver'   => 'pdo_mysql',
    'sslmode'  => 'require',
];

$conn = DriverManager::getConnection($config);

Implementation Patterns

Bind the provider as a singleton. The token generator is stateless apart from the AWS credentials/client; bind it once in a service provider so the AWS SDK client is reused across jobs.

Token cache keyed by (host, port, user, region). Tokens are valid for 15 minutes and are signed for a specific endpoint and user. Cache in-memory for the request/job lifetime with a safety margin (regenerate at ~12 minutes); never persist them to Redis or the database.

Connection factory, not a global config entry. Because the password expires, produce a fresh Doctrine\DBAL\Connection per unit of work rather than holding one in the container:

class AuroraConnectionFactory
{
    public function __construct(private TokenProvider $tokens) {}

    public function make(): Connection
    {
        return DriverManager::getConnection($this->params());
    }
}

Long-running workers (Horizon, queue:work). A DBAL connection opened at boot will die at the token's 15-minute mark on the next new underlying connection, and idle connections get killed by wait_timeout anyway. Rebuild the connection per job, or call DB::purge() on a schedule; do not rely on reconnect-with-old-password.

DBAL 3 vs DBAL 4. v1.1.0 adds DBAL 4 support, which matters if you are on Laravel 11/12 with a newer doctrine/dbal. Driver class names, DriverManager params, and the middleware API changed between majors (Doctrine\DBAL\Driver\Middleware still exists in 4, but several AbstractDriverMiddleware helpers moved). If you wrap this package in your own middleware, test on both majors before bumping.

Middleware pattern. If you want transparent token injection, register a DBAL middleware that mutates $params['password'] on connect(). This is the cleanest seam for Laravel because it keeps config/database.php as the single source of truth.

Testing. Type-hint the package's token provider interface and swap it in tests with a fake returning a fixed string, so your suite never calls AWS. Keep the real factory behind a feature flag and hit a local MariaDB/MySQL without SSL in testing.

Multiple databases. One token per connection tuple. Do not reuse the primary's token for a read replica endpoint — the host is part of the signed request.

Gotchas and Tips

  • It's a Symfony bundle. There is no vendor:publish, no Laravel auto-discovery of its config tree. Treat it as a library: instantiate the provider with an explicit config array and ignore the DependencyInjection/ folder.
  • v1.1.0 notes are thin. "Revert changes from develop" does not say what was reverted. Diff v1.0.1...v1.1.0 before rolling this into production; the practical change you can rely on is the DBAL 3/4 constraint widening.
  • 15-minute hard TTL, no refresh grace. Nothing in the package refreshes a live connection. Design around connection-per-job or a connection pool with short max lifetime.
  • Region mismatch produces a confusing auth failure, not an obvious error: the token is signed for a host and region, and RDS rejects it as a generic access-denied. Verify AWS_REGION/AWS_DEFAULT_REGION in the container.
  • TLS is mandatory for IAM auth. Without sslmode=require (Postgres) or a CA option (PDO::MYSQL_ATTR_SSL_CA) the server returns access-denied rather than a TLS error.
  • Credentials resolution is deferred. If the ECS task role or instance profile is missing, you get a failure at connect() time inside the driver. Probe credentials once at boot in a health check.
  • Never log the token. It appears in the DBAL params array and in DSN strings if you ever build one — URL-encode it if you do, and scrub password from query/connection logging.
  • Clock skew on the host invalidates the signature window; keep NTP healthy on long-lived instances.
  • Aurora Serverless v1 vs v2 differ in IAM auth and connection behaviour; if you use RDS Proxy, point the token at the proxy endpoint's host, not the cluster writer.
  • Maintenance risk: the project has a very small contributor base and a short PR history. Pin to 1.1.*, keep an escape hatch (a five-line Rds\AuthTokenGenerator call with the AWS SDK) so you can drop the dependency if it stalls.
  • Error triage: distinguish SQLSTATE[28000] (auth token rejected — expired, wrong resource id, missing IAM permission) from AWS SDK credential exceptions (no credentials, wrong region) from SQLSTATE[HY000] (network/SG). Catching all three as "DB error" will cost you hours.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager