AWS Cloudformation:“对Lambda函数的权限无效”这是怎么回事?

问题描述

我正在尝试通过Api网关触发器调用lambda ReplySms

这是我的template.yaml:

Resources:
  SmsRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub ${Environment}-${Application}-role
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Action:
              - sts:AssumeRole
            Principal:
              Service:
                - lambda.amazonaws.com
                - apigateway.amazonaws.com
            Effect: Allow
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        - arn:aws:iam::aws:policy/SecretsManagerReadWrite
  SmsApi:
    Type: AWS::Serverless::Api
    Tags:
      username: !Ref UserName
      Application: !Ref Application
    Properties:
      Name: !Sub ${Environment}-sms-service
      StageName: !Ref Environment
      MethodSettings:
        - LoggingLevel: INFO
          DataTraceEnabled: false
          ResourcePath: "/*"
          HttpMethod: "*"
  ReplySms:
    Type: AWS::Serverless::Function
    Properties:
      ReservedConcurrentExecutions: 100
      FunctionName: !Sub ${Environment}-${Application}-reply-sms
      CodeUri: target
      Handler: replySms.handler
      Runtime: nodejs12.x
      MemorySize: 128
      Timeout: 30
      Role: !GetAtt SmsRole.Arn
  ReplySmsResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      RestApiId: !Ref SmsApi
      ParentId: !GetAtt SmsApi.RootResourceId
      PathPart: replysms
  EmptyModel:
    Type: AWS::ApiGateway::Model
    Properties:
      RestApiId: !Ref SmsApi
      ContentType: application/xml
      Description: Empty schema to map lambda response
      Name: EmptyModel
      Schema: {}
  ReplyMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationType: NONE
      HttpMethod: POST
      Integration:
        Type: AWS
        Credentials: !GetAtt SmsRole.Arn
        IntegrationHttpMethod: POST
        Uri: !Sub 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ReplySms.Arn}/invocations'
        PassthroughBehavior: WHEN_NO_TEMPLATES
        RequestTemplates:
          application/x-www-form-urlencoded: |
            #set($httpPost = $input.path('$').split("&"))
            {
            #foreach( $kvPair in $httpPost )
             #set($kvTokenised = $kvPair.split("="))
             #if( $kvTokenised.size() > 1 )
               "$kvTokenised[0]" : "$kvTokenised[1]"#if( $foreach.hasNext ),#end
             #else
               "$kvTokenised[0]" : ""#if( $foreach.hasNext ),#end
             #end
            #end
            }
        IntegrationResponses:
          - StatusCode: 200
            ResponseTemplates: {"application/xml": "$input.path('$')"}
      MethodResponses:
        - StatusCode: 200
          ResponseModels:
            application/xml: !Ref EmptyModel
      ResourceId: !Ref ReplySmsResource
      RestApiId: !Ref SmsApi
  InvokeReplySmsLambda:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunction
      FunctionName: !GetAtt ReplySms.Arn
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SmsApi}/*/POST/replysms"
#  SmsApiDeployment:
#    Type: "AWS::ApiGateway::Deployment"
#    DependsOn:
#      - ReplyMethod
#    Properties:
#      RestApiId: !Ref SmsApi
#      StageName: !Ref Environment
Outputs:
  ApiResourceUrl:
    Value: !Sub https://${SmsApi}.execute-api.${AWS::Region}.amazonaws.com/${Environment}/

自3天以来我一直在进行此操作,但仍然无法弄清楚出了什么问题。从其他答案中我发现我需要添加一个权限资源,因此我添加了InvokeReplySmsLambda,它应该可以修复错误

但仍然得到Execution Failed due to configuration error: Invalid permissions on Lambda function

(66c44450-af76-4c93-accd-xxxxxxxxxxxx) Extended Request Id: RKHI5FEMIAMFc-w=
(66c44450-af76-4c93-accd-b659d3c8f2ee) Verifying Usage Plan for request: 66c44450-af76-4c93-accd-b659d3c8f2ee. API Key:  API Stage: dhrcl2tzqa/sandBox
(66c44450-af76-4c93-accd-b659d3c8f2ee) API Key  authorized because method 'POST /replysms' does not require API Key. Request will not contribute to throttle or quota limits
(66c44450-af76-4c93-accd-b659d3c8f2ee) Usage Plan check succeeded for API Key  and API Stage dhrcl2tzqa/sandBox
(66c44450-af76-4c93-accd-b659d3c8f2ee) Starting execution for request: 66c44450-af76-4c93-accd-b659d3c8f2ee
(66c44450-af76-4c93-accd-b659d3c8f2ee) HTTP Method: POST,Resource Path: /replysms
(66c44450-af76-4c93-accd-b659d3c8f2ee) Execution Failed due to configuration error: Invalid permissions on Lambda function
(66c44450-af76-4c93-accd-b659d3c8f2ee) Method completed with status: 500

任何帮助将不胜感激。

解决方法

首先

删除您的InvokeReplySmsLambda AWS::Lambda::Permission资源。您将不需要它,因为SAM CLI将创建一个策略,该策略可以隐式调用Lambda(docs reference)。

是否需要隐式创建的角色的Arn始终为:FunctionNameRole.Arn(在Yaml中使用类似!GetAtt ReplySmsRole.Arn的用法)。您可以在aws控制台的堆栈详细信息(cloudformation)或“角色”部分(IAM)的资源选项卡之一中确认该值。

第二,

将您的Lambda函数编辑为

  • 删除Role属性

  • 包括一个Policies属性以及您想要的其他策略(SecretsManagerReadWrite)。

    ReplySms:
      Type: AWS::Serverless::Function
      Properties:
        ReservedConcurrentExecutions: 100
        FunctionName: !Sub ${Environment}-${Application}-reply-sms
        CodeUri: target
        Handler: replySms.handler
        Runtime: nodejs12.x
        MemorySize: 128
        Timeout: 30
        Policies:
          - SecretsManagerReadWrite
    

注释:

我还将提到您可以使用Events类型的EventSourceAPI)属性并合并AWS::ApiGateway::Method资源。一个例子可以在这里找到: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-resource-function--examples

hths!