3
votes

I am fairly new to SNS and Lambda. I have successfully created a SNS topic and I am able to send a text message. I did set up an S3 event when a file was uploaded. However, I would like to change the text of that message and therefore created a Lambda function from a blueprint that is supposed to send a message to the SNS topic.

Here is a screenshot of the Designer

Here is a screenshot of the Designer

This is the blueprint code I am using:

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.')

When testing the Lamda function, I receive the following error:

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  

I am not sure I understand what is going wrong and would appreciate the help! Thank you!

2

2 Answers

1
votes

Your code appears to be coming from an old AWS Step Functions manual, which is not relevant for your use-case.

When Amazon S3 sends an event notification, it contains the following information (from 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
      }
   ]
}

You can then access information about the file that triggered the event. For example, this Lambda function sends a message to an SNS queue:

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
    )

However, since you want to send an SMS, you can actually bypass the need for an SNS topic and send an SMS directly:

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"
    )

The easiest way to write such code is to use the Test feature in AWS Lambda. It can simulate a message coming from various sources, such as Amazon S3. In fact, that's how I tested the above functions - I wrote the code and used the Test function to test the code, all without leaving the Lambda console.

0
votes

I found a NodeJs example that worked:

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!');  
    });
};