Asume Roleを使って何も権限を持たないIAMユーザに一時的なCredentialを払い出す方法について記載しています。
1. IAMユーザ Aliceの作成
何も権限を持たないAlice
を作成する。
aws iam create-user --user-name Alice
2. AliceのCredential確認
aws iam create-access-key --user-name Alice
{
"AccessKey": {
"UserName": "Alice",
"AccessKeyId": "XXXXXXXXXXX",
"Status": "Active",
"SecretAccessKey": "XXXXXXXXXXX",
"CreateDate": "2019-05-25T07:20:17Z"
}
}
AccessKeyId
とSecretAccessKey
を~/.aws/credentials
に設定する。
~/.aws/credentials
[default]
aws_access_key_id = XXXXXXXXXXX
aws_secret_access_key = XXXXXXXXXXX
3. Aliceに一時的に付与したいロールを作成する
example-role
という名前でロールを定義し、以下アタッチする。
- 信頼関係
- ポリシー
ここで定義するexample-role
がIAMユーザAlice
に一時的に付与したいロールになる。
信頼関係を定義したexample-role-trust-policy.json
を作成する。
example-role-trust-policy.json
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789010:user/Alice" },
"Action": "sts:AssumeRole"
}
}
example-roleを作成して、信頼関係とポリシー(今回はAmazonS3ReadOnlyAccess)をアタッチする。
# ロールの作成
aws iam create-role --role-name example-role --assume-role-policy-document file://./example-role-trust-policy.json
# 作成したロールにポリシーをアタッチ
aws iam attach-role-policy --role-name example-role --policy-arn "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
# 作成されたロールにアタッチされたポリシーを確認
aws iam list-attached-role-policies --role-name example-role
{
"AttachedPolicies": [
{
"PolicyName": "AmazonS3ReadOnlyAccess",
"PolicyArn": "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}
]
}
3. Aliceが一時的に利用できるCredentialsを払い出す
以下のような定義ファイルをjson形式で作成して、
temp-role.json
{
"RoleArn": "arn:aws:iam::123456789010:role/example-role",
"RoleSessionName": "AWSCLI-Session",
"DurationSeconds": 3600
}
コマンドを実行します。
aws sts assume-role --cli-input-json file://./temp-role.json
{
"Credentials": {
"AccessKeyId": "ASIA3BHYW2I5DZ5TWSNA",
"SecretAccessKey": "L7BrCaaqMw6OehjKYfal+VKu3AyOiVBGBA7KaVNP",
"SessionToken": "FQoGZXIvYXdzEPH//////////wEaDEtezAAgPx3oBVJ3USLyAU+f9XPlKMhq/vAxHUD70Mr9+NybYsujRibsl8V4kU3RcWHOZ4W65ELtKvS80dGlBp95oNgAGu6MUtvIT6gSBLBkymyiEuxYeaxzeXj1JV8NffOl8n0oOC1QrIXaJTdDjb//A6vpXiwIJQV7UonBnbADY4fgA8aMw4TfRQyOUIbt1dmdadaBnBYLoV52DBKTtfKR821zasyLMv4773T2OtUR+ZPh7B12A2qvggENtrYQL1JZXOOb65NdIoKNwZD4zA5OtXsC204xsB3/TP3JIeaw9gAlp1hFx3vqzT/N3mbGABA2xu5WMcRjMFHMp8dN8bHJKMHbo+cF",
"Expiration": "2019-05-25T08:24:49Z"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROA3BHYW2I5O46TBXOWN:AWSCLI-Session",
"Arn": "arn:aws:sts:: 123456789010:assumed-role/example-role/AWSCLI-Session"
}
}
Credentialsが利用できるか確認する
上記で払い出されたアクセスキー、シークレットキー、セッショントークンをここでは環境変数にセットします。
export AWS_ACCESS_KEY_ID="ASIA3BHYW2I5DZ5TWSNA"
export AWS_SECRET_ACCESS_KEY="L7BrCaaqMw6OehjKYfal+VKu3AyOiVBGBA7KaVNP"
export AWS_SESSION_TOKEN="FQoGZXIvYXdzEPH//////////wEaDEtezAAgPx3oBVJ3USLyAU+f9XPlKMhq/vAxHUD70Mr9+NybYsujRibsl8V4kU3RcWHOZ4W65ELtKvS80dGlBp95oNgAGu6MUtvIT6gSBLBkymyiEuxYeaxzeXj1JV8NffOl8n0oOC1QrIXaJTdDjb//A6vpXiwIJQV7UonBnbADY4fgA8aMw4TfRQyOUIbt1dmdadaBnBYLoV52DBKTtfKR821zasyLMv4773T2OtUR+ZPh7B12A2qvggENtrYQL1JZXOOb65NdIoKNwZD4zA5OtXsC204xsB3/TP3JIeaw9gAlp1hFx3vqzT/N3mbGABA2xu5WMcRjMFHMp8dN8bHJKMHbo+cF"
以下のコマンドでS3に対してReadOnlyなアクセスができていればOKです。
# これはOK
aws s3 ls
aws s3 cp s3://任意のバケット名 .
# これはNG
aws s3 cp testfile s3://任意のバケット名
おまけ - AssumeRoleを使ってマネジメントコンソールのURLを発行する
AssumeRoleで一時的な権限を持つユーザに対してマネジメントコンソールにログインするためのURLを発行するプログラムをGoで書いてみました。
main.go
package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"strconv"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
)
func main() {
flag.Parse()
arn := flag.Arg(0)
sessionName := flag.Arg(1)
durationSeconds, _ := strconv.Atoi(flag.Arg(2))
fmt.Println(getManagementConsoleURL(
createSTSClient(), arn, sessionName, int64(durationSeconds)))
}
// マネジメントコンソールにログインするための一時的なURLを取得する
func getManagementConsoleURL(stsClient *sts.STS, arn string, sessionName string, durationSeconds int64) string {
issUserURL := "https://www.google.com"
consoleURL := "https://ap-northeast-1.console.aws.amazon.com/console/home?region=ap-northeast-1"
signIUnURL := "https://signin.aws.amazon.com/federation"
signInToken, err := getSignInToken(stsClient, arn, sessionName, durationSeconds)
if err != nil {
log.Fatalln(err)
}
return signIUnURL + "?Action=login" + "&SigninToken=" + url.QueryEscape(signInToken.Value) + "&Issuser=" + url.QueryEscape(issUserURL) + "&Destination=" + url.QueryEscape(consoleURL)
}
// マネジメントコンソールにサインインするためのトークンを取得する
func getSignInToken(stsClient *sts.STS, arn string, sessionName string, durationSeconds int64) (*TemporarySigninToken, error) {
input := sts.AssumeRoleInput{
DurationSeconds: aws.Int64(3600),
RoleArn: aws.String(arn),
RoleSessionName: aws.String(sessionName),
}
output, err := stsClient.AssumeRole(&input)
if err != nil {
log.Fatalln(err)
}
sessionModel := SessionModel{
*output.Credentials.AccessKeyId,
*output.Credentials.SecretAccessKey,
*output.Credentials.SessionToken,
}
jsonByte, _ := json.Marshal(sessionModel)
siginInTokenUrl := fmt.Sprintf("https://signin.aws.amazon.com/federation?Action=getSigninToken&SessionType=json&Session=%s", url.QueryEscape(string(jsonByte)))
res, err := http.Get(siginInTokenUrl)
if err != nil {
return nil, err
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
var temporarySigninToken TemporarySigninToken
err = json.Unmarshal(body, &temporarySigninToken)
if err != nil {
return nil, err
}
return &temporarySigninToken, nil
}
func createSTSClient() *sts.STS {
return sts.New(createSession())
}
func createSession() *session.Session {
session, err := session.NewSession(&aws.Config{Region: aws.String("ap-northeast-1")})
if err != nil {
log.Fatal("Error creating session", err)
}
return session
}
type SessionModel struct {
SessionId string `json:"sessionId"`
SessionKey string `json:"sessionKey"`
SessionToken string `json:"sessionToken"`
}
type TemporarySigninToken struct {
Value string `json:"SigninToken"`
}
実行すると、URLが払い出されます。
第一引数はRoleのARN, 第二引数はセッションの名前、第三引数は有効期限(秒)になっています。
$ go run main.go arn:aws:iam::123456789010:role/example-role MgtConsoleSession 3600
https://signin.aws.amazon.com/federation?Action=login&SigninToken=n_H5deaNtwwnre19CLEg6vJ29tLRgJIf7dgxeRKy_03fKgZ2BZHjKn2Rgv9p6dQCcgTTtP58Ue0jA44DGXkNj4w91rwPfCiORzeqJkAARK_t5RPo_1aEnwSn2AHKtZIe63EUTSy1u8ekEDMlHwtZBqTi70fkZGw1z2LN3KEu2U_mobOc7NS_Ny0AKAzGV-JgAGRi4CH0ldE0CD_Wn05TlFTCAiTvVAtxI4wJHiYiUhdzvwGJZEfBt4GK2eXmCmXQDJj6TTyzBijM_jhZnFBCBOEh3srIalboDhckmPkYCrulcZXFieNZx0F4NTeT61vZ5X6hglsqZ8wqXf2t0YIBMqBVt-LULSd9whfj69d2uH6vBBw41a60S4TJD3BHNBROPvwRuIxlFEX9KcPEYUA5Y251kOak5irio8hEXtEJ0ZgCQ7SWybZ2yMzoUelAFpuzIsN2a07xDdDL5VhOIPAImTQFikU8l34GL6hnVGxjrJb0a65adu7OsA4aHj5uM_B2xkh14gvB_WV6hGr9ju7n42MudvlNJcSqAmpWDZX73a4IP-8UkXXTlkxbpUv92j1PRn4gHOUW0GCa3hQXS4q0t99uD98n9jY72QZO-Yq6QI02P2vx2s1SZ5fHHjstUIZUurrhZ8zbvsqcLELPddUj9YHzaTrGv6w-mNocQwcBpckkq7Hrvu9EEiC2AAVzc75oJ90wZ2BPoPcer0cbbO6vHduWuH8I61uy3qnbyzTfwnPlyB9Ij5EVpgP20HtZ_4ZYzinShmJKkqvis2w8MIuLTE8X5VYOWFZwdL-VxUUsDQ8rUNYmpYHXpI87rVm7zOiCMYJA5pn8UYU8fctnJq19mUNxdI1qKrL1-AqKDtAxY241gyPL-72J0ufvvB04qdFD61f8mRoOpx3uSqa7plzE0gsF&Issuser=https%3A%2F%2Fwww.google.com&Destination=https%3A%2F%2Fap-northeast-1.console.aws.amazon.com%2Fconsole%2Fhome%3Fregion%3Dap-northeast-1