Getting an error trying to create an AWS API Gateway via Cloudformation
The URI you should use to connect to the Lambda is not the Arn
of the Lambda, but an API gateway invocation URI. Additionally, you need to change the credential line from a ref
to the Arn
of the execution role.
Here a short excerpt of the changed section:
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
Comments
-
Justin808 almost 2 years
I'm trying to make a simple Cloudformation to create a website hosted on S3 with an API Gateway backend. Everything seems OK as far as I can tell but I get errors when trying to create the API Gateway:
Errors found during import: Unable to put integration on 'ANY' for resource at path '/{proxy+}': AWS ARN for integration must contain path or action (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: b28983d9-687c-11e8-8692-27df1db97456)
The gateway should just be a single route that sends everything to a single lambda. Should be super simple.
--- 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