4

I need to programmatically disable a lambda's SNS trigger, however, I seem to be unable to do so. I want this to show "Disabled" in the AWS Lambda console for the function:

lambda sns trigger

Here's the code I've tried:

function updateEndpoints(endpoints, enable) {
    const promises = [];
    endpoints.forEach((endpoint) => {
        console.log(`${enable ? 'Enabling' : 'Disabling'} Endpoint: ${endpoint}`);
        promises.push(
            SNS.setEndpointAttributes({
                EndpointArn: endpoint,
                Attributes: {
                    Enabled: enable ? 'True' : 'False',
                },
            }).promise()
            .catch((e) => {
                console.error(`Error ${enable ? 'Enabling' : 'Disabling'} Endpoint: ${endpoint}`);
                console.error(e);
            }));
    });

    return Promise.all(promises);
}

The endpoint ARN is passed in correctly with a string like (with correct values in place of the <> below):

-
arn:aws:lambda:<region>:<accountId>:function:<functionName>
-

This produces an error from AWS for each endpoint I try to enable or disable:

-
InvalidParameter: Invalid parameter: EndpointArn Reason: Vendor lambda is not of SNS
-

Is it not possible to disable the trigger/endpoint for a lambda via SNS? How would one go about doing this? I would prefer not to have to unsubscribe/subscribe as this would take the subscription objects out of CloudFormation's scope (correct?). I looked at updateEventSourceMappings, however, per the documentation, that only works with DynamoDB streams, Kinesis Streams, and SQS -- not SNS.

0

2 Answers 2

4

I found the (100%) correct way to do this. While the answer from @John Rotenstein could be used, it's not quite right, but should still work.

I found when you click the toggle, the lambda's policy is actually updated:

Enabled:

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "my-lambda-1552674933742",
      "Effect": "Allow",
      "Principal": {
        "Service": "sns.amazonaws.com"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-west-2:1234567890:function:my-lambda",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:sns:us-west-2:1234567890:my-lambda"
        }
      }
    }
  ]
}

Disabled:

{
  "Version": "2012-10-17",
  "Id": "default",
  "Statement": [
    {
      "Sid": "my-lambda-1552674933742",
      "Effect": "Allow",
      "Principal": {
        "Service": "sns.amazonaws.com"
      },
      "Action": "lambda:DisableInvokeFunction",
      "Resource": "arn:aws:lambda:us-west-2:1234567890:function:my-lambda",
      "Condition": {
        "ArnLike": {
          "AWS:SourceArn": "arn:aws:sns:us-west-2:1234567890:my-lambda"
        }
      }
    }
  ]
}

Notice Action is lambda:InvokeFunction vs. lambda:DisableInvokeFunction.

My process to do this is as follows: - Lambda.listFunctions - for each function, Lambda.removePermission - for each function, Lambda.addPermission

Notes:

  • the Lambda api has a default safety throttle of 100 concurrent executions per account per region.
  • You can only update resource-based policies for Lambda resources within the scope of the AddPermission and AddLayerVersionPermission API actions. You can't author policies for your Lambda resources in JSON, or use conditions that don't map to parameters for those actions. See docs here

Also, you can use Lambda.getPolicy to see the policy of the lambda to ensure it is updated.

Sign up to request clarification or add additional context in comments.

1 Comment

This is the way.
1

It appears that there is no capability to "disable" a Lambda subscription to an SNS topic.

I base my reasoning on the follow steps I took:

  • Created an AWS Lambda function
  • Created an Amazon SNS topic
  • Subscribed the Lambda function to the SNS topic (done via the SNS console)
  • Confirmed in the Lambda console that the function subscription to SNS is "enabled"
  • Ran aws sns list-subscriptions-by-topic --topic-arn arn:aws:sns:ap-southeast-2:123456789012:my-topic
  • Saw that the Lambda function was subscribed

The response was:

{
    "Subscriptions": [
        {
            "SubscriptionArn": "arn:aws:sns:ap-southeast-2:123456789012:stack:...",
            "Owner": "123456789012",
            "Protocol": "lambda",
            "Endpoint": "arn:aws:lambda:ap-southeast-2:743112987576:function:my-function",
            "TopicArn": "arn:aws:sns:ap-southeast-2:123456789012:stack"
        }
    ]
}

I then disabled the trigger in the Lambda console and saved the Lambda function. When I re-ran the above command, the results were empty:

{
    "Subscriptions": []
}

When I enabled it again, the subscription returned.

So, my assumption is that, since the "disable/enable" button actually adds and removes a subscription, there does not appear to be any capability to 'disable' a subscription.

1 Comment

Thanks John! I confirmed this functionality, too. After reading through your answer, I clicked "disable" in the lambda console, went to the SNS Topic console and saw the subscription was deleted. When I clicked "enable", the subscription was then created. So to do this programmatically, I'll need to use the SNS API subscribe/unsubscribe functions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.