LoginSignup
12
11

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-04-29

はじめに

下記の記事で説明した構成パターンについて、一部、複雑なものがあります。
この記事は、当該構成の具体的な設定内容・挙動を説明することを目的とします。

【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の仕組みのシンプルさに驚嘆し、またよく考えられていることを実感できると思います。

12
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11