8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

IAMユーザやLambdaからS3バケットにアクセスする方法

Last updated at Posted at 2021-08-28

はじめに

自分や他人のAWSアカウントが所有するS3バケットに対して、IAMユーザーやLambdaへのアクセス権限の付け方に少しハマったため、やり方を整理してメモとして残す。

今回整理した内容

1.アカウントAのS3バケットに、アカウントAで作成したIAMユーザがアクセスする方法(AWSコンソールを用いて)

2.アカウントBのS3バケットに、アカウントAで作成したIAMユーザがアクセスする方法(AWSコンソールを用いて)

3.アカウントBのS3バケットに、アカウントAのS3バケットにあるファイルを、Lambdaを実行してコピーする方法

4.アカウントAのS3バケットに、アカウントAで作成したIAMユーザがアクセスする方法(ローカルPCからAWS CLIを用いて)

※ここで言うアカウントは、AWSアカウントを指している。

1.アカウントAのS3バケットに、アカウントAで作成したIAMユーザがアクセスする方法(AWSコンソールから)

■事前準備

アカウントAのS3バケットに以下の様なバケットを作成したとする。(バケット名は世界全体でユニークな必要があるので、そこは重複しない様に任意な名前で作成)

 ・s3-test-bucket-00001
 ・s3-test-bucket-00002

アカウントA内でIAMユーザーを作成する(ポリシーのアタッチは後でする)

■作成したIAMユーザが各S3バケットにアクセスするための設定

IAMユーザーにバケットへのアクセス権限を付与する方法は大きく2つある。

 ① バケットポリシーに記載
 ② IAMユーザーにアタッチするポリシーに記載

① バケットポリシーに記載する方法

AWSコンソールからS3サービスを開き、対象のバケットを選択する。
『アクセス許可』を開き、【バケットポリシー】に以下の様な記述をする。(説明のためコメントを入れている)

