AWS Fargate環境下のLaravelでIAMロールを利用しSESを利用する方法
Summary
- IAMロールはアクセスキーを発行するよりセキュアである
- Fargateの場合タスク定義のタスクロールに利用したいリソースのポリシーを設定する
- aws-sdkだけでなく、aws-sdk-php-laravelをinstallしておく
- Laravelに記載している環境変数及び環境変数を参照しているプログラムはコメントアウト
ToC
- Why IAM Role?
- Attention to setting IAM Role
- How to setting on AWS Fargate
- How to reference IAM Role on Laravel
Why IAM Role?
単純にセキュアだからです。
一般的な方法として用いられるIAMユーザーを作成してそのユーザーに対してアクセスキーを生成する方法は、簡単なのですが、アクセスキー漏洩のリスクが伴います。
万が一アクセスキーが漏洩し、そのキーの権限がadministratorと同じ場合、AWSアカウントを乗っ取られたのと同じくらいのインシデントになります。
前職の別プロジェクトの開発者が、アクセスキーを誤ってGitHubに公開してしまい見事に乗っ取られ、仮想通貨マイニング用のインスタンスを20台くらい建てられて数十万の請求をされてました。
そのくらいアクセスキーは慎重に扱わないといけない代物です。
アクセスキーを用いる場合は以下に気をつければ最低限のセキュリティリスクは回避できます。
それでも以下リスクは残ります。
- 開発環境で利用するアクセスキーを誤ってブログに載せてしまう
- Slack等で他者に共有してしまう
- アクセスキーのメモをローカルや貸与PCに保管してしまう
上記リスクも避けるためには、そもそもアクセスキーを利用しない方法がベストです。
IAMロールを付与すれば、付与されたAWSサービス内でしか設定したポリシーの権限を利用できません。
また、当たり前ですがプログラムにIAMロールに関する情報を記載する必要がないため漏洩のリスクはありません。
※あるとしたら直接対象のインスタンス等にsshアクセスされてしまって利用されるケースですが、これはまた別の話。
いちいちIAMユーザーの管理をする必要もないのでその点もメリットかと思います。
Attention to setting IAM Role
簡単にまとめますが、以下になります。
- 最低限の権限を付与する
- 複数のポリシーを組み合わせる
- 一つのポリシーに大きな権限を渡すと、使い回しがしにくい
- ポリシーをシンプルにしておくことで、他のリソースに対しても利用できる(ポリシーの管理がしやすい)
How to setting on AWS Fargate
タスク定義の設定における「タスクロール」に利用したいポリシーを定義する
個人的にタスク実行ロールとタスクロールの違いを理解するのに時間がかかりましたが、結論タスクロールに付与する形で問題ないです。
違いは以下です。
タスク実行ロール
Fargateタスクを実行するためのロール
例) タスク定義で設定されているECRイメージを参照する権限を付与 タスクを実行する際に発生するログを出力する権限を付与 etc...
タスクロール
実行されたタスク内のサービスに付与するロール
例) タスク内のプログラムからメール送信するためのSESを利用する権限を付与 ファイルアップロードするためのS3へのアクセス・アップロード権限を付与 etc...
How to reference IAM Role on Laravel
まとめると以下の流れです。
aws-sdk-php-laravelをinstall
通常aws-sdk-phpで事足りるのですが、利用したいAWSサービスによっては、aws-sdk-phpのみだとNGらしいのでinstallしてください。
install及び初期設定方法は以下参照してください。
https://github.com/aws/aws-sdk-php-laravel
環境変数を削除
ここかなりハマりました…
原因の切り分けがうまくできておらず、IAMロールを定義したのに、403エラーが出続けていました。
Laravelの場合、デフォルトだとアクセスキーの設定を.envに記述すると思うのですが、そもそも.envにアクセスキーの環境変数名が存在するだけで
Laravelは.envのみを参照しエラーになります。
ですので、.envにある環境変数名は削除かコメントアウトしてください。
※ちなみに、リソースによっては環境変数名を削除するのではなくnullを指定する必要があると書いてる記事もありますので、利用するリソースがどこで参照されているかを理解して置く必要があります。 ※例えばS3の場合config/filesystems.phpで認証情報を参照するのですが、その際は環境変数の値をnullにすればいいそうです。(未検証)
config/aws.php, config/service.phpのcredentials指定箇所を削除
最後の仕上げです。
環境変数を削除したので、当然環境変数を参照している箇所を削除しないとえらーになります。
今回はSESを利用するための設定変更のため、以下2ファイルの該当箇所を削除します。(※コメントアウトの箇所が該当箇所です。)
config/aws.php
/* |-------------------------------------------------------------------------- | AWS SDK Configuration |-------------------------------------------------------------------------- | | The configuration options set in this file will be passed directly to the | `Aws\Sdk` object, from which all client objects are created. This file | is published to the application config directory for modification by the | user. The full set of possible options are documented at: | http://docs.aws.amazon.com/aws-sdk-php/v3/guide/guide/configuration.html | */ // 'credentials' => [ // 'key' => env('AWS_ACCESS_KEY_ID', ''), // 'secret' => env('AWS_SECRET_ACCESS_KEY', ''), // ], 'region' => env('AWS_DEFAULT_REGION', 'ap-northeast-1'), 'version' => 'latest', 'ua_append' => [ 'L5MOD/' . AwsServiceProvider::VERSION, ],
config/service.php
/* |-------------------------------------------------------------------------- | Third Party Services |-------------------------------------------------------------------------- | | This file is for storing the credentials for third party services such | as Mailgun, Postmark, AWS and more. This file provides the de facto | location for this type of information, allowing packages to have | a conventional file to locate the various service credentials. | */ 'mailgun' => [ 'domain' => env('MAILGUN_DOMAIN'), 'secret' => env('MAILGUN_SECRET'), 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), ], 'postmark' => [ 'token' => env('POSTMARK_TOKEN'), ], // 'ses' => [ // 'key' => env('SES_KEY'), // 'secret' => env('SES_SECRET'), // 'region' => env('SES_REGION'), // ],
Conclusion
これでようやくIAMロールを活用して他のAWSサービスを利用する権限を付与することができました。
アクセスキーの漏洩リスクもないし、アクセスキーをデプロイ時に対象イメージ内に記載する処理を追加する必要もないので、非常にセキュアだと思います。
ぜひ皆さんもIAMロールを活用してセキュアなAWSライフを。