Reputation: 51
I want to use a SNS subscription to trigger a Lambda function. First I have created a topic and subscription via the AWS SDK:
import {SubscribeCommand } from "@aws-sdk/client-sns";
import {snsClient } from "./libs/snsClient.js";
// Set the parameters
const params = {
Protocol: "lambda" /* required */,
TopicArn: "TOPIC_ARN", //TOPIC_ARN
Endpoint: "LAMBDA_FUNCTION_ARN", //LAMBDA_FUNCTION_ARN
};
const run = async () => {
try {
const data = await snsClient.send(new SubscribeCommand(params));
console.log("Success.", data);
return data; // For unit tests.
} catch (err) {
console.log("Error", err.stack);
}
};
run();
It is creating the subscription, but when I check the Lambda, this sub is not appearing as a Lambda trigger.
When I create the subscription manually without using the SDK it's working.
I would like to know why my subscription that created with the SDK is not showing in the Lambda's trigger.
Upvotes: 2
Views: 1165
Reputation: 5448
In my case I was provisionning the Lambda with Terraform and had the same issue.
I had to add the following permissions in order to see the proper link in the Function Overview section of the Lamba referring the Cloudwatch triggers/subscriptions.
resource "aws_lambda_permission" "allow_cloudwatch_general" {
statement_id = "myamq-datadog-forwarder-CloudWatchLogsPermission-general"
action = "lambda:InvokeFunction"
function_name = "myamq-datadog-forwarder"
principal = "logs.amazonaws.com"
source_arn = "arn:aws:logs:${local.region}:${local.account_id}:log-group:${local.amq_general_log_group_name}:*"
}
resource "aws_lambda_permission" "allow_cloudwatch_audit" {
statement_id = "myamq-datadog-forwarder-CloudWatchLogsPermission-audit"
action = "lambda:InvokeFunction"
function_name = "myamq-datadog-forwarder"
principal = "logs.amazonaws.com"
source_arn = "arn:aws:logs:${local.region}:${local.account_id}:log-group:${local.amq_audit_log_group_name}:*"
}
and in local variables I set:
locals{
// link to log
amq_general_log_group_name = "/aws/amazonmq/broker/${aws_mq_broker.myamq.id}/general"
amq_audit_log_group_name = "/aws/amazonmq/broker/${aws_mq_broker.myamq.id}/audit"
}
Upvotes: 0
Reputation: 334
For anyone else who comes to this thread looking to automate using CDK, here's how can you automate everything about the stack and not use the CLI to add the missing pieces.
I ran into a similar issue recently. I needed to add SNS as a trigger, add the necessary permission to the lambda and add the lambda as a subscription to the SNS topic.
import * as cdk from 'aws-cdk-lib';
import * as sns from 'aws-cdk-lib/aws-sns';
export class MyStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
const topic = new sns.Topic(this, 'Subscription Topic', {
fifo: false,
topicName: 'subscription-events-topic',
});
// Get a reference to the existing lambda
const subscriptionLambda = lambda.Function.fromFunctionName(
this,
'ExistingLambda',
'SubscriptionEventsLambda' // <- The name of the existing lambda
);
// subscribe the lambda function to this topic
new sns.CfnSubscription(this, 'Lambda Subscription', {
protocol: 'lambda',
endpoint: subscriptionLambda.functionArn,
topicArn: topic.topicArn,
});
// allow SNS to invoke the lambda
new lambda.CfnPermission(this, 'Allow SNS invocation', {
action: 'lambda:InvokeFunction',
principal: 'sns.amazonaws.com',
functionName: subscriptionLambda.functionName,
sourceArn: topic.topicArn,
});
}
}
I tried using other constructs such as lambda.addPermission
and topic.addSubscription
but for some reason they didn't work.
I got to this SO thread looking for a solution to this problem but couldn't find any.
For anyone that lands here, I hope this helps.
Upvotes: 2
Reputation: 25759
Looks like you are missing the IAM permissions. SNS needs explicit permission to invoke your Lambda.
See How do I subscribe a Lambda function to an Amazon SNS topic in the same account? in the docs. The lambda add-permission
CLI step from the example is the same as the AddPermissionCommand in the SDK Lambda client. Provide your SNS topic's ARN.
Upvotes: 3