sattha14902
sattha14902

Reputation: 51

AWS SNS not attaching a Lambda trigger when the subscription is created via the SDK

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. empty trigger

When I create the subscription manually without using the SDK it's working. enter image description here

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

Answers (3)

рüффп
рüффп

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

Vijay Rangan
Vijay Rangan

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

fedonev
fedonev

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

Related Questions