{
    "Version": "2012-10-17",
    "Statement": [

         List表示するための、権限設定(AWS cliなどから直接ダウンロード・アップロードをする場合は不要かもしれない)
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::*****************************"    IAMユーザーのARN
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::s3-test-bucket-00001"    バケットのARN
        },

         行為権限の設定       
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::*****************************"    IAMユーザーのARN
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::s3-test-bucket-00001/*"    バケットののARN
        }
    ]
}

※【パブリックアクセスをすべて ブロック ⇒ ON】 でもIAMユーザーから接続可能。

上記設定ができている状態で、アクセス権付与したIAMユーザーがAWSコンソールにログインすれば、S3-ObjectのURLにアクセスした際にバケット内を見れて、Actionで設定された操作が可能になる。
※URLは以下の様なものになるはず。
 https://s3.console.aws.amazon.com/s3/buckets/【バケット名】?region=【リージョン名】&tab=objects
 分からなければ、対象バケットの『オブジェクト』画面を開き、アドレスバーのURLをコピーすれば良い。

② IAMユーザーにアタッチするポリシーに記載する方法

以下の様に、IAMにアタッチするポリシーを作成する。

{
    "Version": "2012-10-17",
    "Statement": [

         List表示するための権限設定
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": [
                "arn:aws:s3:::s3-test-bucket-00001",
                "arn:aws:s3:::s3-test-bucket-00002"
            ]
        },

         行為権限の設定
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::s3-test-bucket-00001/*"
            ]
        }
    ]
}

該当のIAMユーザーがこのポリシーをアタッチすれば、先程と同じように閲覧や操作が可能になる。
(上記の場合だと、1と2のバケット内のオブジェクトの存在は見れるけど、2のバケットに対してはGETやPUTの権限はない)

バケットへのアクセスの仕方は先程と同じで、以下の様なURLにアクセスする。
https://s3.console.aws.amazon.com/s3/buckets/【バケット名】?region=【リージョン名】&tab=objects

特定のIAMユーザーに対して、AWSアカウント内のフォルダを全て表示したい場合は、以下の様なStatementをポリシーに追加すれば良い。

{
    "Version": "2012-10-17",
    "Statement": [

         ここが追加部分
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "s3:ListAllMyBuckets",
            "Resource": "*"
        },

         ここを消してしまうと、バケット内に入った時に何も表示されなくなり、コンソール上のGUI操作ができなくなる。
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": [
                "arn:aws:s3:::s3-test-bucket-00001",
                "arn:aws:s3:::s3-test-bucket-00002"
            ]
        },

        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::s3-test-bucket-00001/*"
            ]
        }
    ]
}

2.アカウントBのS3バケットに、アカウントAで作成したIAMユーザがアクセスする方法(AWSコンソールを用いて)

これはIAMユーザーが属しているAWSアカウント内のS3ではないため、クロスアカウントポリシーというのが適用されることになる。簡単に言うと、アクセス制限の際に以下の "両方" を設定する必要がある。

 ① バケットポリシーに記載(アカウントB側に設定する)
 ② IAMユーザーにアタッチするポリシーに記載(アカウントA側に設定する)

具体的な設定としては、以下様に

【アカウントB側のバケットポリシー】
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::**************************"     アカウントAのIAMユーザーのARN
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3::::**************************"     アカウントBのバケットのARN
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::**************************"     アカウントAのIAMユーザーのARN
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::**************************"     アカウントBのバケットのARN
        }
    ]
}
【アカウントA側のIAMユーザーにアタッチするポリシー】
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::**************************"     アカウントBのバケットのARN
        },
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::**************************"     アカウントBのバケットのARN
        }
   ]
}

3.アカウントBのS3バケットに、アカウントAのS3バケットにあるファイルを、Lambdaを実行してコピーする方法

Lambda関数からコピー先として、他人のS3バケットを指定したい時などは基本的なやり方は同じである。
Lambdaのアクセス権限に "実行ロール" として何かしらのロールが割り当てられていると思うが、そのロールにポリシーをアタッチしてあげればいい。(アタッチするポリシーは、②の【アカウントA側のIAMユーザーにアタッチするポリシー】と全く同じで問題ない。 ※LambdaはアカウントA側で作成している前提。) 

しかし、ファイルを送られる側のS3バケットポリシーの中身は若干異なり、IAMユーザーのARNではなく、実行ロールのARNを指定する。 ※LambdaのARNではないので注意!

【アカウントB側のバケットポリシー】
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::**************************"     アカウントAのLambdaの実行ロールのARN
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3::::**************************"     アカウントBのバケットのARN
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::**************************"     アカウントAのLambdaの実行ロールのARN
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::**************************"     アカウントBのバケットのARN
        }
    ]
}

4.アカウントAのS3バケットに、アカウントAで作成したIAMユーザがアクセスする方法(ローカルPCからAWS CLIを用いて)

■ローカルPCの準備

まずはローカルPCにPythonを入れて、以下のコマンドよりawscliboto3をインストールする。

pip install awscli boto3`

aws configureを実行して、接続情報の設定をする。

aws configure

// 以下の様に入力を求められるので、アカウントAで作成したIAMユーザーの情報や、該当の
AWS Access Key ID :
AWS Secret Access Key :
Default region name :
Default output format :

※アクセスキーIDやシークレットアクセスキーが分からない場合は、こちらを参考に。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-quickstart.html

以下のpythonファイルを作成する。(これを実行して、バケット内の【test.txt】を取得することを試してみる。)

import boto3

s3 = boto3.resource('s3')

bucket = 's3-test-bucket-00001'
target_file = 'test.txt'    # バケット直下に入れたテストファイル名
to_path = '【ローカルPCの任意のパス(コピー後のファイル名含む)】'

s3.Bucket(bucket).download_file(target_file, to_path)

■IAMユーザーにアタッチするポリシーの記載中身

{
    "Version": "2012-10-17",
    "Statement": [

         AWSコンソールからの操作を想定しないため、行為権限の設定ポリシーのみ
        {
            "Sid": "VisualEditor2",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:PutObjectAcl"
            ],
            "Resource":  "arn:aws:s3:::s3-test-bucket-00001/*",
        }
}

AWSコンソールからのアクセスではないが、同じAWSアカウント内のIAMユーザーとしてバケットにアクセスするため、バケットポリシーのみ記載だけで良いかと思ったが、エラーが出てしまうのでIAMユーザーにアタッチするポリシーも必要っぽい。

■バケットポリシーの記載中身

IPアドレスで接続許可をしているバケットポリシー。

{
    "Version": "2012-10-17",
    "Id": "SourceIP",
    "Statement": [
        {
            "Sid": "SourceIP",
            "Effect": "Deny",
            "Principal": "*",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::s3-test-bucket-00001/*",
            "Condition": {
                "NotIpAddress": {
                    "aws:SourceIp": "【接続を許可するIPアドレス範囲】"
                }
            }
        }
    ]
}

※AWSの公式ページにVPCエンドポイントやIPアドレスでアクセス制限をかけたい時のポリシーの書き方があるので、こちらを参考に。
 https://aws.amazon.com/jp/premiumsupport/knowledge-center/block-s3-traffic-vpc-ip/

ポリシーの準備ができたら作成したPythonファイルを実行して、ちゃんと取得できていればOK。
試しに許可するIPアドレスを変更したら、ちゃんと取得できなくなることも確認できた。

以上、ポリシーを書きながら色々と試してみました!

8
6
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
8
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?