Fargateコンテナに付与したRoleと同等の権限でローカル開発環境からAWS S3にアクセスする
※記事中ではS3に限定していますが、AWSリソース全般にアクセスする際に使える方法です。
概要
バックエンド(Node.js)をFargateで動かしており、そのコンテナからS3バケットにアクセスしている。ローカル開発(Mac OS)でもDockerを利用しているが、クラウド上のコンテナとRoleは異なる。
ローカル環境と、ステージング・本番環境で差異が生まれないように、下記条件を満たすS3アクセス方法を探ったので備忘として記しておく。
- ソースコードに違いが生じないようにする(各環境用にif分岐など使いたくない)
- クラウド上のコンテナに付与したRoleと同等の権限にする
結論
- Fargateのコンテナと同じアクセス権限をもった Access Key ID と Secret Access Key を
~/.aws/credentials
に[default]
として記載し、その権限でクラウドのS3にアクセスする - Minio は使わない
AWS SDK for JavaScript への認証情報の提供
要は AWS SDK の権限はどう決まるのかという話だが、公式にこのように書いてある。
推奨の順序で認証情報を提供する方法は次のとおりです。
- Amazon EC2 の AWS Identity and Access Management (IAM) ロールから読み込む
- 共有認証情報ファイル (~/.aws/credentials) から読み込む
- 環境変数から読み込む
- ディスク上の JSON ファイルから読み込む
- JavaScript SDK によって提供されるその他の認証情報プロバイダークラス
「1.」はクラウドでの話なので、ローカルで利用する際に推奨されるのは「2.」ということ。因みに「1.」「2.」の方法は、SDKが自動でロードしてくれるので、どちらもソースコードに手を加える必要がない点が重要。
よくやりがちなのが、「3. 環境変数から読み込む」で、下記のようなコードをよく見かける。
AWS.config.update({
accessKeyId: process.env.ACCESS_KEY_ID,
secretKey: process.env.SECRET_KEY
})
この場合、if分岐等でクラウドのコンテナでは読み込ませないなどの処理が必要になる。または、同コードで、クラウドのコンテナにも環境変数に ACCESS_KEY_ID
と SECRET_KEY
を設定しなければならない(漏洩リスクが高まるので絶対やめておくこと)。
本来、環境変数を読み込む場合、AWS_ACCESS_KEY_ID
、AWS_SECRET_ACCESS_KEY
という変数名であればSDKは自動で読み込んでくれるので上記のような心配はない。
ただ .env
ファイルに、クラウドでは不要な環境変数は置きたくないし、だからと言って毎度環境変数を読み込むのは面倒くさい。
したがって、AWSが推奨しているようにローカルでは「2.」の手段をとることが望ましい。
~/.aws/credentials ファイルに認証情報を設定
credentialsファイルに認証情報を記載するが、ここで重要なのは下記2点。
-
[default]
として書くこと - コンテナと同等の権限を持つ
aws_access_key_id
、aws_secret_access_key
を記載すること
[default]
region=ap-northeast-1
aws_access_key_id = XXXXXXXXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
[default]
である必要があるのは、SDKが自動で読み込む対象が [default]
だから。そうでない方法も可能だが、SDKにプロファイル情報を渡す必要が生じ、例によってif分岐が必要になる。
コンテナと同等の権限を持つ必要があるのは、言わずもがなステージング・本番環境との差異をなくすため。
こうすることで権限にもソースコードにも差分は発生しない。
const s3 = new AWS.S3({
apiVersion: "2006-03-01"
});
s3.putObject(params, (err, data) => {
...
});
Dockerコンテナを立ち上げる際、 $HOME/.aws/:/root/.aws/
のように認証情報のあるディレクトリをマウントすることを忘れないように。
Minioについて(余談)
ローカルのS3と言えるMinioに関しては、使う要件に出くわしたことがないし、個人的にはS3を利用する際はクラウドを利用するのがいいと思っている。
理由は単純で、ローカルが軽いままだし、本物にアクセスしたほうがバグが発生しにくくなると思っているから。
Discussion