SPINFさんの AWS LambdaでS3更新時にCloudFrontのInvalidationを実施する を東京リージョンで実現する方法です。
Classmethodさんの 異なるリージョンのAWS Lambdaを利用する を見て、SNSからは任意のリージョンの Lambda が呼べるので、東京リージョンのS3 bucketでも自動的にInvalidationが出来そうだという事でやってみました。
通知メッセージの形式
S3のObject Creationイベントを、SNS Notification 経由で Lambda に飛ばしてみると、
{
"Records": [
{
"EventSource": "aws:sns",
"EventVersion": "1.0",
"EventSubscriptionArn": "arn:aws:sns:ap-northeast-1:000000000000:invalidation:fe80205a-f446-48ac-b536-ab553f8c076f",
"Sns": {
"Type": "Notification",
"MessageId": "d14fcdeb-eb34-5982-9abd-8055cf10fb40",
"TopicArn": "arn:aws:sns:ap-northeast-1:000000000000:invalidation",
"Subject": "Amazon S3 Notification",
"Message": "{\"Records\":[{\"eventVersion\":\"2.0\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"ap-northeast-1\",\"eventTime\":\"2015-05-02T01:01:24.116Z\",\"eventName\":\"ObjectCreated:Put\",\"userIdentity\":{\"principalId\":\"A000000000000\"},\"requestParameters\":{\"sourceIPAddress\":\"1.2.3.4\"},\"responseElements\":{\"x-amz-request-id\":\"83F249C38C9573DC\",\"x-amz-id-2\":\"se8ASGX/20Lpw7LxK191kRxDJeAaXgh29Yugf6LAysthLNa8OFWB+tjEo/B5L6NUHejDJ1kA9TY=\"},\"s3\":{\"s3SchemaVersion\":\"1.0\",\"configurationId\":\"invalidation\",\"bucket\":{\"name\":\"j3tm0t0-test\",\"ownerIdentity\":{\"principalId\":\"A000000000000\"},\"arn\":\"arn:aws:s3:::j3tm0t0-test\"},\"object\":{\"key\":\"dummy\",\"size\":6,\"eTag\":\"f02e326f800ee26f04df7961adbf7c0a\"}}}]}",
"Timestamp": "2015-05-02T01:01:24.256Z",
"SignatureVersion": "1",
"Signature": "XfA0EUOD0sYjwRpkjF36byAJFRrIg0cWeBbb/EyFQbm3MK4JlZFvxbdel6z3H+6b2HVd8TKigkMt2TdWFmXS+q/KdiUgiTKARb8C03VB3VTc/Ihulnrp4/oXsmdaa/Q9Ak1uarQYPsry3EPQQvTqytsVfdg38mriPjCTGxFoAPySXcCAcX8sMPohhq4AnMjIYYVlFpx3MdeXzkvQll4qo1H/ebZf2eYok5CF9K1tBH2r0ZndaK5hEmgm0rtwNeUpGoMixPHw5eq8fHJIUgvpcw8y5bY8p2sRwAGqKxhtIwKSFqHTpSKrmHxZEwFo2WfYzoZz7DHx3982k1u8GEMAVg==",
"SigningCertUrl": "https://sns.ap-northeast-1.amazonaws.com/SimpleNotificationService-d6d679a1d18e95c2f9ffcf11f4f9e198.pem",
"UnsubscribeUrl": "https://sns.ap-northeast-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:ap-northeast-1:000000000000:invalidation:fe80205a-f446-48ac-b536-ab553f8c076f",
"MessageAttributes": {}
}
}
]
}
のような event が実行されます。この中の Records[0].Sns.Message を取り出すと
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "ap-northeast-1",
"eventTime": "2015-05-02T01:01:24.116Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "A000000000000"
},
"requestParameters": {
"sourceIPAddress": "1.2.3.4"
},
"responseElements": {
"x-amz-request-id": "83F249C38C9573DC",
"x-amz-id-2": "se8ASGX/20Lpw7LxK191kRxDJeAaXgh29Yugf6LAysthLNa8OFWB+tjEo/B5L6NUHejDJ1kA9TY="
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "invalidation",
"bucket": {
"name": "j3tm0t0-test",
"ownerIdentity": {
"principalId": "A000000000000"
},
"arn": "arn:aws:s3:::j3tm0t0-test"
},
"object": {
"key": "dummy",
"size": 6,
"eTag": "f02e326f800ee26f04df7961adbf7c0a"
}
}
}
]
}
のようなデータになってます。これはS3からダイレクトにLambdaを呼んだ時の構造と同じです。
イベントソースがSNSだった際には、中から取り出して実行してあげれば良さそうですね。
実装
SPINFさんのスクリプトの冒頭に下記のようなコードを付け加えます(フルのコードはこちら)。
if (event.Records[0].EventSource == "aws:sns")
{
if(event.Records[0].Sns.Subject == "Amazon S3 Notification")
{ // overwrite S3 event object from payload
event=JSON.parse(event.Records[0].Sns.Message);
}
}
テスト
東京リージョンのBucketにダミーファイルをアップしてみます。
~$ aws s3 cp dummy s3://j3tm0t0-test/
upload: ./dummy to s3://j3tm0t0-test/dummy