assume role とは: AWS リソースとか IAM ユーザの「プリンシパル」に IAM role を一時的につけること
プリンシパルの一覧はここ ↓ https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html
assume role をするためには、IAM ロールに「この人たちがこのロールを使っていいですよ」というポリシーを付ける必要がある
たとえば、下のポリシーは「AWS アカウント 1234... が、このロールに対して assume role というアクションをすることを許可しますよ」というポリシー。assume role のプリンシパルは AWS アカウント以外ももちろん指定できる。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "", "Effect": "Allow", "Principal": { "AWS": [ "123456789012" ] // ← AWSアカウントを信頼 }, "Action": "sts:AssumeRole" } ] }
下記より引用
今回は cognito に登録したユーザが IAM role を assume-role できるようにしたかったので、↓を参考にしながら進めた
下準備として、
- Cognito で User Pool をつくって、その中にユーザを登録する
- Cognito で Identity Pool をつくって、「認証されたロール」のところで IAM Role を作る OR 指定する
の2つが必要。IAM Role は「この Identity Pool の人は全員このロール」もできるし、条件に応じてロールを指定することもできる。カスタム属性値を使って指定もできるので結構柔軟にできそう。
各ルールは、トークンクレーム (Amazon Cognito ユーザープールからの ID トークンのユーザー属性など)、一致タイプ、値、および IAM ロールを指定します。一致タイプは、
Equals
、NotEqual
、StartsWith
、またはContains
となります。クレームに一致する値をユーザーが持っている場合、そのユーザーは、認証情報を取得するときにそのロールを引き受けることができます。例えば、custom:dept
カスタム属性値がSales
のユーザーに特定の IAM ロールを割り当てるルールを作成できます。
あとは記事に書いてあるとおりの手順でいけるけど、自分は最初の admin-initiate-auth
の部分を initiate-auth
に変えた。
REGION=xxx USER_POOL_ID=xxx CLIENT_ID=xxx USER_EMAIL=xxx PASSWORD=xxx IDENTITY_POOL_ID=xxx COGNITO_USER_POOL=cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID} echo "initiate auth: get ID token" ID_TOKEN=$(aws cognito-idp initiate-auth \ --client-id ${CLIENT_ID} \ --auth-flow USER_PASSWORD_AUTH \ --auth-parameters "USERNAME=${USER_EMAIL},PASSWORD=${PASSWORD}" \ --query "AuthenticationResult.IdToken" \ --output text) && echo ${ID_TOKEN} echo "" echo "get id: get identity id" IDENTITY_ID=$(aws cognito-identity get-id \ --identity-pool-id ${IDENTITY_POOL_ID} \ --logins "${COGNITO_USER_POOL}=${ID_TOKEN}" \ --query "IdentityId" \ --output text) && echo ${IDENTITY_ID} echo "" echo "get credentails for identity" OUTPUT=$(aws cognito-identity get-credentials-for-identity \ --identity-id ${IDENTITY_ID} \ --logins "${COGNITO_USER_POOL}=${ID_TOKEN}") \ && echo ${OUTPUT} # store the credentials in environment variables export AWS_ACCESS_KEY_ID=$(echo ${OUTPUT} | jq -r '.Credentials.AccessKeyId') export AWS_SECRET_ACCESS_KEY=$(echo ${OUTPUT} | jq -r '.Credentials.SecretKey') export AWS_SESSION_TOKEN=$(echo ${OUTPUT} | jq -r '.Credentials.SessionToken') echo "updated AWS_xx variables"
このスクリプトを実行後に
aws sts get-caller-identity
を実行すると、
{ "UserId": "xxx:CognitoIdentityCredentials", "Account": "xxx", "Arn": "arn:aws:sts::xxx:assumed-role/<ROLE_NAME>/CognitoIdentityCredentials" }
のような出力が得られる。
補足として、 aws sts get-caller-identity
をターミナルで実行する場合、ターミナルの AWS_PROFILE などの環境変数を読んで実行される (いちおう --profile オプションもあるけど詳しく試してない)。なので、自分のスクリプトではてっとりばやく AWS_ACCESS_KEY_ID
とかを設定してる。
感想
「一時クレデンシャル」がなにかよくわかってなかったけど、つまり AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
の期限付きのペアなのね、というのがわかった