代码之家  ›  专栏  ›  技术社区  ›  Adam

无法执行订阅到SNS Topic的Lambda函数

  •  0
  • Adam  · 技术社区  · 6 年前

    兄弟姐妹们,帮帮我!

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

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

    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]
    
    0 回复  |  直到 6 年前
        1
  •  2
  •   jogold Alexandr Solodskiy    6 年前

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

    {
      "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函数。

        2
  •  0
  •   Adam    6 年前

    • SNS主题名为“MyTopicSNS”
    • 名为“SendMessageToLambda”的SNS订阅(已订阅 我的主题)

    用于创建这些服务的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
    

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

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