Skip to content

Commit a4508b8

Browse files
authored
Merge pull request #2523 from usama-khan98/usama-khan98-feature-private-apigw-custom-domain
New serverless pattern - Private Api Gateway Custom Domain Name
2 parents 8f4d800 + a31dad1 commit a4508b8

File tree

4 files changed

+326
-0
lines changed

4 files changed

+326
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Private Amazon API Gateway with private custom domain name
2+
3+
The AWS SAM template deploys a private Amazon API Gateway with a private custom domain name mapped to deployed stage. This template also create a Amazon Route53 A-Alias record in a private hosted zone to map the private custom domain name (e.g. `private.mydomain.com`) to the target VPC Endpoint DNS name. (e.g. `vpce-abcdefgh123456789-abcd1234.execute-api.us-east-1.vpce.amazonaws.com`).
4+
5+
Learn more about this pattern at [Serverless Land Patterns](https://serverlessland.com/patterns/private-apigw-custom-domain)
6+
7+
## Requirements
8+
9+
* An [AWS account](https://signin.aws.amazon.com/signup?request_type=register) with an IAM user or role that has sufficient permissions to make the necessary AWS service calls and manage AWS resources.
10+
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured.
11+
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git).
12+
* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed.
13+
* An [execute-api VPC Endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/interface-endpoints.html).
14+
* A Route 53 [Private Hosted Zone](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/hosted-zones-private.html). (*You can also use Public Hosted Zone but it is recommnded to use Private Hosted Zone to make sure that the Domain Name is only resolvable from within the VPC*)
15+
* An SSL/TLS certificate in [AWS Certificate Manager](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-specify-certificate-for-custom-domain-name.html#how-to-specify-certificate-for-custom-domain-name-setup).
16+
17+
## Deployment Instructions
18+
19+
1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
20+
```bash
21+
git clone https://github.com/aws-samples/serverless-patterns
22+
```
23+
2. Change directory to the pattern directory:
24+
```bash
25+
cd serverless-patterns/private-apigw-custom-domain
26+
```
27+
3. From the command line, use AWS SAM to deploy the AWS resources for the pattern as specified in the template.yml file:
28+
```bash
29+
sam deploy --guided
30+
```
31+
4. During the prompts:
32+
- Enter **stack name** and desired **AWS Region**.
33+
- Enter **DNS Name** of the **execute-api** VPC endpoint for the VpcEndpointDNSName parameter. (e.g. vpce-abcdefgh123456789-abcd1234.execute-api.us-east-1.vpce.amazonaws.com)
34+
- Enter **Hosted Zone ID** of the **execute-api** VPC endpoint for the VPCEndpointHostedZoneID parameter. (This can be found along with the DNS Name of the VPC endpoing on the AWS Console.)
35+
- Enter **Private Custom Domain Name** (e.g. private.mydomain.com) for the CustomDomainName parameter.
36+
- Enter **ACM Certificate ARN** from the same region as Private Amazon API Gateway for the CertificateArn parameter. The certificate must cover the Private Custom Domain name entered in the previous step.
37+
- Enter **Private Hosted Zone ID** that has the domain name you would like to use for the parameter PrivateHostedZoneId.
38+
- Allow SAM to create roles with the required permissions if needed.
39+
40+
Once you have run guided mode once, you can use `sam deploy` in future to use these defaults.
41+
42+
1. Note the outputs from the SAM deployment process. This contain the curl command to test the Private Custom Domain Name.
43+
44+
## Testing
45+
46+
The stack will output the **Private Custom Domain Name**. You can use `curl` to send a HTTP request to the Private Custom Domain endpoint to test the correct mapping to your API.
47+
48+
```bash
49+
curl https://{PrivateCustomDomainName}/
50+
```
51+
52+
## Cleanup
53+
54+
1. Delete the stack
55+
```bash
56+
sam delete
57+
```
58+
1. Confirm the stack has been deleted
59+
```bash
60+
aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus"
61+
```
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"title": "Private Amazon API Gateway with private custom domain name",
3+
"description": "Create a Private API Gateway with a private custom domain name, configure access based on VPC endpoint, and set up DNS routing using Amazon Route 53 private hosted zone.",
4+
"language": "",
5+
"level": "200",
6+
"framework": "SAM",
7+
"introBox": {
8+
"headline": "How it works",
9+
"text": [
10+
"This AWS SAM template demonstrates how to create a private Amazon API Gateway with a private custom domain mame, configure secure access based on a specific VPC endpoint, and route traffic through Route 53 in a private hosted zone.",
11+
"Private custom domain name is only accessible from a VPC endpoint, which is mapped to a stage in private Amazon API Gateway. A custom domain name is configured with an SSL/TLS certificate to provide secure access, and an associated Route 53 A-Alias record ensures that traffic is routed to the API.",
12+
"As prerequisites for this pattern, you must have:"
13+
"* A DNS name of execute-api VPC endpoint",
14+
"* A custom domain name that you would like to create (e.g. private.mydomain.com)",
15+
"* A valid certificate in ACM (Amazon Certificate Manager) in the same Region as Private Amazon API Gateway, that covers the namespace of the domain you would like to use (i.e. *.mydomain.com).",
16+
"* A Route 53 Private Hosted Zone ID that has the domain name you would like to use (e.g. mydomain.com).",
17+
]
18+
},
19+
"gitHub": {
20+
"template": {
21+
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/private-apigw-custom-domain",
22+
"templateURL": "serverless-patterns/private-apigw-custom-domain",
23+
"projectFolder": "private-apigw-custom-domain",
24+
"templateFile": "template.yaml"
25+
}
26+
},
27+
"resources": {
28+
"bullets": [
29+
{
30+
"text": "Custom domain names for private APIs in API Gateway",
31+
"link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-custom-domains.html"
32+
}
33+
]
34+
},
35+
"deploy": {
36+
"text": [
37+
"Deploy the stack: <code>sam deploy --guided</code>
38+
]
39+
},
40+
"testing": {
41+
"text": [
42+
"See the GitHub repo for detailed testing instructions."
43+
]
44+
},
45+
"cleanup": {
46+
"text": [
47+
"Delete the stack: <code>sam delete</code>."
48+
]
49+
},
50+
"authors": [
51+
{
52+
"name": "Usama Ali Khan",
53+
"image": "https://media.licdn.com/dms/image/v2/D4E03AQHcLMpZ1LV9UQ/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1685892371158?e=1737590400&v=beta&t=RaPZkIgm7m3thW4PyKSQNn_w9fMbYBeu5PPrQ6K4vBU",
54+
"bio": "Usama is a Technical Account Manager at Amazon Web Services.",
55+
"linkedin": "usama-ali-khan"
56+
}
57+
]
58+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
{
2+
"title": "Private Amazon API Gateway with private custom domain name",
3+
"description": "Create a Private API Gateway with a custom domain. Configure access via VPC endpoint and set up DNS routing with Amazon Route 53 private hosted zone.",
4+
"language": "",
5+
"level": "200",
6+
"framework": "SAM",
7+
"introBox": {
8+
"headline": "How it works",
9+
"text": [
10+
"This AWS SAM template demonstrates how to create a private Amazon API Gateway with a private custom domain mame, configure secure access based on a specific VPC endpoint, and route traffic through Route 53 in a private hosted zone.",
11+
"Private custom domain name is only accessible from a VPC endpoint, which is mapped to a stage in private Amazon API Gateway. A custom domain name is configured with an SSL/TLS certificate to provide secure access, and an associated Route 53 A-Alias record ensures that traffic is routed to the API.",
12+
"As prerequisites for this pattern, you must have:",
13+
"* A DNS name of execute-api VPC endpoint",
14+
"* A custom domain name that you would like to create (e.g. private.mydomain.com)",
15+
"* A valid certificate in ACM (Amazon Certificate Manager) in the same Region as Private Amazon API Gateway, that covers the namespace of the domain you would like to use (i.e. *.mydomain.com).",
16+
"* A Route 53 Private Hosted Zone ID that has the domain name you would like to use (e.g. mydomain.com)."
17+
]
18+
},
19+
"gitHub": {
20+
"template": {
21+
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/private-apigw-custom-domain",
22+
"templateURL": "serverless-patterns/private-apigw-custom-domain",
23+
"projectFolder": "private-apigw-custom-domain",
24+
"templateFile": "template.yaml"
25+
}
26+
},
27+
"resources": {
28+
"bullets": [
29+
{
30+
"text": "Custom domain names for private APIs in API Gateway",
31+
"link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-private-custom-domains.html"
32+
}
33+
]
34+
},
35+
"deploy": {
36+
"text": ["Deploy the stack: <code>sam deploy --guided</code>"]
37+
},
38+
"testing": {
39+
"text": ["See the GitHub repo for detailed testing instructions."]
40+
},
41+
"cleanup": {
42+
"text": ["Delete the stack: <code>sam delete</code>."]
43+
},
44+
"authors": [
45+
{
46+
"name": "Usama Ali Khan",
47+
"image": "https://media.licdn.com/dms/image/v2/D4E03AQHcLMpZ1LV9UQ/profile-displayphoto-shrink_800_800/profile-displayphoto-shrink_800_800/0/1685892371158?e=1737590400&v=beta&t=RaPZkIgm7m3thW4PyKSQNn_w9fMbYBeu5PPrQ6K4vBU",
48+
"bio": "Usama is a Technical Account Manager at Amazon Web Services.",
49+
"linkedin": "usama-ali-khan"
50+
}
51+
],
52+
"patternArch": {
53+
"icon1": {
54+
"x": 20,
55+
"y": 50,
56+
"service": "route53",
57+
"label": "Amazon Route 53"
58+
},
59+
"icon2": {
60+
"x": 50,
61+
"y": 50,
62+
"service": "apigw",
63+
"label": "Amazon API Gateway"
64+
},
65+
"icon3": {
66+
"x": 80,
67+
"y": 50,
68+
"service": "vpc-endpoint",
69+
"label": "VPC Endpoint"
70+
},
71+
"icon4": {
72+
"x": 20,
73+
"y": 58,
74+
"service": "",
75+
"label": "private hosted zone"
76+
},
77+
"icon5": {
78+
"x": 50,
79+
"y": 58,
80+
"service": "",
81+
"label": "(private)"
82+
},
83+
84+
"line1": {
85+
"from": "icon1",
86+
"to": "icon2",
87+
"label": ""
88+
},
89+
"line2": {
90+
"from": "icon2",
91+
"to": "icon3",
92+
"label": ""
93+
}
94+
}
95+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Transform: AWS::Serverless-2016-10-31
3+
Description: >
4+
Serverless patterns - Amazon Private API Gateway endpoint with Private Custom Domain Name
5+
6+
Parameters:
7+
VpcEndpointDNSName:
8+
Type: String
9+
VPCEndpointHostedZoneID:
10+
Type: String
11+
CustomDomainName:
12+
Type: String
13+
CertificateArn:
14+
Type: String
15+
PrivateHostedZoneId:
16+
Type: String
17+
18+
Resources:
19+
PrivateApi:
20+
Type: AWS::Serverless::Api
21+
Properties:
22+
EndpointConfiguration: PRIVATE
23+
StageName: Prod
24+
AlwaysDeploy: true
25+
DefinitionBody:
26+
openapi: "3.0.1"
27+
info:
28+
version: "1.0"
29+
title: !Sub "PrivateApi-${AWS::StackName}"
30+
paths:
31+
/:
32+
get:
33+
responses:
34+
"200":
35+
description: "200 response"
36+
content:
37+
application/json:
38+
schema:
39+
$ref: "#/components/schemas/Empty"
40+
x-amazon-apigateway-integration:
41+
type: "mock"
42+
responses:
43+
default:
44+
statusCode: "200"
45+
responseTemplates:
46+
application/json: '{\"message\":\"Hello from Amazon Private API Gateway\"\}'
47+
requestTemplates:
48+
application/json: "{\"statusCode\": 200}"
49+
passthroughBehavior: "when_no_match"
50+
x-amazon-apigateway-policy:
51+
Version: "2012-10-17"
52+
Statement:
53+
- Effect: "Allow"
54+
Principal: "*"
55+
Action: "execute-api:Invoke"
56+
Resource: "execute-api:/*"
57+
Condition:
58+
StringEquals:
59+
aws:sourceVpce: !Join ["-", [!Select [0, !Split ["-", !Select [0, !Split [".", !Ref VpcEndpointDNSName]]]], !Select [1, !Split ["-", !Select [0, !Split [".", !Ref VpcEndpointDNSName]]]]]]
60+
61+
PrivateDomainName:
62+
Type: AWS::ApiGateway::DomainNameV2
63+
Properties:
64+
DomainName: !Ref CustomDomainName
65+
CertificateArn: !Ref CertificateArn
66+
EndpointConfiguration:
67+
Types:
68+
- PRIVATE
69+
SecurityPolicy: TLS_1_2
70+
Policy:
71+
Statement:
72+
- Action: 'execute-api:Invoke'
73+
Effect: Allow
74+
Principal: '*'
75+
Resource: 'execute-api:/*'
76+
- Action: 'execute-api:Invoke'
77+
Condition:
78+
StringNotEquals:
79+
aws:SourceVpce : !Join ["-", [!Select [0, !Split ["-", !Select [0, !Split [".", !Ref VpcEndpointDNSName]]]], !Select [1, !Split ["-", !Select [0, !Split [".", !Ref VpcEndpointDNSName]]]]]]
80+
Effect: Deny
81+
Principal: '*'
82+
Resource: 'execute-api:/*'
83+
Version: 2012-10-17
84+
85+
BasePathMapping:
86+
Type: AWS::ApiGateway::BasePathMappingV2
87+
Properties:
88+
RestApiId: !Ref PrivateApi
89+
DomainNameArn: !GetAtt PrivateDomainName.DomainNameArn
90+
Stage: !Ref PrivateApi.Stage
91+
92+
DomainNameAccessAssociation:
93+
Type: AWS::ApiGateway::DomainNameAccessAssociation
94+
Properties:
95+
DomainNameArn: !GetAtt PrivateDomainName.DomainNameArn
96+
AccessAssociationSource: !Join ["-", [!Select [0, !Split ["-", !Select [0, !Split [".", !Ref VpcEndpointDNSName]]]], !Select [1, !Split ["-", !Select [0, !Split [".", !Ref VpcEndpointDNSName]]]]]]
97+
AccessAssociationSourceType: VPCE
98+
99+
R53Alias:
100+
Type: AWS::Route53::RecordSet
101+
Properties:
102+
Name: !Ref CustomDomainName
103+
HostedZoneId: !Ref PrivateHostedZoneId
104+
Type: A
105+
AliasTarget:
106+
DNSName: !Ref VpcEndpointDNSName
107+
HostedZoneId: !Ref VPCEndpointHostedZoneID
108+
109+
Outputs:
110+
CURLCommand:
111+
Description: "Curl Command to test"
112+
Value: !Sub "curl https://${CustomDomainName}/"

0 commit comments

Comments
 (0)