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
Related
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)
I working into decouple a big template with lambdas that use apigateway AWS. I resolve multiple errors about nested stack process, but currently error its not clear. Could you check whats its the problem into definitions?
Main stack show general error from api substack create, but api-substack show next error:
Template error: instance of Fn::Sub references invalid resource attribute CreateCatalogFunctionDev.Arn
Next show a code of templates:
Main Template
SubStackAPIDev:
Type: 'AWS::CloudFormation::Stack'
Properties:
TemplateURL: https://s3.awsroute.com/substack-api.yaml
TimeoutInMinutes: 5
Parameters:
CreateCatalogFunctionDev: !GetAtt CreateCatalogFunctionDev.Outputs.CreateCatalogFunctionDev
SubStackCreateCatalogDev:
Type: 'AWS::CloudFormation::Stack'
Properties:
TemplateURL: https://s3.awsroute.com/substack-create-catalog.yaml
TimeoutInMinutes: 5
Parameters:
APIDev: !GetAtt SubStackAPIDev.Outputs.APIGateway
SubStackCreateCatalogDev
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
SAM template for create catalog
Parameters:
SecretsManagerName:
Type: String
Description: "Secrets Manager Name"
SnsTopicArn:
Type: String
Default: arn:aws:sns:us-west-2:XXXXXX:SNS-errorNotification
Description: "Sns topic error handler email notification"
APIDev:
Type: AWS::Serverless::Api
Resources:
LayerDev:
Type: 'AWS::Serverless::LayerVersion'
Properties:
ContentUri: ../../layer
CompatibleRuntimes:
- python3.6
- python3.7
- python3.8
RetentionPolicy: Delete
CreateCatalogFunctionDev:
Type: AWS::Serverless::Function
Properties:
Description: Recieve api request and and process data.
CodeUri: ../../src/catalog/create_catalog/
Handler: create_catalog.lambda_handler
Runtime: python3.8
FunctionName: CreateCatalogFunctionDev
Role: arn:aws:iam::XXXXXXXX:role/lambda-essential-role
Timeout: 480
Environment:
Variables:
CREATE_CATALOG_SECRET_NAME: !Sub '${SecretsManagerName}'
SNS_ARN: !Sub '${SnsTopicArn}'
Layers:
- arn:aws:lambda:us-west-2:XXXXXXX:layer:requests:1
- arn:aws:lambda:us-west-2:XXXXXXX:layer:requests-oauthlib:1
- !Ref LayerDev
Events:
CreateCatalogApiEvent:
Type: Api
Properties:
Path: /api-channel/products/catalog
Method: POST
RestApiId: !Ref APIDev
SubStack API
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
sub_channels_appi
SAM template for API
Parameters:
SwaggerFile:
Type: String
# TODO dejar URL de S3 de gitla-cicd
Default: "s3://cf-templates-1hurrmgzyzoz3-ap-northeast-1/swagger_dev.yaml"
Description: "This swagger file Amazon S3 path"
SecretsManagerName:
Type: String
Default: "/channels/Dev"
Description: "Secrets Manager Name"
StageName:
Type: String
Default: "${stageVariables.alias}"
Description: "This is the alias to the swagger file"
UsaSupplyApiUrlDev:
Type: String
Default: "https://thecornercloud.com/developers/index.php/"
Description: "Corner Cloud Staging"
SnsTopicArn:
Type: String
Default: arn:aws:sns:us-west-2:000365055762:channels-errorNotification
Description: "Sns topic error handler email notification"
CreateCatalogFunctionDev:
Type: String
Resources:
#######################################
# Serverless LayerVersion
#######################################
LayerDev:
Type: 'AWS::Serverless::LayerVersion'
Properties:
ContentUri: ../../layer
CompatibleRuntimes:
- python3.6
- python3.7
- python3.8
RetentionPolicy: Delete
#######################################
# Serverless API
#######################################
APIDev:
Type: AWS::Serverless::Api
Properties:
Auth:
ApiKeyRequired: true
StageName: dev
EndpointConfiguration: REGIONAL
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: !Ref SwaggerFile
Variables:
alias: dev
#######################################
# ApiGateway ApiKey
#######################################
APIKeyDev:
Type: AWS::ApiGateway::ApiKey
Properties:
Name: "APIKeyDev"
Description: "API Key Dev"
Enabled: true
GenerateDistinctId: false
StageKeys:
- RestApiId: !Ref APIDev
StageName: !Ref APIDev.Stage
#######################################
# ApiGateway UsagePlan
#######################################
APIUsagePlanDev:
Type: AWS::ApiGateway::UsagePlan
DependsOn: APIDev
Properties:
ApiStages:
- ApiId: !Ref APIDev
Stage: !Ref APIDev.Stage
Quota:
Limit: 5000
Period: MONTH
Throttle:
BurstLimit: 200
RateLimit: 100
UsagePlanName: APIUsagePlanDev
#######################################
# ApiGateway UsagePlanKey
#######################################
APIUsagePlanKeyDev:
Type: AWS::ApiGateway::UsagePlanKey
Properties:
KeyId: !Ref APIKeyDev
KeyType: API_KEY
UsagePlanId: !Ref APIUsagePlanDev
#######################################
# ApiGateway Deployment
#######################################
DeploymentApiIdDev:
Type: AWS::ApiGateway::Deployment
Properties:
RestApiId: !Ref APIDev
Outputs:
APIGateway:
Description: "API Gateway Reference"
Value: !Ref APIDev
Export:
Name: !Join [":", [!Ref "AWS::StackName", "APIDev"]]
And finally the swagger file (honestly, I didn't define the api with this method and think that I want remove swagger if is possible).
swagger-dev
swagger: "2.0"
info:
version: "1.0.0"
title: "APIDev"
tags:
- name: "Channels"
description: "Manage Channels process."
schemes:
- "https"
x-amazon-apigateway-api-key-source: "HEADER"
securityDefinitions:
APIKey:
type: apiKey
name: X-Api-Key
in: header
paths:
/channels/products/catalog:
post:
tags:
- "Channels"
summary: " products catalog post."
operationId: "ProductsCatalogPostDev"
produces:
- "application/json"
responses:
201:
description: "Successful Operation"
400:
description: "Invalid parameters"
401:
description: "Unauthorized"
405:
description: "Validation exception"
security:
- APIKey: []
x-amazon-apigateway-integration:
uri:
Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${CreateCatalogFunctionDev.Arn}/invocations
responses:
default:
statusCode: "200"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
Your CreateCatalogFunctionDev is in a different sub-stack then APIDev. You can't reference resources directly across stacks. You either have to export/import their outputs, or pass the references as input parameters.
I'm getting the error below from my cloud formation template. It happens when using json and pure yaml.
error
Resource handler returned message: "Invalid request provided: JSON not well-formed. at Line: 13, Column: 10 (Service: Ssm, Status Code: 400,
template with json
AWSTemplateFormatVersion: "2010-09-09"
Description: "AWS CloudFormation Template for Response Plans"
Parameters:
Environment:
Type: String
Domain:
Type: String
Team:
Type: String
NotificationARN:
Type: AWS::SSM::Parameter::Value<String>
Default: /sandbox06/Topics/PolicyData/arn
Resources:
UpdateAliasResponsePlan:
Type: AWS::SSMIncidents::ResponsePlan
Properties:
Actions:
- SsmAutomation:
RoleArn: !Ref Role
DocumentName: UpdateAliasDocument
# ActionType: UpdateAlias
DisplayName: "UpdateLambdaAlias"
# Engagements:
# Engagements
IncidentTemplate:
Impact: 3
NotificationTargets:
- SnsTopicArn:
Ref: NotificationARN
Summary: "String"
Title: "String"
Name: "UpdateLambdaAlias"
Tags:
- Key: "Team"
Value: !Ref Team
- Key: "Domain"
Value: !Ref Domain
- Key: "Environment"
Value: !Ref Environment
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content: |
{
"schemaVersion": "2.2",
"parameters": {
"Environment": { "type": "string"},
"Domain": { "type": "string"},
"Team": { "type": "string"},
"NotificationARN": { "type": "string", "default": "/sandbox06/Topics/PolicyData/arn"}
},
"mainSteps": [
{ "action": "aws:runShellScript",
"name": "runCommands",
"inputs": {
"runCommand": ["aws lambda update-functionconfiguration --function-name $FunctionArn --version $FunctionVersion"]
}
]
}
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
Policies:
- PolicyName: UpdateAliasPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- lambda:UpdateFunctionConfiguration
Resource:
- !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Environment}-*
template with yaml
AWSTemplateFormatVersion: "2010-09-09"
Description: "AWS CloudFormation Template for Response Plans"
Parameters:
Environment:
Type: String
Domain:
Type: String
Team:
Type: String
NotificationARN:
Type: AWS::SSM::Parameter::Value<String>
Default: /sandbox06/Topics/PolicyData/arn
Resources:
UpdateAliasResponsePlan:
Type: AWS::SSMIncidents::ResponsePlan
Properties:
Actions:
- SsmAutomation:
RoleArn: !Ref Role
DocumentName: UpdateAliasDocument
# ActionType: UpdateAlias
DisplayName: "UpdateLambdaAlias"
# Engagements:
# Engagements
IncidentTemplate:
Impact: 3
NotificationTargets:
- SnsTopicArn:
Ref: NotificationARN
Summary: "String"
Title: "String"
Name: "UpdateLambdaAlias"
Tags:
- Key: "Team"
Value: !Ref Team
- Key: "Domain"
Value: !Ref Domain
- Key: "Environment"
Value: !Ref Environment
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content:
schemaVersion: "2.2"
parameters:
- name: FunctionVersion
type: "String"
defaultValue: "1"
- name: FunctionArn
type: "String"
mainSteps:
- action: aws:runShellScript
name: "runCommand"
inputs:
runCommand: "aws lambda update-function-configuration --function-name $FunctionArn --version $FunctionVersion"
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
Policies:
- PolicyName: UpdateAliasPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- lambda:UpdateFunctionConfiguration
Resource:
- !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Environment}-*
Another YAML Version
AWSTemplateFormatVersion: "2010-09-09"
Description: "AWS CloudFormation Template for Response Plans"
Parameters:
Environment:
Type: String
Domain:
Type: String
Team:
Type: String
NotificationARN:
Type: AWS::SSM::Parameter::Value<String>
Default: /sandbox06/Topics/PolicyData/arn
Resources:
UpdateAliasResponsePlan:
Type: AWS::SSMIncidents::ResponsePlan
Properties:
Actions:
- SsmAutomation:
RoleArn: !Ref Role
DocumentName: UpdateAliasDocument
# ActionType: UpdateAlias
DisplayName: "UpdateLambdaAlias"
# Engagements:
# Engagements
IncidentTemplate:
Impact: 3
NotificationTargets:
- SnsTopicArn:
Ref: NotificationARN
Summary: "String"
Title: "String"
Name: "UpdateLambdaAlias"
Tags:
- Key: "Team"
Value: !Ref Team
- Key: "Domain"
Value: !Ref Domain
- Key: "Environment"
Value: !Ref Environment
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content:
schemaVersion: "2.2"
parameters:
- name: FunctionVersion
type: "String"
defaultValue: "1"
- name: FunctionName
type: "String"
mainSteps:
- name: UpdateLambdaAlias
action: aws:executeAWSApi
inputs:
Service: "lambda"
Api: UpdateFunctionConfiguration
FunctionName: $FunctionName
FunctionVersion: $FunctionVersion
Role:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action: sts:AssumeRole
Path: /
Policies:
- PolicyName: UpdateAliasPolicy
PolicyDocument:
Statement:
- Effect: Allow
Action:
- lambda:UpdateFunctionConfiguration
Resource:
- !Sub arn:${AWS::Partition}:lambda:${AWS::Region}:${AWS::AccountId}:function:${Environment}-*
You're getting the error when it tries to resolve the SSM parameters. It is a 400 error, so it may be that you don't have permission to retrieve the parameter from SSM. In this case it is looking for /sandbox06/Topics/PolicyData/arn so verify that the account you are using to create the stack has permission to retrieve that parameter. This article shows the permissions needed.
If so, also verify that the value of that parameter in SSM would result in a valid template if you pasted it into your template. Verify that the SSM parameter is of type String, as AWS::SSM::Parameter::Value<String> is
A Systems Manager parameter whose value is a string. This corresponds
to the String parameter type in Parameter Store.
That link also mentions the following and gives an alternative if you are want to fetch a secure string:
AWS CloudFormation does not support defining template parameters as
SecureString Systems Manager parameter types.
Also, it may be that you need to format the default to not start with a slash. This page shows an example that does not start with a slash, or for hierarchical parameters that do begin with a slash, it may need to be in single quotes (Example 2 shows it that way)
The problem was with the way I was defining the parameters. I needed to remove the name key.
replace
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content:
schemaVersion: "2.2"
parameters:
- name: FunctionVersion
type: "String"
defaultValue: "1"
- name: FunctionName
type: "String"
mainSteps:
- name: UpdateLambdaAlias
action: aws:executeAWSApi
inputs:
Service: "lambda"
Api: UpdateFunctionConfiguration
FunctionName: $FunctionName
FunctionVersion: $FunctionVersion
with
UpdateAliasDocument:
Type: AWS::SSM::Document
Properties:
Content:
schemaVersion: "2.2"
parameters:
FunctionVersion
type: "String"
defaultValue: "1"
FunctionName
type: "String"
mainSteps:
- name: UpdateLambdaAlias
action: aws:executeAWSApi
inputs:
Service: "lambda"
Api: UpdateFunctionConfiguration
FunctionName: $FunctionName
FunctionVersion: $FunctionVersion
I am trying to create a stack on AWS using CloudFormation. The following my cloud Formation script.
I have create the S3 bucket in us-west (Oregon) region. I have been running the cloudformation script in the same region.
During the creation process, I get the following error. Could you please help me how can I address this error?
CloudFormation Script
AWSTemplateFormatVersion: 2010-09-09
Description: The CloudFormation template for AWS resources required by amazon rekognition video analyzer.
Parameters:
SourceS3BucketParameter:
Type: String
MinLength: "1"
Description: "Enter the name of the S3 bucket containing source .zip files."
ImageProcessorSourceS3KeyParameter:
Type: String
MinLength: "1"
Description: "Enter the name of the S3 key of Image Processor lambda function .zip file."
FrameFetcherSourceS3KeyParameter:
Type: String
MinLength: "1"
Description: "Enter the name of the S3 key of Frame Fetcher lambda function .zip file."
FrameFetcherLambdaFunctionName:
Type: String
Default: "framefetcher"
Description: "Name of the Lambda function that fetches frame metadata from DynamoDB."
ImageProcessorLambdaFunctionName:
Type: String
Default: "imageprocessor"
Description: "Name of the Lambda function that receives and processes frame images."
FrameFetcherApiResourcePathPart:
Type: String
Default: "enrichedframe"
Description: "Path part for the API Gateway resource to access FrameFetcher lambda function."
KinesisStreamNameParameter:
Type: String
Default: "FrameStream"
Description: "Name of the Kinesis stream to receive frames from video capture client."
FrameS3BucketNameParameter:
Type: String
MinLength: "1"
Description: "Name of the S3 bucket for storage of captured frames."
DDBTableNameParameter:
Type: String
Default: "EnrichedFrame"
Description: "Name of the DynamoDB table for persistence & querying of captured frames metadata."
DDBGlobalSecondaryIndexNameParameter:
Type: String
Default: "processed_year_month-processed_timestamp-index"
Description: "Name of the DDB Global Secondary Index for querying of captured frames by Web UI."
ApiGatewayRestApiNameParameter:
Type: String
Default: "RtRekogRestApi"
Description: "Name of the API Gateway Rest API."
ApiGatewayStageNameParameter:
Type: String
Default: "development"
Description: "Name of the API Gateway stage."
ApiGatewayUsagePlanNameParameter:
Type: String
Default: "development-plan"
Description: "Name of the API Gateway Usage Plan."
Resources:
FrameS3Bucket:
Type: "AWS::S3::Bucket"
Properties:
BucketName: !Ref FrameS3BucketNameParameter
ImageProcessorLambdaExecutionRole:
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/AmazonKinesisReadOnlyAccess
- arn:aws:iam::aws:policy/AmazonRekognitionReadOnlyAccess
- arn:aws:iam::aws:policy/AmazonS3FullAccess
- arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
- arn:aws:iam::aws:policy/AmazonSNSFullAccess
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
Path: "/"
DependsOn:
- FrameS3Bucket
- EnrichedFrameTable
FrameFetcherLambdaExecutionRole:
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/AmazonS3FullAccess
- arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
- arn:aws:iam::aws:policy/CloudWatchLogsFullAccess
Path: "/"
DependsOn:
- FrameS3Bucket
- EnrichedFrameTable
FrameStream:
Type: "AWS::Kinesis::Stream"
Properties:
Name: !Ref KinesisStreamNameParameter
ShardCount: 1
ImageProcessorLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: "imageprocessor"
Description: "Function processes frame images fetched from a Kinesis stream."
Handler: "imageprocessor.handler"
Role: !GetAtt ImageProcessorLambdaExecutionRole.Arn
Code:
S3Bucket: !Ref SourceS3BucketParameter
S3Key: !Ref ImageProcessorSourceS3KeyParameter
Timeout: 40 #seconds
MemorySize: 128 #MB
Runtime: python2.7
DependsOn:
- FrameStream
- ImageProcessorLambdaExecutionRole
EventSourceMapping:
Type: "AWS::Lambda::EventSourceMapping"
Properties:
EventSourceArn: !GetAtt FrameStream.Arn
FunctionName: !GetAtt ImageProcessorLambda.Arn
StartingPosition: "TRIM_HORIZON"
DependsOn:
- FrameStream
- ImageProcessorLambda
FrameFetcherLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: "framefetcher"
Description: "Function responds to a GET request by returning a list of frames up to a certain fetch horizon."
Handler: "framefetcher.handler"
Role: !GetAtt FrameFetcherLambdaExecutionRole.Arn
Code:
S3Bucket: !Ref SourceS3BucketParameter
S3Key: !Ref FrameFetcherSourceS3KeyParameter
Timeout: 10 #seconds
MemorySize: 128 #MB
Runtime: python2.7
DependsOn:
- FrameFetcherLambdaExecutionRole
EnrichedFrameTable:
Type: "AWS::DynamoDB::Table"
Properties:
TableName: !Ref DDBTableNameParameter
KeySchema:
- KeyType: "HASH"
AttributeName: "frame_id"
AttributeDefinitions:
- AttributeName: "frame_id"
AttributeType: "S"
- AttributeName: "processed_timestamp"
AttributeType: "N"
- AttributeName: "processed_year_month"
AttributeType: "S"
ProvisionedThroughput:
WriteCapacityUnits: 10
ReadCapacityUnits: 10
GlobalSecondaryIndexes:
- IndexName: !Ref DDBGlobalSecondaryIndexNameParameter
Projection:
ProjectionType: "ALL"
ProvisionedThroughput:
WriteCapacityUnits: 10
ReadCapacityUnits: 10
KeySchema:
- KeyType: "HASH"
AttributeName: "processed_year_month"
- KeyType: "RANGE"
AttributeName: "processed_timestamp"
# API Gateway Resources
VidAnalyzerRestApi:
Type: "AWS::ApiGateway::RestApi"
Properties:
Description: "The amazon rekognition video analyzer public API."
Name: !Ref ApiGatewayRestApiNameParameter
DependsOn: FrameFetcherLambda
EnrichedFrameResource:
Type: "AWS::ApiGateway::Resource"
Properties:
RestApiId: !Ref VidAnalyzerRestApi
ParentId: !GetAtt VidAnalyzerRestApi.RootResourceId
PathPart: !Ref FrameFetcherApiResourcePathPart
EnrichedFrameResourceGET:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref VidAnalyzerRestApi
ResourceId: !Ref EnrichedFrameResource
ApiKeyRequired: true
HttpMethod: GET
AuthorizationType: NONE
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: POST
Uri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FrameFetcherLambda.Arn}/invocations
MethodResponses:
- ResponseModels:
application/json: Empty
StatusCode: 200
ResponseParameters:
"method.response.header.Access-Control-Allow-Origin": true
"method.response.header.Access-Control-Allow-Methods": true
"method.response.header.Access-Control-Allow-Headers": true
# Mock integration to allow Cross-Origin Resource Sharing (CORS)
# for Web UI to invoke API Gateway
EnrichedFrameResourceOPTIONS:
Type: AWS::ApiGateway::Method
Properties:
RestApiId: !Ref VidAnalyzerRestApi
ResourceId: !Ref EnrichedFrameResource
ApiKeyRequired: false
HttpMethod: OPTIONS
AuthorizationType: NONE
Integration:
Type: MOCK
IntegrationHttpMethod: OPTIONS
PassthroughBehavior: WHEN_NO_MATCH
RequestTemplates:
"application/json": '{"statusCode": 200 }'
IntegrationResponses:
- StatusCode: 200
ResponseParameters:
"method.response.header.Access-Control-Allow-Origin": "'*'"
"method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'"
"method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
ResponseTemplates:
"application/json": ''
MethodResponses:
- ResponseModels:
application/json: Empty
StatusCode: 200
ResponseParameters:
"method.response.header.Access-Control-Allow-Origin": true
"method.response.header.Access-Control-Allow-Methods": true
"method.response.header.Access-Control-Allow-Headers": true
VidAnalyzerApiDeployment:
Type: "AWS::ApiGateway::Deployment"
Properties:
Description: "Public API endpoint of video analyzer."
RestApiId: !Ref VidAnalyzerRestApi
DependsOn:
- EnrichedFrameResourceGET
- EnrichedFrameResourceOPTIONS
DevStage:
Type: "AWS::ApiGateway::Stage"
Properties:
DeploymentId: !Ref VidAnalyzerApiDeployment
Description: "API development stage of video analyzer."
RestApiId: !Ref VidAnalyzerRestApi
StageName: !Ref ApiGatewayStageNameParameter
DevUsagePlan:
Type: AWS::ApiGateway::UsagePlan
Properties:
ApiStages:
- ApiId: !Ref VidAnalyzerRestApi
Stage: !Ref DevStage
Description: Development usage plan
UsagePlanName: !Ref ApiGatewayUsagePlanNameParameter
DeletionPolicy: Retain #Had to be added to avoid stack deletion failing due to association with DevStage.
VidAnalyzerApiKey:
Type: "AWS::ApiGateway::ApiKey"
Properties:
Name: "DevApiKey"
Description: "Video Analyzer Dev API Key"
Enabled: true
StageKeys:
- RestApiId: !Ref VidAnalyzerRestApi
StageName: !Ref ApiGatewayStageNameParameter
DependsOn:
- VidAnalyzerApiDeployment
- DevStage
DevUsagePlanKey:
Type: "AWS::ApiGateway::UsagePlanKey"
Properties :
KeyId: !Ref VidAnalyzerApiKey
KeyType: API_KEY
UsagePlanId: !Ref DevUsagePlan
#Give API Gateway permission to invoke FrameFetcher lambda function.
LambdaInvokePermissionSTAR:
Type: "AWS::Lambda::Permission"
Properties:
FunctionName: !GetAtt FrameFetcherLambda.Arn
Action: "lambda:InvokeFunction"
Principal: "apigateway.amazonaws.com"
SourceArn: !Join [ "", ["arn:aws:execute-api:", !Ref "AWS::Region", ':', !Ref "AWS::AccountId", ':', !Ref VidAnalyzerRestApi, '/*/*/', !Ref FrameFetcherLambdaFunctionName]]
DependsOn:
- VidAnalyzerApiDeployment
LambdaInvokePermissionGET:
Type: "AWS::Lambda::Permission"
Properties:
FunctionName: !GetAtt FrameFetcherLambda.Arn
Action: "lambda:InvokeFunction"
Principal: "apigateway.amazonaws.com"
SourceArn: !Join [ "", ["arn:aws:execute-api:", !Ref "AWS::Region", ':', !Ref "AWS::AccountId", ':', !Ref VidAnalyzerRestApi, '/*/GET/', !Ref FrameFetcherApiResourcePathPart]]
DependsOn:
- VidAnalyzerApiDeployment
Outputs:
#API Gateway endpoint Id
VidAnalyzerApiEndpoint:
Description: "Endpoint for invoking video analyzer API."
Value: !Ref VidAnalyzerApiDeployment
#API Key Id
VidAnalyzerApiKey:
Description: "Key for invoking video analyzer API."
Value: !Ref VidAnalyzerApiKey
Error:
The following are the parameters, I have set during the cloudFormation process.
Stack name: streamframerekognition
ApiGatewayRestApiNameParameter : RtRekogRestApi
ApiGatewayStageNameParameter : development
ApiGatewayUsagePlanNameParameter : development-plan
DDBGlobalSecondaryIndexNameParameter : processed_year_month-processed_timestamp-index
DDBTableNameParameter : EnrichedFrame
FrameFetcherApiResourcePathPart : enrichedframe
FrameFetcherLambdaFunctionName : framefetcher
ImageProcessorLambdaFunctionName: imageprocessor
ImageProcessorSourceS3KeyParameter : imagestreamframerekognition
KinesisStreamNameParameter : FrameStream
SourceS3BucketParameter : sourcesstreamframerekognition
FrameFetcherSourceS3KeyParameter : ffstreamframerekognition
FrameS3BucketNameParameter : framesbnpstreamframerekognition
It appears that the object key you are providing as ImageProcessorSourceS3KeyParameter is not a valid key name, or does not exist. Check that a file with that name exists in your S3 bucket.
In the S3 bucket "sourcesstreamframerekognition" you need to have a zip file with your code (S3 Key) for FrameFetcherSourceS3KeyParameter and ImageProcessorSourceS3KeyParameter.
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.