如何获取特定于Cloud Formation的资源属性的AWS Lambda函数的ARN?

时间:2019-08-26 23:21:40

标签: amazon-web-services aws-lambda serverless-framework serverless

我似乎无法获得RefFn:GetAtt返回用于设置资源的有效值。

serverless.yml

...etc...

functions:
  bearerTokenAuthentication:
    handler: app.bearerTokenAuthentication
    name: ${self:service}-auth-bearer

resources:
  - ${file(./serverless_resources.yml)}

serverless_resources.yml

Resources:
  ApiGateway:
    Type: AWS::ApiGateway::RestApi
    Properties:
        Name: restapi-${self:provider.stage}
        Description: Endpoints
        ApiKeySourceType: HEADER # (to read the API key from the X-API-Key header of a request)

  ApiGatewayBearerAuthorizer:
    Type: AWS::ApiGateway::Authorizer
    Properties:
      Type: token
      IdentitySource: method.request.header.Authorization
      Name: BearerAuthorization
      AuthorizerResultTtlInSeconds: 300
      AuthorizerUri: !Join  #arn:aws:apigateway:${self:provider.region}:lambda:path/${self:functions.bearerTokenAuthentication.name}
        - ''
        - - 'arn:aws:apigateway:'
          - !Ref 'AWS::Region'
          - ':lambda:path/2015-03-31/functions/'
          - !GetAtt 
            - bearerTokenAuthentication # also tried !Ref bearerTokenAuthentication and '${self:functions.bearerTokenAuthentication.name}'
            - Arn
          - /invocations
      RestApiId: !Ref ApiGateway

无论我做什么,GetAtt都找不到bearerTokenAuthentication中声明的Lambda函数的ARN。我只是不断收到此错误:

  

错误:CloudFormation模板无效:模板错误:Fn :: GetAtt实例引用了未定义的资源bearerTokenAuthentication

...或尝试使用Ref ...

  

错误:CloudFormation模板无效:模板格式错误:模板的Resources块中未解决的资源依赖性[bearerTokenAuthentication]

是否可以从资源部分引用Lambda ARN?通过错误消息看来,它正在寻找“资源”名称。我一直以为lambda函数声明也被认为是一种资源(当然除了明显的Resources:块之外),也许我误会了一些东西。

2 个答案:

答案 0 :(得分:1)

我知道了。我有一个NodeJS项目,并且正在使用serverless.yml进行部署的“无服务器”命令行(sls)。事实证明,它创建了一个.serverless子目录,其中包含一些文件。其中之一是称为cloudformation-template-update-stack.json的AWS Cloud Formation的已编译模板。看来,该实用程序喜欢通过将第一个字符大写并将“ LambdaFunction”添加到所有函数名称中(无论出于何种原因)来处理名称。在这种情况下,bearerTokenAuthentication被重命名为BearerTokenAuthenticationLambdaFunction(实际资源名称)。在查看编译后的模板后,一切都变得清晰了。该实用程序似乎还可以弄清依赖项,这是一个很好的认识。这是最终结果:

  AuthorizerUri: !Join 
    - ''
    - - 'arn:aws:apigateway:'
      - !Ref 'AWS::Region'
      - ':lambda:path/2015-03-31/functions/'
      - !GetAtt [ BearerTokenAuthenticationLambdaFunction, Arn ]
      - '/invocations'

其他“陷阱”:

如果您还使用带有功能的AWS::ApiGateway::RestApi映射,请不要定义event资源(就像我在问题中所做的那样),否则将创建2个API。 event项会自动导致创建一个名为“ ApiGatewayRestApi”的API,该API是sls实用程序生成的资源名称。最后一个文件的最后一行更改为:

  RestApiId: !Ref ApiGatewayRestApi

我的ApiGateway:部分已删除。

信用转到这篇文章,这有助于使我更清楚地了解正在发生的事情:https://forum.serverless.com/t/fixed-how-do-i-get-reference-api-gateway-restapi-id-in-serverless-yml/3397/5

上一个答案:

我也找到了另一种方法。在找到正确的(更短的)方法之前,我一直在这样做。我能够拉出lambda名称并手动缝合所需的URI:

  AuthorizerUri: !Join
    - ''
    - - 'arn:aws:apigateway:'
      - !Ref 'AWS::Region'
      - ':lambda:path/2015-03-31/functions/arn:aws:lambda:'
      - !Ref 'AWS::Region'
      - ':'
      - !Ref 'AWS::AccountId'
      - ':function:'
      - '${self:functions.bearerTokenAuthentication.name}'
      - '/invocations'

我希望这可以帮助您节省一些时间来理解复杂的.yml文件。我也无法理解为什么难以理解。某人要做的就是(对我而言)是“ sls接受一个'serverless.yml'文件,以及可选的include文件(例如特定于云系统本身的声明,例如AWS Cloud Formation),并生成模板JSON文件目标云服务系统用来部署您的解决方案的工具。此外,您输入的名称可能会被弄乱,因此请检查模板。”我还感到惊讶的是,没有人创建过一个编辑器来使所有这些事情变得更容易-也许有一天我会研究一下自己。 ;)

答案 1 :(得分:0)

您始终可以转到已部署的lambda并查找aws:cloudformation:logical-id标记。这样,您将获得应该在serverless.yaml中使用的逻辑ID。 (也不喜欢这种幕后花招。)