我有一个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-1ed3453c5d86
,lambda
类型,端点为:arn:aws:lambda:ap-southeast-1:178284945954:function:wowauctions_get_auction_data
我已经确认这是ARN的正确功能。一切似乎都正确连线:
我手动触发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但不会发生调用。为什么呢?
答案 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)
endpoint
必须与Lambda的ARN完全匹配)一旦确认了这些基本检查,仍然看不到调用,则必须是权限错误。在AWS控制台中打开Lambda时,应该会看到SNS被列为触发器:
为进行比较,如果缺少权限,您将不会看到SNS:
如果您不使用自动部署(例如,使用CloudFormation或Terraform),也可以手动添加缺少的权限:
SNS
下选择Add triggers
(您需要向下滚动列表才能看到它)Configure triggers
中,选择SNS主题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
}