【AWS】IAM ~ 別AWSアカウントのS3にファイルアップロード ~

■ はじめに

Github Workflow で Self-Hosted runner (EC2) 上で作成したファイルを
この Self-Hosted runner とは、別のAWS アカウントにファイルを置きたい。
そこで、別AWSアカウントのS3にファイルをアップロードすることを
調べてみた。

目次

【1】やりたいこと
【2】考えるポイント
 1)IAMロールおよびポリシー
 2)S3バケットポリシー
 3)(Option:KMS使用時)KMSキー
【3】手順
 1)アカウント「B」のS3 バケット作成
 2)アカウント「A」のIAM Policy作成
 3)アカウント「A」で使用するRoleにPolicyをアタッチする
 4)アカウント「B」のS3 バケットPolicy作成
 5)(Option:KMS使用時)アカウント「B」でKMSキーポリシーにアカウント「A」への使用許可
 6)(Option:KMS使用時)アカウント「A」でKMSキーの使用許可
 7)動作確認

【1】やりたいこと

AWSアカウント「A」から、
別アカウント「B」(クロスアカウント)にある
S3バケットにファイルをアップロードしたい

【2】考えるポイント

* 以下の関連記事でも触れているが、考えるポイントは、以下の3点。

クロスアカウントでのS3アクセスに関するトラブル
https://dk521123.hatenablog.com/entry/2022/06/30/193834

1)IAMロールおよびポリシー

* AWSアカウント「A」側のIAMロールおよびポリシー付与が必要

2)S3バケットポリシー

* AWSアカウント「B」側で、
 AWSアカウント「A」側のIAMロールに対して、
 S3バケットを許可(Allow)する必要がある

3)(Option:KMS使用時)KMSキー

* AWSアカウント「B」側のS3バケットでKMSキーを暗号化している場合は
 そのKMSキーの使用許可(Allow)をAWSアカウント「A」「B」両方で
 行う必要がある

【3】手順

1)アカウント「B」のS3 バケット作成

受け入れ先のアカウント「B」のS3 バケット作成する
 => すでにあれば、Skip

2)アカウント「A」のIAM Policy作成

* アカウント「A」で、アカウント「B」の
 S3 バケットにファイルをアップロード可能な
 IAM Policyを作成する
 => KMS使用している場合は、実際では
 「6)(Option:KMS使用時)アカウント「A」でKMSキーの使用許可」
 と同時にやってしまっていい
 => 削除が必要な場合は「"s3:DeleteObject",」を追加すればいい

イメージ:S3バケット使用許可Policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListBucket",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::<S3バケット名>",
                "arn:aws:s3:::<S3バケット名>/*"
            ]
        }
    ]
}

イメージ:全体S3バケット参照許可Policy(要らないかも)
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/using-with-s3-actions.html#using-with-s3-actions-related-to-buckets

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}

3)アカウント「A」で使用するRoleにPolicyをアタッチする

2)で作成したIAM PolicyをアクセスしたいIAM Roleに対して
(例えば、EC2 でアクセスする場合は、EC2 の IAM Role)
アタッチする

4)アカウント「B」のS3 バケットPolicy作成

アカウント「B」に作業を戻って、
S3バケットのバケットPolicyに
アカウント「A」の IAM Policy を許可(Allow)するようにする
 => 削除が必要な場合は「"s3:DeleteObject",」を追加すればいい
 => 「"AWS" : "arn:aws:iam::<AWSアカウント「A」ID>:role/<IAM Role>"」がキモ

イメージ

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<AWSアカウント「A」ID>:role/<IAM Role>"
            },
            "Action": [
                "s3:GetObject",
                "s3:ListBucket",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::<S3バケット名>",
                "arn:aws:s3:::<S3バケット名>/*"
            ]
        }
    ]
}

5)(Option:KMS使用時)アカウント「B」でKMSキーポリシーにアカウント「A」への使用許可

* KMS使用する場合、アカウント「B」でKMSキーポリシーに対して
 アカウント「A」への使用許可を行う必要がある
 => 「"AWS" : "arn:aws:iam::<AWSアカウント「A」ID>:role/<IAM Role>"」がキモ

イメージ

{
  "Version" : "2012-10-17",
  "Id" : "demo-key-policy-for-cross-accounts",
  "Statement" : [ {
    "Sid" : "Enable IAM User Permissions for Cross accounts",
    "Effect" : "Allow",
    "Principal" : {
      "AWS" : "arn:aws:iam::<AWSアカウント「A」ID>:role/<IAM Role>"
    },
    "Action": [
      "kms:Encrypt",
      "kms:Decrypt",
      "kms:ReEncrypt*",
      "kms:GenerateDataKey*",
      "kms:DescribeKey"
    ],
    "Resource" : "*"
  } ]
}

6)(Option:KMS使用時)アカウント「A」でKMSキーの使用許可

* KMS使用する場合、アカウント「A」でKMSキーの使用許可を行うために
 IAMポリシーを追加し、2)で行ったようにIAMロールにアタッチする
 => 実際は「2)アカウント「A」のIAM Policy作成」と同時やるといいかも。
 => ちなみに「kms:GenerateDataKey」は絶対必要(そういうエラーがでたので)

イメージ

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:ReEncrypt*",
                "kms:GenerateDataKey*",
                "kms:DescribeKey"
            ],
            "Resource": [
                "arn:aws:kms:<AWS Region>:<AWSアカウント「B」ID>":key:*"
            ]
        }
    ]
}

7)動作確認

* アカウント「A」側で動作確認してみる

確認例:ファイルのPut

echo "Hello world!!" > hello.txt
aws s3 cp hello.txt s3://<アカウント「B」のS3バケット名>/tests/hello.txt

参考文献

https://repost.aws/ja/knowledge-center/s3-cross-account-upload-access
https://docs.aws.amazon.com/ja_jp/mediaconvert/latest/ug/write-your-outputs-to-another-accounts-amazon-s3-bucket.html
https://cloud5.jp/cross-account-upload-to-s3/
https://www.capybara-engineer.com/entry/2021/05/20/120604

関連記事

IAM ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2017/02/26/231046
IAM ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2022/07/03/000000
IAM ~ IAM Policy ~
https://dk521123.hatenablog.com/entry/2020/09/30/133123
IAM ~ クロスアカウント ~
https://dk521123.hatenablog.com/entry/2022/05/23/000000
AWS CLIaws sts
https://dk521123.hatenablog.com/entry/2023/04/13/000000
IAM ~ Service-Linked Roles ~
https://dk521123.hatenablog.com/entry/2023/01/22/000000
クロスアカウントでのS3アクセスに関するトラブル
https://dk521123.hatenablog.com/entry/2022/06/30/193834