インスタンスロールに S3 アクセスを許可する

AWSBeginner
オンラインで実践に進む

はじめに

EC2 アプリケーションは S3 からレポートを読み取る必要があります。インスタンスプロファイルを通じてアプリケーションに IAM ロールを割り当て、実際のレポート読み取りを確認し、権限を取り消したときの動作を観察します。

EC2 の起動、User Data、基本的な IAM ポリシーを理解していることが前提です。この新しい環境には、アプリケーションイメージ、ネットワーク、キーペア、架空のデータを含む S3 バケットが用意されています。アプリケーションインスタンスとその認可用リソースを作成します。

認定試験との関連

このラボでは最小権限とワークロードのロールを練習し、AWS Certified Cloud Practitioner のセキュリティ目標のタスク 2.3 と、コンピューティング目標のタスク 3.3 の理解に役立てます。

ロールのないアプリケーションを起動する

このステップではレポートサーバーを起動し、アプリケーションがまだ S3 を読み取れないことを確認します。

作業ディレクトリで、用意されたイメージ、ネットワーク、レポートバケットの ID を読み込みます。

cd /home/labex/project
source launch.env

用意された起動スクリプトを確認します。アプリケーションの S3 バケットとオブジェクトキーを設定しますが、認証情報は渡しません。

cat role-user-data.sh

この設定で role-server という名前のサーバーを起動します。

aws ec2 \
  run-instances \
  --image-id "$AMI_ID" \
  --instance-type t3.micro \
  --subnet-id "$SUBNET_ID" \
  --security-group-ids "$SECURITY_GROUP_ID" \
  --key-name report-key \
  --count 1 \
  --user-data file://role-user-data.sh \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=role-server}]'

ID を保存します。

INSTANCE_ID=$(aws ec2 \
  describe-instances \
  --filters Name=tag:Name,Values=role-server \
  --query 'Reservations[0].Instances[0].InstanceId' \
  --output text)
aws ec2 \
  wait instance-running \
  --instance-ids "$INSTANCE_ID"

AWS View を開き、Refresh resources をクリックして role-server を選択し、Check application をクリックします。HTTP 200 と Role report server を確認します。次に Read S3 report をクリックします。HTTP 503 と Application storage unavailable が期待されます。実行中のアプリケーションにはまだロールの認証情報がありません。

EC2 上のアプリケーションはインスタンスメタデータを通じて、割り当てられたロールの一時認証情報を取得できます。AWS SDK はその情報を使って API リクエストに署名します。公式の EC2 ロールガイドでは、この手順を説明しています。ターミナルの認証情報をアプリケーションへコピーせず、ロールを設定します。

インスタンスプロファイルでアクセスを許可する

このステップでは、ロールの信頼ポリシーと権限ポリシーを作成し、ロールをインスタンスプロファイルに追加してサーバーに関連付けます。

信頼ポリシーは、誰がロールを引き受けられるかを定義します。EC2 サービスを信頼する JSON ポリシーを作成します。区切り文字を引用符で囲んだヒアドキュメントにより、JSON がそのまま保持されます。

cat > ec2-trust.json <<'JSON'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "ec2.amazonaws.com"},
    "Action": "sts:AssumeRole"
  }]
}
JSON

この信頼ポリシーで report-reader ロールを作成します。

aws iam \
  create-role \
  --role-name report-reader \
  --assume-role-policy-document file://ec2-trust.json

権限ポリシーは、引き受けたロールが実行できる操作を定義します。このアプリケーションに必要なのは report.csv に対する s3:GetObject だけです。オブジェクト ARN にはバケットとキーの両方が含まれます。前の引用符付きヒアドキュメントとは異なり、以下の引用符なしの JSON は $REPORT_BUCKET を用意されたバケット名に展開します。

cat > read-report.json <<JSON
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "s3:GetObject",
    "Resource": "arn:aws:s3:::$REPORT_BUCKET/report.csv"
  }]
}
JSON

展開されたリソース ARN を確認します。

cat read-report.json

このインラインポリシーをロールに追加します。

aws iam \
  put-role-policy \
  --role-name report-reader \
  --policy-name ReadReport \
  --policy-document file://read-report.json

インスタンスプロファイルは IAM ロールを EC2 に提供します。CLI を使う場合、ロールとプロファイルを別々に作成します。分かりやすくするため、同じ名前のプロファイルを作成します。

aws iam \
  create-instance-profile \
  --instance-profile-name report-reader

ロールをプロファイルに追加します。

