尝试通过Cloudformation创建AWS API Gateway时出现错误

16

我正在尝试创建一个简单的Cloudformation,用于在S3上托管网站,并带有API Gateway后端。据我所知,一切都很顺利,但在尝试创建API Gateway时出现了错误:

 

导入期间发现错误:无法将集成放置在'/ {proxy +}'路径资源的“ANY”上:集成的AWS ARN必须包含路径或操作(服务:AmazonApiGateway;状态代码:400;错误代码:BadRequestException;请求ID:b28983d9-687c-11e8-8692-27df1db97456)

网关应该只是一个单独的路由,将所有内容发送到单个lambda。应该非常简单。

---
AWSTemplateFormatVersion: '2010-09-09'
Description: Website S3 Hosted, API Gateway Backend
Parameters:
  DomainName:
    Type: String
    Description: The DNS name of an Amazon Route 53 hosted zone e.g. server.com
    AllowedPattern: '(?!-)[a-zA-Z0-9-.]{1,63}(?<!-)'
    ConstraintDescription: must be a valid DNS zone name.
Mappings:
  S3RegionMap:
    us-east-1:
      S3HostedZoneId: Z3AQBSTGFYJSTF
      S3WebsiteEndpoint: s3-website-us-east-1.amazonaws.com
    us-west-1:
      S3HostedZoneId: Z2F56UZL2M1ACD
      S3WebsiteEndpoint: s3-website-us-west-1.amazonaws.com
    us-west-2:
      S3HostedZoneId: Z3BJ6K6RIION7M
      S3WebsiteEndpoint: s3-website-us-west-2.amazonaws.com
    eu-west-1:
      S3HostedZoneId: Z1BKCTXD74EZPE
      S3WebsiteEndpoint: s3-website-eu-west-1.amazonaws.com
    ap-southeast-1:
      S3HostedZoneId: Z3O0J2DXBE1FTB
      S3WebsiteEndpoint: s3-website-ap-southeast-1.amazonaws.com
    ap-southeast-2:
      S3HostedZoneId: Z1WCIGYICN2BYD
      S3WebsiteEndpoint: s3-website-ap-southeast-2.amazonaws.com
    ap-northeast-1:
      S3HostedZoneId: Z2M4EHUR26P7ZW
      S3WebsiteEndpoint: s3-website-ap-northeast-1.amazonaws.com
    sa-east-1:
      S3HostedZoneId: Z31GFT0UA1I2HV
      S3WebsiteEndpoint: s3-website-sa-east-1.amazonaws.com
