Fargateで特権ユーザ"以外"でタスクロールを使ってAWSサービスにアクセスする
2020.06.30
はじめまして!
はじめまして、こんにちわ!ゲストブロガーのフォージビジョン 山口です。
Amazon Web Service(AWS)を触っていて身についたノウハウや、面白いと思ったこと、ログ分析に関するポイントなどを書いていく予定です。
今回は、AWSのECS FargateというサービスをテーマにワンポイントのTipsをご紹介します。
ECSやFargateとという言葉が混在するとわかりにくいと思いますので、ここでは全てFargateとして統一します。
Fargateで特権ユーザ"以外"でタスクロールを使ってAWSサービスにアクセスする
タスクロールとは
EC2を使っている方は馴染み深いIAMロールですが、Fargateのコンテナで利用する場合は同じ役割をタスクロールと呼びます。(Fargateコンテナをデプロイする時のロールはタスク実行ロールと呼ばれて違う役割になるので注意です)
タスクロールはAWSマネージメントコンソールでFargateのタスク定義より設定可能です。
コンテナからAWSのサービス(API)に対してアクセスが必要な時にアクセス範囲や権限をコントロールするのに便利です。
APIキーを環境変数はパラメータストアなどで渡すことも可能ですが、IAMロールの方がAPIキーのローテーションやキーの漏洩などのリスクが少ないため、回避策が存在しない(回避策のコストがリスクを上回る)時以外は、私はAPIキーを採用しません。
タスクロール利用時の注意点
EC2使う場合のIAMロールとFargateのタスクロールでは、AWS認証情報を取得するための接続先が異なります。
・EC2の場合(AWS認証情報を取得するインスタンスメタデータエンドポイント)
http://169.254.169.254/latest/meta-data/iam/security-credentials/
・Fargateの場合(AWS認証情報を取得するタスクメタデータエンドポイント)
http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
この差分でどういう時に影響が出るかと言うと、コンテナ上でrootユーザ以外で動作しているアプリケーションからタスクロールの認証情報を使って、AWSサービスにアクセスする場合です。
例えば、AWS SDK for Python (Boto3) を使って、uWSGIユーザで起動したWebアプリケーションからS3バケットにアクセスするときを想像してください。
この時、特に気にせずEC2インスタンスのIAMロールと同じようにタスクロールを適用するだけではエラーが発生します。
なぜ、エラーが発生するのか
Fargateのタスクロールが参照するAWS認証情報の取得先は、実はプロセスID 1(特権ユーザプロセス)のみに適用される環境変数となっています。
したがって、一般ユーザである、uWSGIユーザで起動したプロセスのWebアプリケーションでは、AWS認証情報を取得に必要なタスクメタデータエンドポイントへ接続するための環境変数が適用していない事となります。
結果、下記のようなエラーが発生し、AWS認証情報を取得できません。
botocore.utils: Caught retryable HTTP exception while making metadata service request to http://169.254.169.254/latest/meta-data/iam/security-credentials/: Could not connect to the endpoint URL: "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
解決策
特権ユーザの環境変数として適用されているタスクメタデータエンドポイントを一般ユーザも参照できるようにしてあげれば解決出来ます。
解決策の1つとして、Dockerfileに下記の記述を加える方法があります。ほとんどのケースでは、この方法で解決可能だと思います。(/bin/falseなど非ログインユーザにも適用可能)
RUN echo 'export $(strings /proc/1/environ | grep AWS_CONTAINER_CREDENTIALS_RELATIVE_URI)' >> /etc/bashrc
この記述を加えたあとにタスクロールが適用されたFargateコンテナから、uWSGIユーザで起動したプロセスのWebアプリケーションからAWSサービスにアクセスすると、下記のようにタスクメタデータエンドポイントからAWS認証情報を取得可能になります。
urllib3.connectionpool: http://169.254.170.2:80 "GET /v2/credentials/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX HTTP/1.1" 200 1382
以上、ゲストブログ初投稿でした。
こんな感じで、今後もAWSに関しては各サービスを使う上でのノウハウや、面白いと思った書いていきます。
ブログの内容でもっと良い方法があるよ、などありましたらツイッターなどでフィードバックもらえると嬉しいです!
※参考 AWS Forums: Making AWS APIs calls from Fargate https://forums.aws.amazon.com/thread.jspa?threadID=273767#898645