Skip to content

Commit c44c325

Browse files
committed
Add private API Gateway with public custom domain pattern
1 parent b622b42 commit c44c325

File tree

9 files changed

+969
-1
lines changed

9 files changed

+969
-1
lines changed

private-apigw-public-custom-domain

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# Amazon Private API Gateway with VPC Endpoints and Public Domain
2+
3+
This pattern creates an Amazon Private API Gateway that is only accessible through VPC endpoints, with public custom domain name resolution for internal only access through an Amazon internal Application Load Balancer.
4+
5+
This architecture is intended for:
6+
- **Internal APIs**: APIs that should only be accessible from within your network
7+
- **Hybrid Connectivity**: APIs accessible from on-premises via VPN/Direct Connect
8+
- **Public DNS Resolution**: APIs that resolve publicly but are only accessible privately
9+
10+
Learn more about this pattern at Serverless Land Patterns: << Add the live URL here >>
11+
12+
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](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
13+
14+
## Project Structure
15+
16+
```
17+
├── app.py # CDK app entry point
18+
├── cdk.json # CDK configuration
19+
├── requirements.txt # Python dependencies
20+
├── private_api_gateway/
21+
│ ├── __init__.py
22+
│ └── private_api_gateway_stack.py # Main stack definition
23+
└── README.md # This file
24+
```
25+
## Architecture
26+
27+
- **VPC**: 10.0.0.0/16 with DNS support
28+
- **Subnets**: 2 public + 2 private subnets across 2 AZs
29+
- **NAT Gateway**: Managed by CDK in public subnets
30+
- **Private API Gateway**: PetStore sample API with VPC endpoint restriction
31+
- **Application Load Balancer**: Internal ALB for SSL termination
32+
- **Lambda Automation**: Custom resource for VPC endpoint target registration
33+
34+
![image](architecture/architecture.png)
35+
36+
## Requirements
37+
38+
1. **Python Environment**: Python 3.8+ with venv
39+
2. **AWS CDK**: Installed and AWS Account bootstrapped
40+
3. **ACM Certificate**: Valid certificate for your domain in the deployment region
41+
4. **AWS CLI**: Configured with appropriate permissions
42+
5. **Custom Domain**: A domain name you control with DNS management access
43+
44+
## Deployment Instructions
45+
46+
### 1. Install Dependencies
47+
```bash
48+
# Create virtual environment
49+
python3 -m venv .venv
50+
51+
# Activate virtual environment
52+
source .venv/bin/activate # or your venv activation command
53+
54+
# Install CDK dependencies
55+
pip install -r requirements.txt
56+
```
57+
58+
### 2. Get Parameters
59+
60+
You must provide both context parameters:
61+
62+
1. **domain_name**: Your custom domain name (e.g., api.example.com)
63+
2. **certificate_arn**: ARN of your ACM certificate that covers the domain
64+
65+
### 3. CDK Deployment
66+
67+
```bash
68+
# Deploy with both required parameters
69+
cdk deploy \
70+
-c domain_name=api.example.com \
71+
-c certificate_arn=arn:aws:acm:region:account:certificate/cert-id
72+
73+
# Example with subdomain
74+
cdk deploy \
75+
-c domain_name=privateapi.mycompany.com \
76+
-c certificate_arn=arn:aws:acm:region:account:certificate/<certificate-id>
77+
```
78+
79+
#### Outputs
80+
81+
The stack provides these outputs:
82+
- **VPCId**: VPC identifier
83+
- **ALBDNSName**: ALB DNS name for CNAME record
84+
- **ALBHostedZoneId**: ALB hosted zone ID
85+
- **VPCEndpointId**: VPC endpoint identifier
86+
- **APIGatewayId**: API Gateway identifier
87+
- **CustomDomainName**: Your custom domain
88+
- **APIEndpoint**: Full API URL
89+
- **PublicDNSInstructions**: DNS record to create
90+
91+
### 4. DNS Configuration
92+
93+
After deployment, you must create a DNS record in your domain's hosted zone:
94+
95+
1. **Get ALB DNS name** from CDK outputs
96+
2. **Create CNAME record**:
97+
```
98+
api.example.com -> internal-alb-xxx.region.elb.amazonaws.com
99+
```
100+
101+
## Testing
102+
103+
Test from within the VPC (EC2 instance or Client VPN):
104+
```bash
105+
curl https://api.example.com/pets
106+
curl https://api.example.com/pets/2
107+
```
108+
109+
### Expected Responses
110+
```json
111+
# GET /pets
112+
[
113+
{"id": 1, "type": "dog", "price": 249.99},
114+
{"id": 2, "type": "cat", "price": 124.99},
115+
{"id": 3, "type": "fish", "price": 0.99}
116+
]
117+
118+
# GET /pets/2
119+
{
120+
"id": 2,
121+
"type": "cat",
122+
"price": 124.99
123+
}
124+
```
125+
126+
## Security Features
127+
128+
- API only accessible through VPC endpoint
129+
- Security groups restrict access to VPC and Client VPN ranges
130+
- ALB provides SSL termination with your certificate
131+
- Resource policies enforce VPC endpoint access only
132+
133+
## Troubleshooting
134+
135+
### Certificate Issues
136+
- Ensure certificate is in the same region as deployment
137+
- Verify certificate covers your domain name
138+
- Check certificate validation status
139+
140+
### DNS Issues
141+
- Verify CNAME or ALIAS record points to ALB DNS name
142+
- Check DNS propagation with `nslookup your-domain.com`
143+
- Ensure you have DNS management access for your domain
144+
145+
### Lambda Function Issues
146+
- Check CloudWatch logs for the RegisterVPCEndpointTargets function
147+
- Verify IAM permissions for EC2 and ELB operations
148+
149+
### Target Registration
150+
- Manually check target group health in AWS Console
151+
- Verify VPC endpoint has network interfaces created
152+
153+
## Cleanup
154+
155+
# Destroy
156+
157+
```bash
158+
cdk destroy -c domain_name=api.example.com -c certificate_arn=YOUR-CERT-ARN
159+
```
160+
----
161+
Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
162+
163+
SPDX-License-Identifier: MIT-0
164+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/usr/bin/env python3
2+
import aws_cdk as cdk
3+
from private_api_gateway.private_api_gateway_stack import PrivateApiGatewayStack
4+
5+
app = cdk.App()
6+
7+
# Get required context parameters
8+
domain_name = app.node.try_get_context("domain_name")
9+
certificate_arn = app.node.try_get_context("certificate_arn")
10+
11+
if not domain_name:
12+
raise ValueError("domain_name context parameter is required. Use: cdk deploy -c domain_name=api.example.com")
13+
14+
if not certificate_arn:
15+
raise ValueError("certificate_arn context parameter is required. Use: cdk deploy -c certificate_arn=arn:aws:acm:...")
16+
17+
PrivateApiGatewayStack(
18+
app,
19+
"PrivateApiGatewayStack",
20+
domain_name=domain_name,
21+
certificate_arn=certificate_arn,
22+
env=cdk.Environment(
23+
account=app.account,
24+
region=app.region
25+
)
26+
)
27+
28+
app.synth()
66.3 KB
Loading

0 commit comments

Comments
 (0)