AWS.
Identity-based Policy và Resource-based Policy
A. Identity-based Policy (Gắn vào Định danh)
Đây là loại phổ biến nhất. Nó trả lời cho câu hỏi: “Tôi (User/Role) có quyền làm gì?”
- Gắn vào đâu: IAM User, IAM Group, hoặc IAM Role.
- Đặc điểm: Nó quy định những gì identity đó có thể làm.
- Cú pháp: Không cần trường
Principal(vì mặc định là chính người đang mang policy đó). - Ví dụ: Giấy phép lái xe (Bạn mang theo người, cho phép bạn lái xe máy).
// Gắn vào Role của Nim
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket"
}
B. Resource-based Policy (Gắn vào Tài nguyên)
Loại này ít phổ biến hơn nhưng cực mạnh (S3, SQS, SNS, Lambda, KMS mới có). Nó trả lời cho câu hỏi: “Ai được phép đụng vào Tôi (Resource)?”
- Gắn vào đâu: Trực tiếp vào AWS Resource (S3 Bucket, SQS Queue, KMS Key…).
- Đặc điểm: Nó quy định ai được phép truy cập vào resource này. Đây là chìa khóa cho Cross-account access.
- Cú pháp: Bắt buộc phải có trường
Principal(để chỉ định ai được vào). - Ví dụ: Bảng nội quy dán trước cửa phòng Server (Quy định ai được vào, bất kể họ có chìa khóa hay không).
// Gắn vào S3 Bucket
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::123456789:user/Nim" }, // BẮT BUỘC CÓ
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket"
}
Set up private access for S3 across accounts and regions.
Solution 1: VPC Peering + Remote Endpoint (The “Classic” Private Way)
Chào Nim, dưới đây là bản dịch sang tiếng Việt cho tài liệu kỹ thuật bạn gửi. Tôi giữ nguyên các thuật ngữ chuyên ngành (VPC, CIDR, Endpoint…) để bạn dễ đối chiếu trên console AWS.
Kịch bản 2: VPC Peering + Remote Interface Endpoint cho phép EC2 ở Account A truy cập S3 ở Account B hoàn toàn thông qua mạng private của AWS, không cần sử dụng public internet hay NAT gateways.
Dưới đây là hướng dẫn từng bước để cấu hình mô hình này.
Tổng quan Kiến trúc
- Nguồn (Source): EC2 trong VPC A (Account A, Region A).
- Đích (Destination): Interface Endpoint trong VPC B (Account B, Region B).
- Kết nối: Kết nối VPC Peering giữa VPC A và VPC B.
- Luồng Traffic: EC2 -> Peering -> Interface Endpoint (Region B) -> S3 Bucket (Region B).
Giai đoạn 1: Nền tảng Mạng (VPC Peering)
Bạn phải kết nối hai mạng lưới này để EC2 có thể “nhìn thấy” địa chỉ Private IP của endpoint ở vùng (region) bên kia.
- Kiểm tra các khối CIDR (CIDR Blocks):
- Đảm bảo VPC A (ví dụ:
10.0.0.0/16) và VPC B (ví dụ:192.168.0.0/16) có dải IP không trùng lặp (non-overlapping). Nếu trùng, việc peering sẽ thất bại.
- Đảm bảo VPC A (ví dụ:
- Tạo kết nối Peering:
- Tại Account A (VPC Console) > Peering Connections > Create Peering Connection.
- Requester (Bên yêu cầu): VPC A.
- Accepter (Bên chấp nhận): Chọn Another Account (nhập ID của Account B) và Another Region (chọn Region B).
- Hành động tại Account B: Chuyển sang Account B, vào mục Peering Connections, và bấm Accept (Chấp nhận) yêu cầu này.
- Cập nhật Route Tables (Cực kỳ quan trọng):
- Tại Account A (Subnet chứa EC2): Thêm một route trỏ tới CIDR của VPC B (ví dụ:
192.168.0.0/16) đi qua Peering-Connection-ID (pcx-xxxx). - Tại Account B (Subnet chứa Endpoint): Thêm một route trỏ tới CIDR của VPC A (ví dụ:
10.0.0.0/16) đi qua cùng cái Peering-Connection-ID đó.
- Tại Account A (Subnet chứa EC2): Thêm một route trỏ tới CIDR của VPC B (ví dụ:
Giai đoạn 2: Tạo S3 Interface Endpoint (Tại Account B)
Bước này tạo ra một “cánh cửa” để vào S3 nằm ngay trong mạng private của Region B.
- Vào Account B > VPC Console > Endpoints > Create Endpoint.
- Service Name: Chọn
com.amazonaws.[region-b].s3. - Type: Chọn Interface (KHÔNG PHẢI Gateway).
- VPC: Chọn VPC B.
- Subnets: Chọn các subnet trong VPC B nơi bạn muốn đặt các network interface cho endpoint này.
- Security Group: Tạo/Chọn một Security Group cho endpoint này, cho phép Inbound HTTPS (443) từ CIDR của VPC A (ví dụ:
10.0.0.0/16). - Bấm Create.
- Kết quả: Ghi lại cái tên miền DNS cụ thể vừa được tạo ra (ví dụ:
vpce-012345-abcdef.s3.us-west-1.vpce.amazonaws.com).
Giai đoạn 3: Cập nhật Quyền hạn (Permissions)
Bạn cần cho phép traffic và IAM role một cách tường minh.
- Bucket Policy (Tại Account B):
Cập nhật bucket policy để cho phép truy cập từ Interface Endpoint.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccessFromEndpoint",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Account-A-ID]:role/[EC2-Role-Name]"
},
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket-name",
"arn:aws:s3:::my-bucket-name/*"
],
"Condition": {
"StringEquals": {
"aws:SourceVpce": "vpce-[your-endpoint-id]"
}
}
}
]
}
- Security Group (Tại Account A):
Đảm bảo Security Group gắn với EC2 instance của bạn cho phép Outbound HTTPS (443) tới dải CIDR của VPC B.
Giai đoạn 4: Truy cập Bucket (Bước “Bí mật”)
Đây là chỗ hầu hết mọi người bị mắc kẹt. Theo mặc định, AWS CLI và SDK sẽ cố tìm bucket thông qua đường public internet. Bạn phải ép buộc (force) chúng sử dụng URL của private endpoint mới tạo.
KHÔNG dùng lệnh: aws s3 ls s3://my-bucket-name
(Lệnh này sẽ bị treo hoặc thất bại vì nó cố phân giải IP public của S3, cái mà EC2 private của bạn không thể kết nối tới.)
BẠN PHẢI DÙNG:
Bash
aws s3 ls s3://my-bucket-name --region [Region-B] --endpoint-url https://vpce-012345-abcdef.s3.us-west-1.vpce.amazonaws.com
Tại sao?
- Phân giải DNS: EC2 của bạn ở Region A không biết rằng
s3.us-west-1.amazonaws.comcần phải trỏ về IP Private nằm ở VPC B. - Cách khắc phục: Cờ
--endpoint-urlra lệnh cho CLI bỏ qua DNS S3 công cộng và nói chuyện trực tiếp với địa chỉ Interface Endpoint cụ thể của bạn. Vì bạn đã thiết lập VPC Peering và Route Tables, request này sẽ đi theo đường private tới Region B.
https://www.doit.com/blog/accessing-s3-buckets-across-aws-regions-using-vpc-peering

