STSとS3のVPCエンドポイントを利用してプライベートに別アカウントのS3バケットを利用してみる

2019.07.09

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ご機嫌いかがでしょうか、豊崎です。

先日、STSのVPCエンドポイントが東京リージョンで利用可能になりました。この投稿ではプライベートサブネットのEC2から別AWSアカウント上のS3に対して、VPCエンドポイント(STSおよびS3)を利用して接続を行えるかを検証してみたいと思います。

 

[新機能] AWS Security Token Service(STS)が東京リージョンで PrivateLink(Interface Endpoit)に対応しました

前提

まずAWSアカウントを2つ所有しており、それぞれのAWSアカウントに管理者権限を所有していることを想定しています。

また、以下図のVPCやサブネット、2台のEC2(踏み台からプライベートサブネットのEC2にもログインできる状態)などについてはすでに作成されているものとします。本投稿で作成していくのは以下の内容のみになります。

  • アカウントA
    • 対象のS3バケット
    • S3の操作が許可されているIAMRole:demo-Role-A
    • demo-Role-Aの信頼ポリシーにアカウントBを登録
  • アカウントB
    • S3のゲートウェイ型VPCエンドポイント
    • STSのインターフェイス型VPCエンドポイント
    • アカウントAに対するAssumeRoleのみが許可されているIAMRole:demo-Role-B
    • demo-Role-Bをプライベートサブネットに配置されているEC2にアタッチ

完成イメージは以下となります。

 

やってみた

準備

まずはアカウントAで以下の準備をしていきたいと思います。

  • 操作対象のS3バケット
  • S3の操作が許可されているIAMRole、demo-Role-A
  • demo-Role-Aの信頼ポリシーにアカウントBを登録

次にアカウントBで以下を準備します。

  • S3のゲートウェイ型VPCエンドポイント
  • STSのインターフェイス型VPCエンドポイント
  • demo-Role-Aに対するAssumeRoleのみが許可されているIAMRole、demo-Role-B
  • demo-Role-Bをプライベートサブネットに配置されているEC2にアタッチ

アカウントA

まずはアカウントA側で各リソースを作成していきます。

操作対象のS3バケットの作成

作成手順については割愛しますが、AWSマネジメントコンソールのS3ダッシュボードから「demo-private-sts-s3」という名前のS3バケットを作成しました。

S3の操作が許可されているIAMRole、demo-Role-Aを作成し信頼ポリシーにアカウントBを登録

続いて、IAMダッシュボード>ロール>ロールの作成から、「demo-Role-A」を作成していきます。

 

信頼されたエンティティの種類で「別のAWSアカウント」を選択し、アカウントBのAWSアカウントを入力することで信頼ポリシーに登録します。今回は検証の為、AWSアカウント全体を信頼しています。

作成したIAMRoleにS3の操作権限を付与します。ここでは「AmazonS3FullAccess」を付与しています。

指定した内容を確認して、ロールを作成します。

アカウントB

続いてアカウントBで各種リソースを作成します。

S3のゲートウェイ型VPCエンドポイントの作成

AWSマネジメントコンソールのVPCエンドポイント>エンドポイントの作成からVPCエンドポイントを作成していきます。

S3を選択し、今回対象のVPCを選択します。プライベートサブネットにアタッチしてあるルートテーブルを指定してVPCエンドポイントの作成をします。ポリシーの設定は特に行なっていません。

STSのインターフェイス型VPCエンドポイント

同様にSTSのVPCエンドポイントを作成していきます。こちらはVPCとサブネットを指定します。対象となるサブネットは同じなので以下のように設定を行いました。

インターフェース型のVPCエンドポイントの場合セキュリティグループの指定を行う必要があります。今回は検証なので、VPC内のIPは全て通信を許可するセキュリティグループをVPCエンドポイントに設定しています。またポリシーについてはこちらも特に設定を行なっていません。

demo-Role-Aに対するAssumeRoleのみが許可されているIAMRole、demo-Role-B

まずはIAMダッシュボードからポリシーを作成します。

ポリシーは以下のように設定します。Resource部分にはアカウントAで作成したIAMRoleのARNを指定します。

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "arn:aws:iam::<アカウントAのAWSアカウントID>:role/demo-Role-A"
  }
}

