Adding a subscription to an SNS topic in CloudFormation is easily done with a few lines:
1 2 3 4 5 6 7 8 9 10 11 12 |
"lambdaTopic": { "Properties": { "DisplayName": "Topic that invokes the Lambda function", "Subscription": [ { "Endpoint": { "Fn::GetAtt": [ "lambdaFunction", "Arn" ] }, "Protocol": "lambda" } ] }, "Type": "AWS::SNS::Topic" } |
But that’s actually not enough. While creating a subscription in the AWS Console is a single step it implicitly creates a Lambda permission for SNS to invoke the function. This needs to be added as a separate resource in CloudFormation:
1 2 3 4 5 6 7 8 9 |
"lambdaPermission": { "Properties": { "Action": "lambda:InvokeFunction", "FunctionName": { "Fn::GetAtt": [ "lambdaFunction", "Arn" ] }, "Principal": "sns.amazonaws.com", "SourceArn": { "Ref": "lambdaTopic" } }, "Type": "AWS::Lambda::Permission" } |
This will allow SNS to successfully invoke the function.
If you send a JSON message to your SNS topic that will be encapsulated in the event sent to Lambda (as JSON) and you will have to unpack it in your function like in this example for node.js runtime:
1 2 3 4 5 |
exports.handler = function(event, context) { // Read options from the event. var json = JSON.parse(event.Records[0].Sns.Message); ... } |
Great post. Saved me from pulling out what little hair I have. Thanks.
but how to send json message to lambda from this SNS
If you send a JSON payload to SNS (in my case I was forwarding scaling notification from an Auto Scaling Group) you’ll get the JSON as a string in the message body of the SNS message. In your Lambda function you need to unpack the string into a data structure. (I’ll add a snippet of example code)
Thank you so much.