Amazon ECS (on ECS) で、nginx ユーザーとして起動している PHP (php-fpm) アプリが、S3 にファイルをアップロードできなかった時の対処方法です。
前提条件
- Amazon Linux 2023 のコンテナー
- Concrete CMS 9.2.x
- PHP バージョンは Amazon Linux 2023 レポジトリの v8.2.x
- MariaDB は 10.11.x
- Nginx & php-fpm を nginx ユーザーとして起動
- ECS タスクロールに S3 バケットにアップロードできる権限を付与
- Concrete CMS 用 S3 バケット IAM Policy サンプル プラス、他のタスクロール
エラー
Concrete CMS 管理画面から、S3 でファイルをアップロードしようとすると、以下の 403 エラーが出てしまいました。
Error executing "ListObjectsV2" on "https://[バケット名].s3.ap-northeast-1.amazonaws.com/?list-type=2&prefix=&delimiter=%2F"
; AWS HTTP error: Client error: `GET https://[バケット名].s3.ap-northeast-1.amazonaws.com/?list-type=2&prefix=&delimiter=%2F
` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>EY5N4E (truncated...)
AccessDenied (client): Access Denied - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>[省略]</RequestId><HostId>[省略]</HostId></Error>
しかし (ECS on EC2 なので) コンテナーの中に bash で入って、aws s3 の CLI コマンドを打つと、ちゃんと問題なくファイルをアップロードできました。 ECS のタスクロールは正常でした。
root ユーザーでは正常に S3 にアクセスできたのに、nginx ユーザーではアクセスできなかったのです。
原因: Nginx ユーザーに AWS_CONTAINER_CREDENTIALS_RELATIVE_URI が渡ってなかった
ECS タスクロールから降ってくる IAM ロールの認証情報に必要な AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
サーバー ENVIRONMENT 環境変数は、root ユーザーにしか付与されず、nginx ユーザーには渡らなかったのです。
PHPのSDKは AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
か AWS_CONTAINER_CREDENTIALS_FULL_URI
をみに行くようになっていたとのことです。
一時的に usermod -s /bin/bash nginx
コマンドで nginx ユーザーとして su - nginx
コマンドでログインできるようにして printenv
コマンドで、environment を確認できます。
(実際は、弊社マカルーデジタルのエンジニアが PHP スクリプトを作ってデバッグしました。)
解決方法: php-fpm 設定で root の environment 情報をクリアしないように設定
そこで「ECS上のPHPアプリからAWS SDKを使うとmetadata endpointへアクセスできない問題の備忘録」ブログ記事に詳細と解決方法が記載されています。
僕は、以下の設定を追記することにしました。
clear_env = no
イメージをビルドし直し、無事に php-fpm から S3 バケットにアップロードできました!
注意: この方法は php-fpm でアクセスできるようにするものです。 bash (or CLI) での nginx ユーザーからはまだアップロードはできません。