はじめに
S3バケットにアップロードされたオブジェクトを他アカウント上にあるLambdaを用いて別のS3バケットへコピーする環境を構築しようとした際にIAM周りでつまずいたので、設定方法の備忘録としてのメモになります。Lambda関数はコピー元S3バケットにオブジェクトがアップロードされた時をトリガーとして実行されます(S3のイベント通知機能)。
S3のレプリケーション機能とかを使えば簡単なのに
今回の構成は以下の図の通りです。
コピー元アカウント | コピー先アカウント | |
---|---|---|
アカウントID | 000000000000 | 111111111111 |
S3バケット名 | source-bucket-name | destination-bucket-name |
Lambda関数名 | - | object-copy-function |
Lambdaの設定
まずは、LambdaからS3にアクセスするための実行ロール、S3からLambdaを呼び出すためのリソースポリシーを設定します。
実行ロール
S3へのアクセス権限を付与します。
今回はオブジェクトのコピーのみ行えれば良いので、権限設定のベストプラクティスに基づいて最小権限のS3:Putobject
とS3:GetObject
をそれぞれ付与します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::source-bucket-name",
"arn:aws:s3:::source-bucket-name/*"
]
},
{
"Effect": "Allow",
"Action": "s3:PutObject",
"Resource": [
"arn:aws:s3:::destination-bucket-name",
"arn:aws:s3:::destination-bucket-name/*"
]
},
]
}
リソースポリシー
S3のイベント通知からLambdaを呼び出すために、S3からLambdaの実行を許可するリソースベースのポリシーを追加します。
Conditionの部分にはコピー元S3バケットがあるAWSアカウントのIDとARNを入れます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "s3.amazonaws.com"
},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-northeast-1:111111111111:function:object-copy-function",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "000000000000"
},
"ArnLike": {
"AWS:SourceArn": "arn:aws:s3:::source-bucket-name"
}
}
},
]
}
コピー元S3バケットの設定
バケットポリシー
他アカウント上のLambdaからのアクセスを許可するよう、バケットポリシーを設定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::source-bucket-name",
"Condition": {
"StringEquals": {
"AWS:SourceAccount": "111111111111"
},
}
},
]
}
イベント通知
オブジェクト作成時にLambdaを実行するよう、S3バケットのプロパティからイベント通知を作成します。
設定保存時に指定したLambda関数に対して接続確認が行われるため、適切な権限が設定されていないとUnable to validate the following destination configurations
エラーが発生します。
おわりに
今回はS3のイベント通知で他アカウントのLambdaを呼び出し、オブジェクトのコピーをクロスアカウントで行う際の権限や設定についてまとめてみました。IAMは複雑で理解が難しいですが、実際に手を動かしながら設定すると理解が捗りますね。