Edited at

【AWS】AWSアカウントをまたいでS3 Bucket間コピーする(実践編)【クロスアカウント】

More than 1 year has passed since last update.


はじめに

下記の記事で説明した構成パターンについて、一部、複雑なものがあります。

この記事は、当該構成の具体的な設定内容・挙動を説明することを目的とします。

【AWS】AWSアカウントをまたいでS3 Bucket間コピーする(解説編)【クロスアカウント】

https://qiita.com/tmiki/items/cef01fa5d34c55dbbeae


想定構成


  • ファイルコピー元AWSアカウント


    • AWSアカウントID: 111111111111111

    • S3 Bucket: inter-bucket-copy-src

    • IAM User: src-user

    • IAM Role: src-role



  • ファイルコピー先AWSアカウント


    • AWSアカウントID: 999999999999999

    • S3 Bucket: inter-bucket-copy-dst

    • IAM User: dst-user

    • IAM Role: dst-role




実践


Type2: コピー元S3 BucketにBucket Policyを付与する

下記と同等の内容です。

https://qiita.com/tmiki/items/cef01fa5d34c55dbbeae#type2-%E3%82%B3%E3%83%94%E3%83%BC%E5%85%83s3-bucket%E3%81%ABbucket-policy%E3%82%92%E4%BB%98%E4%B8%8E%E3%81%99%E3%82%8B%E3%82%88%E3%82%8A%E8%A4%87%E9%9B%91

まずは構成をおさらいしましょう。

type2.PNG


ファイルコピー元AWSアカウントのAWSリソース設定


S3 Bucket: inter-bucket-copy-src

Bucket Policyは以下のようになります。

dst-roleの権限でコピー操作を行うこととなりますので、当該Roleからの参照権限が必要になります。


BucketPolicy

{

"Version": "2012-10-17",
"Statement": {
"Sid": "SourceBucketPolicy-1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::999999999999999:role/dst-role"
},
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::inter-bucket-copy-src",
"arn:aws:s3:::inter-bucket-copy-src/*"
]
}
}


IAM User: arn:aws:iam::111111111111111:user/src-user

Permissionsは以下のように、AssumeRoleを実行する権限さえあれば十分です。

対象のResourceには、具体的なRole名を指定することもできますが、「*」を指定した方が管理しやすいと思います。


permissions

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"*"
]
}
]
}


IAM Role: arn:aws:iam::111111111111111:role/src-role

※このケースでは利用しません


ファイルコピー先AWSアカウントのAWSリソース設定


S3 Bucket: inter-bucket-copy-dst

※Bucket Policyは不要


IAM Role: arn:aws:iam::999999999999999:role/dst-role

PermissionsとTrust Relationshipsは以下のようになります。


  • Permissions

コピー元S3 Bucketへの参照権限、およびコピー先S3 Bucketへの書込権限が全て必要です。


permissions

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::inter-bucket-copy-src",
"arn:aws:s3:::inter-bucket-copy-src/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::inter-bucket-copy-dst/*"
]
}
]
}


  • Trust Relationships

src-userにAssumeRoleさせるための設定を追加します。


TrustRelationships

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111111:user/src-user"
},
"Action": "sts:AssumeRole"
}
]
}


手順

手順を確認していきます。


  1. src-userは、dst-roleをAssumeRoleするようAPIを発行する。

  2. temporary credentialsを取得する。temporary credentialsはdst-roleの権限でAWS APIを発行できる。

  3. temporary credentialsを利用してPUT Object - Copyを発行する。

  4. inter-bucket-copy-src上のファイルをinter-bucket-copy-dstにコピーする。

以下から、具体的なコマンド、AWS APIのレスポンス等を詳しく見ていきます。


1. src-userは、dst-roleをAssumeRoleするようAPIを発行する。

項番1,2は併せて説明します。


2. temporary credentialsを取得する。temporary credentialsはdst-roleの権限でAWS APIを発行できる。

まず、適当なLinuxマシンを用意し、AWS CLIをインストールします。

src-userのAWS Credentialsを準備し、AWS CLIにセットします。

$ aws configure

AWS Access Key ID [None]: AKIA****************
AWS Secret Access Key [None]: duOb********************************n6mM
Default region name [None]: ap-northeast-1
Default output format [None]: json

AssumeRoleを実行します。オプション「--role-session-name」の値は必須ですが、任意の文字列を指定することができます。

「AccessKeyId」「SecretAccessKey」「SesionToken」という値が返却されたことが分かります。

$ aws sts assume-role --role-arn "arn:aws:iam::999999999999999:role/dst-role" --role-session-name "you-can-put-any-string"

