Using AWS::Serverless::API, I am desiring to have route/model validation. Initially I had everything working in the SAM Template. The problem I was having is the AWS::Serverless::Api needed to attach models to it and with my AWS::Serverless::Function routes, I could only use one model per route.
So I decided to switch to using an open api file and going with the oneOf Schema property, but I would like to use it for only the routes that need model validation. It seems as though when I build my template, it ignores all the routes I had previously created and only pulls from my open api file instead of keeping everything I had in place and just overriding the one route.
So I have a few questions.
Can you use an open api file for only 1 route and then use the routes previously in the template file in addition to it.
Can you add multiple models to the AWS::Serverless::Function so that someone could use an object or an array of objects (with validation)
How can you make the open api file actually validate against the model schema because it currently isn't working.
everything has been trimmed down to make it easier to read
template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: >-
demo-api
Transform:
- AWS::Serverless-2016-10-31
Resources:
api:
Type: AWS::Serverless::Api
DependsOn:
- authorizer
- userPool
Properties:
StageName: !Ref stage
Domain:
DomainName: !If
- custom
- !Sub "${customStack}.${developmentDomain}"
- !FindInMap [domains, !Ref stage, domain]
CertificateArn: !FindInMap [certificates, !Ref stage, arn]
Route53:
HostedZoneId: !FindInMap [zones, !Ref stage, id]
Cors:
AllowMethods: "'*'"
AllowOrigin: "'*'"
AllowHeaders: "'*'"
Auth:
AddDefaultAuthorizerToCorsPreflight: false
DefaultAuthorizer: lambda
Authorizers:
cognito:
UserPoolArn: !GetAtt userPool.Arn
lambda:
FunctionArn: !GetAtt authorizer.Arn
FunctionPayloadType: REQUEST
Identity:
ReauthorizeEvery: 0
GatewayResponses:
DEFAULT_4XX:
ResponseParameters:
Headers:
Access-Control-Allow-Origin: "'*'"
BAD_REQUEST_BODY:
ResponseTemplates:
"application/json": '{ "errors": "$context.error.validationErrorString", "message" : "$context.error.messageString" }'
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: apidefinition.yaml
getContact:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/contacts/index.get
Environment:
Variables:
CONTACTS_TABLE: !If [custom, !Ref customContacts, !Ref contacts]
Description: Fetch Contact by id
Policies:
- DynamoDBCrudPolicy:
TableName: !If [custom, !Ref customContacts, !Ref contacts]
Events:
Api:
Type: Api
Properties:
RestApiId: !Ref api
Path: /contacts/{id}
Method: GET
getContacts:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/contacts/index.getMany
Environment:
Variables:
CONTACTS_TABLE: !If [custom, !Ref customContacts, !Ref contacts]
Description: Fetch Contacts
Policies:
- DynamoDBCrudPolicy:
TableName: !If [custom, !Ref customContacts, !Ref contacts]
Events:
Api:
Type: Api
Properties:
RestApiId: !Ref api
Path: /contacts
Method: GET
RequestParameters:
- method.request.querystring.client_id:
Required: true
Caching: true
postContact:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/contacts/index.post
Description: Create Contact
Environment:
Variables:
CONTACTS_TABLE: !If [custom, !Ref customContacts, !Ref contacts]
Policies:
- DynamoDBCrudPolicy:
TableName: !If [custom, !Ref customContacts, !Ref contacts]
Events:
Api:
Type: Api
Properties:
RestApiId: !Ref api
Path: /contacts
Method: POST
putContact:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/contacts/index.put
Environment:
Variables:
CONTACTS_TABLE: !If [custom, !Ref customContacts, !Ref contacts]
Description: Update Contact
Policies:
- DynamoDBCrudPolicy:
TableName: !If [custom, !Ref customContacts, !Ref contacts]
Events:
Api:
Type: Api
Properties:
RestApiId: !Ref api
Path: /contacts/{id}
Method: PUT
deleteContact:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/contacts/index.delete
Environment:
Variables:
CONTACTS_TABLE: !If [custom, !Ref customContacts, !Ref contacts]
Description: Destroy Contact
Policies:
- DynamoDBCrudPolicy:
TableName: !If [custom, !Ref customContacts, !Ref contacts]
Events:
Api:
Type: Api
Properties:
RestApiId: !Ref api
Path: /contacts/{id}
Method: DELETE
apidefinition.yaml
openapi: 3.0.1
info:
title:
Fn::Sub: "${AWS::StackName}"
description: testing support of oneOf schema definitions
version: 0.0.1
x-amazon-apigateway-request-validators:
# validateRequestParameters: true
body:
validateRequestBody: true
validateRequestParameters: false
paths:
/contacts:
post:
summary: Create one or many contacts.
requestBody:
content:
application/json:
schema:
oneOf:
- $ref: '#/components/schemas/Contact'
- $ref: '#/components/schemas/Contacts'
x-amazon-apigateway-integration:
type: "aws_proxy"
uri:
Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${postContact.Arn}/invocations"
httpMethod: "POST"
# x-amazon-apigateway-request-validators:
# body:
# validateRequestBody: true
# validateRequestParameters: false
components:
schemas:
Contact:
title: Contact Object
type: object
properties:
client_id:
type: number
title: Associated client ID
email:
type: string
title: Email
first_name:
type: string
title: First Name
create_time:
type: integer
title: Creation time (unix)
required:
- email
- client_id
Contacts:
title: Contacts Array
type: array
items:
type: object
required:
- email
- client_id
properties:
client_id:
type: number
title: Associated client ID
email:
type: string
title: Email
first_name:
type: string
title: First Name
title: State
create_time:
type: integer
title: Creation time (unix)
Related
The following is my template.yaml configuration. For some reason, even without the proper credentials, my HelloWorldFunction still returns a response.
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description:
Globals:
Api:
Cors:
AllowMethods: "'GET,POST,OPTIONS'"
AllowHeaders: "'content-type'"
AllowOrigin: "'http://127.0.0.1:8887'"
AllowCredentials: true
Resources:
HelloWorldApi:
Type: AWS::Serverless::Api
Properties:
StageName: dev
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: !GetAtt MyCognitoUserPool.Arn
MyCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: <pool name here>
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: false
MyCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
UserPoolId: !Ref MyCognitoUserPool
ClientName: <client name here>
GenerateSecret: false
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./
Handler: index.helloWorldHandler
Runtime: nodejs14.x
Events:
ApiEvent:
Type: Api
Properties:
Path: /hello
Method: get
RestApiId: !Ref HelloWorldApi
LabUIAuth:
Type: AWS::Serverless::Function
Properties:
Timeout: 100
CodeUri: ./
Handler: index.authHandler
Runtime: nodejs14.x
Events:
CreateUser:
Type: Api
Properties:
Path: /auth/create-user
Method: post
ConfirmUser:
Type: Api
Properties:
Path: /auth/confirm-user
Method: post
Login:
Type: Api
Properties:
Path: /auth/login
Method: post
Refresh:
Type: Api
Properties:
Path: /auth/refresh
Method: get
I followed the AWS documentation as best I could, but my endpoint remains open. I added the UserPool and UserPoolClient with correct references and names, but it doesn't look like anything is happening. What do I need to change to protect my endpoint?
I am creating an api gateway with cloudformation. Actually I am using a swagger.yaml which is uploaded in s3 as body. I want to keep the swagger.yaml parameterized, but I can't pass the arn of my lambda function to the file. I have tried some solutions but nothing seems to work for me. I hope anyone can help me here.
Api GW:
AWSTemplateFormatVersion: 2010-09-09
Description: API
Parameters:
application:
Type: String
Default: test
apiGatewayName:
Type: String
Default: hub
apiGatewayStageName:
Type: String
AllowedPattern: "[a-z0-9]+"
Default: dev
apiGatewayHTTPMethod:
Type: String
Default: GET
lambdaFunctionName:
Type: String
AllowedPattern: "[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+"
Default: crawler
############################ REST API ############################
Resources:
apiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
EndpointConfiguration:
Types:
- REGIONAL
BodyS3Location:
Bucket: !Sub ${application}-${apiGatewayStageName}-${AWS::AccountId}
Key: api_swagger.yml
Name: !Ref apiGatewayName
Tags:
-
Key: Project
Value: test
apiGatewayDeployment:
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId: !Ref apiGateway
StageName: !Ref apiGatewayStageName
Tags:
-
Key: Project
Value: test
############################ usagePlan ############################
usagePlan:
Type: 'AWS::ApiGateway::UsagePlan'
DependsOn:
apiKey
Properties:
ApiStages:
- ApiId: !Ref apiGateway
Stage: !Ref apiGatewayStageName
Description: test usage plan
Quota:
Limit: 1000
Period: MONTH
Throttle:
BurstLimit: 200
RateLimit: 100
UsagePlanName: ${application}-usageplan
Tags:
-
Key: Project
Value: test
usagePlanKey:
Type: 'AWS::ApiGateway::UsagePlanKey'
DependsOn:
usagePlan
Properties:
KeyId: !Ref apiKey
KeyType: API_KEY
UsagePlanId: !Ref usagePlan
Tags:
-
Key: Project
Value: test
############################ apiKey ############################
apiKey:
Type: AWS::ApiGateway::ApiKey
DependsOn:
- apiGatewayDeployment
- apiGateway
Properties:
CustomerId: String
Description: ApiKey for ${application}-api
Enabled: True
Name: ${application}-apikey
StageKeys:
- RestApiId: !Ref apiGateway
StageName: !Ref apiGatewayStageName
Tags:
-
Key: Project
Value: test
############################ apiGatewayRootMethod ############################
lambdaRootMethodInvoke:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt lambdaFunction.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/*/POST/
Tags:
-
Key: Project
Value: test
############################ applicationRuleBufferZoneMethod ############################
lambdaBufferZoneInvoke:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt lambdaFunction.Arn
Principal: apigateway.amazonaws.com
SourceArn: !Sub arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/*/${apiGatewayHTTPMethod}/application/rule/bufferZoneList
Tags:
-
Key: Project
Value: test
############################ Lambda Functions ############################
lambdaFunction:
Type: AWS::Lambda::Function
DependsOn:
- apiGateway
Properties:
Layers:
- arn:aws:lambda:eu-central-1:770693421928:layer:Klayers-python38-boto3:108
Code:
S3Bucket: !Sub ${application}-${apiGatewayStageName}-${AWS::AccountId}
S3Key: crawler.zip
Description: DynamoDB Crawler
FunctionName: !Ref lambdaFunctionName
Handler: crawler.lambda_handler
MemorySize: 128
Role: !GetAtt lambdaIAMRole.Arn
Runtime: python3.8
Tags:
-
Key: Project
Value: test
############################ Lambda IAM Role ############################
lambdaIAMRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- sts:AssumeRole
Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Policies:
- PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- dynamodb:DeleteItem
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:Query
- dynamodb:Scan
- dynamodb:UpdateItem
Effect: Allow
Resource: "*"
PolicyName: dynamoDBAccess
- PolicyDocument:
Version: 2012-10-17
Statement:
- Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Effect: Allow
Resource:
- !Sub arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${lambdaFunctionName}:*
PolicyName: cloudWatchLogs
Tags:
-
Key: Project
Value: test
lambdaLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${lambdaFunctionName}
RetentionInDays: 90
Tags:
-
Key: Project
Value: test
############################ Output ############################
Outputs:
apiGatewayInvokeURL:
Value: !Sub https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGatewayStageName}
BucketUrl:
Value: !Sub s3://${application}-${apiGatewayStageName}-${AWS::AccountId}/api_swagger.yml
swagger.yaml
openapi: 3.0.1
info:
title: Label Hub
termsOfService: http://swagger.io/terms/
contact:
email: apiteam#swagger.io
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
version: 1.0.0
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
servers:
- url: https://example.labelhub.de/v2
security:
- api_key: []
paths:
/application/rule/bufferZoneList:
get:
tags:
- application
summary: Returns list of buffer zones per field object for drift management
description: Returns a map of status codes to quantities
operationId: getApplicationRuleDrift
parameters:
- name: pName
in: query
required: true
schema:
type: string
- name: cCode
in: query
required: true
schema:
type: string
- name: cType
in: query
required: true
schema:
type: string
- name: nType
in: query
schema:
type: string
- name: timing
in: query
schema:
type: string
- name: rate
in: query
schema:
type: string
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/bufferZoneList'
x-amazon-apigateway-integration:
type: "aws_proxy"
httpMethod: "POST"
uri:
Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaFunction.Arn}/invocations"
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
contentHandling: "CONVERT_TO_TEXT"
components:
schemas:
crop:
type: object
properties:
id:
type: integer
format: int64
name:
type: string
cropTypeList:
type: array
items:
$ref: '#/components/schemas/crop'
bufferZone:
type: object
properties:
bufferZone:
type: integer
example: 5
unit:
type: string
example: m
areaType:
type: string
example: WATERBODY_VEGETATED
bufferZoneList:
type: array
items:
$ref: '#/components/schemas/bufferZone'
layout:
required:
- "name"
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
status:
type: "string"
description: "label layout status in the application"
enum:
- "available"
- "pending"
MODEL444ead:
type: "object"
properties:
file:
type: "string"
description: "file to upload"
format: "binary"
apiResponse:
type: "object"
properties:
code:
type: "integer"
format: "int32"
type:
type: "string"
message:
type: "string"
product:
type: "object"
properties:
id:
type: "integer"
format: "int64"
name:
type: "string"
MODEL6f7c6f:
type: "object"
additionalProperties:
type: "integer"
format: "int32"
securitySchemes:
api_key:
type: "apiKey"
name: "x-api-key"
in: "header"
Any solutions to pass the uri to my swagger file ?
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/create-reusable-transform-function-snippets-and-add-to-your-template-with-aws-include-transform.html
The documentation includes the follow note:
We don't currently support using shorthand notations for YAML snippets.
Instead of
uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:crawler/invocations"
use
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaFunction.Arn}/invocations
!Sub is shorthand notation so won't be supported
Edit:
Issue with swagger.yaml
x-amazon-apigateway-integration:
type: "aws_proxy"
httpMethod: "POST"
uri:
Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaFunction.Arn}/invocations"
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
contentHandling: "CONVERT_TO_TEXT"
The above is incorrect YAML due to wrong indentation of the Fn::Sub line. Change this to:
x-amazon-apigateway-integration:
type: "aws_proxy"
httpMethod: "POST"
uri:
Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaFunction.Arn}/invocations"
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
contentHandling: "CONVERT_TO_TEXT"
Issue with template.yaml
Resources:
apiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
EndpointConfiguration:
Types:
- REGIONAL
BodyS3Location:
Bucket: !Sub ${application}-${apiGatewayStageName}-${AWS::AccountId}
Key: api_swagger.yml
Name: !Ref apiGatewayName
Tags:
-
Key: Project
Value: test
should be
Resources:
apiGateway:
Type: AWS::ApiGateway::RestApi
Properties:
EndpointConfiguration:
Types:
- REGIONAL
Body:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: !Sub "s3://{application}-${apiGatewayStageName}-${AWS::AccountId}/api_swagger.yml"
Name: !Ref apiGatewayName
Tags:
-
Key: Project
Value: test
As the very first link of my answer mentions, the include transform is required (and was the basis of my original answer!).
After fixing both these issues, I got a circular dependency issue. Since this is outside the scope of your original question and I did not want to spend time debugging more issues, I did not make any more changes, but here are some resources to help you with that:
https://aws.amazon.com/blogs/infrastructure-and-automation/handling-circular-dependency-errors-in-aws-cloudformation/
Work around circular dependency in AWS CloudFormation
In this documentation:
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-controlling-access-to-apis-cognito-user-pool.html
there's this snippet of SAM template:
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: Prod
Cors: "'*'"
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: !GetAtt MyCognitoUserPool.Arn
MyFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./src
Handler: lambda.handler
Runtime: nodejs12.x
Events:
Root:
Type: Api
Properties:
RestApiId: !Ref MyApi
Path: /
Method: GET
MyCognitoUserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: !Ref CognitoUserPoolName
Policies:
PasswordPolicy:
MinimumLength: 8
UsernameAttributes:
- email
Schema:
- AttributeDataType: String
Name: email
Required: false
MyCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
UserPoolId: !Ref MyCognitoUserPool
ClientName: !Ref CognitoUserPoolClientName
GenerateSecret: false
Where are CognitoUserPoolName and CognitoUserPoolClientName defined?
This code is just a snippet from a CloudFormation template. CognitoUserPoolName and CognitoUserPoolClientName are strings which should be specified by you. One way of doing this is by passing them as parameters:
Parameters:
CognitoUserPoolName:
Type: String
Description: Cognito User Pool name
CognitoUserPoolClientName:
Type: String
Description: Cognito User Pool Client name
Here is a CloudFormation puzzle I think I cannot solve without your help. I'm trying to create a template for a REST API with CloudFormation (YAML). The API has a Lambda Proxy and has to have a MethodResponse as shown in the attached image.
This is my template so far which produces the following error when building the stack:
PostMethod: Value of property ResponseParameters must be an
object
ApiGatewayAccount:
Type: "AWS::ApiGateway::Account"
Properties:
CloudWatchRoleArn: "some role"
RestApi:
Type: "AWS::ApiGateway::RestApi"
Properties:
Description: "some rest api"
EndpointConfiguration:
Types:
- REGIONAL
Name: RestApi
SomeResource:
Type: "AWS::ApiGateway::Resource"
Properties:
ParentId:
Fn::GetAtt:
- "RestApi"
- "RootResourceId"
PathPart: part
RestApiId:
Ref: "RestApi"
SomeSubResource:
Type: "AWS::ApiGateway::Resource"
Properties:
ParentId:
Ref: "SomeResource"
PathPart: count
RestApiId:
Ref: "RestApi"
SomeResponseModel:
Type: "AWS::ApiGateway::Model"
Properties:
ContentType: "text/html"
Description: "Empty text/html response."
Name: someresponse
RestApiId:
!Ref RestApi
Schema: {}
PostMethod:
Type: "AWS::ApiGateway::Method"
Properties:
HttpMethod: POST
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri:
Fn::Join:
- ""
- - "arn:aws:apigateway:"
- "some-region"
- ":lambda:path/2015-03-31/functions/"
- "some-arn-of-lambda-function"
MethodResponses:
-
ResponseModels:
Key: "application/x-www.form-urlencoded"
Value:
!Ref SomeResponse
ResponseParameters:
- method.response.header.Content-Length: true
- method.response.header.Content-Type: true
- method.response.header.Connection: true
StatusCode: 200
OperationName: SomeName
ResourceId:
!Ref "SomeSubResource"
RestApiId:
!Ref "RestApi"
According to the documentation, it would seem that this should not be a list of key-value pairs, but instead just an object, where each entry is just another key/value.
I expect the following would work:
ResponseParameters:
method.response.header.Content-Length: true
method.response.header.Content-Type: true
method.response.header.Connection: true
We are currently using API Keys to secure access to our API Gateway. However, we are moving to an IAM model with access/secret key. I understand that swagger does not allow us to do this (we currently have api_key set in swagger to enable API Key authentication).
I have created the policy needed for the various operations as:
SvcAccountPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: !Sub 'iam-${EnvTag}'
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- 'execute-api:Invoke'
Resource:
- !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SomeApi}/*/GET/*'
- !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SomeApi}/*/POST/*'
- !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SomeApi}/*/PUT/*'
- !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SomeApi}/*/DELETE/*'
Users:
- !Ref userSvcAcct
My lambda function is shown below. I am still new to cloud formation, and would love some help on what I can do to add a lambda authorizer to this ( I believe it will be in the Events->ApiPost/Get etc section), that would allow me to use secret/access key.
FtpUserMgmtLambda:
Type: AWS::Serverless::Function
Properties:
Description: Lambda handler function for FTP user management
Handler: 'handler.UserManagementHandler::handleRequest'
Runtime: java8
MemorySize: 512
Timeout: 300
FunctionName: !Ref LambdaFunctionName
Role: !GetAtt UserMgmtLambdaRole.Arn
CodeUri:
Bucket: !Ref LambdaCodeS3Bucket
Key: !Ref LambdaCodeFileName
VpcConfig:
SomeConfig stuff here
Environment:
Variables:
dbPort: !Ref UserStoreDbPort
dbUser: !Ref UserStoreDbUserId
dbName: !Ref UserStoreDbName
environment: !Ref EnvTag
basepath: 'somepath'
Events:
ApiPost:
Type: Api
Properties:
RestApiId: !Ref SomeApi
Path: /path
Method: POST
Auth: <<Dont know what to do here! HELP>>
ApiGet:
Type: Api
Properties:
RestApiId: !Ref SomeApi
Path: /path
Method: GET
Auth: *<<Dont know what to do here! HELP>>*
Tags:
Name: !Ref LambdaFunctionName
function: lambda function that manages ftp users
Fixed this through Swagger. Example code as under:
---
swagger: "2.0"
info:
version: "2017-10-17T17:47:44Z"
title: "User-Mgt-API"
basePath: "/${environment}"
schemes:
- "https"
paths:
/ftpuser:
post:
x-amazon-apigateway-auth:
type: aws_iam
produces:
- "application/json"
responses:
200:
description: "When create user request successful"
schema:
$ref: "#/definitions/Empty"
400:
description: "When API vallidation error happens"
schema:
$ref: "#/definitions/Empty"
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FtpUserMgmtLambda.Arn}/invocations
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
definitions:
Empty:
type: "object"
title: "Empty Schema"
Then in the cloudformation, added the following to the serverless API definition to process the swagger file. Of course,
FtpUserMgmtApi:
Type: AWS::Serverless::Api
Properties:
Name: !Ref ApiName
StageName: !Ref ApiDeploymentStageName
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: !Sub s3://${swaggerS3Location}
Hope this helps. There is also an example on the web to use x-amazon-apigateway-any-method using which I derived the above. That link is here.