Trong phần này mình còn nhận được câu hỏi là:
Trên ec2 cài openvpn và mình chỉ cho phép các client sử dụng openvpn đó mới được access vào S3 thôi.

Thì mình tìm được hình trên:
ở đây bạn có 2 điều cần biết là Interface Endpoint nó configure Security Group.
Nghía là bạn có thể allow chỉ cho phép IP VPN server access to Interface Endpoint.
Thứ 2 bạn cấu câú hình trong permission trong S3:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowVPNUsers",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::my-bucket-name",
"arn:aws:s3:::my-bucket-name/*"
],
"Condition": {
"StringEquals": {
"aws:SourceVpce": "vpce-012345-abcdef"
}
}
}
]
}
S3 kiểm tra aws:SourceVpce matches.
S3 Multi-Region Access Point (MRAP)
là phương pháp hiện đại, đơn giản hóa cho việc truy cập private giữa các region (cross-region). Nó hoạt động bằng cách để AWS tự định tuyến traffic của bạn thông qua mạng trục toàn cầu (Global Backbone) của họ mà không cần cấu hình VPC Peering phức tạp.
Trong kịch bản này, Account B (Chủ sở hữu Bucket) sẽ thiết lập MRAP, và Account A (chứa EC2) sẽ kết nối tới đó thông qua một Interface Endpoint cục bộ.
Tổng quan Kiến trúc
- Account B: Tạo Multi-Region Access Point (MRAP) cho bucket.
- Account B: Cấp quyền cho Account A trong Policy của MRAP.
- Account A: Tạo một Interface Endpoint dành cho service
com.amazonaws.s3-global.accesspoint. - Luồng đi (Flow): EC2 -> Interface Endpoint tại Account A -> Mạng toàn cầu AWS -> Bucket tại Account B.
Bước 1: Tạo MRAP (Tại Account B)
Vì MRAP chỉ có thể chứa các bucket thuộc cùng một account, nên chủ sở hữu bucket (Account B) phải là người tạo nó.
- Truy cập S3 Console (Account B).
- Ở menu bên trái, chọn Multi-Region Access Points.
- Bấm Create Multi-Region Access Point.
- Name: Đặt một cái tên duy nhất (ví dụ:
my-global-access). - Add Buckets: Chọn bucket của bạn ở Region B (
my-cross-region-bucket).- Lưu ý: Bạn có thể chỉ chọn 1 bucket nếu bạn chỉ muốn hưởng lợi về khả năng định tuyến (routing) mà không cần tính năng sao chép dữ liệu (replication).
- Block Public Access: Đảm bảo đã tích chọn “Block all public access”.
- Bấm Create.
- Chờ đợi: Quá trình tạo có thể mất tới 24 giờ (nhưng thường chỉ mất 10-20 phút).
- Copy Alias: Sau khi tạo xong, hãy copy cái MRAP Alias (ví dụ:
my-global-access.mrap). Bạn sẽ cần cái này cho phía EC2.
Bước 2: Cấu hình Quyền hạn (Tại Account B)
Bạn cần cho phép IAM Role của Account A được phép “nói chuyện” với Access Point mới này.
- Sửa MRAP Policy:
- Chọn MRAP mới tạo > Tab Permissions > Edit Policy.
- Thêm policy sau để cho phép Role của Account A:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAccountA",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::[Account-A-ID]:role/[EC2-Role-Name]"
},
"Action": "s3:*",
"Resource": "arn:aws:s3::[Account-B-ID]:accesspoint/[MRAP-Alias]"
}
]
}
- Verify Bucket Policy:
- Đảm bảo Bucket Policy gốc (nằm trên chính cái bucket đó) cũng phải cho phép cùng Principal (Account A). MRAP không thể cấp quyền truy cập nếu bucket gốc từ chối hoặc không cho phép rõ ràng (trừ khi chủ sở hữu MRAP cũng là chủ sở hữu Bucket, nhưng tốt nhất vẫn nên allow rõ ràng).
Bước 3: Tạo Interface Endpoint (Tại Account A)
Đây là bước “ma thuật”. Thay vì phải peering, Account A sẽ tạo một cánh cửa cục bộ để đi ra mạng lưới S3 toàn cầu.
- Đăng nhập vào Account A (phía EC2).
- Vào VPC Console > Endpoints > Create Endpoint.
- Name:
MRAP-Endpoint. - Service Category: Chọn AWS Services.
- Service Name: Tìm kiếm từ khóa
accesspointvà chọn đúng service này:com.amazonaws.s3-global.accesspoint(Lưu ý: KHÔNG chọn service s3 tiêu chuẩn). - VPC & Subnets: Chọn VPC và các Subnet nơi EC2 (hoặc VPN) của bạn đang chạy.
- Security Group: Gắn một Security Group cho phép Inbound HTTPS (443) từ EC2 (hoặc VPN Client) của bạn.
- Bấm Create.
Bước 4: Truy cập Dữ liệu
Bây giờ bạn đã sẵn sàng để kết nối.
- Endpoint URL: Bạn không cần phải tìm cái tên DNS
vpce-cụ thể của endpoint vừa tạo. - The Alias: Chỉ cần sử dụng MRAP Alias lấy ở Bước 1. AWS sẽ tự động phân giải alias này về địa chỉ Private IP của Interface Endpoint nằm ngay trong VPC của bạn.
Câu lệnh (từ EC2 hoặc VPN Client):
aws s3 ls s3://arn:aws:s3::[Account-B-ID]:accesspoint/[MRAP-Alias]/
Lưu ý: Bạn sử dụng MRAP ARN thay cho tên bucket.
Tại sao cách này tốt hơn cho OpenVPN?
- Không xung đột IP (No IP Conflicts): Bạn không cần lo lắng nếu Account A và Account B có dải mạng chồng lấn nhau (ví dụ: cả hai đều dùng
10.0.0.0/16). VPC Peering sẽ thất bại trong trường hợp này, nhưng MRAP thì hoạt động hoàn hảo. - Định tuyến đơn giản hơn (Simpler Routing): Bạn không cần đẩy (push) các route IP của Account B xuống VPN clients. Bạn chỉ cần đảm bảo client có thể phân giải được MRAP Alias (đây là DNS public) và route được tới IP của Interface Endpoint cục bộ (nằm ngay trong Account A).
Security Group (Cho Endpoint ở Account A): Đối với thiết lập OpenVPN của bạn:
- Source: Cho phép HTTPS (443) từ VPN Virtual CIDR (ví dụ:
10.8.0.0/24) HOẶC từ Private IP của EC2 nếu bạn đang dùng NAT. - Vì endpoint nằm cục bộ trong Account A, traffic của VPN client chỉ đi theo đường:
VPN -> EC2 -> Local Endpoint. Nó không bao giờ rời khỏi Account A cho đến khi nó đi vào mạng backbone private của AWS.
CloudFront + WAF -> ALB (EKS)
Thiết lập này mang lại khả năng chống DDoS vượt trội và chuyển chi phí cũng như việc xử lý WAF ra biên (edge).
Tổng quan Kiến trúc
- Yêu cầu người dùng -> CloudFront (Edge Location).
- AWS WAF (Gắn vào CloudFront) kiểm tra lưu lượng truy cập (Chặn theo địa lý + Giới hạn tốc độ).
- CloudFront -> ALB (EKS Ingress).
- Biện pháp bảo mật: ALB sẽ từ chối mọi truy cập trực tiếp từ internet. Nó sẽ CHỈ chấp nhận lưu lượng từ CloudFront.
Giai đoạn 1: Tạo Web ACL (WAF) ở Region GLOBAL
Khác với WAF dựa trên ALB trước đây (vốn là Regional – theo vùng), CloudFront WAF bắt buộc phải được tạo tại vùng us-east-1 (Global).
- Truy cập WAF Console > Web ACLs > Create web ACL.
- Resource type: Chọn CloudFront distributions (Global).
- Name:
Global-Edge-Protection. - Add Rules (Thêm quy tắc):
- Geo-Block: Chặn yêu cầu từ các quốc gia cụ thể (giống như hướng dẫn trước).
- Rate-Limit: Chặn các IP gửi > 2000 yêu cầu/5 phút.
- Finish: Tạo Web ACL. Bạn chưa cần gắn nó vào đâu lúc này.
Giai đoạn 2: Tạo CloudFront Distribution
Bây giờ chúng ta sẽ đặt CloudFront phía trước ALB hiện có của bạn.
- Truy cập CloudFront Console > Create Distribution.
- Origin Domain: Chọn DNS Name của ALB hiện có từ danh sách thả xuống (ví dụ:
k8s-default-myingress-xxxx.us-east-1.elb.amazonaws.com). - Protocol: Chọn Match Viewer to Origin (hoặc HTTPS only).
- Add Custom Header (BƯỚC BẢO MẬT QUAN TRỌNG):
- Chúng ta cần một “cái bắt tay bí mật” để ALB biết yêu cầu thực sự đến từ CloudFront của bạn.
- Header Name:
X-CF-Secret-Key(hoặc tên tùy chỉnh bất kỳ). - Value: Tạo một chuỗi dài ngẫu nhiên (ví dụ:
SuperSecretKey123!@#). - Lưu lại giá trị này; chúng ta sẽ cần nó cho Listener Rule của ALB sau này.
- Default Cache Behavior:
- Viewer Protocol Policy: Redirect HTTP to HTTPS.
- Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE.
- Cache Policy: Chọn
CachingDisabled(cho các API động) hoặcCachingOptimized(cho các trang tĩnh). Quan trọng: Nếu dùng Websockets hoặc header động, hãy dùng policy “AllViewer” hoặc policy tùy chỉnh.
- Web Application Firewall (WAF):
- Chọn Web ACL
Global-Edge-Protectionbạn đã tạo ở Giai đoạn 1.
- Chọn Web ACL
- Create Distribution.
- Copy Distribution Domain Name (ví dụ:
d12345.cloudfront.net).
Giai đoạn 3: Khóa chặt ALB (Hạn chế truy cập trực tiếp)
Hiện tại, người dùng có thể “lách” qua CloudFront (và WAF của bạn) bằng cách truy cập thẳng vào ALB. Chúng ta phải ngăn chặn điều này.
Phương pháp A: Giới hạn bằng Security Group (Layer 4)
Cách này giới hạn lưu lượng để chỉ các IP của CloudFront mới có thể truy cập ALB của bạn.
- Tìm Security Group đang gắn với ALB của bạn.
- Edit Inbound Rules.
- Xóa rule
0.0.0.0/0(Allow All) hiện tại cho HTTP/HTTPS. - Thêm một Rule mới:
- Type: HTTPS.
- Source: Tìm kiếm
pl-(Prefix List). Chọncom.amazonaws.global.cloudfront.origin-facing.
- Kết quả: Bây giờ chỉ các máy chủ AWS CloudFront mới có thể mở kết nối đến ALB của bạn.
Phương pháp B: Xác thực Header (Layer 7) – Rất khuyến nghị
Ngay cả khi đã giới hạn IP, một CloudFront distribution khác (từ tài khoản của hacker) về lý thuyết vẫn có thể trỏ đến ALB của bạn. Việc xác thực Custom Header sẽ ngăn chặn điều này.
Bạn cần cập nhật Ingress YAML để thực thi quy tắc này trên ALB Listener.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-ingress
namespace: default
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
# 1. Xóa annotation WAF khỏi đây (vì WAF hiện đã ở trên CloudFront)
# alb.ingress.kubernetes.io/wafv2-acl-arn: <XÓA_DÒNG_NÀY>
# 2. Thêm Listener Rule để kiểm tra Secret Header
# Điều này tạo một quy tắc: Nếu header khớp, chuyển tiếp đến target group.
# Nếu KHÔNG khớp, hành động mặc định (được cấu hình bên dưới) sẽ được áp dụng.
alb.ingress.kubernetes.io/actions.check-header: >
{"type":"forward","forwardConfig":{"targetGroups":[{"serviceName":"my-service","servicePort":80}]}}
# 3. Định nghĩa điều kiện: Header 'X-CF-Secret-Key' phải bằng 'SuperSecretKey123!@#'
alb.ingress.kubernetes.io/conditions.check-header: >
[{"field":"http-header","httpHeaderConfig":{"httpHeaderName":"X-CF-Secret-Key", "values":["SuperSecretKey123!@#"]}}]
# TÙY CHỌN: Từ chối tất cả những cái khác.
# Một cách đơn giản hơn thường dùng là dựa vào Security Groups (Phương pháp A) kết hợp với kiểm tra ở tầng ứng dụng,
# HOẶC cấu hình Listener để trả về 403 theo mặc định nếu không có quy tắc nào khớp.
spec:
rules:
- http:
paths:
# Kết nối action "check-header" vào đường dẫn
- path: /
pathType: Prefix
backend:
service:
name: check-header # Tham chiếu tên action đã định nghĩa trong annotation
port:
name: use-annotation
Phương án thay thế đơn giản cho Phương pháp B: Nếu việc sửa đổi các annotation phức tạp trong Ingress YAML quá rủi ro cho bạn ngay lúc này, bạn có thể vào thủ công EC2 Console > Load Balancers > Listeners > Rules.
- Chỉnh sửa rule mặc định (Rule cuối cùng). Đổi action thành “Return fixed response 403 Forbidden“.
- Chèn một Rule có độ ưu tiên 1 (Priority 1):
- IF Header
X-CF-Secret-KeylàSuperSecretKey123!@# - THEN Forward to
My-Target-Group.
- IF Header
Giai đoạn 4: Cập nhật DNS
Cuối cùng, trỏ domain thật của bạn (ví dụ: api.example.com) về CloudFront.
- Truy cập Route 53.
- Tìm A Record cho
api.example.com. - Đổi Alias Target từ ALB sang CloudFront Distribution Domain.
Tóm tắt luồng hoạt động mới
- Hacker -> IP trực tiếp của ALB -> Bị chặn bởi Security Group (Prefix List).
- Hacker -> CloudFront giả của hacker -> ALB -> Bị chặn bởi Listener Rule (Thiếu Secret Header).
- User -> CloudFront của bạn -> Kiểm tra WAF -> Thêm Secret Header -> ALB -> Thành công.