I've managed to deploy an AWS HTTP API with differents routes and lambda integrations via yaml SAM template with OpenAPI definition but I'm stuck with adding custom lambda authorizer to my routes. When I deploy the stack I got some timeout for API creation :
ROLLBACK_IN_PROGRESS AWS::CloudFormation::Stack CloudArYer The following resource(s) failed to
create: [Api]. . Rollback requested by
user.
CREATE_FAILED AWS::ApiGatewayV2::Api Api Internal server error (Service:
AmazonApiGatewayV2; Status Code: 500;
Error Code: InternalServerException;
Request ID: 18242cfd-
cc94-4909-a26a-6631806f94e7; Proxy:
null)
here is the main part of my template with API definition :
...
AuthorizerLambdaTemplate:
Type: AWS::Serverless::Application
Properties:
Location: ./templates/Authorizer-template-function.yaml
Parameters:
ProjectName: !Sub "${ProjectName}"
ProjectApiKey: !Sub "${ProjectApiKey}"
Api:
Type: AWS::Serverless::HttpApi
Properties:
StageName: CloudArYerAPI
CorsConfiguration:
AllowCredentials: true
AllowHeaders: "*"
AllowMethods:
- GET
- POST
- PUT
AllowOrigins:
- https://*
DefinitionBody:
openapi: 3.0.1
info:
title: CoudArYer-API
description: HTTP API for connected chicken coop (Cloud Ar Yer)
version: 2020-09-26
paths:
/config/{device}:
get:
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/GETLambda"
/event/{type}:
post:
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/POSTLambda"
/image/{origin}/{device}:
put:
x-amazon-apigateway-integration:
$ref: "#/components/x-amazon-apigateway-integrations/PUTLambda"
security:
- CloudArYer-Authorizer: []
components:
securitySchemes:
CloudArYer-Authorizer:
type: apiKey
name: authorization
in: header
x-amazon-apigateway-authtype: custom
x-amazon-apigateway-authorizer:
type: request
identitySource: $request.header.authorization
authorizerUri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${AuthorizerLambdaTemplate.Outputs.FunctionArn}/invocations
authorizerCredentials: !GetAtt ApiGatewayAuthorizerRole.Arn
authorizerPayloadFormatVersion: "2.0"
authorizerResultTtlInSeconds: 60
enableSimpleResponses: true
x-amazon-apigateway-integrations:
PUTLambda:
payloadFormatVersion: "2.0"
type: "aws_proxy"
httpMethod: "POST"
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${PUTImageLambdaTemplate.Outputs.FunctionArn}/invocations
connectionType: "INTERNET"
GETLambda:
payloadFormatVersion: "2.0"
type: "aws_proxy"
httpMethod: "POST"
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GETConfigLambdaTemplate.Outputs.FunctionArn}/invocations
connectionType: "INTERNET"
POSTLambda:
payloadFormatVersion: "2.0"
type: "aws_proxy"
httpMethod: "POST"
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${POSTEventLambdaTemplate.Outputs.FunctionArn}/invocations
connectionType: "INTERNET"
ApiGatewayAuthorizerRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "apigateway.amazonaws.com"
Action:
- sts:AssumeRole
Policies:
- PolicyName: "InvokeAuthorizerFunction"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- lambda:InvokeAsync
- lambda:InvokeFunction
Resource: !GetAtt AuthorizerLambdaTemplate.Outputs.FunctionArn
...
My authorizer lambda is define in a nested stack (AuthorizerLambdaTemplate)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
AuthorizerFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "${ProjectName}-Authorizer-Lambda"
CodeUri: ../src/authorizer
Handler: handler.authorizer
Runtime: nodejs10.x
Role: !Sub "${CustomAuthorizerFunctionRole.Arn}"
Environment:
Variables:
ProjectApiKey: !Sub "${ProjectApiKey}"
CustomAuthorizerFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
Parameters:
ProjectName:
Type: String
ProjectApiKey:
Type: String
Outputs:
FunctionArn:
Description: Arn Authorizer function
Value: !GetAtt AuthorizerFunction.Arn
and the code for lambda is defined as follow in an extenal directory
exports.authorizer = async(event) => {
let response = {
"isAuthorized": false,
"context": {
"stringKey": "test"
}
};
if (event.headers.authorization === process.env.ProjectApiKey) {
response = {
"isAuthorized": true,
"context": {
"stringKey": "test"
}
};
}
return response;
};
I do not understand why the deployment is blocked on the API creation ... and failed with an InternalServerException. Where am I wrong on the stack definition. I've browsed many sites, snippets... but less info for new HTTP API and for instance no clue to fix my issue.
Thanks for your potential help ! :-)