{
"AssumedRoleUser": {
"AssumedRoleId": "AROAXXXXXXXXXXXXXXXXX:you-can-put-any-string",
"Arn": "arn:aws:sts::999999999999999:assumed-role/dst-role/you-can-put-any-string"
},
"Credentials": {
"SecretAccessKey": "0hq4**********************************",
"SessionToken": "FQoD************************************************************************************************************************************************************************************************************",
"Expiration": "2018-04-29T12:57:34Z",
"AccessKeyId": "ASIAXXXXXXXXXXXXXXXX"
}
}


3. temporary credentialsを利用してPUT Object - Copyを発行する。

項番3,4は併せて説明します。


4. inter-bucket-copy-src上のファイルがinter-bucket-copy-dstにコピーされる。

まず、AssumeRoleの結果、返却された値は下記の通りでした。

Item Name
Value

AccessKeyId
ASIAXXXXXXXXXXXXXXXX

SecretAccessKey
0hq4**********************************

SesionToken
FQoD************************************************************************************************************************************************************************************************************

この値を環境変数にセットすることで、AWS CLIから利用できるようになります。

$ export AWS_ACCESS_KEY_ID="ASIAXXXXXXXXXXXXXXXX"

$ export AWS_SECRET_ACCESS_KEY="0hq4**********************************"
$ export AWS_SESSION_TOKEN="FQoD************************************************************************************************************************************************************************************************************"

GetCallerIdentityを実行することで、現在のユーザを確認することができます。

$ aws sts get-caller-identity

{
"Account": "999999999999999",
"UserId": "AROAXXXXXXXXXXXXXXXXX:you-can-put-any-string",
"Arn": "arn:aws:sts::999999999999999:assumed-role/dst-role/you-can-put-any-string"
}

ここまでくれば、後は簡単です。

単純に、AWS CLIでS3オブジェクトのコピーを行うだけです。

$ aws s3 sync s3://inter-bucket-copy-src/any-dir/ s3://inter-bucket-copy-dst/any-dir/


Type2.1: コピー元S3 BucketにBucket Policyを付与し、IAM Role for EC2 instancesを併用する

上記の構成において、AssumeRoleする主体がIAM Userではなく、EC2 Instance Profileになるケースです。

type2.1.PNG


ファイルコピー元AWSアカウントのAWSリソース設定


S3 Bucket: inter-bucket-copy-src

Bucket Policyは以下のようになります。

dst-roleの権限でコピー操作を行うこととなりますので、当該Roleからの参照権限が必要になります。


BucketPolicy

{

"Version": "2012-10-17",
"Statement": {
"Sid": "SourceBucketPolicy-1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::999999999999999:role/dst-role"
},
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::inter-bucket-copy-src",
"arn:aws:s3:::inter-bucket-copy-src/*"
]
}
}


IAM User: arn:aws:iam::111111111111111:user/src-user

※このケースでは利用しません


IAM Role: arn:aws:iam::111111111111111:role/src-role

PermissionsとTrust Relationshipsは以下のようになります。


  • Permissions

Permissionsは以下のように、AssumeRoleを実行する権限さえあれば十分です。


permissions

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"*"
]
}
]
}


  • Trust Relationships

EC2 Instance Profileとして利用するための設定が必要です。これは通常、よく利用しているものですね。


TrustRelationships

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}


ファイルコピー先AWSアカウントのAWSリソース設定


S3 Bucket: inter-bucket-copy-dst

※Bucket Policyは不要


IAM Role: arn:aws:iam::999999999999999:role/dst-role

PermissionsとTrust Relationshipsは以下のようになります。


  • Permissions

コピー元S3 Bucketへの参照権限、およびコピー先S3 Bucketへの書込権限が全て必要です。


permissions

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::inter-bucket-copy-src",
"arn:aws:s3:::inter-bucket-copy-src/*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::inter-bucket-copy-dst/*"
]
}
]
}


  • Trust Relationships

src-roleにAssumeRoleさせるための設定を追加します。


TrustRelationships

{

"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111111:role/src-role"
},
"Action": "sts:AssumeRole"
}
]
}


手順

手順を確認していきます。

1. EC2インスタンスにsshログインし、当該EC2インスタンスに紐づくRole(src-role)のTemporary Credentialsを取得する

2. src-roleの権限で、dst-roleをAssumeRoleするようAPIを発行する。

3. dst-roleに紐づくtemporary credentialsを取得する。このtemporary credentialsはdst-roleの権限でAWS APIを発行できる。

