🔑

【AWS】安全なAWSキーの運用のためにAssumeRoleを活用する方法

に公開

はじめに

AWSのアクセスキー(Access Key / Secret Access Key)は便利ですが、漏洩するとクラウド環境全体に深刻な影響を与える可能性があります。
そのためにAssumeRoleを活用する方法は他記事でもたくさん紹介されていますが、
今回久しぶりに設定したので、備忘録として記載します。

※毎度ですが記事に掲載しているCLIの出力は実際の出力を元に記事用に加工しています。

実践

用意するもの

  • IAMロール(今回はS3アクセス用のロールを作成します)
  • IAMユーザー(AssumeRole専用ユーザー)

IAM ユーザーの作成

はじめに、AssumeRole 用の IAM ユーザーを作成します。

$ aws iam create-user --user-name AssumeRoleTestUser
{
    "User": {
        "Path": "/",
        "UserName": "AssumeRoleTestUser",
        "UserId": "AIDAWxxxxxxxxxxxxxxxx",
        "Arn": "arn:aws:iam::111122223333:user/AssumeRoleTestUser",
        "CreateDate": "2025-08-17T09:15:34+00:00"
    }
}

IAM ロールの作成

次にロールを作成します。今回はAmazonS3FullAccess権限を付与する例です。

最初にAssumeRoleを許可する信頼ポリシーを作成し、ロール作成の際に指定します。
先にIAMユーザーを作成しておかないと、存在しないIAMユーザーをPrincipalに指定できずエラーになります。

# 信頼ポリシー(特定ユーザーのみAssumeRole許可)
$ cat > trust-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": { "AWS": "arn:aws:iam::111122223333:user/AssumeRoleTestUser" },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

# ロール作成
$ aws iam create-role --role-name S3FullAccessRole \
    --assume-role-policy-document file://trust-policy.json
{
    "Role": {
        "Path": "/",
        "RoleName": "S3FullAccessRole",
        "RoleId": "AROAWxxxxxxxxxxxxxxxx",
        "Arn": "arn:aws:iam::111122223333:role/S3FullAccessRole",
        "CreateDate": "2025-08-17T09:15:43+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "AWS": "arn:aws:iam::111122223333:user/AssumeRoleTestUser"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
    }
}

作成したロールに、AmazonS3FullAccess権限を付与します。

# S3FullAccess ポリシーをアタッチ
$ aws iam attach-role-policy --role-name S3FullAccessRole \
    --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

IAMユーザーの権限の編集

最初に作成したIAMユーザーの権限を設定します。ここではAssumeRoleを実行するための権限のみを付与します。

# AssumeRole権限のみ付与
cat > assume-role-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::111122223333:role/S3FullAccessRole"
    }
  ]
}
EOF

aws iam put-user-policy --user-name AssumeRoleTestUser \
    --policy-name AssumeRolePolicy \
    --policy-document file://assume-role-policy.json

これで、ユーザーはS3のみフルアクセス可能なロールをAssumeできるだけの権限を持ちました。
ユーザー自身にはS3にアクセスする権限はありません。

動作確認

設定した権限が正しく働いているか確認してみましょう。

AssumeRole前

では、AssumeRole専用ユーザーのアクセスキーを取得します。
もちろんAWSマネジメントコンソールから発行しても問題ないです。

$ aws iam create-access-key --user-name AssumeRoleTestUser

{
    "AccessKey": {
        "UserName": "AssumeRoleTestUser",
        "AccessKeyId": "AKIAxxxxxxxxxxxxxxxx",
        "Status": "Active",
        "SecretAccessKey": "7DvRoc775rMGVs0p3/Q3r/zehmzRJ7z+xxxxxxxx",
        "CreateDate": "2025-08-17T09:19:01+00:00"
    }
}

このkey/secをもとに、aws configureを設定していない環境から試してみましょう。

$ aws s3 ls

An error occurred (AccessDenied) when calling the ListBuckets operation: User: arn:aws:iam::111122223333:user/AssumeRoleTestUser is not authorized to perform: s3:ListAllMyBuckets because no identity-based policy allows the s3:ListAllMyBuckets action

当然、アクセス権限がないのでエラーになります。

AssumeRoleの実行

ではaws sts assume-roleコマンドを使って、先ほど作成したロールをAssumeしてみます。
このコマンドを使用すると、以下のように一時的なkey/sec情報やSessionToken、有効期限が返ってきます。

aws sts assume-role \
>   --role-arn arn:aws:iam::111122223333:role/S3FullAccessRole \
>   --role-session-name iam-role
{
    "Credentials": {
        "AccessKeyId": "ASIAxxxxxxxxxxxxxxxx",
        "SecretAccessKey": "V73J5cJlqN/lQI5qEPZFpixNZsjcxxxxxxxxxxxx",
        "SessionToken": "FwoGZXIvYXdzExxxx(中略)xxxxq3UwyOMltAcKs/bTA==",
        "Expiration": "2025-08-17T11:25:35+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "AROAWxxxxxxxxxxxxxxxx:iam-role",
        "Arn": "arn:aws:sts::111122223333:assumed-role/S3FullAccessRole/iam-role"
    }
}

これらの情報を利用してaws configureが設定できるよう、
今回は以下のようにスクリプトを組んでみました。

#!/bin/bash

ROLE_ARN="arn:aws:iam::111122223333:role/S3FullAccessRole"
SESSION_NAME="iam-role"
PROFILE_NAME="assumed"

CREDS=$(aws sts assume-role \
  --role-arn $ROLE_ARN \
  --role-session-name $SESSION_NAME \
  --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
  --output text)

aws configure set aws_access_key_id $(echo $CREDS | awk '{print $1}') --profile $PROFILE_NAME
aws configure set aws_secret_access_key $(echo $CREDS | awk '{print $2}') --profile $PROFILE_NAME
aws configure set aws_session_token $(echo $CREDS | awk '{print $3}') --profile $PROFILE_NAME

AssumeRole後

今度はAssumeRoleを実行した後の状態で、S3のバケット一覧を取得してみます。

$ aws s3 ls --profile assumed

2025-01-01 00:00:00 my-bucket-1
2025-01-02 00:00:00 my-bucket-2

無事、S3のバケット一覧が取得できました。

なお、AssumeRoleで取得したセッショントークンは有効期限があり、
それを過ぎてしまうと以下のようにエラーになります。

$ aws s3 ls --profile assumed

An error occurred (ExpiredToken) when calling the ListBuckets operation: The provided token has expired.

おわりに

基本的なことは結構AIがやってくれるようになったこの頃、基本に立ち返ってまとめるのも悪くないなという記事でした。
ここまで読んでいただきありがとうございます。

Discussion