-
Notifications
You must be signed in to change notification settings - Fork 920
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Amazon API Gateway GeoLocation REST API Disaster Recovery #2394
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,129 @@ | ||||||
# Amazon API Gateway GeoLocation REST API Disaster Recovery | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
Customers often want to access the resources from the same country where user resides and this pattern will help them to achieve the same. This demo also demonstrates an Amazon API Gateway multi-region active-passive public API that proxies two independent multi-region active-passive Lambda function. | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the AWS Pricing page for details. You are responsible for any AWS costs incurred. No warranty is implied in this example. | ||||||
|
||||||
# Requirements | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should add required AWS resources here as well (domain, certificate) |
||||||
|
||||||
* Create an AWS account if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources. | ||||||
* AWS CLI installed and configured | ||||||
* Git Installed | ||||||
* AWS Serverless Application Model (AWS SAM) installed | ||||||
|
||||||
|
||||||
# Deployment Instructions | ||||||
|
||||||
1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository: | ||||||
|
||||||
``` | ||||||
git clone https://github.com/aws-samples/serverless-patterns | ||||||
``` | ||||||
|
||||||
|
||||||
2. Change directory to: | ||||||
|
||||||
``` | ||||||
cd apigw-geo-location-failover | ||||||
``` | ||||||
|
||||||
3. From the command line, use AWS SAM to deploy the AWS resources for the stack as specified in the template.yml file on the primary region: | ||||||
|
||||||
``` | ||||||
sam deploy -—guided —config-env primary | ||||||
``` | ||||||
|
||||||
- During the prompts: | ||||||
|
||||||
* **Stack Name:** Enter a stack name. | ||||||
* **AWS Region:** Enter the desired secondary AWS Region. This stack has been tested with both us-east-1 and us-east-2. **Make sure to use a different region from the primary one but within the same country**. | ||||||
* **PublicHostedZoneId:** You must have a public hosted zone in Route 53 with your domain name (i.e. mydomain.com). Enter the Hosted Zone Id for this hosted zone. | ||||||
* **DomainName:** Enter your custom domain name (i.e. externalapi.mydomain.com). | ||||||
* **CertificateArn** You must have an ACM certificate that covers your custom domain namespace (i.e. *.mydomain.com) on the region your are deploying this stack. Enter the ARN for this certificate here. **Make sure you are getting the certificate arn for the right region**. | ||||||
* **FailoverDomainName:** Enter your failover domain name (i.e. failover.mydomain.com) | ||||||
* **Priority:** Enter “SECONDARY” here | ||||||
* **GeoLocationValue:** Enter the country code | ||||||
* Allow SAM CLI to create IAM roles with the required permissions. | ||||||
* Allow SAM CLI to create the LambdaRegionalApi Lambda function. | ||||||
* **SAM configuration environment** Accept the **secondary** default value. | ||||||
|
||||||
Once you have run `sam deploy --guided --config-env primary` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy --config-env primary` in future to use these defaults. | ||||||
|
||||||
|
||||||
4. From the command line, use AWS SAM to deploy the AWS resources for the stack as specified in the template.yml file on the secondary region: | ||||||
|
||||||
``` | ||||||
sam deploy —guided —config-env secondary | ||||||
``` | ||||||
|
||||||
- During the prompts: | ||||||
|
||||||
* **Stack Name:** Enter a stack name. | ||||||
* **AWS Region:** Enter the desired secondary AWS Region. This stack has been tested with both us-east-1 and us-east-2. **Make sure to use a different region from the primary one but within the same country**. | ||||||
* **PublicHostedZoneId:** You must have a public hosted zone in Route 53 with your domain name (i.e. mydomain.com). Enter the Hosted Zone Id for this hosted zone. | ||||||
* **DomainName:** Enter your custom domain name (i.e. externalapi.mydomain.com). | ||||||
* **CertificateArn** You must have an ACM certificate that covers your custom domain namespace (i.e. *.mydomain.com) on the region your are deploying this stack. Enter the ARN for this certificate here. **Make sure you are getting the certificate arn for the right region**. | ||||||
* **FailoverDomainName:** Enter your failover domain name (i.e. failover.mydomain.com) | ||||||
* **Priority:** Enter “SECONDARY” here | ||||||
* **GeoLocationValue:** Enter the country code | ||||||
* Allow SAM CLI to create IAM roles with the required permissions. | ||||||
* Allow SAM CLI to create the LambdaRegionalApi Lambda function. | ||||||
* **SAM configuration environment** Accept the **secondary** default value. | ||||||
|
||||||
Once you have run `sam deploy --guided --config-env secondary` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy --config-env secondary` in future to use these defaults. | ||||||
|
||||||
``` | ||||||
Note the output from the SAM deployment process. These contain details which are used for testing. | ||||||
``` | ||||||
|
||||||
# How it works | ||||||
|
||||||
1. You will deploy the same template in two separate regions: | ||||||
|
||||||
- When you deploy template in the Primary region, it will create a custom domain name , Geolocation route of custom domain name mapped to failover route, a Primary Record for failover routing mapped to API gateway domain name and Lambda function integrated with API gateway. | ||||||
- When you deploy template in the Secondary region, it will create a custom domain name, a Primary Record for failover routing mapped to API Gateway domain name and Lambda function integrated with API gateway. | ||||||
|
||||||
|
||||||
2. If an issue with the primary region occurs, you can user Amazon Route53 ARC to route traffic to the secondary region. | ||||||
|
||||||
3. This example demonstrates the failover only and does not encompass authentication and data for the multiple regions. | ||||||
|
||||||
Testing | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
Once the stack is deployed, get the custom domain name output parameter. | ||||||
Paste the URL in a browser, or in Postman, or using the curl command. | ||||||
Eg: | ||||||
|
||||||
``` | ||||||
curl https://externalapi.mydomain.com/ | ||||||
``` | ||||||
|
||||||
You should see a response similar to when request made from the same country as GeoLocation: | ||||||
|
||||||
``` | ||||||
{"message" : "Hello World! This is the regional API"} | ||||||
``` | ||||||
|
||||||
You should see a response similar to when request made from the same country as GeoLocation: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate or something missing, no different command executed |
||||||
|
||||||
``` | ||||||
Could not resolve host: https | ||||||
Closing connection | ||||||
curl: (6) Could not resolve host: https | ||||||
``` | ||||||
|
||||||
|
||||||
|
||||||
# Cleanup | ||||||
|
||||||
1. Delete the stack on the primary region. | ||||||
|
||||||
``` | ||||||
sam delete --config-env primary | ||||||
``` | ||||||
|
||||||
2. Delete the stack on the secondary region. | ||||||
|
||||||
``` | ||||||
sam delete --config-env secondary | ||||||
``` |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The file is syntactically incorrect, and e.g. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
{ | ||
"title": "Amazon API Gateway GeoLocation REST API Disaster Recovery”, | ||
"description": "The SAM template deploys a multi-region active-passive public API that proxies two independent multi-region active-passive Lambda function ”, | ||
"language": "Python", | ||
"level": "200", | ||
"framework": "SAM", | ||
"gitHub": { | ||
"template": { | ||
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-geo-location-failover", | ||
"templateURL": "serverless-patterns/apigw-geo-location-failover", | ||
"projectFolder": "apigw-geo-location-failover", | ||
"templateFile": "template.yaml" | ||
} | ||
}, | ||
"deploy": { | ||
"text": [ | ||
"sam deploy" | ||
] | ||
}, | ||
"testing": { | ||
"text": [ | ||
"See the GitHub repo for detailed testing instructions." | ||
] | ||
}, | ||
"cleanup": { | ||
"text": [ | ||
"Delete the stack: <code>sam delete</code>." | ||
] | ||
}, | ||
"authors": [ | ||
{ | ||
"name": "Manasvi Jain", | ||
"image": "https://avatars.githubusercontent.com/u/56217984?v=4", | ||
"bio": "Cloud Engineer at AWS", | ||
"linkedin": "https://www.linkedin.com/in/manasvi-jain-36b9941a3/" | ||
}, | ||
{ | ||
"name": "Umang Aggarwal", | ||
"image": "https://avatars.githubusercontent.com/Umang071", | ||
"bio": "Cloud Engineer II @ AWS", | ||
"linkedin": "https://www.linkedin.com/in/umangaggarwal" | ||
} | ||
] | ||
} | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,128 @@ | ||||||
AWSTemplateFormatVersion: '2010-09-09' | ||||||
Transform: AWS::Serverless-2016-10-31 | ||||||
Description: Serverless patterns - Amazon API Gateway Custom Domain Name (uksb-1tthgi812) (tag:apigw-custom-domain-regional) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
Parameters: | ||||||
|
||||||
DomainName: | ||||||
Type: String | ||||||
|
||||||
CertificateArn: | ||||||
Type: String | ||||||
|
||||||
PublicHostedZoneId: | ||||||
Type: String | ||||||
|
||||||
FailoverDomainName: | ||||||
Type: String | ||||||
|
||||||
GeoLocationValue: | ||||||
Type: String | ||||||
|
||||||
Priority: | ||||||
Type: String | ||||||
Description: PRIMARY or SECONDARY | ||||||
AllowedValues: ["PRIMARY", "SECONDARY"] | ||||||
|
||||||
Conditions: | ||||||
CreatePrimaryResources: !Equals | ||||||
- !Ref Priority | ||||||
- PRIMARY | ||||||
|
||||||
Resources: | ||||||
#Lambda function | ||||||
LambdaRegionalApi: | ||||||
Type: AWS::Serverless::Function | ||||||
Properties: | ||||||
Handler: index.lambda_handler | ||||||
InlineCode: | | ||||||
import json | ||||||
def lambda_handler(event, context): | ||||||
return { | ||||||
"statusCode": 200, | ||||||
"body": json.dumps({ | ||||||
"message" : "Hello World! This is the regional API"}) | ||||||
} | ||||||
Runtime: python3.9 | ||||||
Events: | ||||||
HelloWorld: | ||||||
Type: Api | ||||||
Properties: | ||||||
Path: / | ||||||
Method: get | ||||||
RestApiId: | ||||||
Ref: ApiRegional | ||||||
|
||||||
#REST Regional API | ||||||
ApiRegional: | ||||||
Type: AWS::Serverless::Api | ||||||
Properties: | ||||||
StageName: prod | ||||||
EndpointConfiguration: REGIONAL | ||||||
|
||||||
CustomDomainRegional: | ||||||
Type: AWS::ApiGatewayV2::DomainName | ||||||
Properties: | ||||||
DomainName: !Ref DomainName | ||||||
DomainNameConfigurations: | ||||||
- SecurityPolicy: TLS_1_2 | ||||||
CertificateArn: !Ref CertificateArn | ||||||
EndpointType: REGIONAL | ||||||
|
||||||
MappingRegional: | ||||||
Type: AWS::ApiGatewayV2::ApiMapping | ||||||
DependsOn: | ||||||
- CustomDomainRegional | ||||||
Properties: | ||||||
DomainName: !Ref DomainName | ||||||
ApiId: !Ref ApiRegional | ||||||
Stage: !Ref ApiRegional.Stage | ||||||
|
||||||
HealthCheck: | ||||||
Type: AWS::Route53::HealthCheck | ||||||
Properties: | ||||||
HealthCheckConfig: | ||||||
EnableSNI: true | ||||||
FullyQualifiedDomainName: !Sub ${ApiRegional}.execute-api.${AWS::Region}.amazonaws.com | ||||||
Type: HTTPS | ||||||
FailureThreshold: 3 ## Default is 3 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
MeasureLatency: true ## Cannot be changed after creation | ||||||
ResourcePath: /Prod | ||||||
|
||||||
FailoverRecord: | ||||||
Type: AWS::Route53::RecordSet | ||||||
DependsOn: | ||||||
- CustomDomainRegional | ||||||
Properties: | ||||||
Failover: !Ref Priority | ||||||
Name: !Ref FailoverDomainName | ||||||
HostedZoneId: !Ref PublicHostedZoneId | ||||||
HealthCheckId: !Ref HealthCheck | ||||||
SetIdentifier: !Sub ${AWS::Region}-failover | ||||||
AliasTarget: | ||||||
DNSName: !GetAtt CustomDomainRegional.RegionalDomainName | ||||||
HostedZoneId: !GetAtt CustomDomainRegional.RegionalHostedZoneId | ||||||
Type: A | ||||||
|
||||||
GeoLocationRecord: | ||||||
Condition: CreatePrimaryResources | ||||||
Type: AWS::Route53::RecordSet | ||||||
DependsOn: | ||||||
- FailoverRecord | ||||||
Properties: | ||||||
GeoLocation: | ||||||
CountryCode: !Ref GeoLocationValue | ||||||
Name: !Ref DomainName | ||||||
SetIdentifier: !Sub ${AWS::Region}-geolocation | ||||||
HostedZoneId: !Ref PublicHostedZoneId | ||||||
AliasTarget: | ||||||
DNSName: !Ref FailoverDomainName | ||||||
HostedZoneId: !Ref PublicHostedZoneId | ||||||
Type: A | ||||||
|
||||||
Outputs: | ||||||
|
||||||
# Custom Domain Name endpoint to be used during tests | ||||||
CustomDomainNameEndpoint: | ||||||
Description: Custom Domain Name endpoint | ||||||
Value: !Sub "https://${DomainName}"/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please improve on the testing part and provide an example on how to verify the failover is working.