无法执行订阅SNS主题的Lambda函数

时间:2019-04-11 18:22:04

标签: amazon-web-services amazon-sns

请帮助我的兄弟姐妹!

我有一个CF堆栈,正在推送一些SNS主题和订阅。其中一些订阅称为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当量。

enter image description here

我尝试向我的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]

2 个答案:

答案 0 :(得分: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函数。

答案 1 :(得分:0)

为了使其他有相同问题的人希望在此线程中使用该解决方案,我在下面合并了决议。

我们正在创建三件事:

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

我还有一个此处未定义的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函数。