LambdaとSSMでEC2からS3のオブジェクト取得させる
AWS環境で,Lambdaを用いてS3からEC2にオブジェクトを取得させる設定をしたのでメモがてら残しておく.
概要
Lambdaを使い,AWS Systems Manager(SSM)経由でEC2にAWSコマンドを実行させ,S3からオブジェクトを取得する.また,S3にあるオブジェクトは他AWSアカウントからPUTされたと想定する.以下に図を示す.
S3のバケットポリシーの設定
AWSアカウント間をまたぐS3バケットへのアップロードでは,オブジェクトの権限に気をつける.
例えば,AというAWSアカウントがS3バケットを作成したとして,Bという他のAWSアカウントからS3バケットへオブジェクトをPUTする.PUTする際にオプションを何も指定しなければ,S3バケットへPUTされたオブジェクトの所有者はBとなってしまい,AにあるEC2からはGETできないしマネージメントコンソールからもダウンロードできない.これを避けるため,PUTする際(aws-cliの場合)に--acl bucket-owner-full-control
オプションをつけて実行する.これにより,PUTしたオブジェクトの所有者がAアカウントになりAアカウントからGETすることが可能となる.詳しくは以下のブログが参考になった.
test-bucket
というS3バケットを用意し,他のアカウントからPUTしてもらう.PUTしてもらう際に--acl bucket-owner-full-control
オプションをつけておかないとPUTできないようにCondition
を設定したバケットポリシーを以下に示す.もっと制限をかけたければPrincipal
やCondtion
を適宜追加する.
{ "Version": "2012-10-17", "Id": "PolicyId2", "Statement": [ { "Sid": "Test", "Effect": "Allow", "Principal": "*", "Action": [ "s3:PutObject", "s3:PutObjectAcl" ], "Resource": "arn:aws:s3:::test-bucket/*", "Condition": { "StringEquals": "s3:x-amz-acl": "bucket-owner-full-control" } } ] }
EC2の設定
EC2では,S3からオブジェクトを取得するために,今回はAWSコマンドを使う.AWSコマンドがない場合はインストールを行う.また,LambdaでSSMを使うのでEC2インスタンスにSSMエージェントが入っていない場合もインストールしておく.さらに,SSMがEC2を扱うことができるようにAmazonEC2RoleforSSM
ポリシーが付与されたロールをEC2にアタッチしておく.
Lambdaの設定
Lambdaでは,SSMを使ってEC2上でAWSコマンドを実行してS3からオブジェクトをEC2上に配置する.まずは,LambdaがSSMを扱うことができるようにAmazonSSMFullAccess
ポリシーが付与されたロールをLambdaにアタッチする.また,EC2上で実行するAWSコマンドで必要なシークレットIDとシークレットキーは環境変数としてLambdaで渡すようにする.Pythonで記述したLambdaの例を以下に示す.
import boto3 import os ACCESS_KEY_ID = os.environ['ACCESS_KEY_ID'] SECRET_ACCESS_KEY = os.environ['SECRET_ACCESS_KEY'] ssm = boto3.client('ssm') def lambda_handler(event, context): bucket = 'test-bukect/' ec2_dir = '/var/tmp' s3_dir = 'test/' commands = [ "export AWS_ACCESS_KEY_ID=" + ACCESS_KEY_ID, "export AWS_SECRET_ACCESS_KEY=" + SECRET_ACCESS_KEY, "export AWS_DEFAULT_REGION=ap-northeast-1", 'aws s3 sync s3://' + bucket + s3_dir + " " + ec2_dir ] ssm.send_command( InstanceIds = ('i-123456789',), DocumentName = "AWS-RunShellScript", Parameters = { "commands": commands, "executionTimeout": ["3600"] } )
これで,Lambdaを実行すればtest-bucket
の/testディレクトリ以下にある内容がEC2上の/var/tmp
以下にコピーされる.
まとめ
- LambdaとSSMを用いてEC2からS3のオブジェクト取得させた
- 他アカウントからのS3へのPUTでは
bucket-owner-full-control
をつける