以编程方式禁用/启用Lambda SNS触发器

时间:2019-03-08 18:46:08

标签: amazon-web-services aws-lambda aws-sdk

我需要以编程方式禁用Lambda的SNS触发器,但是,我似乎无法这样做。我希望它在此功能的AWS Lambda控制台中显示“已禁用”:

lambda sns trigger

这是我尝试过的代码:

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

端点ARN可以通过类似字符串的方式正确传入(用正确的值代替下面的<>):

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

这会为我尝试启用或禁用的每个端点从AWS产生一个错误:

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

是否无法通过SNS禁用Lambda的触发/端点?人们将如何去做呢?我希望不必取消订阅/订阅,因为这会使订阅对象脱离CloudFormation的范围(对吗?)。但是,根据文档,我查看了updateEventSourceMappings,该文档仅适用于DynamoDB流,Kinesis流和SQS,而不适用于SNS。

2 个答案:

答案 0 :(得分:1)

似乎没有能力“禁用” SNS主题的Lambda订阅。

我的推理基于我采取的以下步骤:

  • 创建了一个AWS Lambda函数
  • 创建了一个Amazon SNS主题
  • 将Lambda函数订阅到SNS主题(通过SNS控制台完成)
  • 在Lambda控制台中确认SNS的功能订阅已“启用”
  • aws sns list-subscriptions-by-topic --topic-arn arn:aws:sns:ap-southeast-2:123456789012:my-topic
  • 看到Lambda函数已订阅

答复为:

{
    "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"
        }
    ]
}

然后我在Lambda控制台中禁用触发器并保存Lambda函数。当我重新运行以上命令时,结果为空:

{
    "Subscriptions": []
}

再次启用后,订阅返回。

因此,我的假设是,由于“禁用/启用”按钮实际上是添加和删除订阅,因此似乎没有“禁用”订阅的任何功能< / strong>。

答案 1 :(得分:0)

我找到了(100%)正确的方法。虽然可以使用@John Rotenstein的答案,但这并不完全正确,但仍然可以使用。

我发现当您单击切换开关时,lambda的策略实际上已更新:

已启用:

{
  "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"
        }
      }
    }
  ]
}

已禁用:

{
  "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"
        }
      }
    }
  ]
}

通知操作lambda:InvokeFunctionlambda:DisableInvokeFunction

我执行此操作的过程如下: -Lambda.listFunctions -对于每个函数,Lambda.removePermission -对于每个函数,Lambda.addPermission

注意:

  • Lambda api的默认安全限制是每个区域每个帐户100个并发执行。
  • 您只能在AddPermission和AddLayerVersionPermission API操作范围内更新Lambda资源的基于资源的策略。您不能在JSON中为Lambda资源编写策略,也不能使用不映射到这些操作的参数的条件。 See docs here

此外,您还可以使用Lambda.getPolicy查看lambda的策略以确保已更新。