4. dst-roleのtemporary credentialsを利用してPUT Object - Copyを発行する。

5. inter-bucket-copy-src上のファイルがinter-bucket-copy-dstにコピーされる。

以下から、具体的なコマンド、AWS APIのレスポンス等を詳しく見ていきます。


1. EC2インスタンスにsshログインし、当該EC2インスタンスに紐づくRole(src-role)のTemporary Credentialsを取得する

対象EC2インスタンスにsshログインします。

下記のドキュメントに従い、Temporary Credentialsを取得します。

IAM Roles for Amazon EC2 - Amazon Elastic Compute Cloud -> Retrieving Security Credentials from Instance Metadata

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html

$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/src-role

{
"Code" : "Success",
"LastUpdated" : "2012-04-26T16:39:16Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "ASIAIOSFODNN7EXAMPLE",
"SecretAccessKey" : "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
"Token" : "nczJ************************************************toKenExaMpLe",
"Expiration" : "2017-05-17T15:09:54Z"
}

この値を環境変数にセットすることで、AWS CLIから利用できるようになります。

$ export AWS_ACCESS_KEY_ID="ASIAIOSFODNN7EXAMPLE"

$ export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
$ export AWS_SESSION_TOKEN="nczJ************************************************toKenExaMpLe"

GetCallerIdentityを実行することで、現在のユーザを確認することができます。

$ aws sts get-caller-identity

{
"Account": "111111111111111",
"UserId": "AROA*************QIOE:i-0123456789abcdeff",
"Arn": "arn:aws:sts::111111111111111:assumed-role/src-role/i-0123456789abcdeff"
}


2. src-roleの権限で、dst-roleをAssumeRoleするようAPIを発行する。

項番2,3は併せて説明します。


3. dst-roleに紐づくtemporary credentialsを取得する。このtemporary credentialsはdst-roleの権限でAWS APIを発行できる。

これ以降の操作は、先ほどのType2のケースと同一です。

AssumeRoleを実行します。オプション「--role-session-name」の値は必須ですが、任意の文字列を指定することができます。

「AccessKeyId」「SecretAccessKey」「SesionToken」という値が返却されたことが分かります。

$ aws sts assume-role --role-arn "arn:aws:iam::999999999999999:role/dst-role" --role-session-name "you-can-put-any-string"

{
"AssumedRoleUser": {
"AssumedRoleId": "AROAXXXXXXXXXXXXXXXXX:you-can-put-any-string",
"Arn": "arn:aws:sts::999999999999999:assumed-role/dst-role/you-can-put-any-string"
},
"Credentials": {
"SecretAccessKey": "0hq4**********************************",
"SessionToken": "FQoD************************************************************************************************************************************************************************************************************",
"Expiration": "2018-04-29T12:57:34Z",
"AccessKeyId": "ASIAXXXXXXXXXXXXXXXX"
}
}


4. dst-roleのtemporary credentialsを利用してPUT Object - Copyを発行する。

項番4,5は併せて説明します。


5. inter-bucket-copy-src上のファイルがinter-bucket-copy-dstにコピーされる。

AssumeRoleの結果、返却された値は下記の通りでした。

Item Name
Value

AccessKeyId
ASIAXXXXXXXXXXXXXXXX

SecretAccessKey
0hq4**********************************

SesionToken
FQoD************************************************************************************************************************************************************************************************************

この値を環境変数にセットすることで、AWS CLIから利用できるようになります。

$ export AWS_ACCESS_KEY_ID="ASIAXXXXXXXXXXXXXXXX"

$ export AWS_SECRET_ACCESS_KEY="0hq4**********************************"
$ export AWS_SESSION_TOKEN="FQoD************************************************************************************************************************************************************************************************************"

GetCallerIdentityを実行することで、現在のユーザを確認することができます。

$ aws sts get-caller-identity

{
"Account": "999999999999999",
"UserId": "AROAXXXXXXXXXXXXXXXXX:you-can-put-any-string",
"Arn": "arn:aws:sts::999999999999999:assumed-role/dst-role/you-can-put-any-string"
}

ここまでくれば、後は簡単です。

単純に、AWS CLIでS3オブジェクトのコピーを行うだけです。

$ aws s3 sync s3://inter-bucket-copy-src/any-dir/ s3://inter-bucket-copy-dst/any-dir/


おわりに

このケースは一見複雑そうにみえますが、一つ一つの仕組みを確認し、理解していくと、それほど難しいものでないことが分かります。

理解を深めていくにつれ、IAM/STSの仕組みのシンプルさに驚嘆し、またよく考えられていることを実感できると思います。