为什么SNS不会触发我的lambda?

时间:2016-09-25 16:34:16

标签: amazon-web-services aws-lambda amazon-sns apex-framework

我有一个AWS lambda函数,我通过apex创建。我还通过terraform创建了一个SNS主题和订阅。

我的主题是:arn:aws:sns:ap-southeast-1:178284945954:fetch_realm_auctions

我订阅了arn:aws:sns:ap-southeast-1:178284945954:fetch_realm_auctions:2da1d182-946d-4afd-91cb-1ed3453c5d86lambda类型,端点为:arn:aws:lambda:ap-southeast-1:178284945954:function:wowauctions_get_auction_data

我已经确认这是ARN的正确功能。一切似乎都正确连线:

SNS picture

我手动触发SNS:

aws sns publish 
  --topic-arn arn:aws:sns:ap-southeast-1:178284945954:fetch_realm_auctions 
  --message '{"endpoint": "https://us.api.battle.net", "realm": "spinebreaker"}'

它返回消息ID但不会发生调用。为什么呢?

7 个答案:

答案 0 :(得分:6)

我添加了一个内联策略来允许调用lambda:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1474873816000",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "arn:aws:lambda:ap-southeast-1:178284945954:function:wowauctions_get_auction_data"
            ]
        }
    ]
}

它现在正在运作。

答案 1 :(得分:1)

正如Robo在评论中提到的,添加基于Principal的权限是最简单的方法:

"FooFunctionPermission" : {
    "Type" : "AWS::Lambda::Permission",
    "Properties" : {
        "Action" : "lambda:InvokeFunction",
        "FunctionName" : { "Ref" : "FooFunction" },
        "Principal" : "sns.amazonaws.com"
    }
}

答案 2 :(得分:1)

对我来说,问题是我在cloudformation模板的SourceAccount中指定了AWS::Lambda::Permission参数,而documentation则说明以下内容:

  

添加策略时,请勿使用--source-account参数将源帐户添加到Lambda策略。 Amazon SNS事件源不支持源帐户,这将导致访问被拒绝。由于源帐户包含在源ARN中,因此这对安全性没有影响。

我删除SourceAccount后,一切正常。

答案 3 :(得分:0)

有相同的问题:   1)创建并部署简单的lambda   2)从java sdk手动创建aws sns主题   3)从Java SDK创建sns订阅(在sns主题和      lambda)

然后,当我从控制台向该主题推送一些消息时,我遇到了问题-lambda并未拦截该消息。而且,sns触发器甚至都没有在lambda中注册。

所以我仅使用以下命令解决了这个问题: https://docs.aws.amazon.com/cli/latest/reference/lambda/add-permission.html

运行aws lambda add-permission ......之后,一切都正常了。

答案 4 :(得分:0)

SNS主题需要具有调用Lambda的权限。

下面是一个示例,您可以在Terraform中表达它:

# Assumption: both SNS topic and Lambda are deployed in the same region
# resource "aws_sns_topic" "instance" { ... }
# resource "aws_lambda_function" "instance" {... }

# Step 1: Allow the SNS topic to invoke the Lambda
resource "aws_lambda_permission" "allow_invocation_from_sns" {
  statement_id  = "AllowExecutionFromSNS"
  action        = "lambda:InvokeFunction"
  function_name = "${aws_lambda_function.instance.function_name}"
  principal     = "sns.amazonaws.com"
  source_arn    = "${aws_sns_topic.instance.arn}"
}

# Step 2: Subscribe the Lambda to the SNS topic
resource "aws_sns_topic_subscription" "instance" {
  topic_arn = "${aws_sns_topic.instance.arn}"
  protocol  = "lambda"
  endpoint  = "${aws_lambda_function.instance.arn}"
}

一些用于解决此问题的常规提示(未触发Lambda)

  1. 我的邮件到达Lambda吗? -将您的电子邮件地址订阅到SNS主题。如果您收到电子邮件,则将知道邮件何时到达该主题。
  2. Lambda是否已订阅该主题? -在AWS控制台中(在SNS->主题下)检查订阅是否正确(endpoint必须与Lambda的ARN完全匹配)

一旦确认了这些基本检查,仍然看不到调用,则必须是权限错误。在AWS控制台中打开Lambda时,应该会看到SNS被列为触发器:

enter image description here

为进行比较,如果缺少权限,您将不会看到SNS:

enter image description here

如果您不使用自动部署(例如,使用CloudFormation或Terraform),也可以手动添加缺少的权限:

  1. SNS下选择Add triggers(您需要向下滚动列表才能看到它)
  2. Configure triggers中,选择SNS主题
  3. 点击Add并保存Lambda

答案 5 :(得分:0)

这篇文章帮助我走得更远,但有一个失踪之处。 Terraform将创建错误的订阅。您必须放下$LATEST

resource "aws_sns_topic" "cloudwatch_notifications" {
  name = "aws-${var.service_name}-${var.stage}-alarm"
}

data "aws_lambda_function" "cloudwatch_lambda" {
  function_name = "sls-${var.service_name}-${var.stage}-cloudwatch-alarms"
}

resource "aws_lambda_permission" "with_sns" {
  statement_id  = "AllowExecutionFromSNS"
  action        = "lambda:InvokeFunction"
  function_name = "${replace(data.aws_lambda_function.cloudwatch_lambda.arn, ":$LATEST", "")}"
  principal     = "sns.amazonaws.com"
  source_arn    = "${aws_sns_topic.cloudwatch_notifications.arn}"
}

resource "aws_sns_topic_subscription" "cloudwatch_subscription" {
  topic_arn = "${aws_sns_topic.cloudwatch_notifications.arn}"
  protocol  = "lambda"
  endpoint  = "${replace(data.aws_lambda_function.cloudwatch_lambda.arn, ":$LATEST", "")}"
}

答案 6 :(得分:0)

这是此问题的具体答案-我已在其他地方删除了其他答案!

对于Terraform用户,另请参见此处: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_permission

显示了“ aws_lambda_permission”资源的使用;示例之一涵盖了SNS,复制到此处:

resource "aws_lambda_permission" "with_sns" {
  statement_id  = "AllowExecutionFromSNS"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.func.function_name
  principal     = "sns.amazonaws.com"
  source_arn    = aws_sns_topic.default.arn
}