ポリシーの名前は「demo-Role-B-policy」で作成をしました。

次にEC2にアタッチする用のロール「demo-Role-B」を作成します。

信頼されたエンティティはAWSサービスのEC2を選択します。

ポリシーには先ほど作成した「demo-Role-B-policy」を選択して作成します。

demo-Role-Bをプライベートサブネットに配置されているEC2にアタッチする

EC2ダッシュボードから、IAMRoleのアタッチを行います。

 

先ほど作成したIAMRoleをアタッチします。

 

ようやく準備完了です。それではプライベートなEC2から別アカウントのS3への操作を試したいと思います。

S3を操作してみる

踏み台サーバを経由して、プライベートサブネットに配置したEC2にSSHしました。

まずは外部へのアクセスができないことを確認し、そのままアカウントAのS3:「demo-private-sts-s3」にアクセスしてみます。

#外部へアクセスできない
$ curl https://www.google.co.jp/
curl: (7) Failed to connect to www.google.co.jp port 443: 接続がタイムアウトしました

##APIの呼び出しに使用されるIAMの情報を確認。当然demo-Role-Bになってる。
$ aws sts get-caller-identity --region ap-northeast-1 --endpoint https://sts.ap-northeast-1.amazonaws.com
{
    "Account": "<アカウントBのAWSアカウントID>",
    "UserId": "XXXXXXXXXXXXXXXXXXXX:i-xxxxxxxxxxxxxxxx",
    "Arn": "arn:aws:sts::<アカウントBのAWSアカウントID>:assumed-role/demo-Role-B/i-xxxxxxxxxxxxxxxx"
}

#S3の参照を試しアクセスが拒否されました。
$ aws s3 ls --region ap-northeast-1 s3://demo-private-sts-s3

An error occurred (AccessDenied) when calling the ListObjectsV2 operation: Access Denied

では、アカウントA側に作成した「demo-Role-A」の権限を借り受けてS3:「demo-private-sts-s3」へアクセスしてみます。

#「demo-Role-A」の権限を借り受ける
$ aws sts assume-role --role-arn "arn:aws:iam::<アカウントAのAWSアカウントID>:role/demo-Role-A" --role-session-name "demo-session" --endpoint https://sts.ap-northeast-1.amazonaws.com --region ap-northeast-1
{
    "AssumedRoleUser": {
        "AssumedRoleId": "XXXXXXXXXXXXXXXXXXXXX:demo-session",
        "Arn": "arn:aws:sts::<アカウントAのAWSアカウントID>:assumed-role/demo-Role-A/demo-session"
    },
    "Credentials": {
        "SecretAccessKey": "<シークレットアクセスキー>",
        "SessionToken": "<セッショントークン>",
        "Expiration": "2019-07-09T01:53:10Z",
        "AccessKeyId": "<アクセスキー>"
    }
}

#出力された内容を環境変数に設定
$export AWS_ACCESS_KEY_ID="<アクセスキー>"
$export AWS_SECRET_ACCESS_KEY="<シークレットアクセスキー>"
$export AWS_SESSION_TOKEN="<セッショントークン>"

#APIの呼び出しに使用されるIAMの情報がdemo-Role-Aになっていることを確認
$ aws sts get-caller-identity --region ap-northeast-1 --endpoint https://sts.ap-northeast-1.amazonaws.com
{
    "Account": "<アカウントAのAWSアカウントID>",
    "UserId": "XXXXXXXXXXXXXXXXXXXXX:demo-session",
    "Arn": "arn:aws:sts::<アカウントAのAWSアカウントID>:assumed-role/demo-Role-A/demo-session"
}

#再度S3にアクセス
$ aws s3 ls --region ap-northeast-1 s3://demo-private-sts-s3
2019-07-09 00:56:32    4703599 demo001.jpg

無事S3にアクセスすることができました。

さいごに

STSのVPCエンドポイントが東京リージョンにきたことで、パブリックな通信を行わずに別アカウントのS3に接続することが可能になりました。複数の会社でプロジェクトを進める際に利用するケースがあるのではないでしょうか。

この記事が誰かのお役に立てば幸いです。