Resources:
  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: lambda.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: '/'
      Policies:
      - PolicyName: execution
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action:
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:PutLogEvents
            Resource: '*'
          - Effect: Allow
            Action:
            - s3:GetObject
            - s3:PutObject
            - s3:ListBucket
            Resource: '*'
          - Effect: Allow
            Action:
            - ec2:DescribeNetworkInterfaces
            - ec2:CreateNetworkInterface
            - ec2:DeleteNetworkInterface
            Resource: '*'
          - Effect: Allow
            Action:
            - cognito-idp:AdminGetUser
            - cognito-idp:AdminUpdateUserAttributes
            Resource: '*'
  APIGatewayExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: apigateway.amazonaws.com
          Action:
          - sts:AssumeRole
      Path: '/'
      Policies:
      - PolicyName: execution
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action:
            - logs:CreateLogGroup
            - logs:CreateLogStream
            - logs:PutLogEvents
            Resource: '*'
          - Effect: Allow
            Action:
            - lambda:InvokeFunction
            Resource: '*'
  LambdaFunctionAPI:
    Type: AWS::Lambda::Function
    Properties:
      Code:
        ZipFile: exports.handler = function (event, context, callback) { callback(null, event); };
      Handler: index.handler
      MemorySize: 128
      Role: !GetAtt LambdaExecutionRole.Arn
      Runtime: nodejs4.3
      Timeout: 30
  APIGateway:
    Type: AWS::ApiGateway::RestApi
    Properties:              
      FailOnWarnings: true
      Name: !Join ['-', !Split ['.', !Join ['.', ['api', !Ref DomainName]]]]
      Body:
        swagger: '2.0'
        info:
          version: 0.0.1
          title: !Join [' ', ['API route for', !Ref DomainName]]
        basePath: '/api'
        paths:
          '/{proxy+}':
            options:
              summary: CORS support
              description: |
                Enable CORS by returning correct headers
              consumes:
                - application/json
              produces:
                - application/json
              tags:
                - CORS
              x-amazon-apigateway-integration:
                type: mock
                requestTemplates:
                  application/json: |
                    {
                      "statusCode" : 200
                    }
                responses:
                  "default":
                    statusCode: "200"
                    responseParameters:
                      method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
                      method.response.header.Access-Control-Allow-Methods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
                      method.response.header.Access-Control-Allow-Origin: "'*'"
                    responseTemplates:
                      application/json: |
                        {}
              responses:
                '200':
                  description: Default response for CORS method
                  headers:
                    Access-Control-Allow-Headers:
                      type: "string"
                    Access-Control-Allow-Methods:
                      type: "string"
                    Access-Control-Allow-Origin:
                      type: "string"
            x-amazon-apigateway-any-method:
              produces:
              - "application/json"
              responses:
                '200':
                  description: "200 response"
                  schema:
                    $ref: "#/definitions/Empty"
              x-swagger-router-controller: main
              x-amazon-apigateway-integration:
                type: aws_proxy
                httpMethod: POST
                uri: !GetAtt LambdaFunctionAPI.Arn
                credentials: !Ref APIGatewayExecutionRole

        definitions:
          Empty:
            type: "object"
            title: "Empty Schema"
  APIDeployment:
    Type: AWS::ApiGateway::Deployment
    Properties:
      RestApiId: !Ref APIGateway
      Description: Deploy for live
      StageName: Live
  WebsiteBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName:
        Ref: DomainName
      AccessControl: PublicRead
      WebsiteConfiguration:
        IndexDocument: index.html
        ErrorDocument: 404.html
      Tags:
      - Key: Name
        Value: !Join ['_', ['WebsiteBucket', !Ref 'AWS::StackName']]
      - Key: Domain
        Value: !Ref DomainName
    DeletionPolicy: Retain
  WWWBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Join ['.', ['www', !Ref DomainName]]
      AccessControl: PublicRead
      WebsiteConfiguration:
        RedirectAllRequestsTo:
          HostName: !Ref WebsiteBucket
      Tags:
      - Key: Name
        Value: !Join ['_', ['WWWBucket', !Ref 'AWS::StackName']]
      - Key: Domain
        Value: !Ref DomainName
  WebsiteBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref WebsiteBucket
      PolicyDocument:
        Statement:
        - Action:
          - s3:GetObject
          Effect: Allow
          Resource: !Join ['', ['arn:aws:s3:::', !Ref WebsiteBucket, '/*']]
          Principal: '*'
  WWWBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref WWWBucket
      PolicyDocument:
        Statement:
        - Action:
          - s3:GetObject
          Effect: Allow
          Resource: !Join ['', ['arn:aws:s3:::', !Ref WWWBucket, '/*']]
          Principal: '*'
  DNS:
    Type: AWS::Route53::HostedZone
    Properties:
      HostedZoneConfig:
        Comment: !Join [' ', ['Hosted zone for', !Ref DomainName]]
      Name: !Ref DomainName
      HostedZoneTags:
      - Key: Application
        Value: Blog
  DNSRecord:
    Type: AWS::Route53::RecordSetGroup
    DependsOn: DNS
    Properties:
      HostedZoneName:
        Fn::Join: ['', [!Ref DomainName, '.']]
      Comment: Zone records.
      RecordSets:
      - Name: !Ref DomainName
        Type: A
        AliasTarget:
          HostedZoneId: !FindInMap [S3RegionMap, !Ref 'AWS::Region', S3HostedZoneId]
          DNSName: !FindInMap [S3RegionMap, !Ref 'AWS::Region', S3WebsiteEndpoint]
      - Name: !Join ['.', ['www', !Ref DomainName]]
        Type: A
        AliasTarget:
          HostedZoneId: !FindInMap [S3RegionMap, !Ref 'AWS::Region', S3HostedZoneId]
          DNSName: !FindInMap [S3RegionMap, !Ref 'AWS::Region', S3WebsiteEndpoint]
Outputs:
  S3WebsiteURL:
    Value: !GetAtt WebsiteBucket.WebsiteURL
    Description: URL for website hosted on S3
2个回答

29

连接Lambda所需使用的URI不是Lambda的Arn,而是API网关调用URI。此外,您需要将凭证行从ref更改为执行角色的Arn

这里是更改后部分的简短摘录:

x-amazon-apigateway-integration:
  type: aws_proxy
  httpMethod: POST
  uri: !Sub  "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunctionAPI.Arn}/invocations"
  credentials: !GetAtt APIGatewayExecutionRole.Arn

2
一个Lambda的API网关调用URI从哪里获取? - Vihung
1
您可以使用Jens Walter提供的模板构建它: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunctionAPI.Arn}/invocations" - ChKl
这个ARN中的2015-03-31代表什么意思? - Adwait Mathkari
2015-03-31只是一个必须存在的常量。我通过这个进行了验证:"arn:aws:apigateway:${var.AWS_REGION}:lambda:path/2015-03-31/functions/${var.LAMBDA_FN_ARN}/invocations" - Adwait Mathkari

2

如果您正在使用terraform并遇到此错误,以下方法可解决问题(请注意,uri参数不应该是lambda arn,而是不同的调用arn):

resource "aws_api_gateway_integration" "ordersIntegration" {
    rest_api_id             = aws_api_gateway_rest_api.msdApi.id
    resource_id             = aws_api_gateway_resource.orders.id
    http_method             = aws_api_gateway_method.ordersget.http_method
    integration_http_method = "POST"
    type                    = "AWS_PROXY"
    uri                     = "arn:aws:apigateway:${var.AWS_REGION}:lambda:path/2015-03-31/functions/${var.LAMBDA_FN_ARN}/invocations"
}

LAMBDA_FN_ARN是一个简单的字符串,格式为"arn:aws:lambda:${var.AWS_REGION}:${var.AWS_ACCOUNT_ID}:function:${var.LAMBDA_NAME}"。同时,2015-03-31是一个常量值,需要被使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接