はじめに
自分や他人の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側に設定する)
具体的な設定としては、以下様に
{
"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
}
]
}
{
"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ではないので注意!
{
"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を入れて、以下のコマンドよりawscli
とboto3
をインストールする。
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アドレスを変更したら、ちゃんと取得できなくなることも確認できた。