A collection of APIGW demos (v1 and v2)
Last active
May 15, 2024 18:14
-
-
Save jhw/c27fb54c71c5e3be6bc0d5e9a204225d to your computer and use it in GitHub Desktop.
APIGW demos
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
*.pyc | |
__pycache__ | |
env | |
tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
AppName=sb-apigw-demo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<!-- python -m http.server --> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>CORS Test</title> | |
<script> | |
window.onload = function() { | |
fetch('https://apigwdemo.spaaseu.link/hello-get?message=Hello%20World') | |
.then(response => { | |
if (!response.ok) { | |
throw new Error('Network response was not ok'); | |
} | |
return response.text(); | |
}) | |
.then(data => { | |
document.getElementById('response').textContent = data; | |
}) | |
.catch(error => { | |
console.log(error); | |
document.getElementById('response').textContent = "There was an error calling /hello-get; please see the console log for more details" | |
}); | |
}; | |
</script> | |
</head> | |
<body> | |
<div id="response">Loading...</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from botocore.exceptions import ClientError | |
import boto3, os, re, sys, yaml | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
if len(sys.argv) < 3: | |
raise RuntimeError("please enter email, password") | |
email, password = sys.argv[1:3] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
userpoolkey=hungarorise("app-user-pool") | |
if userpoolkey not in outputs: | |
raise RuntimeError("userpool not found") | |
userpool=outputs[userpoolkey] | |
clientkey=hungarorise("app-user-pool-web-client") | |
if clientkey not in outputs: | |
raise RuntimeError("client not found") | |
client=outputs[clientkey] | |
cognito=boto3.client("cognito-idp") | |
resp0=cognito.sign_up(ClientId=client, | |
Username=email, | |
Password=password) | |
print (yaml.safe_dump(resp0, | |
default_flow_style=False)) | |
resp1=cognito.admin_confirm_sign_up(UserPoolId=userpool, | |
Username=email) | |
print (yaml.safe_dump(resp1, | |
default_flow_style=False)) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation delete-stack --stack-name $AppName |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from botocore.exceptions import ClientError | |
import boto3, os, re, sys, yaml | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
if len(sys.argv) < 2: | |
raise RuntimeError("please enter email") | |
email=sys.argv[1] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
userpoolkey=hungarorise("app-user-pool") | |
if userpoolkey not in outputs: | |
raise RuntimeError("userpool not found") | |
userpool=outputs[userpoolkey] | |
cognito=boto3.client("cognito-idp") | |
resp=cognito.admin_delete_user(UserPoolId=userpool, | |
Username=email) | |
print (yaml.safe_dump(resp, | |
default_flow_style=False)) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation deploy --stack-name $AppName --template-file $1 --capabilities CAPABILITY_NAMED_IAM --parameter-overrides DomainName=$DOMAIN_NAME CertificateArn=$CERTIFICATE_ARN | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from botocore.exceptions import ClientError | |
import boto3, os, re, sys | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
bucketkey=hungarorise("app-bucket") | |
if bucketkey not in outputs: | |
raise RuntimeError("bucket not found") | |
bucketname=outputs[bucketkey] | |
s3=boto3.client("s3") | |
paginator=s3.get_paginator("list_objects_v2") | |
pages=paginator.paginate(Bucket=bucketname) | |
for struct in pages: | |
if "Contents" in struct: | |
for obj in struct["Contents"]: | |
print (obj["Key"]) | |
s3.delete_object(Bucket=bucketname, | |
Key=obj["Key"]) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<title>Hello World</title> | |
</head> | |
<body> | |
<div>Hello World!</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import boto3, re, sys | |
if __name__ == "__main__": | |
try: | |
if len(sys.argv) < 2: | |
raise RuntimeError("please enter region") | |
region = sys.argv[1] | |
if not re.search("^\\D{2}\\-\\D{4}\\-\\d{1}$", region): | |
raise RuntimeError("region is invalid") | |
acm = boto3.client("acm", region_name = region) # NB | |
for cert in acm.list_certificates()["CertificateSummaryList"]: | |
print ("--- %s ---" % (cert["DomainName"])) | |
print ("arn: %s" % cert["CertificateArn"]) | |
cert_ = acm.describe_certificate(CertificateArn = cert["CertificateArn"])["Certificate"] | |
print ("status: %s" % cert_["Status"]) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stack-events --stack-name $AppName --query "StackEvents[].{\"1.Timestamp\":Timestamp,\"2.Id\":LogicalResourceId,\"3.Type\":ResourceType,\"4.Status\":ResourceStatus,\"5.Reason\":ResourceStatusReason}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stacks --stack-name $AppName --query 'Stacks[0].Outputs' --output table |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
. app.props | |
aws cloudformation describe-stack-resources --stack-name $AppName --query "StackResources[].{\"1.Timestamp\":Timestamp,\"2.LogicalId\":LogicalResourceId,\"3.PhysicalId\":PhysicalResourceId,\"4.Type\":ResourceType,\"5.Status\":ResourceStatus}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
aws cloudformation describe-stacks --query "Stacks[].{\"1.Name\":StackName,\"2.Status\":StackStatus}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from botocore.exceptions import ClientError | |
import boto3, os, re, sys, yaml | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
userpoolkey=hungarorise("app-user-pool") | |
if userpoolkey not in outputs: | |
raise RuntimeError("userpool not found") | |
userpool=outputs[userpoolkey] | |
cognito=boto3.client("cognito-idp") | |
resp=cognito.list_users(UserPoolId=userpool) | |
print (yaml.safe_dump(resp, | |
default_flow_style=False)) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from botocore.exceptions import ClientError | |
import boto3, json, os, re, requests, sys, urllib.parse | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
if len(sys.argv) < 4: | |
raise RuntimeError("please enter email, password, message") | |
email, password, message = sys.argv[1:4] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
userpoolkey=hungarorise("app-user-pool") | |
if userpoolkey not in outputs: | |
raise RuntimeError("userpool not found") | |
userpool=outputs[userpoolkey] | |
clientkey=hungarorise("app-user-pool-admin-client") | |
if clientkey not in outputs: | |
raise RuntimeError("client not found") | |
client=outputs[clientkey] | |
cg=boto3.client("cognito-idp") | |
authresp=cg.admin_initiate_auth(UserPoolId=userpool, | |
ClientId=client, | |
AuthFlow='ADMIN_NO_SRP_AUTH', | |
AuthParameters={"USERNAME": email, | |
"PASSWORD": password}) | |
token=authresp["AuthenticationResult"]["IdToken"] | |
url="https://apigwdemo.spaaseu.link/hello-get?message=%s" % urllib.parse.quote(message) | |
headers={"Authorization": "Bearer %s" % token, | |
"Accept": "application/json"} | |
print (headers) | |
print () | |
resp=requests.get(url, | |
headers=headers) | |
print (resp.text) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from botocore.exceptions import ClientError | |
import boto3, json, os, re, requests, sys, urllib.parse | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
if len(sys.argv) < 4: | |
raise RuntimeError("please enter email, password, message") | |
email, password, message = sys.argv[1:4] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
userpoolkey=hungarorise("app-user-pool") | |
if userpoolkey not in outputs: | |
raise RuntimeError("userpool not found") | |
userpool=outputs[userpoolkey] | |
clientkey=hungarorise("app-user-pool-admin-client") | |
if clientkey not in outputs: | |
raise RuntimeError("client not found") | |
client=outputs[clientkey] | |
cg=boto3.client("cognito-idp") | |
authresp=cg.admin_initiate_auth(UserPoolId=userpool, | |
ClientId=client, | |
AuthFlow='ADMIN_NO_SRP_AUTH', | |
AuthParameters={"USERNAME": email, | |
"PASSWORD": password}) | |
token=authresp["AuthenticationResult"]["IdToken"] | |
url="https://apigwdemo.spaaseu.link/hello-post" | |
headers={"Authorization": "Bearer %s" % token, | |
"Accept": "application/json"} | |
print (headers) | |
print () | |
struct={"message": message} | |
resp=requests.post(url, | |
headers=headers, | |
data=json.dumps(struct)) | |
print (resp.text) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from botocore.exceptions import ClientError | |
import boto3, os, re, sys | |
def hungarorise(text): | |
return "".join([tok.capitalize() | |
for tok in re.split("\\-|\\_", text)]) | |
def fetch_outputs(cf, stackname): | |
outputs={} | |
for stack in cf.describe_stacks()["Stacks"]: | |
if (stack["StackName"].startswith(stackname) and | |
"Outputs" in stack): | |
for output in stack["Outputs"]: | |
outputs[output["OutputKey"]]=output["OutputValue"] | |
return outputs | |
if __name__=="__main__": | |
try: | |
props=dict([tuple(row.split("=")) | |
for row in open("app.props").read().split("\n") | |
if row!='']) | |
stackname=props["AppName"] | |
cf=boto3.client("cloudformation") | |
outputs=fetch_outputs(cf, stackname) | |
bucketkey=hungarorise("app-bucket") | |
if bucketkey not in outputs: | |
raise RuntimeError("bucket not found") | |
bucketname=outputs[bucketkey] | |
s3=boto3.client("s3") | |
print (s3.put_object(Bucket=bucketname, | |
Key="index.html", | |
Body=open("index.html").read(), | |
ContentType="text/html")) | |
except RuntimeError as error: | |
print ("Error: %s" % str(error)) | |
except ClientError as error: | |
print ("Error: %s" % str(error)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
awscli | |
boto3 | |
botocore | |
pyyaml | |
requests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
export AWS_DEFAULT_OUTPUT=table | |
export AWS_PROFILE=woldeploy | |
export AWS_REGION=eu-west-1 | |
export CERTIFICATE_ARN=arn:aws:acm:us-east-1:119552584133:certificate/74aeb9e7-1db1-4ece-bbf5-9e3d4f800f36 | |
export DOMAIN_NAME=apigwdemo.spaaseu.link | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Outputs": { | |
"AppIdentityPool": { | |
"Value": { | |
"Ref": "AppIdentityPool" | |
} | |
}, | |
"AppRestApi": { | |
"Value": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"AppUserPool": { | |
"Value": { | |
"Ref": "AppUserPool" | |
} | |
}, | |
"AppUserPoolAdminClient": { | |
"Value": { | |
"Ref": "AppUserPoolAdminClient" | |
} | |
}, | |
"AppUserPoolWebClient": { | |
"Value": { | |
"Ref": "AppUserPoolWebClient" | |
} | |
} | |
}, | |
"Parameters": { | |
"CertificateArn": { | |
"Type": "String" | |
}, | |
"DomainName": { | |
"Type": "String" | |
} | |
}, | |
"Resources": { | |
"AppAuthorizer": { | |
"Properties": { | |
"IdentitySource": "method.request.header.Authorization", | |
"Name": { | |
"Fn::Sub": "app-authorizer-${AWS::StackName}" | |
}, | |
"ProviderARNs": [ | |
{ | |
"Fn::GetAtt": [ | |
"AppUserPool", | |
"Arn" | |
] | |
} | |
], | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"Type": "COGNITO_USER_POOLS" | |
}, | |
"Type": "AWS::ApiGateway::Authorizer" | |
}, | |
"AppBasePathMapping": { | |
"DependsOn": [ | |
"AppDomainName" | |
], | |
"Properties": { | |
"DomainName": { | |
"Ref": "DomainName" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"Stage": "prod" | |
}, | |
"Type": "AWS::ApiGateway::BasePathMapping" | |
}, | |
"AppDeployment": { | |
"DependsOn": [ | |
"AppHelloGetPrivateLambdaMethod", | |
"AppHelloGetCorsMethod", | |
"AppHelloPostPrivateLambdaMethod", | |
"AppHelloPostCorsMethod" | |
], | |
"Properties": { | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Deployment" | |
}, | |
"AppDomainName": { | |
"Properties": { | |
"CertificateArn": { | |
"Ref": "CertificateArn" | |
}, | |
"DomainName": { | |
"Ref": "DomainName" | |
} | |
}, | |
"Type": "AWS::ApiGateway::DomainName" | |
}, | |
"AppGatewayResponse4xx": { | |
"Properties": { | |
"ResponseParameters": { | |
"gatewayresponse.header.Access-Control-Allow-Headers": "'*'", | |
"gatewayresponse.header.Access-Control-Allow-Origin": "'*'" | |
}, | |
"ResponseType": "DEFAULT_4XX", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::GatewayResponse" | |
}, | |
"AppGatewayResponse5xx": { | |
"Properties": { | |
"ResponseParameters": { | |
"gatewayresponse.header.Access-Control-Allow-Headers": "'*'", | |
"gatewayresponse.header.Access-Control-Allow-Origin": "'*'" | |
}, | |
"ResponseType": "DEFAULT_5XX", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::GatewayResponse" | |
}, | |
"AppHelloGetCorsMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "OPTIONS", | |
"Integration": { | |
"IntegrationResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Sec'", | |
"method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'", | |
"method.response.header.Access-Control-Allow-Origin": "'*'" | |
}, | |
"ResponseTemplates": { | |
"application/json": "" | |
}, | |
"StatusCode": 200 | |
} | |
], | |
"PassthroughBehavior": "WHEN_NO_MATCH", | |
"RequestTemplates": { | |
"application/json": "{\"statusCode\": 200}" | |
}, | |
"Type": "MOCK" | |
}, | |
"MethodResponses": [ | |
{ | |
"ResponseModels": { | |
"application/json": "Empty" | |
}, | |
"ResponseParameters": { | |
"method.response.header.Access-Control-Allow-Headers": false, | |
"method.response.header.Access-Control-Allow-Methods": false, | |
"method.response.header.Access-Control-Allow-Origin": false | |
}, | |
"StatusCode": 200 | |
} | |
], | |
"ResourceId": { | |
"Ref": "AppHelloGetResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppHelloGetFunction": { | |
"Properties": { | |
"Code": { | |
"ZipFile": "def handler(event, context):\n message=event[\"queryStringParameters\"][\"message\"]\n return {\"statusCode\": 200,\n \"headers\": {\"Content-Type\": \"text/plain\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Headers\": \"Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent\",\n \"Access-Control-Allow-Methods\": \"OPTIONS,GET\"},\n \"body\": f\"you sent '{message}' via GET\"}" | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 512, | |
"Role": { | |
"Fn::GetAtt": [ | |
"AppHelloGetRole", | |
"Arn" | |
] | |
}, | |
"Runtime": "python3.10", | |
"Timeout": 5 | |
}, | |
"Type": "AWS::Lambda::Function" | |
}, | |
"AppHelloGetParameterRequestValidator": { | |
"Properties": { | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"ValidateRequestBody": false, | |
"ValidateRequestParameters": true | |
}, | |
"Type": "AWS::ApiGateway::RequestValidator" | |
}, | |
"AppHelloGetPermission": { | |
"Properties": { | |
"Action": "lambda:InvokeFunction", | |
"FunctionName": { | |
"Ref": "AppHelloGetFunction" | |
}, | |
"Principal": "apigateway.amazonaws.com", | |
"SourceArn": { | |
"Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${AppRestApi}/${AppStage}/GET/hello-get" | |
} | |
}, | |
"Type": "AWS::Lambda::Permission" | |
}, | |
"AppHelloGetPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
}, | |
{ | |
"Action": [ | |
"s3:GetObject" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "app-hello-get-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "AppHelloGetRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"AppHelloGetPrivateLambdaMethod": { | |
"Properties": { | |
"AuthorizationType": "COGNITO_USER_POOLS", | |
"AuthorizerId": { | |
"Ref": "AppAuthorizer" | |
}, | |
"HttpMethod": "GET", | |
"Integration": { | |
"IntegrationHttpMethod": "POST", | |
"Type": "AWS_PROXY", | |
"Uri": { | |
"Fn::Sub": [ | |
"arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${arn}/invocations", | |
{ | |
"arn": { | |
"Fn::GetAtt": [ | |
"AppHelloGetFunction", | |
"Arn" | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RequestParameters": { | |
"method.request.querystring.message": true | |
}, | |
"RequestValidatorId": { | |
"Ref": "AppHelloGetParameterRequestValidator" | |
}, | |
"ResourceId": { | |
"Ref": "AppHelloGetResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppHelloGetResource": { | |
"Properties": { | |
"ParentId": { | |
"Fn::GetAtt": [ | |
"AppRestApi", | |
"RootResourceId" | |
] | |
}, | |
"PathPart": "hello-get", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Resource" | |
}, | |
"AppHelloGetRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "lambda.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"AppHelloPostCorsMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "OPTIONS", | |
"Integration": { | |
"IntegrationResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Sec'", | |
"method.response.header.Access-Control-Allow-Methods": "'POST,OPTIONS'", | |
"method.response.header.Access-Control-Allow-Origin": "'*'" | |
}, | |
"ResponseTemplates": { | |
"application/json": "" | |
}, | |
"StatusCode": 200 | |
} | |
], | |
"PassthroughBehavior": "WHEN_NO_MATCH", | |
"RequestTemplates": { | |
"application/json": "{\"statusCode\": 200}" | |
}, | |
"Type": "MOCK" | |
}, | |
"MethodResponses": [ | |
{ | |
"ResponseModels": { | |
"application/json": "Empty" | |
}, | |
"ResponseParameters": { | |
"method.response.header.Access-Control-Allow-Headers": false, | |
"method.response.header.Access-Control-Allow-Methods": false, | |
"method.response.header.Access-Control-Allow-Origin": false | |
}, | |
"StatusCode": 200 | |
} | |
], | |
"ResourceId": { | |
"Ref": "AppHelloPostResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppHelloPostFunction": { | |
"Properties": { | |
"Code": { | |
"ZipFile": "import json\ndef handler(event, context):\n body=json.loads(event[\"body\"])\n message=body[\"message\"]\n return {\"statusCode\": 200,\n \"headers\": {\"Content-Type\": \"text/plain\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Headers\": \"Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent\",\n \"Access-Control-Allow-Methods\": \"OPTIONS,POST\"},\n \"body\": f\"you sent '{message}' via POST\"}" | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 512, | |
"Role": { | |
"Fn::GetAtt": [ | |
"AppHelloPostRole", | |
"Arn" | |
] | |
}, | |
"Runtime": "python3.10", | |
"Timeout": 5 | |
}, | |
"Type": "AWS::Lambda::Function" | |
}, | |
"AppHelloPostModel": { | |
"Properties": { | |
"ContentType": "application/json", | |
"Name": "AppHelloPostModel", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"Schema": { | |
"$schema": "http://json-schema.org/draft-04/schema#", | |
"additionalProperties": false, | |
"properties": { | |
"message": { | |
"type": "string" | |
} | |
}, | |
"required": [ | |
"message" | |
], | |
"type": "object" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Model" | |
}, | |
"AppHelloPostPermission": { | |
"Properties": { | |
"Action": "lambda:InvokeFunction", | |
"FunctionName": { | |
"Ref": "AppHelloPostFunction" | |
}, | |
"Principal": "apigateway.amazonaws.com", | |
"SourceArn": { | |
"Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${AppRestApi}/${AppStage}/POST/hello-post" | |
} | |
}, | |
"Type": "AWS::Lambda::Permission" | |
}, | |
"AppHelloPostPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
}, | |
{ | |
"Action": [ | |
"s3:GetObject", | |
"s3:PutObject" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "app-hello-post-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "AppHelloPostRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"AppHelloPostPrivateLambdaMethod": { | |
"Properties": { | |
"AuthorizationType": "COGNITO_USER_POOLS", | |
"AuthorizerId": { | |
"Ref": "AppAuthorizer" | |
}, | |
"HttpMethod": "POST", | |
"Integration": { | |
"IntegrationHttpMethod": "POST", | |
"Type": "AWS_PROXY", | |
"Uri": { | |
"Fn::Sub": [ | |
"arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${arn}/invocations", | |
{ | |
"arn": { | |
"Fn::GetAtt": [ | |
"AppHelloPostFunction", | |
"Arn" | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RequestModels": { | |
"application/json": "AppHelloPostModel" | |
}, | |
"RequestValidatorId": { | |
"Ref": "AppHelloPostSchemaRequestValidator" | |
}, | |
"ResourceId": { | |
"Ref": "AppHelloPostResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppHelloPostResource": { | |
"Properties": { | |
"ParentId": { | |
"Fn::GetAtt": [ | |
"AppRestApi", | |
"RootResourceId" | |
] | |
}, | |
"PathPart": "hello-post", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Resource" | |
}, | |
"AppHelloPostRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "lambda.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"AppHelloPostSchemaRequestValidator": { | |
"Properties": { | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"ValidateRequestBody": true, | |
"ValidateRequestParameters": false | |
}, | |
"Type": "AWS::ApiGateway::RequestValidator" | |
}, | |
"AppIdentityPool": { | |
"Properties": { | |
"AllowUnauthenticatedIdentities": true, | |
"CognitoIdentityProviders": [ | |
{ | |
"ClientId": { | |
"Ref": "AppUserPoolWebClient" | |
}, | |
"ProviderName": { | |
"Fn::GetAtt": [ | |
"AppUserPool", | |
"ProviderName" | |
] | |
} | |
} | |
] | |
}, | |
"Type": "AWS::Cognito::IdentityPool" | |
}, | |
"AppIdentityPoolAuthorizedPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"cognito-sync:*" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
}, | |
{ | |
"Action": [ | |
"cognito-identity:*" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
}, | |
{ | |
"Action": [ | |
"lambda:InvokeFunction" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "app-identity-pool-authorized-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "AppIdentityPoolAuthorizedRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"AppIdentityPoolAuthorizedRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRoleWithWebIdentity" | |
], | |
"Condition": { | |
"ForAnyValue:StringLike": { | |
"cognito-identity.amazonaws.com:amr": "authorized" | |
}, | |
"StringEquals": { | |
"cognito-identity.amazonaws.com:aud": { | |
"Ref": "AppIdentityPool" | |
} | |
} | |
}, | |
"Effect": "Allow", | |
"Principal": { | |
"Federated": "cognito-identity.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"AppIdentityPoolRoleAttachment": { | |
"Properties": { | |
"IdentityPoolId": { | |
"Ref": "AppIdentityPool" | |
}, | |
"Roles": { | |
"authenticated": { | |
"Fn::GetAtt": [ | |
"AppIdentityPoolAuthorizedRole", | |
"Arn" | |
] | |
}, | |
"unauthenticated": { | |
"Fn::GetAtt": [ | |
"AppIdentityPoolUnauthorizedRole", | |
"Arn" | |
] | |
} | |
} | |
}, | |
"Type": "AWS::Cognito::IdentityPoolRoleAttachment" | |
}, | |
"AppIdentityPoolUnauthorizedPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"cognito-sync:*" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "app-identity-pool-unauthorized-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "AppIdentityPoolUnauthorizedRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"AppIdentityPoolUnauthorizedRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRoleWithWebIdentity" | |
], | |
"Condition": { | |
"ForAnyValue:StringLike": { | |
"cognito-identity.amazonaws.com:amr": "unauthorized" | |
}, | |
"StringEquals": { | |
"cognito-identity.amazonaws.com:aud": { | |
"Ref": "AppIdentityPool" | |
} | |
} | |
}, | |
"Effect": "Allow", | |
"Principal": { | |
"Federated": "cognito-identity.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"AppRecordSet": { | |
"Properties": { | |
"AliasTarget": { | |
"DNSName": { | |
"Fn::GetAtt": [ | |
"AppDomainName", | |
"DistributionDomainName" | |
] | |
}, | |
"EvaluateTargetHealth": false, | |
"HostedZoneId": { | |
"Fn::GetAtt": [ | |
"AppDomainName", | |
"DistributionHostedZoneId" | |
] | |
} | |
}, | |
"HostedZoneName": { | |
"Fn::Sub": [ | |
"${prefix}.${suffix}.", | |
{ | |
"prefix": { | |
"Fn::Select": [ | |
1, | |
{ | |
"Fn::Split": [ | |
".", | |
{ | |
"Ref": "DomainName" | |
} | |
] | |
} | |
] | |
}, | |
"suffix": { | |
"Fn::Select": [ | |
2, | |
{ | |
"Fn::Split": [ | |
".", | |
{ | |
"Ref": "DomainName" | |
} | |
] | |
} | |
] | |
} | |
} | |
] | |
}, | |
"Name": { | |
"Ref": "DomainName" | |
}, | |
"Type": "A" | |
}, | |
"Type": "AWS::Route53::RecordSet" | |
}, | |
"AppRestApi": { | |
"Properties": { | |
"Name": { | |
"Fn::Sub": "app-rest-api-${AWS::StackName}" | |
} | |
}, | |
"Type": "AWS::ApiGateway::RestApi" | |
}, | |
"AppStage": { | |
"Properties": { | |
"DeploymentId": { | |
"Ref": "AppDeployment" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"StageName": "prod" | |
}, | |
"Type": "AWS::ApiGateway::Stage" | |
}, | |
"AppUserPool": { | |
"Properties": { | |
"AutoVerifiedAttributes": [ | |
"email" | |
], | |
"Policies": { | |
"PasswordPolicy": { | |
"MinimumLength": 8, | |
"RequireLowercase": true, | |
"RequireNumbers": true, | |
"RequireSymbols": true, | |
"RequireUppercase": true | |
} | |
}, | |
"Schema": [ | |
{ | |
"AttributeDataType": "String", | |
"Mutable": true, | |
"Name": "email", | |
"Required": true, | |
"StringAttributeConstraints": { | |
"MinLength": "1" | |
} | |
} | |
], | |
"UsernameAttributes": [ | |
"email" | |
] | |
}, | |
"Type": "AWS::Cognito::UserPool" | |
}, | |
"AppUserPoolAdminClient": { | |
"Properties": { | |
"ExplicitAuthFlows": [ | |
"ALLOW_ADMIN_USER_PASSWORD_AUTH", | |
"ALLOW_REFRESH_TOKEN_AUTH" | |
], | |
"PreventUserExistenceErrors": "ENABLED", | |
"UserPoolId": { | |
"Ref": "AppUserPool" | |
} | |
}, | |
"Type": "AWS::Cognito::UserPoolClient" | |
}, | |
"AppUserPoolWebClient": { | |
"Properties": { | |
"ExplicitAuthFlows": [ | |
"ALLOW_USER_SRP_AUTH", | |
"ALLOW_REFRESH_TOKEN_AUTH" | |
], | |
"PreventUserExistenceErrors": "ENABLED", | |
"UserPoolId": { | |
"Ref": "AppUserPool" | |
} | |
}, | |
"Type": "AWS::Cognito::UserPoolClient" | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Outputs": { | |
"AppRestApi": { | |
"Value": { | |
"Ref": "AppRestApi" | |
} | |
} | |
}, | |
"Parameters": { | |
"CertificateArn": { | |
"Type": "String" | |
}, | |
"DomainName": { | |
"Type": "String" | |
} | |
}, | |
"Resources": { | |
"AppBasePathMapping": { | |
"DependsOn": [ | |
"AppDomainName" | |
], | |
"Properties": { | |
"DomainName": { | |
"Ref": "DomainName" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"Stage": "prod" | |
}, | |
"Type": "AWS::ApiGateway::BasePathMapping" | |
}, | |
"AppDeployment": { | |
"DependsOn": [ | |
"AppHelloGetPublicLambdaMethod", | |
"AppHelloGetCorsMethod", | |
"AppHelloPostPublicLambdaMethod", | |
"AppHelloPostCorsMethod" | |
], | |
"Properties": { | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Deployment" | |
}, | |
"AppDomainName": { | |
"Properties": { | |
"CertificateArn": { | |
"Ref": "CertificateArn" | |
}, | |
"DomainName": { | |
"Ref": "DomainName" | |
} | |
}, | |
"Type": "AWS::ApiGateway::DomainName" | |
}, | |
"AppGatewayResponse4xx": { | |
"Properties": { | |
"ResponseParameters": { | |
"gatewayresponse.header.Access-Control-Allow-Headers": "'*'", | |
"gatewayresponse.header.Access-Control-Allow-Origin": "'*'" | |
}, | |
"ResponseType": "DEFAULT_4XX", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::GatewayResponse" | |
}, | |
"AppGatewayResponse5xx": { | |
"Properties": { | |
"ResponseParameters": { | |
"gatewayresponse.header.Access-Control-Allow-Headers": "'*'", | |
"gatewayresponse.header.Access-Control-Allow-Origin": "'*'" | |
}, | |
"ResponseType": "DEFAULT_5XX", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::GatewayResponse" | |
}, | |
"AppHelloGetCorsMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "OPTIONS", | |
"Integration": { | |
"IntegrationResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Sec'", | |
"method.response.header.Access-Control-Allow-Methods": "'GET,OPTIONS'", | |
"method.response.header.Access-Control-Allow-Origin": "'*'" | |
}, | |
"ResponseTemplates": { | |
"application/json": "" | |
}, | |
"StatusCode": 200 | |
} | |
], | |
"PassthroughBehavior": "WHEN_NO_MATCH", | |
"RequestTemplates": { | |
"application/json": "{\"statusCode\": 200}" | |
}, | |
"Type": "MOCK" | |
}, | |
"MethodResponses": [ | |
{ | |
"ResponseModels": { | |
"application/json": "Empty" | |
}, | |
"ResponseParameters": { | |
"method.response.header.Access-Control-Allow-Headers": false, | |
"method.response.header.Access-Control-Allow-Methods": false, | |
"method.response.header.Access-Control-Allow-Origin": false | |
}, | |
"StatusCode": 200 | |
} | |
], | |
"ResourceId": { | |
"Ref": "AppHelloGetResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppHelloGetFunction": { | |
"Properties": { | |
"Code": { | |
"ZipFile": "def handler(event, context):\n message=event[\"queryStringParameters\"][\"message\"]\n return {\"statusCode\": 200,\n \"headers\": {\"Content-Type\": \"text/plain\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Headers\": \"Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent\",\n \"Access-Control-Allow-Methods\": \"OPTIONS,GET\"},\n \"body\": f\"you sent '{message}' via GET\"}" | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 512, | |
"Role": { | |
"Fn::GetAtt": [ | |
"AppHelloGetRole", | |
"Arn" | |
] | |
}, | |
"Runtime": "python3.10", | |
"Timeout": 5 | |
}, | |
"Type": "AWS::Lambda::Function" | |
}, | |
"AppHelloGetParameterRequestValidator": { | |
"Properties": { | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"ValidateRequestBody": false, | |
"ValidateRequestParameters": true | |
}, | |
"Type": "AWS::ApiGateway::RequestValidator" | |
}, | |
"AppHelloGetPermission": { | |
"Properties": { | |
"Action": "lambda:InvokeFunction", | |
"FunctionName": { | |
"Ref": "AppHelloGetFunction" | |
}, | |
"Principal": "apigateway.amazonaws.com", | |
"SourceArn": { | |
"Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${AppRestApi}/${AppStage}/GET/hello-get" | |
} | |
}, | |
"Type": "AWS::Lambda::Permission" | |
}, | |
"AppHelloGetPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
}, | |
{ | |
"Action": [ | |
"s3:GetObject" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "app-hello-get-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "AppHelloGetRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"AppHelloGetPublicLambdaMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "GET", | |
"Integration": { | |
"IntegrationHttpMethod": "POST", | |
"Type": "AWS_PROXY", | |
"Uri": { | |
"Fn::Sub": [ | |
"arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${arn}/invocations", | |
{ | |
"arn": { | |
"Fn::GetAtt": [ | |
"AppHelloGetFunction", | |
"Arn" | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RequestParameters": { | |
"method.request.querystring.message": true | |
}, | |
"RequestValidatorId": { | |
"Ref": "AppHelloGetParameterRequestValidator" | |
}, | |
"ResourceId": { | |
"Ref": "AppHelloGetResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppHelloGetResource": { | |
"Properties": { | |
"ParentId": { | |
"Fn::GetAtt": [ | |
"AppRestApi", | |
"RootResourceId" | |
] | |
}, | |
"PathPart": "hello-get", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Resource" | |
}, | |
"AppHelloGetRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "lambda.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"AppHelloPostCorsMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "OPTIONS", | |
"Integration": { | |
"IntegrationResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Sec'", | |
"method.response.header.Access-Control-Allow-Methods": "'POST,OPTIONS'", | |
"method.response.header.Access-Control-Allow-Origin": "'*'" | |
}, | |
"ResponseTemplates": { | |
"application/json": "" | |
}, | |
"StatusCode": 200 | |
} | |
], | |
"PassthroughBehavior": "WHEN_NO_MATCH", | |
"RequestTemplates": { | |
"application/json": "{\"statusCode\": 200}" | |
}, | |
"Type": "MOCK" | |
}, | |
"MethodResponses": [ | |
{ | |
"ResponseModels": { | |
"application/json": "Empty" | |
}, | |
"ResponseParameters": { | |
"method.response.header.Access-Control-Allow-Headers": false, | |
"method.response.header.Access-Control-Allow-Methods": false, | |
"method.response.header.Access-Control-Allow-Origin": false | |
}, | |
"StatusCode": 200 | |
} | |
], | |
"ResourceId": { | |
"Ref": "AppHelloPostResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppHelloPostFunction": { | |
"Properties": { | |
"Code": { | |
"ZipFile": "import json\ndef handler(event, context):\n body=json.loads(event[\"body\"])\n message=body[\"message\"]\n return {\"statusCode\": 200,\n \"headers\": {\"Content-Type\": \"text/plain\",\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Headers\": \"Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent\",\n \"Access-Control-Allow-Methods\": \"OPTIONS,POST\"},\n \"body\": f\"you sent '{message}' via POST\"}" | |
}, | |
"Handler": "index.handler", | |
"MemorySize": 512, | |
"Role": { | |
"Fn::GetAtt": [ | |
"AppHelloPostRole", | |
"Arn" | |
] | |
}, | |
"Runtime": "python3.10", | |
"Timeout": 5 | |
}, | |
"Type": "AWS::Lambda::Function" | |
}, | |
"AppHelloPostModel": { | |
"Properties": { | |
"ContentType": "application/json", | |
"Name": "AppHelloPostModel", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"Schema": { | |
"$schema": "http://json-schema.org/draft-04/schema#", | |
"additionalProperties": false, | |
"properties": { | |
"message": { | |
"type": "string" | |
} | |
}, | |
"required": [ | |
"message" | |
], | |
"type": "object" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Model" | |
}, | |
"AppHelloPostPermission": { | |
"Properties": { | |
"Action": "lambda:InvokeFunction", | |
"FunctionName": { | |
"Ref": "AppHelloPostFunction" | |
}, | |
"Principal": "apigateway.amazonaws.com", | |
"SourceArn": { | |
"Fn::Sub": "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${AppRestApi}/${AppStage}/POST/hello-post" | |
} | |
}, | |
"Type": "AWS::Lambda::Permission" | |
}, | |
"AppHelloPostPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"logs:CreateLogGroup", | |
"logs:CreateLogStream", | |
"logs:PutLogEvents" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
}, | |
{ | |
"Action": [ | |
"s3:GetObject", | |
"s3:PutObject" | |
], | |
"Effect": "Allow", | |
"Resource": "*" | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "app-hello-post-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "AppHelloPostRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"AppHelloPostPublicLambdaMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "POST", | |
"Integration": { | |
"IntegrationHttpMethod": "POST", | |
"Type": "AWS_PROXY", | |
"Uri": { | |
"Fn::Sub": [ | |
"arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${arn}/invocations", | |
{ | |
"arn": { | |
"Fn::GetAtt": [ | |
"AppHelloPostFunction", | |
"Arn" | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RequestModels": { | |
"application/json": "AppHelloPostModel" | |
}, | |
"RequestValidatorId": { | |
"Ref": "AppHelloPostSchemaRequestValidator" | |
}, | |
"ResourceId": { | |
"Ref": "AppHelloPostResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppHelloPostResource": { | |
"Properties": { | |
"ParentId": { | |
"Fn::GetAtt": [ | |
"AppRestApi", | |
"RootResourceId" | |
] | |
}, | |
"PathPart": "hello-post", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Resource" | |
}, | |
"AppHelloPostRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "lambda.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"AppHelloPostSchemaRequestValidator": { | |
"Properties": { | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"ValidateRequestBody": true, | |
"ValidateRequestParameters": false | |
}, | |
"Type": "AWS::ApiGateway::RequestValidator" | |
}, | |
"AppRecordSet": { | |
"Properties": { | |
"AliasTarget": { | |
"DNSName": { | |
"Fn::GetAtt": [ | |
"AppDomainName", | |
"DistributionDomainName" | |
] | |
}, | |
"EvaluateTargetHealth": false, | |
"HostedZoneId": { | |
"Fn::GetAtt": [ | |
"AppDomainName", | |
"DistributionHostedZoneId" | |
] | |
} | |
}, | |
"HostedZoneName": { | |
"Fn::Sub": [ | |
"${prefix}.${suffix}.", | |
{ | |
"prefix": { | |
"Fn::Select": [ | |
1, | |
{ | |
"Fn::Split": [ | |
".", | |
{ | |
"Ref": "DomainName" | |
} | |
] | |
} | |
] | |
}, | |
"suffix": { | |
"Fn::Select": [ | |
2, | |
{ | |
"Fn::Split": [ | |
".", | |
{ | |
"Ref": "DomainName" | |
} | |
] | |
} | |
] | |
} | |
} | |
] | |
}, | |
"Name": { | |
"Ref": "DomainName" | |
}, | |
"Type": "A" | |
}, | |
"Type": "AWS::Route53::RecordSet" | |
}, | |
"AppRestApi": { | |
"Properties": { | |
"Name": { | |
"Fn::Sub": "app-rest-api-${AWS::StackName}" | |
} | |
}, | |
"Type": "AWS::ApiGateway::RestApi" | |
}, | |
"AppStage": { | |
"Properties": { | |
"DeploymentId": { | |
"Ref": "AppDeployment" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"StageName": "prod" | |
}, | |
"Type": "AWS::ApiGateway::Stage" | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Outputs": { | |
"AppBucket": { | |
"Value": { | |
"Ref": "AppBucket" | |
} | |
}, | |
"AppRestApi": { | |
"Value": { | |
"Ref": "AppRestApi" | |
} | |
} | |
}, | |
"Parameters": { | |
"CertificateArn": { | |
"Type": "String" | |
}, | |
"DomainName": { | |
"Type": "String" | |
} | |
}, | |
"Resources": { | |
"AppBasePathMapping": { | |
"DependsOn": [ | |
"AppDomainName" | |
], | |
"Properties": { | |
"DomainName": { | |
"Ref": "DomainName" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"Stage": "prod" | |
}, | |
"Type": "AWS::ApiGateway::BasePathMapping" | |
}, | |
"AppBucket": { | |
"Properties": { | |
"NotificationConfiguration": { | |
"EventBridgeConfiguration": { | |
"EventBridgeEnabled": true | |
} | |
} | |
}, | |
"Type": "AWS::S3::Bucket" | |
}, | |
"AppDeployment": { | |
"DependsOn": [ | |
"AppProxyMethod", | |
"AppRedirectMethod" | |
], | |
"Properties": { | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Deployment" | |
}, | |
"AppDomainName": { | |
"Properties": { | |
"CertificateArn": { | |
"Ref": "CertificateArn" | |
}, | |
"DomainName": { | |
"Ref": "DomainName" | |
} | |
}, | |
"Type": "AWS::ApiGateway::DomainName" | |
}, | |
"AppPolicy": { | |
"Properties": { | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"s3:GetObject" | |
], | |
"Effect": "Allow", | |
"Resource": { | |
"Fn::Sub": "arn:aws:s3:::${AppBucket}/*" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
}, | |
"PolicyName": { | |
"Fn::Sub": "app-policy-${AWS::StackName}" | |
}, | |
"Roles": [ | |
{ | |
"Ref": "AppRole" | |
} | |
] | |
}, | |
"Type": "AWS::IAM::Policy" | |
}, | |
"AppProxyMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "GET", | |
"Integration": { | |
"Credentials": { | |
"Fn::GetAtt": [ | |
"AppRole", | |
"Arn" | |
] | |
}, | |
"IntegrationHttpMethod": "ANY", | |
"IntegrationResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Content-Type": "integration.response.header.Content-Type" | |
}, | |
"StatusCode": 200 | |
}, | |
{ | |
"SelectionPattern": "404", | |
"StatusCode": 404 | |
} | |
], | |
"PassthroughBehavior": "WHEN_NO_MATCH", | |
"RequestParameters": { | |
"integration.request.path.proxy": "method.request.path.proxy" | |
}, | |
"Type": "AWS", | |
"Uri": { | |
"Fn::Sub": "arn:aws:apigateway:${AWS::Region}:s3:path/${AppBucket}/{proxy}" | |
} | |
}, | |
"MethodResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Content-Type": true | |
}, | |
"StatusCode": 200 | |
}, | |
{ | |
"StatusCode": 404 | |
} | |
], | |
"RequestParameters": { | |
"method.request.path.proxy": true | |
}, | |
"ResourceId": { | |
"Ref": "AppResource" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppRecordSet": { | |
"Properties": { | |
"AliasTarget": { | |
"DNSName": { | |
"Fn::GetAtt": [ | |
"AppDomainName", | |
"DistributionDomainName" | |
] | |
}, | |
"EvaluateTargetHealth": false, | |
"HostedZoneId": { | |
"Fn::GetAtt": [ | |
"AppDomainName", | |
"DistributionHostedZoneId" | |
] | |
} | |
}, | |
"HostedZoneName": { | |
"Fn::Sub": [ | |
"${prefix}.${suffix}.", | |
{ | |
"prefix": { | |
"Fn::Select": [ | |
1, | |
{ | |
"Fn::Split": [ | |
".", | |
{ | |
"Ref": "DomainName" | |
} | |
] | |
} | |
] | |
}, | |
"suffix": { | |
"Fn::Select": [ | |
2, | |
{ | |
"Fn::Split": [ | |
".", | |
{ | |
"Ref": "DomainName" | |
} | |
] | |
} | |
] | |
} | |
} | |
] | |
}, | |
"Name": { | |
"Ref": "DomainName" | |
}, | |
"Type": "A" | |
}, | |
"Type": "AWS::Route53::RecordSet" | |
}, | |
"AppRedirectMethod": { | |
"Properties": { | |
"AuthorizationType": "NONE", | |
"HttpMethod": "GET", | |
"Integration": { | |
"IntegrationResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Location": { | |
"Fn::Sub": "'https://${DomainName}/index.html'" | |
} | |
}, | |
"ResponseTemplates": { | |
"application/json": "{}" | |
}, | |
"StatusCode": 302 | |
} | |
], | |
"RequestTemplates": { | |
"application/json": "{\"statusCode\" : 302}" | |
}, | |
"Type": "MOCK" | |
}, | |
"MethodResponses": [ | |
{ | |
"ResponseParameters": { | |
"method.response.header.Location": true | |
}, | |
"StatusCode": 302 | |
} | |
], | |
"ResourceId": { | |
"Fn::GetAtt": [ | |
"AppRestApi", | |
"RootResourceId" | |
] | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Method" | |
}, | |
"AppResource": { | |
"Properties": { | |
"ParentId": { | |
"Fn::GetAtt": [ | |
"AppRestApi", | |
"RootResourceId" | |
] | |
}, | |
"PathPart": "{proxy+}", | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
} | |
}, | |
"Type": "AWS::ApiGateway::Resource" | |
}, | |
"AppRestApi": { | |
"Properties": { | |
"Name": { | |
"Fn::Sub": "app-rest-api-${AWS::StackName}" | |
} | |
}, | |
"Type": "AWS::ApiGateway::RestApi" | |
}, | |
"AppRole": { | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Statement": [ | |
{ | |
"Action": [ | |
"sts:AssumeRole" | |
], | |
"Effect": "Allow", | |
"Principal": { | |
"Service": "apigateway.amazonaws.com" | |
} | |
} | |
], | |
"Version": "2012-10-17" | |
} | |
}, | |
"Type": "AWS::IAM::Role" | |
}, | |
"AppStage": { | |
"Properties": { | |
"DeploymentId": { | |
"Ref": "AppDeployment" | |
}, | |
"RestApiId": { | |
"Ref": "AppRestApi" | |
}, | |
"StageName": "prod" | |
}, | |
"Type": "AWS::ApiGateway::Stage" | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment