{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Test Template", "Parameters": { "CustomAuthLambdaS3Bucket": { "Type": "String", "Description": "Name of the S3 bucket containing Custom Authorizer Lambda package", "Default": "auth0-custom-auth" }, "CustomAuthLambdaS3KeyName": { "Type": "String", "Description": "Custom Authorizer Lambda package file name", "Default": "Archive.zip" }, "StageName": { "Type": "String", "Description": "Name of the stage that you want the API to be deployed in.", "Default": "beta" }, "WebsiteS3BucketName": { "Default": "auth0.myspa", "Description" : "The name of the bucket hosting your web site. This bucket will be created", "Type": "String", "MinLength": "1", "MaxLength": "64", "AllowedPattern" : ".*" } }, "Resources": { "S3Bucket" : { "Type" : "AWS::S3::Bucket", "Properties" : { "AccessControl" : "PublicRead", "BucketName" : {"Ref": "WebsiteS3BucketName"}, "WebsiteConfiguration" : { "IndexDocument" : "index.html", "ErrorDocument" : "error.html" } }, "DeletionPolicy" : "Delete" }, "BucketPolicy" : { "Type" : "AWS::S3::BucketPolicy", "Properties" : { "PolicyDocument" : { "Id" : "WebsiteBucketPolicy", "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadForGetBucketObjects", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource" : { "Fn::Join" : [ "", [ "arn:aws:s3:::", { "Ref" : "WebsiteS3BucketName" } , "/*" ] ] } } ] }, "Bucket" : { "Ref" : "S3Bucket" } } }, "MoviesLambda": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "MoviesHandler", "Description": "Movies backend function", "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "BasicLambdaExecutionRole", "Arn" ] }, "Code": { "ZipFile": { "Fn::Join": [ "", [ "'use strict'; \n", "exports.handler = (event, context, callback) => {\n", " callback(null, 'Movie Info retrieved from Movie API');\n", "};" ] ] } }, "Runtime": "nodejs4.3" } }, "DevicesLambda": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "DevicesHandler", "Description": "Devices backend function", "Handler": "index.handler", "Role": { "Fn::GetAtt": [ "BasicLambdaExecutionRole", "Arn" ] }, "Code": { "ZipFile": { "Fn::Join": [ "", [ "'use strict'; \n", "exports.handler = (event, context, callback) => {\n", " callback(null, 'Device info retrieved from Device API');\n", "};" ] ] } }, "Runtime": "nodejs4.3" } }, "Auth0CustomAuthorizerLambda": { "Type": "AWS::Lambda::Function", "Properties": { "FunctionName": "Auth0CustomAuthorizer", "Description": "Custom Authorizer", "Handler": "CustomAuth.handler", "Role": { "Fn::GetAtt": [ "BasicLambdaExecutionRole", "Arn" ] }, "Code": { "S3Bucket": { "Ref": "CustomAuthLambdaS3Bucket" }, "S3Key": { "Ref": "CustomAuthLambdaS3KeyName" } }, "Runtime": "nodejs4.3" } }, "BasicLambdaExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": [ "lambda.amazonaws.com" ] }, "Action": [ "sts:AssumeRole" ] } ] }, "Path": "/", "Policies": [ { "PolicyName": "root", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": "arn:aws:logs:*:*:*" } ] } } ] } }, "MovieCustomAuthorizerLambdaInvokePermission": { "Type": "AWS::Lambda::Permission", "Properties": { "FunctionName": { "Fn::GetAtt": [ "Auth0CustomAuthorizerLambda", "Arn" ] }, "Action": "lambda:InvokeFunction", "Principal": "apigateway.amazonaws.com", "SourceArn": { "Fn::Join": [ "", [ "arn:aws:execute-api:", { "Ref": "AWS::Region" }, ":", { "Ref": "AWS::AccountId" }, ":", { "Ref": "MoviesAPI" }, "/authorizers/", { "Ref": "MovieCustomAuthorizer" } ] ] } } }, "DeviceCustomAuthorizerLambdaInvokePermission": { "Type": "AWS::Lambda::Permission", "Properties": { "FunctionName": { "Fn::GetAtt": [ "Auth0CustomAuthorizerLambda", "Arn" ] }, "Action": "lambda:InvokeFunction", "Principal": "apigateway.amazonaws.com", "SourceArn": { "Fn::Join": [ "", [ "arn:aws:execute-api:", { "Ref": "AWS::Region" }, ":", { "Ref": "AWS::AccountId" }, ":", { "Ref": "DevicesAPI" }, "/authorizers/", { "Ref": "DeviceCustomAuthorizer" } ] ] } } }, "MovieBackendLambdaInvokePermission": { "Type": "AWS::Lambda::Permission", "Properties": { "FunctionName": { "Fn::GetAtt": [ "MoviesLambda", "Arn" ] }, "Action": "lambda:InvokeFunction", "Principal": "apigateway.amazonaws.com", "SourceArn": { "Fn::Join": [ "", [ "arn:aws:execute-api:", { "Ref": "AWS::Region" }, ":", { "Ref": "AWS::AccountId" }, ":", { "Ref": "MoviesAPI" }, "/*/GET/movie" ] ] } } }, "DeviceBackendLambdaInvokePermission": { "Type": "AWS::Lambda::Permission", "Properties": { "FunctionName": { "Fn::GetAtt": [ "DevicesLambda", "Arn" ] }, "Action": "lambda:InvokeFunction", "Principal": "apigateway.amazonaws.com", "SourceArn": { "Fn::Join": [ "", [ "arn:aws:execute-api:", { "Ref": "AWS::Region" }, ":", { "Ref": "AWS::AccountId" }, ":", { "Ref": "DevicesAPI" }, "/*/GET/device" ] ] } } }, "DevicesAPI": { "Type": "AWS::ApiGateway::RestApi", "Properties": { "Name": "devices", "Description": "Devices API" } }, "MoviesAPI": { "Type": "AWS::ApiGateway::RestApi", "Properties": { "Name": "movies", "Description": "Movies API" } }, "MovieAPIResource": { "Type": "AWS::ApiGateway::Resource", "Properties": { "RestApiId": { "Ref": "MoviesAPI" }, "ParentId": { "Fn::GetAtt": [ "MoviesAPI", "RootResourceId" ] }, "PathPart": "movie" } }, "DeviceAPIResource": { "Type": "AWS::ApiGateway::Resource", "Properties": { "RestApiId": { "Ref": "DevicesAPI" }, "ParentId": { "Fn::GetAtt": [ "DevicesAPI", "RootResourceId" ] }, "PathPart": "device" } }, "MovieCustomAuthorizer": { "Type": "AWS::ApiGateway::Authorizer", "Properties": { "AuthorizerResultTtlInSeconds": "0", "AuthorizerUri": { "Fn::Join": [ "", [ "arn:aws:apigateway:", { "Ref": "AWS::Region" }, ":lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ "Auth0CustomAuthorizerLambda", "Arn" ] }, "/invocations" ] ] }, "Type": "TOKEN", "IdentitySource": "method.request.header.Authorization", "Name": "MoviesAuth0Authorizer", "RestApiId": { "Ref": "MoviesAPI" } } }, "DeviceCustomAuthorizer": { "Type": "AWS::ApiGateway::Authorizer", "Properties": { "AuthorizerResultTtlInSeconds": "0", "AuthorizerUri": { "Fn::Join": [ "", [ "arn:aws:apigateway:", { "Ref": "AWS::Region" }, ":lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ "Auth0CustomAuthorizerLambda", "Arn" ] }, "/invocations" ] ] }, "Type": "TOKEN", "IdentitySource": "method.request.header.Authorization", "Name": "DeviceAuth0Authorizer", "RestApiId": { "Ref": "DevicesAPI" } } }, "GetMovie": { "Type": "AWS::ApiGateway::Method", "Properties": { "AuthorizationType": "CUSTOM", "AuthorizerId": { "Ref": "MovieCustomAuthorizer" }, "RestApiId": { "Ref": "MoviesAPI" }, "ResourceId": { "Ref": "MovieAPIResource" }, "HttpMethod": "GET", "Integration": { "Type": "AWS", "IntegrationHttpMethod": "POST", "Uri": { "Fn::Join": [ "", [ "arn:aws:apigateway:", { "Ref": "AWS::Region" }, ":lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ "MoviesLambda", "Arn" ] }, "/invocations" ] ] }, "IntegrationResponses": [ { "ResponseParameters": { "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with'", "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'", "method.response.header.Access-Control-Allow-Origin": "'*'" }, "StatusCode": 200 } ] }, "MethodResponses": [ { "ResponseParameters": { "method.response.header.Access-Control-Allow-Headers": true, "method.response.header.Access-Control-Allow-Methods": true, "method.response.header.Access-Control-Allow-Origin": true }, "StatusCode": 200 } ] } }, "OptionsMovie": { "Type": "AWS::ApiGateway::Method", "Properties": { "AuthorizationType": "NONE", "RestApiId": { "Ref": "MoviesAPI" }, "ResourceId": { "Ref": "MovieAPIResource" }, "HttpMethod": "OPTIONS", "Integration": { "Type": "MOCK", "RequestTemplates": { "application/json": "{\"statusCode\": 200}" }, "IntegrationResponses": [ { "ResponseParameters": { "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with'", "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'", "method.response.header.Access-Control-Allow-Origin": "'*'" }, "StatusCode": 200 } ] }, "MethodResponses": [ { "ResponseParameters": { "method.response.header.Access-Control-Allow-Headers": true, "method.response.header.Access-Control-Allow-Methods": true, "method.response.header.Access-Control-Allow-Origin": true }, "StatusCode": 200 } ] } }, "GetDevice": { "Type": "AWS::ApiGateway::Method", "Properties": { "AuthorizationType": "CUSTOM", "AuthorizerId": { "Ref": "DeviceCustomAuthorizer" }, "RestApiId": { "Ref": "DevicesAPI" }, "ResourceId": { "Ref": "DeviceAPIResource" }, "HttpMethod": "GET", "Integration": { "Type": "AWS", "IntegrationHttpMethod": "POST", "Uri": { "Fn::Join": [ "", [ "arn:aws:apigateway:", { "Ref": "AWS::Region" }, ":lambda:path/2015-03-31/functions/", { "Fn::GetAtt": [ "DevicesLambda", "Arn" ] }, "/invocations" ] ] }, "IntegrationResponses": [ { "ResponseParameters": { "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with'", "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'", "method.response.header.Access-Control-Allow-Origin": "'*'" }, "StatusCode": 200 } ] }, "MethodResponses": [ { "ResponseParameters": { "method.response.header.Access-Control-Allow-Headers": true, "method.response.header.Access-Control-Allow-Methods": true, "method.response.header.Access-Control-Allow-Origin": true }, "StatusCode": 200 } ] } }, "OptionsDevice": { "Type": "AWS::ApiGateway::Method", "Properties": { "AuthorizationType": "NONE", "RestApiId": { "Ref": "DevicesAPI" }, "ResourceId": { "Ref": "DeviceAPIResource" }, "HttpMethod": "OPTIONS", "Integration": { "Type": "MOCK", "RequestTemplates": { "application/json": "{\"statusCode\": 200}" }, "IntegrationResponses": [ { "ResponseParameters": { "method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with'", "method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'", "method.response.header.Access-Control-Allow-Origin": "'*'" }, "StatusCode": 200 } ] }, "MethodResponses": [ { "ResponseParameters": { "method.response.header.Access-Control-Allow-Headers": true, "method.response.header.Access-Control-Allow-Methods": true, "method.response.header.Access-Control-Allow-Origin": true }, "StatusCode": 200 } ] } }, "DeviceApiDeployment": { "DependsOn": [ "GetDevice", "OptionsDevice" ], "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "DevicesAPI" }, "Description": "Staged Devices endpoint", "StageName": {"Ref" : "StageName"} } }, "MovieApiDeployment": { "DependsOn": [ "GetMovie", "OptionsMovie" ], "Type": "AWS::ApiGateway::Deployment", "Properties": { "RestApiId": { "Ref": "MoviesAPI" }, "Description": "Staged Movies endpoint", "StageName": {"Ref" : "StageName"} } } }, "Outputs": { "S3BucketSecureURL" : { "Value" : { "Fn::Join" : [ "", [ { "Fn::GetAtt" : [ "S3Bucket", "WebsiteURL" ] } ] ] }, "Description" : "Amazon S3 website endpoint" } } }