AWS Lambda 函数在 S3 上传时触发 SNS 主题

AWS Lambda function to trigger SNS topic on S3 upload

我对 SNS 和 Lambda 还很陌生。我已成功创建 SNS 主题,并且可以发送短信。上传文件时,我确实设置了一个 S3 事件。但是,我想更改该消息的文本,因此从应该向 SNS 主题发送消息的蓝图中创建了一个 Lambda 函数。

这是设计器的屏幕截图

这是我使用的蓝图代码:

from __future__ import print_function

import json
import urllib
import boto3

print('Loading message function...')


    def send_to_sns(message, context):
    
        # This function receives JSON input with three fields: the ARN of an SNS topic,
        # a string with the subject of the message, and a string with the body of the message.
        # The message is then sent to the SNS topic.
        #
        # Example:
        #   {
        #       "topic": "arn:aws:sns:REGION:123456789012:MySNSTopic",
        #       "subject": "This is the subject of the message.",
        #       "message": "This is the body of the message."
        #   }
    
        sns = boto3.client('sns')
        sns.publish(
            TopicArn=message['arn:aws:sns:MySNS_ARN'],
            Subject=message['File upload'],
            Message=message['Files uploaded successfully']
        )
    
        return ('Sent a message to an Amazon SNS topic.')

在测试 Lamda 函数时,我收到以下错误:

Response:
{
  "stackTrace": [
    [
      "/var/task/lambda_function.py",
      25,
      "send_to_sns",
      "TopicArn=message['arn:aws:sns:MySNS_ARN'],"
    ]
  ],
  "errorType": "KeyError",
  "errorMessage": "'arn:aws:sns:MySNS_ARN'"
}

Request ID:
"7253aa4c-7635-11e8-b06b-838cbbafa9df"

Function Logs:
START RequestId: 7253aa4c-7635-11e8-b06b-838cbbafa9df Version: $LATEST
'arn:aws:sns:MySNS_ARN': KeyError
Traceback (most recent call last):
  File "/var/task/lambda_function.py", line 25, in send_to_sns
    TopicArn=message['arn:aws:sns:MySNS_ARN'],
KeyError: 'arn:aws:sns:MySNS_ARN'

END RequestId: 7253aa4c-7635-11e8-b06b-838cbbafa9df
REPORT RequestId: 7253aa4c-7635-11e8-b06b-838cbbafa9df  Duration: 550.00 ms Billed Duration: 600 ms     Memory Size: 128 MB Max Memory Used: 30 MB  

我不确定我是否了解出了什么问题,非常感谢您的帮助!谢谢!

您的代码似乎来自旧的 AWS Step Functions 手册,这与您的用例无关。

当 Amazon S3 发送 事件通知 时,它包含以下信息(来自 Event Message Structure - Amazon Simple Storage Service):

{  
   "Records":[  
      {  
         "eventVersion":"2.0",
         "eventSource":"aws:s3",
         "awsRegion":"us-east-1",
         "eventTime":The time, in ISO-8601 format, for example, 1970-01-01T00:00:00.000Z, when S3 finished processing the request,
         "eventName":"event-type",
         "userIdentity":{  
            "principalId":"Amazon-customer-ID-of-the-user-who-caused-the-event"
         },
         "requestParameters":{  
            "sourceIPAddress":"ip-address-where-request-came-from"
         },
         "responseElements":{  
            "x-amz-request-id":"Amazon S3 generated request ID",
            "x-amz-id-2":"Amazon S3 host that processed the request"
         },
         "s3":{  
            "s3SchemaVersion":"1.0",
            "configurationId":"ID found in the bucket notification configuration",
            "bucket":{  
               "name":"bucket-name",
               "ownerIdentity":{  
                  "principalId":"Amazon-customer-ID-of-the-bucket-owner"
               },
               "arn":"bucket-ARN"
            },
            "object":{  
               "key":"object-key",
               "size":object-size,
               "eTag":"object eTag",
               "versionId":"object version if bucket is versioning-enabled, otherwise null",
               "sequencer": "a string representation of a hexadecimal value used to determine event sequence, 
                   only used with PUTs and DELETEs"            
            }
         }
      },
      {
          // Additional events
      }
   ]
}

然后您可以访问有关触发事件的文件的信息。例如,此 Lambda 函数将消息发送到 SNS 队列:

import boto3

def lambda_handler(event, context):

    bucket = event['Records'][0]['s3']['bucket']['name']
    key =    event['Records'][0]['s3']['object']['key']

    sns = boto3.client('sns')
    sns.publish(
        TopicArn = 'arn:aws:sns:ap-southeast-2:123456789012:stack',
        Subject = 'File uploaded: ' + key,
        Message = 'File was uploaded to bucket: ' + bucket
    )

但是,由于您想发送 SMS,实际上您可以绕过对 SNS 主题的需求,直接发送 SMS :

import boto3

def lambda_handler(event, context):

    bucket = event['Records'][0]['s3']['bucket']['name']
    key =    event['Records'][0]['s3']['object']['key']

    sns = boto3.client('sns')
    sns.publish(
        Message = 'File ' + key + ' was uploaded to ' + bucket,
        PhoneNumber = "+14155551234"
    )

编写此类代码的最简单方法是使用 AWS Lambda 中的 Test 功能。它可以模拟来自各种来源(例如 Amazon S3)的消息。事实上,这就是我测试上述功能的方式——我编写代码并使用 Test 函数测试代码,所有这些都没有离开 Lambda 控制台。

我找到了一个有效的 NodeJs 示例:

console.log('Loading function');

var AWS = require('aws-sdk');  
AWS.config.region = 'us-east-1';

exports.handler = function(event, context) {  
    console.log("\n\nLoading handler\n\n");
    var sns = new AWS.SNS();

    sns.publish({
        Message: 'File(s) uploaded successfully',
        TopicArn: 'arn:aws:sns:_my_ARN'
    }, function(err, data) {
        if (err) {
            console.log(err.stack);
            return;
        }
        console.log('push sent');
        console.log(data);
        context.done(null, 'Function Finished!');  
    });
};