Skip to content

Allow AWS SDK credential chain for S3 storage#6121

Open
TheJenne18 wants to merge 1 commit into
BookStackApp:developmentfrom
TheJenne18:fix/s3-credential-chain
Open

Allow AWS SDK credential chain for S3 storage#6121
TheJenne18 wants to merge 1 commit into
BookStackApp:developmentfrom
TheJenne18:fix/s3-credential-chain

Conversation

@TheJenne18
Copy link
Copy Markdown

Summary

When running BookStack with STORAGE_TYPE=s3 on infrastructure that provides AWS credentials via the SDK credential chain (EC2 instance profile, ECS task role on Fargate/EC2, EKS IRSA, Lambda execution role, etc.), all S3 operations fail with errors such as:

Unable to check existence for: uploads/images/gallery/2026-06/<file>.png

even though the environment correctly exposes credentials and the role has full S3+KMS permissions.

Root cause

app/Config/filesystems.php defaulted STORAGE_S3_KEY to 'your-key' and STORAGE_S3_SECRET to 'your-secret'. When these env vars are not set, those literal placeholder strings are handed to the AWS PHP SDK as explicit credentials. Because explicit credentials are present, the SDK does not consult its default credential provider chain, and every S3 call fails with 403, which Flysystem v3 wraps as UnableToCheckFileExistence.

The AWS SDK only walks the chain (env vars → container creds → instance metadata → ...) when key and secret are null/absent.

Change

Default the key and secret of the s3 disk to env('STORAGE_S3_KEY') / env('STORAGE_S3_SECRET') without a fallback (i.e. null when unset). Existing setups that set these env vars explicitly are unaffected; IAM-role-based setups now work out of the box.

Reproduction (before)

  1. Deploy BookStack on ECS Fargate with STORAGE_TYPE=s3, STORAGE_S3_BUCKET, STORAGE_S3_REGION set, and no STORAGE_S3_KEY / STORAGE_S3_SECRET.
  2. Attach an IAM task role with the required S3/KMS permissions on the bucket.
  3. POST /api/image-gallery → HTTP 500, Unable to check existence for: ….

Workaround that confirmed the diagnosis

Setting STORAGE_S3_KEY=null and STORAGE_S3_SECRET=null (Laravel's env() converts the string "null" to PHP null) makes uploads succeed via the task role. With this PR that workaround is no longer needed.

Test plan

  • Existing S3 setups with explicit STORAGE_S3_KEY/STORAGE_S3_SECRET keep working.
  • S3 setups on ECS/EC2 with an IAM role and no explicit credentials now work.
  • Local / local_secure storage unaffected.

When STORAGE_S3_KEY / STORAGE_S3_SECRET are unset, the previous default
placeholder strings ('your-key' / 'your-secret') were passed as explicit
credentials to the AWS PHP SDK. Because the SDK treats any non-null
key+secret as credentials, it never consulted its default credential
provider chain, breaking IAM-role-based setups (ECS task role on
Fargate/EC2, EKS IRSA, EC2 instance profile, Lambda execution role).

Changing the defaults to null lets the SDK fall through to the
credential chain when these env vars are omitted, while preserving
existing behaviour for users who set them explicitly.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant