Ошибка выполнения лямбда-функции, подписанной на тему SNS - PullRequest
0 голосов
/ 11 апреля 2019

Помоги мне, братья и сестры!

У меня есть стек CF, который выдвигает некоторые темы и подписки SNS. Некоторые из этих подписок вызывают лямбда-функции. После того, как я загрузил стек, я протестирую темы 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 через веб-консоль, вы получаете эту опцию. Что эквивалентно 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 ]

1 голос
/ 13 апреля 2019

Вам необходимо добавить ресурс 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, когда уведомление приходит из вашей темы.

0 голосов
/ 15 апреля 2019

В интересах других людей с той же проблемой, которые ищут решение в этой теме, я объединил решение ниже.

Мы создаем три вещи:

  • SNS Тема с именем "MyTopicSNS"
  • Подписка SNS с именем «SendMessageToLambda» (подписана на MyTopicSNS)
  • CloudWatch Alarm отправляет сообщение в «MyTopicSNS»

У меня также есть лямбда-функция (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.

...