Slide 7
Slide 7 text
CloudFormation
{"AWSTemplateFormatVersion":"2010-09-09","Description":"Creates an API gateway that's
backed by a Lambda function","Parameters":{"APIName":{"Description":"Name of the API
to
create","Type":"String","AllowedPattern":"[A-Za-z0-9]*","MinLength":"4","MaxLength":"2
048","ConstraintDescription":"must contain only alphanumeric characters (at least
four)"},"APIDescription":{"Description":"Description of the API to
create","Type":"String","Default":"No description provided. Provide 'APIDescription'
param to override this."},"APIPath":{"Description":"URL path for the
API","Type":"String","Default":"api","AllowedPattern":"[A-Za-z0-9]*","MinLength":"1","
MaxLength":"64","ConstraintDescription":"must contain only alphanumeric characters
(1-64 chars)"},"APIStageName":{"Description":"Stage name to deploy the API
to","Type":"String","Default":"dev","AllowedPattern":"[A-Za-z0-9]*","MinLength":"1","M
axLength":"64","ConstraintDescription":"must contain only alphanumeric characters
(1-64 chars)"},"LambdaCodeBucket":{"Description":"Name of the S3 bucket that's storing
the Lamba function's zip file","Type":"String"},"LambdaCodePath":{"Description":"Path
to the zip file of code for the Lambda
function","Type":"String"},"APIGatewayCustomResourceARN":{"Description":"The ARN
pointing to the Lambda function that creates custom API gateway resources (install
from https://apigatewaycloudformation.bynordenfelt.com/). Example:
arn:aws:lambda:us-east-1:123456789012:function:APIGatewayCustomResource-LambdaFunction
-ABCDEFG123","Type":"String"},"DynamoReadCapacityUnits":{"Description":"Provisioned
read
throughput","Type":"Number","Default":"1","MinValue":"1","MaxValue":"10000","Constrain
tDescription":"must be between 1 and
10000"},"DynamoWriteCapacityUnits":{"Description":"Provisioned write
throughput","Type":"Number","Default":"1","MinValue":"1","MaxValue":"10000","Constrain
tDescription":"must be between 1 and
10000"}},"Resources":{"BackingLambdaFunction":{"Type":"AWS::Lambda::Function","Propert
ies":{"Code":{"S3Bucket":{"Ref":"LambdaCodeBucket"},"S3Key":{"Ref":"LambdaCodePath"}},
"FunctionName":{"Fn::Join":["-",[{"Ref":"AWS::StackName"},{"Ref":"APIName"}]]},"Handle
r":"index.handler","MemorySize":"128","Role":{"Fn::GetAtt":["BackingLambdaExecutionRol
e","Arn"]},"Runtime":"nodejs4.3","Timeout":"3"}},"BackingLambdaInvokePermission":{"Typ
e":"AWS::Lambda::Permission","Properties":{"FunctionName":{"Fn::GetAtt":["BackingLambd
aFunction","Arn"]},"Action":"lambda:
InvokeFunction","Principal":"apigateway.amazonaws.com"}},"BackingLambdaExecutionRole":
{"Type":"AWS::IAM::Role","Properties":{"AssumeRolePolicyDocument":{"Version":"2012-10-
17","Statement":[{"Effect":"Allow","Principal":{"Service":["lambda.amazonaws.com"]},"A
ction":["sts:AssumeRole"]}]},"Policies":[{"PolicyName":{"Fn::Join":["-",[{"Ref":"AWS::
StackName"},"UseDBPolicy"]]},"PolicyDocument":{"Version":"2012-10-17","Statement":[{"E
InvokeFunction","Principal":"apigateway.amazonaws.com"}},"BackingLambdaExecutionRole":{"Type
":"AWS::IAM::Role","Properties":{"AssumeRolePolicyDocument":{"Version":"2012-10-17","Stateme
nt":[{"Effect":"Allow","Principal":{"Service":["lambda.amazonaws.com"]},"Action":["sts:Assum
eRole"]}]},"Policies":[{"PolicyName":{"Fn::Join":["-",[{"Ref":"AWS::StackName"},"UseDBPolicy
"]]},"PolicyDocument":{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Action":["dyna
modb:DeleteItem","dynamodb:GetItem","dynamodb:PutItem","dynamodb:Query","dynamodb:Scan","dyn
amodb:UpdateItem"],"Resource":{"Fn::Join":["",["arn:aws:dynamodb:",{"Ref":"AWS::Region"},":"
,{"Ref":"AWS::AccountId"},":table/",{"Ref":"APIDynamoDBTable"}]]}},{"Effect":"Allow","Action
":["logs:CreateLogGroup","logs:CreateLogStream","logs:PutLogEvents"],"Resource":"*"}]}}]}},"
MainAPI":{"Type":"Custom::RestApi","Properties":{"name":{"Fn::Join":["-",[{"Ref":"AWS::Stack
Name"},{"Ref":"APIName"}]]},"description":{"Ref":"APIDescription"},"ServiceToken":{"Ref":"AP
IGatewayCustomResourceARN"}}},"MainAPIResource":{"Type":"Custom::ApiResource","Properties":{
"ServiceToken":{"Ref":"APIGatewayCustomResourceARN"},"restApiId":{"Ref":"MainAPI"},"parentId
":{"Fn::GetAtt":["MainAPI","parentResourceId"]},"pathPart":{"Ref":"APIPath"},"corsConfigurat
ion":{"allowMethods":["GET","POST"],"allowHeaders":["x-my-header","some-other-header"],"allo
wDefaultHeaders":true,"allowOrigin":"*","exposeHeaders":["some-header","x-another-header"],"
maxAge":1800}}},"APIMethodGet":{"Type":"Custom::ApiMethod","Properties":{"ServiceToken":{"Re
f":"APIGatewayCustomResourceARN"},"restApiId":{"Ref":"MainAPI"},"resourceId":{"Ref":"MainAPI
Resource"},"method":{"httpMethod":"GET","parameters":["querystring.sortBy","header.x-test-he
ader","path.entityType"]},"integration":{"type":"AWS","uri":{"Fn::Join":[":",["arn:aws:apiga
teway",{"Ref":"AWS::Region"},"lambda:path/2015-03-31/functions/arn:aws:lambda",{"Ref":"AWS::
Region"},{"Ref":"AWS::AccountId"},"function",{"Fn::Join":["/",[{"Fn::Join":["-",[{"Ref":"AWS
::StackName"},{"Ref":"APIName"}]]},"invocations"]]}]]},"httpMethod":"POST","requestTemplates
":{"application/json":["input-pass-through-full",{"DynamoDBTableName":{"Ref":"APIDynamoDBTab
le"}}]},"requestParameters":{"integration.request.querystring.sortBy":"'hardcodedValue'"}},"
responses":{"default":{"statusCode":"200","headers":{"X-Custom-Header":"'hardcodedValue'"}},
".*NotFound.*":{"statusCode":"404"}}}},"APIMethodPost":{"Type":"Custom::ApiMethod","Properti
es":{"ServiceToken":{"Ref":"APIGatewayCustomResourceARN"},"restApiId":{"Ref":"MainAPI"},"res
ourceId":{"Ref":"MainAPIResource"},"method":{"httpMethod":"POST","parameters":["querystring.
sortBy","header.x-test-header","path.entityType"]},"integration":{"type":"AWS","uri":{"Fn::J
oin":[":",["arn:aws:apigateway",{"Ref":"AWS::Region"},"lambda:path/2015-03-31/functions/arn:
aws:lambda",{"Ref":"AWS::Region"},{"Ref":"AWS::AccountId"},"function",{"Fn::Join":["/",[{"Fn
::Join":["-",[{"Ref":"AWS::StackName"},{"Ref":"APIName"}]]},"invocations"]]}]]},"httpMethod"
:"POST","requestTemplates":{"application/json":["input-pass-through-full",{"DynamoDBTableNam
e":{"Ref":"APIDynamoDBTable"}}]},"requestParameters":{"integration.request.querystring.sortB
y":"'hardcodedValue'"}},"responses":{"default":{"statusCode":"200","headers":{"X-Custom-Head
er":"'hardcodedValue'"}},".*NotFound.*":{"statusCode":"404"}}}},"DeployApi":{"Type":"Custom:
:ApiDeploy","DependsOn":["APIMethodGet","APIMethodPost"],"Properties":{"ServiceToken":{"Ref"
:"APIGatewayCustomResourceARN"},"restApiId":{"Ref":"MainAPI"},"stageName":{"Ref":"APIStageNa