aws iam \
  add-role-to-instance-profile \
  --instance-profile-name report-reader \
  --role-name report-reader

既存のインスタンスにプロファイルを関連付け、削除時に使う関連付け ID を保存します。

ASSOCIATION_ID=$(aws ec2 \
  associate-iam-instance-profile \
  --instance-id "$INSTANCE_ID" \
  --iam-instance-profile Name=report-reader \
  --query 'IamInstanceProfileAssociation.AssociationId' \
  --output text)

関連付けを確認します。

aws ec2 \
  describe-iam-instance-profile-associations \
  --association-ids "$ASSOCIATION_ID" \
  --query 'IamInstanceProfileAssociations[].{Instance:InstanceId,State:State,Profile:IamInstanceProfile.Arn}'

associated と report-reader プロファイルを確認します。AWS View を更新し、Read S3 report をクリックします。HTTP 200 と period,total、Q1,320 が期待されます。アプリケーションは SDK のロール認証情報を使って実際の S3 オブジェクトを取得します。関連付けがまだ伝播中であれば、少し待ってからリクエストを再試行してください。

このロールは 1 つのオブジェクトの読み取りを許可し、バケット全体へのアクセスや管理者権限は与えません。インスタンスプロファイルガイドでは、プロファイルによるロールの提供と、関連付け変更の伝播に時間がかかる理由を説明しています。

権限の取り消しを確認する

このステップではロールのレポート権限を削除し、認可の失敗とアプリケーションの障害を区別します。

自分で作成したインラインポリシーだけを削除します。

aws iam \
  delete-role-policy \
  --role-name report-reader \
  --policy-name ReadReport

ロールに残っているインラインポリシーを一覧表示します。

aws iam \
  list-role-policies \
  --role-name report-reader

空の PolicyNames 一覧が期待されます。インスタンスプロファイルは関連付けられたままですが、ロールはレポートの読み取りを許可しなくなります。

AWS View で Check application をクリックし、HTTP 200 を確認します。サーバーはまだ実行中です。次に Read S3 report をクリックします。HTTP 403 と Access denied が期待されます。権限変更がまだ伝播していない場合は、少し待って再度リクエストしてください。正常なヘルス応答と S3 の拒否が同時に見られる場合、インスタンス停止やアプリケーション欠落ではなく認可の問題を示します。

SDK は一時認証情報をキャッシュすることがあります。ロールの権限を削除すると、その認証情報で実行できる操作が変わります。インスタンスプロファイルの削除によって、すでに発行された認証情報が直ちに失効するわけではありません。

インスタンスとロールを削除する

このステップでは、自分で作成した関連付け、サーバー、プロファイル、ロールを削除します。

保存した関連付け ID でプロファイルの関連付けを解除します。

aws ec2 \
  disassociate-iam-instance-profile \
  --association-id "$ASSOCIATION_ID"

アプリケーションインスタンスを終了します。

aws ec2 \
  terminate-instances \
  --instance-ids "$INSTANCE_ID"
aws ec2 \
  wait instance-terminated \
  --instance-ids "$INSTANCE_ID"

使わなくなったインスタンスプロファイルからロールを削除します。

aws iam \
  remove-role-from-instance-profile \
  --instance-profile-name report-reader \
  --role-name report-reader

空のプロファイルを削除します。

aws iam \
  delete-instance-profile \
  --instance-profile-name report-reader

インラインポリシーは権限取り消し時に削除済みです。自分のロールを削除します。

aws iam \
  delete-role \
  --role-name report-reader

インスタンスが終了したことを確認します。

aws ec2 \
  describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[].Instances[].{Instance:InstanceId,State:State.Name}'

指定した名前のロールとプロファイルがないことを確認します。

aws iam \
  list-roles \
  --query "Roles[?RoleName=='report-reader'].RoleName"
aws iam \
  list-instance-profiles \
  --query "InstanceProfiles[?InstanceProfileName=='report-reader'].InstanceProfileName"

両方の一覧が [] であることを確認します。AWS View を更新して、サーバーが実行中の対象ではないことを確認してください。用意された S3 データ、ネットワーク、キーペアはそのまま残します。

まとめ

IAM ロールに EC2 の信頼関係と 1 つの S3 オブジェクトの読み取り権限を設定し、インスタンスプロファイルでロールを提供して、アプリケーションが実際にレポートを読み取ることを確認しました。その後、権限を取り消し、S3 の拒否とアプリケーションの正常稼働を区別しました。最後にインスタンス、プロファイル、ロールを削除しました。