クロスアカウントでS3バケットにアクセスしてみた

AWS

複数アカウント環境において、1つのアカウントにデータを集約したいといったことがあると思います。
今回はインターネットと直接通信できないプライベートサブネット上のEC2から別アカウントのS3バケットにVPCエンドポイント経由でアクセスしてみます。

構成イメージ

簡単に説明するとアカウントAのアクセス元サーバが、アカウントBのS3バケットにアクセスできるRole BにAssumeRole(スイッチロール)することで実現できます。
AWS STSにより一時的にRoleBの認証情報を作成し、アクセス元サーバがその認証情報を使用してRoleBにAssumeRoleできる仕組みになっています。
STSやS3へVPCエンドポイント経由でアクセスしているため、インターネットに直接繋がっていないプライベートサブネットからでもアクセスできます。

手順の流れ

【事前準備】

STSのVPCエンドポイントに付けるセキュリティグループを作成しておきます。
ルールは下記のとおりです。
※セキュリティグループ名は「VPC-Endpoint」としておきます。

【全体の流れ】

  1. 【アカウントB】S3バケット作成
  2. 【アカウントB】Role Bの作成
  3. 【アカウントA】VPCエンドポイントの作成
  4. 【アカウントA】Role Aの作成
  5. 【アカウントA】アカウントBのs3バケットへアクセス

1. 【アカウントB】S3バケット作成

アカウントBのS3に新規バケットを作成していきます。

暗号化は必須ではないですが、今回はバケットを暗号化してみます。
キータイプについては「SSE-KMS」、キーは「AWS管理キー」を使用します。

作成後、バケットが作成されていることを確認。

2. 【アカウントB】Role Bの作成

アカウントBのバケットにアクセスするためのIAMロール(Role B)を作成します。

信頼されたエンティティタイプは「AWSアカウント」を選択。
AWSアカウントは別のAWSアカウントを選択し、アカウントAのAWSアカウントIDを入力します。

s3にアクセスするための許可ポリシーを設定。
今回はFullAccessを使用。

ロール名は「RoleB」として作成します。

RoleBが作成されたことを確認。(アカウントAのAWSアカウントIDが表示されます。)

3. 【アカウントA】VPCエンドポイントの作成

アカウントAでSTS/S3のVPCエンドポイントを作成します。

STSエンドポイント作成

サービスは「com.amazonaws.ap-northeast-1.sts」を選択。

VPCはアカウントAで使用しているものを選択。
サブネットはエンドポイントを配置するサブネットを選択。

セキュリティグループは事前に作成しておいたVPCエンドポイント用のものを使用します。

エンドポイントを作成。

S3エンドポイント作成

サービスは「com.amazonaws.ap-northeast-1.s3」を選択。

VPCはアカウントAで使用しているものを選択。
ルートテーブルはアクセス元サーバのサブネットに関連付けされているものを選択。

エンドポイントを作成。

4. 【アカウントA】Role Aの作成

STSを使用してアカウントBのRoleBにAssumeRoleするためのRoleAを新規作成します。

信頼されたエンティティタイプは「AWSのサービス」を選択。
ユースケースは「EC2を選択」。

許可ポリシーの追加で「ポリシーの作成」を選択。

ポリシーの作成はJSONタブに切り替えて下記をポリシーとして設定します。
ResourceにはアカウントBのAWSアカウントIDとRoleBを記述してます。

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "arn:aws:iam::[アカウントBのAWSアカウントID]:role/RoleB"
  }
}

ポリシー作成後、RoleAに追加するポリシーとして先ほど作成したポリシー(ポリシー名はsts-accessとして作成。)が表示されるので
選択し、次へ。

ロール名は「RoleA」として作成。

RoleAが作成されたことを確認。

ここでRoleAをアクセス元サーバに設定します。
EC2の画面でアクセス元サーバを選択し、セキュリティ ⇒ IAMロールの変更を選択。

IAMロールにRoleAを選択し、保存します。

5. 【アカウントA】アカウントBのs3バケットへアクセス

以上で環境準備は整ったので実際にs3バケットへアクセスしてみます。

aws cliコマンドを使用してassume-roleしていきます。
–role-arnにはアカウントBのRoleB、–role-session-nameは任意のセッション名、
–endpointはstsのVPCエンドポイントのURL、–regionには東京リージョン(ap-northeast-1)をそれぞれ指定します。

[アカウントBのAWSアカウントID]:role/RoleB" --role-session-name "cross-account-test" --endpoint https://sts.ap-northeast-1.amazonaws.com --region ap-northeast-1

コマンド実行後、下記の様な認証情報が出力されます。

{
    "Credentials": {
        "AccessKeyId": "アクセスキー",
        "SecretAccessKey": "シークレットアクセスキー",
        "SessionToken": "セッショントークン",
        "Expiration": "2022-05-15T09:44:57+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "XXXXXXXXXXXXXX:cross-account-test",
        "Arn": "arn:aws:sts::XXXXXXXXXXX:assumed-role/RoleB/cross-account-test"
    }
}

出力内容を環境変数に設定します。

# export AWS_ACCESS_KEY_ID="アクセスキー"
# export AWS_SECRET_ACCESS_KEY="シークレットアクセスキー"
# export AWS_SESSION_TOKEN="セッショントークン"

IAMの情報がアカウントBのRoleBになっていることを確認します。

# aws sts get-caller-identity --region ap-northeast-1 --endpoint https://sts.ap-northeast-1.amazonaws.com

{
    "UserId": "XXXXXXXXXXXXX:cross-account-test",
    "Account": "XXXXXXXXXXXXX",
    "Arn": "arn:aws:sts::XXXXXXXXXXXXX:assumed-role/RoleB/cross-account-test"
}

この状態でs3バケットにファイルをコピーしてみます。

# aws s3 cp /tmp/s3-put-test.txt s3://shimmy-cross-account-test/
upload: ../tmp/s3-put-test.txt to s3://shimmy-cross-account-test/s3-put-test.txt

lsでバケット内を確認するとコピーしたファイルが確認できました。

# aws s3 ls --region ap-northeast-1 s3://shimmy-cross-account-test
2022-05-15 09:00:20          0 s3-put-test.txt
補足事項

AWS STSによる認証情報を環境変数として設定していない場合、下記の様にアクセスが拒否されます。

# aws s3 ls --region ap-northeast-1 s3://shimmy-cross-account-test
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

以上で完了になります。

コメント

タイトルとURLをコピーしました