はじめに
下記の記事で説明した構成パターンについて、一部、複雑なものがあります。
この記事は、当該構成の具体的な設定内容・挙動を説明することを目的とします。
【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を付与する
ファイルコピー元AWSアカウントのAWSリソース設定
S3 Bucket: inter-bucket-copy-src
Bucket Policyは以下のようになります。
dst-roleの権限でコピー操作を行うこととなりますので、当該Roleからの参照権限が必要になります。
{
"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名を指定することもできますが、「*」を指定した方が管理しやすいと思います。
{
"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への書込権限が全て必要です。
{
"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させるための設定を追加します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111111:user/src-user"
},
"Action": "sts:AssumeRole"
}
]
}
手順
手順を確認していきます。
- src-userは、dst-roleをAssumeRoleするようAPIを発行する。
- temporary credentialsを取得する。temporary credentialsはdst-roleの権限でAWS APIを発行できる。
- temporary credentialsを利用してPUT Object - Copyを発行する。
- 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になるケースです。
ファイルコピー元AWSアカウントのAWSリソース設定
S3 Bucket: inter-bucket-copy-src
Bucket Policyは以下のようになります。
dst-roleの権限でコピー操作を行うこととなりますので、当該Roleからの参照権限が必要になります。
{
"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を実行する権限さえあれば十分です。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"*"
]
}
]
}
- Trust Relationships
EC2 Instance Profileとして利用するための設定が必要です。これは通常、よく利用しているものですね。
{
"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への書込権限が全て必要です。
{
"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させるための設定を追加します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111111:role/src-role"
},
"Action": "sts:AssumeRole"
}
]
}
手順
手順を確認していきます。
- EC2インスタンスにsshログインし、当該EC2インスタンスに紐づくRole(src-role)のTemporary Credentialsを取得する
- src-roleの権限で、dst-roleをAssumeRoleするようAPIを発行する。
- dst-roleに紐づくtemporary credentialsを取得する。このtemporary credentialsはdst-roleの権限でAWS APIを発行できる。
- dst-roleのtemporary credentialsを利用してPUT Object - Copyを発行する。
- 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の仕組みのシンプルさに驚嘆し、またよく考えられていることを実感できると思います。