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

Aws Secrets Bundle Laravel Package

vpyzhyk/aws-secrets-bundle

A Symfony bundle that pulls secrets from AWS Secrets Manager into your application configuration at runtime, keeping credentials out of env files and source control. Simple setup for PHP apps.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the framework check — do this before anything else. vPyzhyk/aws-secrets-bundle is a Symfony bundle, not a Laravel package. Release 3.0.1 confirms this: the only substantive change is a bump of symfony/dependency-injection to ^7.0, and the second PR is "Fix namespaces" — both container/DI concerns that have no meaning in a Laravel app. There is no ServiceProvider, no config/*.php publish tag, and Composer auto-discovery will not register anything. So:

  • If you are in a Laravel app: do not composer require this. Use it as a reference implementation and copy the pattern (see below), built on aws/aws-sdk-php.
  • If you maintain a Symfony service alongside Laravel (monorepo, shared infra repo), then 3.0.1 is directly relevant and you should read the next two sections as an upgrade review.

Minimal steps (Symfony context):

composer require vpyzhyk/aws-secrets-bundle:^3.0.1
php bin/console cache:clear          # mandatory after this upgrade, see Gotchas

Then look, in this order:

  1. DependencyInjection/Configuration.php — the config tree. This tells you every knob you actually have (secret names, env/prefix, cache TTL, AWS region/credentials). Read it before the README; it is the source of truth.
  2. DependencyInjection/*Extension.php — where secrets get injected into parameters/services, and when (compile time vs. runtime). This determines your entire caching and boot-latency strategy.
  3. The secret provider/loader class — your extension point for custom retrieval (SSM Parameter Store, Vault, etc.).

First use case: move the database password out of .env/parameters.yml and into Secrets Manager so that a rotation in AWS doesn't require a redeploy or a config repo change. Verify with:

aws secretsmanager get-secret-value --secret-id prod/app/db --query SecretString --output text

If that call works from your shell's role, the bundle's job is just to surface the same value as a container parameter.

Laravel-native equivalent (what you'd actually ship):

// app/Providers/SecretsServiceProvider.php — registered in bootstrap/providers.php
public function register(): void
{
    if (app()->environment('local')) {
        return; // never hit AWS on a laptop
    }

    $client = new \Aws\SecretsManager\SecretsManagerClient([
        'region'  => config('services.aws.region'),
        'version' => 'latest',
    ]);

    $json = Cache::remember('secrets:'.config('app.env'), now()->addHour(), function () use ($client) {
        return $client->getSecretValue(['SecretId' => config('services.aws.secret_id')])
            ->get('SecretString');
    });

    foreach (json_decode($json, true) as $key => $value) {
        config([str_replace('__', '.', $key) => $value]);
    }
}

Key the secret JSON as database__connections__mysql__password and the str_replace maps it onto real config paths.

Implementation Patterns

Compile-time vs. runtime injection. The bundle's default posture is to resolve secrets through the DI container. That is fast at runtime but means secrets land in the compiled container dump under var/cache. If you need secrets not on disk, resolve them lazily through a service that fetches on first get() — the same pattern you'd write in Laravel with a lazy config() binding or an invokable resolver.

Always cache. Secrets Manager charges per 10,000 API calls and each call has real latency (~50–150 ms, worse cold). At container boot that latency is paid on every request if you fetch naively. Three-layer approach that works in both frameworks:

  1. Build/deploy time: fetch once in CI, write to .env / a cached file / an SSM-backed parameter store — zero runtime calls.
  2. Runtime warm cache: Redis/file cache with TTL shorter than your rotation window (1 hour is a sane default).
  3. In-process memoization: a private ?array $cache in the provider so a single request never double-fetches.

Environment-scoped secret naming. Use a convention like {env}/{app}/{component} (prod/billing/db). Never let a staging container read a prod secret — enforce with separate IAM roles per environment, not with a config flag.

Rotation without redeploy. Prefer fetching by name (prod/app/db) and letting Secrets Manager resolve AWSCURRENT, rather than pinning a version ID. Cache TTL must be shorter than the rotation schedule or you'll serve a dead password for an hour after rotation.

Graceful degradation. Wrap the fetch in try/catch with a fallback to existing env config. A boot-time hard dependency on AWS means an API outage (or a missing VPC endpoint) is a full application outage. In Laravel terms: catch, log, and config() the fallback; don't throw from register().

IAM, not keys. ECS task role, EKS IRSA, or EC2 instance profile. If you find yourself putting AWS_ACCESS_KEY_ID in .env to make this work, the integration is wrong. Verify identity with aws sts get-caller-identity inside the container, not on your laptop.

Gotchas and Tips

^7.0 is a hard constraint, not a range. symfony/dependency-injection: ^7.0 excludes Symfony 6.4 LTS entirely and requires PHP 8.2+. If any app in the repo is on 6.4, this version is simply uninstallable — you'll get a Composer conflict that mentions the DI component, not this bundle, so the error looks unrelated. Pin 3.0.0 there, or relax the constraint via a fork with ^6.4 || ^7.0.

"Fix namespaces" in a patch release is a red flag. Namespace/class relocation should be a minor or major bump. Consequences:

  • Run composer dump-autoload -o — with an authoritative classmap, stale entries hide the breakage locally and blow up in CI.
  • Any container referencing a moved class will fail at compile time, not install time. php bin/console cache:clear and check for Class not found before deploying.
  • If you extends or implements any of the bundle's classes (a custom secret provider is the common case), diff 3.0.0...3.0.1 and confirm your parent FQCNs still exist.

Clear the cache after upgrading — always. Symfony's compiled container will keep resolving the old namespace until var/cache is wiped. Symptom: install succeeds, cache:clear succeeds, but the app 500s on boot with a confusing DI error. rm -rf var/cache/* and regenerate.

Secrets on disk is a real exposure. If the compiled container inlines secret values, they're in var/cache, in your Docker image layers if you warm the cache during build, and in any artifact you ship. Confirm whether your config resolves values eagerly or lazily before you rely on this in production.

Missing VPC endpoint = boot-time hang. In a private subnet with no NAT, the Secrets Manager API call silently times out. Set an explicit connect_timeout/timeout on the client and add the secretsmanager interface endpoint. A 30-second default timeout at container boot looks like "the app is just slow."

Debugging checklist, in order:

  1. aws secretsmanager get-secret-value --secret-id <id> from inside the container.
  2. aws sts get-caller-identity — is the task role what you think it is?
  3. php bin/console cache:warmup -vvv — DI errors surface here with the offending parameter.
  4. Confirm the secret is plaintext (SecretString), not SecretBinary — base64 decoding surprises are common.
  5. Check the secret name you configured against the actual ARN; a typo'd name returns ResourceNotFoundException, which some wrappers swallow into null.

Extension points worth knowing: the config tree (override the service/loader choice), the provider class (subclass to swap AWS for SSM or Vault), and DI decoration if you need to intercept resolution without forking. In your Laravel port, the equivalent seam is a container binding for an interface like SecretsProvider — do that on day one, because you will eventually need to add a second backend or a test double.

Testing: never let the test suite touch AWS. Bind the provider to a fixture-backed fake in TestCase::setUp() / phpunit.xml and assert that config paths populate correctly. If the bundle is a hard boot dependency, integration tests need a stubbed client or they'll be flaky and slow.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager