AWS IAMにおける,AssumeRole・PassRoleの利用についての備忘録的な記事になります.
AWS IAM
IAMは,各種リソースへのアクセスを安全にコントロールするために使用されるサービスです.
AssumeRole
AssumeRole は,AWSのリソースが,IAMロールを引き受けることを表します.
PassRole
PassRole は、 AWSのリソースに IAMロールを渡す(パスする)ことを表します.
今回やりたいこと
本記事では,下図の内容をCLIで実施しながら,AssumeRole・PassRoleの挙動を確認します.
①:開発用のIAMユーザー(dev-user)を作成し検証
②:dev-userがEC2を作成できるような一時権限を取得
③:dev-userでEC2を作成し,EC2にS3読み取りの権限を付与する
②では,dev-userがIAM ロールに設定された権限(EC2作成権限)を引き受けます.
③では,dev-userがEC2にIAMロールに設定された権限(S3読み取り権限)を付与します.(同時にEC2は,S3読み取り権限を引き受けることになります.)
AssumeRole
作業用のIAMユーザーを作成
まずは管理者権限を持つユーザーにて,今回の作業用IAMユーザーを作成します.
ユーザー名はdev-user
とします.現時点では何の権限もありません.
#ユーザーの作成 aws iam create-user \ --user-name dev-user \ --path "/blog/dev/" #Arnの確認 aws iam list-users \ --path-prefix "/blog/dev/" \ --query 'Users[].Arn' \ --output text
IAMロールを作成
dev-userが引き受けることになる,IAMロール(EC2作成権限)を作成します.
TRUST_FILE='./trust-ec2-create-role.json' cat << EOF > ${TRUST_FILE} { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Principal": { "AWS": "arn:aws:iam::XXXXX:user/blog/dev/dev-user" } } ] } EOF #Roleの作成 aws iam create-role \ --role-name ec2-create-role \ --assume-role-policy-document file://trust-ec2-create-role.json \ --path "/blog/dev/"
信頼関係のAction
に,AssumeRoleが出てきます.
PrincipalにIAMユーザー(dev-user)のArnを指定することで,dev-userがこのIAMロールを引き受けることができるようになります.
※ユーザー名で指定する方法の場合、上記のように信頼関係の設定のみで,ユーザーにもIAMロールを引き受ける権限(sts:AssumeRole)が許可されます.アカウントの場合,ユーザーのポリシーの設定も必要となります.
上記で作成したIAMロールにアタッチするポリシーを作成します.EC2を作成できればよいので,ec2:RunInstances
を許可します.
また,後ほどEC2にロールを付与する(PassRole)ために,事前にec2:AssociateIamInstanceProfile
ec2:ReplaceIamInstanceProfileAssociation
も許可しておきます.
POLICY_FILE='./policy-ec2-create.json' cat << EOF > ${POLICY_FILE} { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": [ "ec2:RunInstances", "ec2:AssociateIamInstanceProfile", "ec2:ReplaceIamInstanceProfileAssociation" ], "Resource": "*" } ] } EOF #policyを作成 aws iam create-policy \ --policy-name policy-ec2-create \ --policy-document file://policy-ec2-create.json
下記のコマンドで,ロールにポリシーをアタッチします.
#ポリシーのArnを取得 POLICY_ARN=$(aws iam list-policies --query 'Policies[?starts_with(PolicyName,`policy-ec2`)].Arn' \ --output text) && echo ${POLICY_ARN} #ロールにポリシーをアタッチ aws iam attach-role-policy \ --role-name ec2-create-role \ --policy-arn ${POLICY_ARN}
これで,dev-userはEC2を作成する権限を引き受ける準備ができました. 以降,dev-userで作業するために,dev-userのアクセスキーを発行しておきます.
aws iam create-access-key --user-name dev-user
AssumeRoleの実施
dev-userに切り替え,何もしていない状態で,EC2インスタンスを立ち上げる下記のコマンドを実行してみます.
aws ec2 run-instances \ --image-id ami-0fe23c115c3ba9bac \ --count 1 \ --instance-type t2.micro \ --associate-public-ip-address
現時点では,権限がないため,エラーとなります.
An error occurred (UnauthorizedOperation) when calling the RunInstances operation: You are not authorized to perform this operation.
EC2作成用のロールを引き受けます.(AssumeRoleします)
aws sts
コマンドを使用し,対象のIAMロールのArnにEC2作成用のロールArnを指定します.
aws sts assume-role \ --role-arn "arn:aws:iam::XXXXX:role/blog/dev/ec2-create-role" \ --role-session-name temp-session \ --duration-second 900
実行すると,下記のように一時的なクレデンシャルを取得できます.
{ "Credentials": { "AccessKeyId": "XXX", "SecretAccessKey": "XXX", "SessionToken": "XXX", "Expiration": "2022-07-02T08:41:21+00:00" }, "AssumedRoleUser": { "AssumedRoleId": "XXXXXXXXXX:temp-session", "Arn": "arn:aws:sts::XXXXX:assumed-role/ec2-create-role/temp-session" } }
環境変数AWS_ACCESS_KEY
,AWS_SECRET_ACCESS_KEY
,AWS_SESSION_TOKEN
を上記で取得したものに置き換えることで一時的な認証情報で作業します.
変更が適用されているかどうかは,下記のコマンドで作業中のプロファイルすることで判断できます.
aws sts get-caller-identity
{ "UserId": "XXXXXXXXXXXXXXX", "Account": "XXXXX", "Arn": "arn:aws:iam::XXXXX:user/dev-user" }
この状態で,上記のaws ec2 run-instances
を実行するとEC2インスタンスを起動することができます.
PassRole
作成したEC2インスタンスには,他のリソースを操作する権限はないので,EC2からaws s3 ls
としても権限不足によるエラーとなります.
EC2からS3バケットを読み取ることができるように,dev-userからEC2にIAMロールを付与します.
dev-userで上記のIAMロールをAssumeRoleした状態で,下記のコマンドを実行します.
aws ec2 associate-iam-instance-profile \ --instance-id i-03f95fdd292ae52b4 \ --iam-instance-profile Name=s3readInstanceProfile
コマンドでは,作成済みの(※作成手順は記事最後に記載)インスタンスプロファイルを,先程作成したEC2に紐づけていますが,このコマンドの実行結果はエラーになります.dev-userには,EC2インスタンスにIAMロールを渡す(PassRoleする)権限がないためです.
※この場合,厳密にはインスタンスプロファイルに紐づいたIAMロールを渡そうとしています.
公式ドキュメントを確認しておきます.
下記の通り,EC2にIAMロールを付与するには,PassRole
が必要なことがわかります.
dev-userが引き受けた,EC2作成用のIAMロールに,ec2:RunInstances
以外の許可を与えたのはこのためです.
IAM ロールを持つインスタンスの起動、および既存インスタンスへの IAM ロールのアタッチと置換を許可するには、以下の API アクション を実行するためのアクセス許可を付与します。
- iam:PassRole
- ec2:AssociateIamInstanceProfile
- ec2:ReplaceIamInstanceProfileAssociation
PassRole可能なIAMロールを作成
この作業は管理者権限を持つIAMユーザーで実施しています.
EC2作成用のIAMロールのポリシーを変更し,PassRole付きのポリシーとします.Action
PassRoleのResource
に,S3への読み取り権を持つIAMロール(※事前作成済み.作成方法は記事先後に記載.)を指定することで,このポリシーを付与されたリソースは,他のリソースにS3アクセスの権限をPassできるようになります.
TRUST_POLICY_FILE='./policy-ec2-create.json' cat << EOF > ${TRUST_POLICY_FILE} { "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Action": [ "ec2:RunInstances", "ec2:AssociateIamInstanceProfile", "ec2:ReplaceIamInstanceProfileAssociation", ], "Resource": "*" }, { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::XXXXX:role/s3read" } ] } EOF #先に作成したポリシーを作り直すために,一旦IAMロールからdetach POLICY_ARN=$(aws iam list-policies --query 'Policies[?starts_with(PolicyName,`policy-ec2`)].Arn' \ --output text) && echo ${POLICY_ARN} aws iam detach-role-policy \ --role-name ec2-create-role \ --policy-arn ${POLICY_ARN} #PassRoleの権限がないポリシーを削除 aws iam delete-policy --policy-arn ${POLICY_ARN} #PassRoleの権限があるポリシーを作成 aws iam create-policy \ --policy-name policy-ec2-create \ --policy-document file://policy-ec2-create.json #新しく作成したポリシーのArnを取得 POLICY_ARN=$(aws iam list-policies --query 'Policies[?starts_with(PolicyName,`policy-ec2`)].Arn' \ --output text) && echo ${POLICY_ARN} #ec2 create roleにPassRole可能なポリシーをアタッチ aws iam attach-role-policy \ --role-name ec2-create-role \ --policy-arn ${POLICY_ARN}
PassRoleを実施
ここから,dev-userで作業します.
dev-userにて,PassRoleの権限を付与したEC2作成用のIAMロールを引き受けます.
#dev-userで実施 aws sts assume-role \ --role-arn "arn:aws:iam::XXXXX:role/blog/dev/ec2-create-role" \ --role-session-name temp-session \ --duration-second 900
作成済みのEC2に,先程のIAMロールでは,エラーとなった下記のコマンドを実行し,S3読み取り権限を持つインスタンスプロファイルを紐づけます.
aws ec2 associate-iam-instance-profile \ --instance-id i-03f95fdd292ae52b4 \ --iam-instance-profile Name=s3readInstanceProfile
{ "IamInstanceProfileAssociation": { "AssociationId": "iip-assoc-01c1886db23b64937", "InstanceId": "i-0d8012d6a3f4abf80", "IamInstanceProfile": { "Arn": "arn:aws:iam::XXXXX:instance-profile/s3readInstanceProfile", "Id": "XXXXXXXXXXX" }, "State": "associating" } }
PassRoleの権限を付与したことで,問題無く実行できるようになります.
EC2からもS3の読み取りができるようになります.
まとめ
個人的に,AssumeRoleと特にPassRoleのイメージがあまりわかなかったのですが,CLIを通して細かく設定していくことで,基本的でありながらセキュリティの観点では,理解必須の機能であることを再認識できました.今回は以上になります.
(※)S3読み取り権限を持つインスタンスプロファイルの作成
EC2に付与するS3読み取り可能なIAMロールの作成手順です.
※この作業は管理者権限を持つユーザーで実行しています.
TRUST_POLICY_FILE='./ec2-role-trust-policy.json' cat << EOF > ${TRUST_POLICY_FILE} { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com"}, "Action": "sts:AssumeRole" } ] } EOF #IAMロールの作成 aws iam create-role \ --role-name s3read \ --assume-role-policy-document file://ec2-role-trust-policy.json #IAMポリシーのArnを取得 POLICY_ARN=$(aws iam list-policies --query 'Policies[?starts_with(PolicyName,`AmazonS3ReadOnlyAccess`)].Arn' \ --output text) && echo ${POLICY_ARN} #IAMロールにポリシーをアタッチ aws iam attach-role-policy \ --role-name s3read \ --policy-arn ${POLICY_ARN}
インスタンスプロファイルにIAMロールを紐づけます.
#インスタンスプロファイルを作成 aws iam create-instance-profile \ --instance-profile-name s3readInstanceProfile #インスタンスプロファイルとIAMロールを紐づけ aws iam add-role-to-instance-profile \ --role-name s3read \ --instance-profile-name s3readInstanceProfile