Table of Contents13 sections
VPC Endpoint Setup Guide
Cross-Account Private API Gateway Access
1. Vấn đề gặp phải:
Gọi API nội bộ giữa hai AWS Account — tưởng dễ, hoá ra không đơn giản
Trong kiến trúc multi-account AWS, một bài toán phổ biến là Account A (ví dụ: microservice backend) cần gọi API được deploy trên Account B (ví dụ: platform team). Câu hỏi đặt ra ngay lập tức:
Vấn đề 1 — Bảo mật: Nếu expose API Gateway qua public internet, traffic sẽ đi ra ngoài AWS network. Điều này vi phạm yêu cầu bảo mật của nhiều tổ chức (PCI-DSS, HIPAA, SOC 2).
Vấn đề 2 — Chi phí & Latency: Traffic qua internet tốn thêm NAT Gateway cost, tăng latency không cần thiết khi cả hai bên đều trong AWS.
Vấn đề 3 — Resource Policy phức tạp: Private API Gateway mặc định từ chối mọi request từ ngoài VPC của nó — kể cả từ account khác trong cùng tổ chức AWS.
Kết quả là team thường chọn giải pháp "tạm thời" như đặt API lên public với IP whitelist, hoặc dùng VPN site-to-site — cả hai đều tốn effort vận hành và khó scale.
2. Giải pháp:
VPC Interface Endpoint + Private API Gateway
AWS cung cấp đúng công cụ cho bài toán này: VPC Interface Endpoint (dùng AWS PrivateLink). Traffic không bao giờ rời khỏi AWS backbone network — an toàn, nhanh, và không cần public IP.
Kiến trúc đích: Account A tạo một Interface Endpoint cho
execute-apitrong VPC của mình → kết nối qua PrivateLink đến Private API Gateway ở Account B → API Gateway áp Resource Policy cho phép Account A.

3. Demo:
Triển khai thực tế
1. Tạo Private API Gateway ở Account B
Deploy API Gateway với endpoint type là PRIVATE. Gắn VPC Endpoint ID của Account A vào cấu hình.
Account B — Terraform / AWS CLI
# terraform
resource "aws_api_gateway_rest_api" "private_api" {
name = "cross-account-private-api"
endpoint_configuration {
types = ["PRIVATE"]
vpc_endpoint_ids = [var.consumer_vpc_endpoint_id]
}
}2. Gắn Resource Policy cho phép Account A
Resource Policy kiểm soát ai được phép invoke API. Cần allow cả VPC Endpoint ID lẫn Account ID của consumer.
Account B — Resource Policy (JSON)
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT_A_ID>:root"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:ap-southeast-1:<ACCOUNT_B_ID>:*/*/*/*",
"Condition": {
"StringEquals": {
"aws:sourceVpce": "<VPCE_ID_FROM_ACCOUNT_A>"
}
}
}]
}3. Tạo Interface Endpoint ở Account A
Tạo VPC Interface Endpoint cho service com.amazonaws.ap-southeast-1.execute-api trong private subnet của Account A.
Account A — Terraform
resource "aws_vpc_endpoint" "execute_api" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.ap-southeast-1.execute-api"
vpc_endpoint_type = "Interface"
subnet_ids = aws_subnet.private[*].id
security_group_ids = [aws_security_group.vpce_sg.id]
# Quan trọng: tắt private DNS nếu gọi cross-account
private_dns_enabled = false
}⚠ private_dns_enabled = false khi gọi cross-account, vì private DNS chỉ resolve đúng trong account tạo endpoint. Account A sẽ cần gọi API qua DNS của endpoint (VPC Endpoint DNS name).
4. Cấu hình Security Group cho Endpoint
Security Group của Interface Endpoint phải cho phép inbound HTTPS (443) từ các resource sẽ gọi API.
Account A — Security Group
resource "aws_security_group" "vpce_sg" {
name = "vpce-execute-api-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"] # VPC CIDR của Account A
}
}5. Gọi API từ Account A
Vì private_dns_enabled = false, cần dùng DNS name của endpoint kết hợp với header Host hoặc dùng execute-api URL dạng đặc biệt.
Account A — Gọi API (curl / Python boto3)
# Lấy DNS name của VPCE
VPCE_DNS="vpce-0abc123def456.execute-api.ap-southeast-1.vpce.amazonaws.com"
API_ID="abcdef1234"
STAGE="prod"
# Gọi API với Host header chỉ định API ID
curl -X GET \
https://$VPCE_DNS/$STAGE/my-resource \
-H "Host: $API_ID.execute-api.ap-southeast-1.amazonaws.com" \
--aws-sigv4 "aws:amz:ap-southeast-1:execute-api"6. Xác minh kết nối
Kiểm tra VPC Flow Logs và CloudWatch Logs của API Gateway để xác nhận traffic đi đúng path nội bộ.
Account B — CloudWatch Logs (API Gateway Access Log)
{
"requestId": "abc-123",
"sourceIp": "10.0.1.55", // IP nội bộ Account A ✓
"httpMethod": "GET",
"path": "/prod/my-resource",
"status": 200,
"responseLatency": 12 // ms — nhanh hơn nhiều so với internet
}4. Kết luận:
Khi nào nên dùng pattern này?
VPC Endpoint + Private API Gateway là lựa chọn đúng đắn khi bạn cần giao tiếp nội bộ giữa các AWS Account mà không muốn traffic ra internet. Tuy nhiên cần lưu ý một số trade-off:
Ưu điểm
Traffic hoàn toàn trong AWS network — không qua internet
Latency thấp, không cần NAT Gateway cho outbound
Kiểm soát chi tiết qua Resource Policy + VPC Endpoint Policy
Phù hợp compliance: PCI-DSS, HIPAA, SOC 2
Cần chú ý
private_dns_enabled = falsebắt buộc khi cross-account — phải set Host header thủ côngMỗi Interface Endpoint tốn ~$0.01/giờ/AZ — cần tính toán chi phí nếu nhiều endpoint
Resource Policy và VPC Endpoint Policy phải khớp nhau — lỗi thường gặp là thiếu một trong hai
Với kiến trúc này, bạn có thể xây dựng internal service mesh hoàn toàn private trong AWS — không internet, không VPN, không IP whitelist — chỉ cần cấu hình đúng IAM và network policy.
