AWS CloudFormation堆栈:具有嵌套路径的API网关资源?

时间:2020-05-14 03:46:20

标签: amazon-web-services amazon-cloudformation aws-api-gateway

我手动构建了一个API网关资源,如下所示:

GET
  /assets/{items} - (points to S3 bucket)
  /{proxy+} - points to Lambda function

enter image description here

我想在Cloudformation YAML模板中模拟此设置,但不确定如何执行。这是我正在使用的当前模板(为简便起见,部分减少了它):

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  apiGatewayStageName:
    Type: String
    AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
    Default: call
  lambdaFunctionName:
    Type: String
    AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
    Default: my-function
  s3BucketName:
    Type: String
    AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
Resources:
  apiGateway:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: my-api
      Description: My API
    Metadata:
      ...
  apiGatewayRootMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      HttpMethod: POST
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub 
          - >-
            arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt lambdaFunction.Arn
      ResourceId: !GetAtt apiGateway.RootResourceId
      RestApiId: !Ref apiGateway
    Metadata:
      ...
  apiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - apiGatewayRootMethod
      - apiGatewayGETMethod
    Properties:
      RestApiId: !Ref apiGateway
      StageName: !Ref apiGatewayStageName
    Metadata:
      ...
  lambdaFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      ...
  lambdaApiGatewayInvoke:
    ...
  lambdaIAMRole:
    ...
  lambdaLogGroup:
    ...
  apiGatewayGETMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub 
          - >-
            arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt lambdaFunction.Arn
      ResourceId: !GetAtt apiGateway.RootResourceId
      RestApiId: !Ref apiGateway
    Metadata:
      'AWS::CloudFormation::Designer':
        id: 1a329c4d-9d18-499e-b852-0e361af324f4
  s3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Ref s3BucketName
    Metadata:
      ...
Outputs:
  apiGatewayInvokeURL:
    Value: !Sub >-
      https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGatewayStageName}
  lambdaArn:
    Value: !GetAtt lambdaFunction.Arn

这是许多调整的结果,除了浏览官方文档外,我没有任何CloudFormation知识。创建该模板后面的堆栈时,其API网关资源如下所示: enter image description here

POST操作是不必要的,只有反复试验才可以执行。 GET资源是唯一重要的资源,因为Lambda函数返回的应用程序尚未执行任何发布请求。

必须从堆栈的这一部分创建一个GET:

apiGatewayGETMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub 
          - >-
            arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt lambdaFunction.Arn
      ResourceId: !GetAtt apiGateway.RootResourceId
      RestApiId: !Ref apiGateway

必须做些什么才能使GET资源具有指向S3存储桶的嵌套/assets/{items}路径和指向Lambda的{proxy+}路径?我是否需要为apiGatewayAssetsapiGatewayLambdaProxy之类的路径指定单独的同级资源,然后以某种方式将它们连接到apiGatewayGETMethod

2020-05-17更新

让我震惊的当前部分是该资源:

apiGatewayAssetsItemsResourceMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      ResourceId: !Ref apiGatewayAssetsItemsResource
      RestApiId: !Ref apiGateway
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        Type: AWS
        Credentials: arn:aws:iam::XXXXXX:role/AnExistingRole
        IntegrationHttpMethod: GET
        PassthroughBehavior: WHEN_NO_MATCH
        RequestParameters:
          integration.request.path.item: 'method.request.path.item'
          method.request.path.item: true
        Uri: !Sub >-
          arn:aws:apigateway:${AWS::Region}:s3:path/${s3BucketName}/{item}

这会导致CloudFormation堆栈创建错误,其状态原因为Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression parameter specified: method.request.path.item] (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: XXXXXX)

但是,如果我尝试使用完全相同的资源(减去RequestParameters条目)来创建它,则会成功创建它。尽管在控制台中查看该API Gateway GET方法时,它缺少“集成请求”框中的Paths: item行。我当前正在使用的完整模板:

AWSTemplateFormatVersion: 2010-09-09
Parameters:
  apiGatewayStageName:
    Type: String
    AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
    Default: call
  lambdaFunctionName:
    Type: String
    AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
    Default: my-function
  s3BucketName:
    Type: String
    AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
Resources:
  apiGateway:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: my-api
      Description: My API
  apiGatewayDeployment:
    Type: 'AWS::ApiGateway::Deployment'
    DependsOn:
      - apiGatewayGETMethod
    Properties:
      RestApiId: !Ref apiGateway
      StageName: !Ref apiGatewayStageName
  lambdaFunction:
    ...
  lambdaApiGatewayInvoke:
    ...
  lambdaIAMRole:
    ...
  lambdaLogGroup:
    ...
  apiGatewayGETMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub 
          - >-
            arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt lambdaFunction.Arn
      ResourceId: !GetAtt apiGateway.RootResourceId
      RestApiId: !Ref apiGateway
  s3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Ref s3BucketName
  BucketPolicy:
    ...
  apiGatewayAssetsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref apiGateway
      ParentId: !GetAtt 
        - apiGateway
        - RootResourceId
      PathPart: assets
  apiGatewayAssetsItemsResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref apiGateway
      PathPart: '{item}'
      ParentId: !Ref apiGatewayAssetsResource
  apiGatewayAssetsItemsResourceMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      ResourceId: !Ref apiGatewayAssetsItemsResource
      RestApiId: !Ref apiGateway
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        Type: AWS
        Credentials: arn:aws:iam::XXXXXX:role/AnExistingRole
        IntegrationHttpMethod: GET
        PassthroughBehavior: WHEN_NO_MATCH
        Uri: !Sub >-
          arn:aws:apigateway:${AWS::Region}:s3:path/${s3BucketName}/{item}
  apiGatewayLambdaResource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      RestApiId: !Ref apiGateway
      PathPart: '{proxy+}'
      ParentId: !GetAtt 
        - apiGateway
        - RootResourceId
  apiGatewayLambdaResourceMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      AuthorizationType: NONE
      RestApiId: !Ref apiGateway
      ResourceId: !Ref apiGatewayLambdaResource
      HttpMethod: ANY
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: GET
        Uri: !Sub 
          - >-
            arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt lambdaFunction.Arn
Outputs:
  apiGatewayInvokeURL:
    Value: !Sub >-
      https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGatewayStageName}
  lambdaArn:
    Value: !GetAtt lambdaFunction.Arn

1 个答案:

答案 0 :(得分:2)

因此,您需要执行以下操作:

  • 使用PathPart为assets创建一个AWS :: ApiGateway :: Resource,这将使用Rest API中RootResourceId attr的ParentId
  • 使用PathPart为{item}创建一个AWS :: ApiGateway :: Resource,它将使用上面资产Resource的ParentId。
  • 为上述资源的ResourceId创建一个AWS :: ApiGateway :: Method。这将使用HTTP_PROXY并将Uri设置为S3存储桶路径,并确保在路径中包含{{ item }}变量。
  • 使用PathPart为{proxy+}创建一个AWS :: ApiGateway :: Resource,这将使用Rest API中RootResourceId attr的ParentId
  • 为上述资源的ResourceId创建一个AWS :: ApiGateway :: Method。这将使用AWS_PROXY并将uri设置为引用Lambda函数。

希望这会有所帮助