【问题标题】:Failing to Execute Lambda Function Subscribed to SNS Topic订阅 SNS 主题的 Lambda 函数执行失败
【发布时间】:2019-09-02 11:16:42
【问题描述】:

帮助我的兄弟姐妹们!

我有一个推送一些 SNS 主题和订阅的 CF 堆栈。其中一些订阅调用 Lambda 函数。推送堆栈后,我将通过手动向其推送通知来测试调用 lambda 的 SNS 主题。 Lambda 从不开火。当我记录主题的交付状态时,我会得到如下信息:

{
    "notification": {
        "messageMD5Sum": "dfdd100c8699626047a347c435c981fa",
        "messageId": "423e1faf-088a-55f8-b2dc-4a86703224c9",
        "topicArn": "arn:aws:sns:us-east-2:643112374624:Foobar",
        "timestamp": "2019-04-11 17:16:40.096"
    },
    "delivery": {
        "deliveryId": "aae702b2-4787-5c7c-87e6-579b3f3f7f67",
        "destination": "arn:aws:lambda:us-east-2:642113479024:function:SomeLambdaFunction",
        "providerResponse": "{\"ErrorCode\":\"AccessDeniedException\",\"ErrorMessage\":\"User: sns.amazonaws.com is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-2:642113479024:function:SomeLambdaFunction\",\"lambdaRequestId\":\"Unrecoverable\"}",
        "dwellTimeMs": 35,
        "attempts": 1,
        "statusCode": 403
    },
    "status": "FAILURE"
}

因此,我需要授予 SNS(或至少该 SNS 主题)权限以执行特定的 lambda 函数,这对我来说是完全有意义的。我如何承认这一点对我来说是个谜。有什么帮助吗?

当您通过 Web 控制台创建 Lambda 时,您会看到此选项。什么是 CF 等价物。

我尝试向我的 CloudFormation 堆栈模板添加权限:

PolicyName:
  Type: AWS::Lambda::Permission
  Properties:
    FunctionName: !GetAtt { MyLambdaFunctionName, Arn }
    Action: 'lambda:InvokeFunction'
    Principal: sns.amazonaws.com
    SourceArn: !GetAtt { MySNSTopicName, Arn }

当我尝试部署包含策略的堆栈模板时,它失败并出现错误:

Failed to create the changeset: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Invalid template property or properties [PolicyName]

【问题讨论】:

    标签: amazon-web-services amazon-sns


    【解决方案1】:

    您需要添加具有以下属性 (JSON) 的 AWS::Lambda::Permission 资源:

    {
      "Type" : "AWS::Lambda::Permission",
      "Properties" : {
        "Action" : "lambda:InvokeFunction",
        "FunctionName" : {
          "Fn::GetAtt": [
            "<YOURLAMBDA>",
            "Arn"
          ]
        },
        "Principal" : "sns.amazonaws.com",
        "SourceArn": {
          "Ref": "<YOURTOPIC>"
        }
      }
    }
    

    或者如果使用 YAML:

    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt YOURLAMBDA.Arn
      Principal: sns.amazonaws.com
      SourceArn: !Ref YOURTOPIC
    

    当通知来自您的主题时,这将有效地允许 SNS 调用您的 Lambda 函数。

    【讨论】:

    • 感谢您的帮助!这完全有道理。你把权限sn-p放在哪里。我在我的 CF 模板中有它,但是当我尝试从模板部署堆栈时,它会爆炸。
    • 用我添加到 CloudFormation 堆栈模板和错误的 sn-p 更新了我的帖子。谢谢!
    • 当使用短格式符号时,它应该是!GetAtt MyLambdaFunctionName.Arn,对于主题,您需要使用!Ref MySNSTopicName,因为这是返回arn,请参阅docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/…
    • 再次感谢!我使用了!GetAtt [ Function, Arn ] 表示法,但这种方法很有效。
    【解决方案2】:

    为了方便其他有相同问题的人使用此线程中的解决方案,我已合并以下解决方案。

    我们正在创造三样东西:

    • 名为“MyTopicSNS”的 SNS 主题
    • 名为“SendMessageToLambda”的 SNS 订阅(订阅 MyTopicSNS)
    • CloudWatch 警报向“MyTopicSNS”提交消息

    我还有一个未在此处定义的 Lambda 函数 (FunctionToDoSomething)。

    用于创建这些服务的 CloudFormation 模板:

      MyTopicSNS:
        Type: AWS::SNS::Topic
        Properties:
          DisplayName: MyTopicSNS
          TopicName: MyTopicSNS
      SendMessageToLambda:
          Type: AWS::SNS::Subscription
          Properties:
            Endpoint: !GetAtt [ FunctionToDoSomething, Arn ]
            Protocol: lambda
            TopicArn: !Ref MyTopicSNS
    
      Alarm:
        Type: AWS::CloudWatch::Alarm
        Properties:
          AlarmName: Alarm
          Namespace: "AWS/SQS"
          MetricName: "ApproximateNumberOfMessagesVisible"
          Dimensions:
            - Name: "QueueName"
              Value: { "Fn::GetAtt" : [ "ErrorQueue", "QueueName"] }
          Statistic: Sum
          Period: 300
          EvaluationPeriods: 1
          Threshold: 0
          ComparisonOperator: GreaterThanThreshold
          TreatMissingData: "notBreaching"
          AlarmActions:
            - !Ref MyTopicSNS
    

    然后我添加了以下 IAM 策略来授予 SNS 主题权限以执行 Lambda 函数:

      GrantPermissions:
        Type: AWS::Lambda::Permission
        Properties:
          Action: 'lambda:InvokeFunction'
          FunctionName: !GetAtt [ FunctionToDoSomething, Arn ]
          Principal: 'sns.amazonaws.com'
          SourceArn: !Ref MyTopicSNS
    

    一旦我这样做了,主题的消息就会触发 Lambda 函数。

    【讨论】:

      猜你喜欢
      • 2021-09-03
      • 1970-01-01
      • 2020-09-18
      • 2018-02-27
      • 1970-01-01
      • 1970-01-01
      • 2016-05-31
      • 1970-01-01
      • 2020-09-11
      相关资源
      最近更新 更多