healthengine/laravel-easy-aws
healthengine/laravel-easy-aws simplifies connecting Laravel applications to Amazon Web Services. It offers straightforward configuration and convenient helpers for common AWS services, reducing boilerplate so teams can integrate cloud functionality faster with less setup.
healthengine/laravel-easy-aws is a small integration package whose job is to wrap AWS SDK credential resolution in Laravel's cache so that dynamic (STS/assume-role/instance-profile) credentials are fetched once and reused until they are near expiry. That matters most when you have many PHP workers, queue consumers, or short-lived containers that would otherwise call STS or IMDS on every request.
Minimal setup:
composer require healthengine/laravel-easy-aws
composer.json for extra.laravel.providers), register the service provider in config/app.php.php artisan vendor:publish --tag=easy-aws-config
The published config/easy-aws.php is the source of truth for the option names — the package is tiny enough that reading src/ alongside the config file takes a few minutes and saves guesswork.AWS_REGION=ap-southeast-2
AWS_ROLE_ARN=arn:aws:iam::123456789012:role/app-role
AWS_ROLE_SESSION_NAME=my-app
EASY_AWS_CACHE_STORE=redis
EASY_AWS_CACHE_TTL=3000
php artisan tinker
>>> app(Aws\Sdk::class)->createSts()->getCallerIdentity();
A successful call confirms the cached provider is wired into the SDK. Run it twice — the second call should not hit STS.First real use case: put the cached provider behind every AWS client in a Laravel app so that S3, SQS, SNS, DynamoDB, etc. all share one cached CredentialsInterface. This is the highest-leverage thing the package does and the reason to prefer it over hand-rolling CredentialProvider::cache() in each service.
Resolve the SDK from the container, not new Sdk(). The package's value comes from the singleton binding. Inject Aws\Sdk and let the provider supply cached credentials:
use Aws\Sdk;
final class ReportUploader
{
public function __construct(private Sdk $sdk) {}
public function upload(string $path, string $body): void
{
$this->sdk->createS3()->putObject([
'Bucket' => config('filesystems.disks.s3.bucket'),
'Key' => $path,
'Body' => $body,
]);
}
}
Keep one cache key per identity. If you assume different roles for different tenants or services, do not share the default cache entry. Either build one container binding per role (preferred) or vary the config/cache key by role ARN and region before resolving the SDK. Cross-tenant credential leakage is the failure mode to design against.
Use it as the credential layer, not the client layer. Configure your existing packages (Laravel's S3 filesystem driver, aws/aws-sdk-php-laravel, custom SQS consumers) to consume the same credentials. In practice you either bind Aws\Sdk and hand it to those integrations, or configure them with the credential_provider option pointing at the package's provider.
Pick a cache store appropriate to the deployment. Redis or Memcached is right for anything multi-instance; file is acceptable only for single-node setups. The whole point is that N app containers share one credential fetch, so a per-container store largely defeats the cache.
Size the TTL against the session duration. STS credentials from AssumeRole default to one hour and cap at twelve. Set the cache TTL below that (e.g. 50 minutes for a one-hour session) so the SDK refreshes before expiry rather than serving a token that expires mid-request. The SDK's own credential cache has similar semantics; keep the two windows aligned.
Testing. Bind a fake or static credential provider in tests so no network call is made, and use the array cache driver only if you also stub the provider — otherwise every test triggers an STS call. If the package exposes a facade, Facade::shouldReceive(...) works; otherwise $this->swap(Aws\Sdk::class, $fakeSdk) is the cleanest seam.
Long-running processes. For queue workers (queue:work) and Octane, make sure the provider is resolved per-job or at least not cached for the lifetime of the process beyond the credential TTL. The cached provider should re-resolve when the underlying cache entry expires; verify this by running a worker past the TTL in staging before trusting it in production.
src/ is small; check what the service provider binds, what env keys it reads, and whether the cache key includes region/role. Do not assume parity with Aws\Credentials\CredentialProvider::cache().file, redis, and database stores serialize; the array store does not persist across requests. If your credential object is not serializable, the cache write silently degrades and you are back to per-request STS calls.InvalidClientTokenId or timeouts. If you are in a non-default partition or use a regional STS endpoint, set it explicitly; the package may only forward region to the SDK.RoleSessionName must match CloudTrail expectations. The package cannot fix IAM misconfiguration; surface STS errors verbatim during debugging.SignatureDoesNotMatch / RequestExpired that look like credential bugs. Check with date -u before blaming the cache.composer.json, and be prepared to vendor the credential-provider class into your app if the package is abandoned. Because the integration is small, inlining it later is a low-cost escape hatch — do not build abstractions on top of the package that would be hard to unwind.Aws\CacheInterface adapter around Cache::store(...) is often less work than fighting the package's defaults.2026-10-19 release date in the metadata looks anomalous. Verify the actual tag and diff before upgrading — treat version bumps as untested until you have re-run the tinker credential check in a deployed environment.How can I help you explore Laravel packages today?