[AWS]S3 Bucket Notification

[AWS]S3 Bucket Notification

应内部客户要求,尝试了一下S3 bucket的通知推送,这里记录一下。

分别使用了推送到SNS Topic和推送到Lambda(之后消费Gchat webhook)。

SNS Topic

S3-->Properties-->Events, Sent to SNS Topic.
需要注意的是,在SNS Topic里,需要修改policy让S3推消息,比如:

{
  "Version": "2012-10-17",
  "Id": "__default_policy_ID",
  "Statement": [
    {
      "Sid": "publish-from-s3",
      "Effect": "Allow",
      "Principal": {
        "Service": "s3.amazonaws.com"
      },
      "Action": "SNS:Publish",
      "Resource": "arn:aws:sns:ap-southeast-1:xxxxxxxxx:testing-notification-hz",
      "Condition": {
        "ArnLike": {
          "aws:SourceArn": "arn:aws:s3:::testing-notification-hz"
        }
      }
    }
  ]
}

Lambda

S3-->Properties-->Events, Sent to Lambda.
这个和之前为codepipeline做的Slack Notification集成大同小异,大体思路是

  • 事件触发由S3主导
  • 在event的json里剥离出有效信息(如果吃不准event的format可以先用logging取样到cloudwatch看看)
  • Call Google Chat Webhook
  • 如果有其他操作需求,还需记得妥善配置IAM role, VPC和security group

代码示例:

import json
import logging
from urllib import request
from urllib.request import Request, urlopen
from urllib import error as ERROR


logger = logging.getLogger()
logger.setLevel(logging.INFO)

GOOGLE_WEBHOOK_URL = 'https://chat.googleapis.com/v1/spaces/YYYYYYYYQ/messages?key=xxxxxxxxxx'


def lambda_handler(event, context):
    
    logger.info("Event: " + str(event))

    object_name = event['Records'][0]['s3']['object']['key']
    object_size = event['Records'][0]['s3']['object']['size']
    bucket_name = event['Records'][0]['s3']['bucket']['name']

    google_message = {
        'text' : 'New object created detected: `%s` of size `%s` in bucket `%s`'  %(object_name,object_size,bucket_name)
    }

    req2 = Request(GOOGLE_WEBHOOK_URL, data=json.dumps(google_message).encode("utf-8"), headers={'Content-Type': 'application/json; charset=UTF-8'}, method='POST')
    try:
        response2 = urlopen(req2)
        response2.read()
        logger.info("Message posted to google chat")
    except ERROR.HTTPError as e:
        logger.error("Request failed: %d %s", e.code, e.reason)
    except ERROR.URLError as e:
        logger.error("Server connection failed: %s", e.reason)

Subscribe to 隅

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe