Chuyện gì đang xảy ra
Bạn đã thiết lập một CloudFront distribution trỏ đến một S3 bucket, chọn Origin Access Control (OAC) làm phương thức truy cập, và bây giờ mọi request đều gặp lỗi này:
403 ERROR: The request could not be satisfied.
Request blocked. We can't connect to the server for this app or website at this time.
Không có gì tải được. Truy cập trực tiếp S3 vẫn hoạt động bình thường khi bucket ở chế độ public — nhưng CloudFront không thể kết nối được.
OAC đã thay thế Origin Access Identity (OAI) cũ hơn từ năm 2022. OAC bảo mật hơn, nhưng yêu cầu một bucket policy cụ thể mà hầu hết các hướng dẫn bỏ qua hoặc làm sai. Nếu không có policy này, S3 sẽ coi mọi request từ CloudFront là ẩn danh và trả về 403. Chỉ vậy thôi. Đó là toàn bộ vấn đề.
Nguyên nhân gốc rễ
Khi OAC được gắn vào, CloudFront ký các request tới S3 bằng SigV4. S3 cần một bucket policy rõ ràng nêu rằng: "chỉ cho phép s3:GetObject khi request đến từ đúng CloudFront distribution này." Không có policy thì không có quyền truy cập — dù OAC đã được cấu hình đúng ở phía CloudFront.
Các lỗi phổ biến dẫn đến tình trạng này:
- OAC đã được thiết lập trong CloudFront nhưng bucket policy chưa bao giờ được cập nhật
- Policy vẫn tham chiếu đến một OAI (
arn:aws:iam::cloudfront:user/...) thay vì điều kiện OAC - Block Public Access đang được bật nhưng không có policy nào cấp quyền truy cập cho CloudFront
- Policy sử dụng sai ARN của CloudFront distribution
Bước 1 — Xác nhận distribution đang dùng OAC
Mở CloudFront console → distribution của bạn → tab Origins → nhấp vào S3 origin → kiểm tra Origin access. Mục này phải hiển thị Origin access control settings (recommended) kèm tên OAC. Không phải "Public", không phải OAI.
Qua CLI:
aws cloudfront get-distribution-config --id YOUR_DISTRIBUTION_ID \
--query 'DistributionConfig.Origins.Items[0].S3OriginConfig'
Nếu OriginAccessIdentity trống và OAC xuất hiện dưới OriginAccessControlId, nghĩa là OAC đang hoạt động.
Bước 2 — Kiểm tra bucket policy hiện tại
aws s3api get-bucket-policy --bucket YOUR_BUCKET_NAME --query Policy --output text | python3 -m json.tool
Output trống? Đó là câu trả lời của bạn. Nếu bạn thấy một principal như arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ..., policy vẫn đang trỏ đến OAI — sẽ không hoạt động với OAC.
Bước 3 — Áp dụng bucket policy OAC đúng
Cách khắc phục là tạo bucket policy cấp s3:GetObject cho service principal của CloudFront, giới hạn trong distribution cụ thể của bạn.
Trước tiên, lấy ARN của distribution:
aws cloudfront get-distribution --id YOUR_DISTRIBUTION_ID \
--query 'Distribution.ARN' --output text
Trông như thế này: arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE
Tạo file policy:
cat > bucket-policy.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowCloudFrontOAC",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*",
"Condition": {
"StringEquals": {
"AWS:SourceArn": "arn:aws:cloudfront::123456789012:distribution/EDFDVBD6EXAMPLE"
}
}
}
]
}
EOF
Áp dụng policy:
aws s3api put-bucket-policy \
--bucket YOUR_BUCKET_NAME \
--policy file://bucket-policy.json
Bước 4 — Giữ nguyên Block Public Access
Đừng tắt Block Public Access để "sửa" lỗi 403. Đó là cách làm sai. OAC được tạo ra chính xác để bạn có thể giữ cả bốn cờ Block Public Access ở trạng thái BẬT trong khi CloudFront vẫn phục vụ nội dung.
Kiểm tra:
aws s3api get-public-access-block --bucket YOUR_BUCKET_NAME
Cả bốn cờ phải là true. Nếu bạn đã tắt chúng, hãy bật lại — policy OAC đã xử lý quyền truy cập mà không cần public access.
Bước 5 — Xóa cache CloudFront
CloudFront có thể đã cache lại response 403. Buộc làm mới cache:
aws cloudfront create-invalidation \
--distribution-id YOUR_DISTRIBUTION_ID \
--paths "/*"
Kiểm tra trạng thái (thường hoàn thành trong 30–60 giây):
aws cloudfront list-invalidations \
--distribution-id YOUR_DISTRIBUTION_ID \
--query 'InvalidationList.Items[0].Status'
Xác nhận kết quả
Chạy lệnh curl nhanh để kiểm tra response headers:
curl -I https://YOUR_CLOUDFRONT_DOMAIN/your-file.html
Bạn sẽ thấy HTTP/2 200 với x-cache: Miss from cloudfront ở lần truy cập đầu tiên, rồi Hit from cloudfront ở các lần tiếp theo.
Hãy thử truy cập một đường dẫn mà bạn biết là không tồn tại. S3 sẽ trả về 404, không phải 403. Lỗi 404 trên các file không tồn tại xác nhận policy đang hoạt động đúng — và không bị cấp quyền quá mức.
Thích dùng giao diện hơn CLI? Dùng phím tắt trên console
AWS Console có một phím tắt tích hợp giúp bỏ qua toàn bộ việc viết JSON thủ công. Vào CloudFront distribution → Origins → chỉnh sửa S3 origin → kéo xuống phần OAC → nhấp "Copy policy". Sau đó mở S3 → Permissions → Bucket Policy → dán vào và lưu lại. AWS tự động tạo ra policy chính xác cho distribution của bạn.
Các trường hợp đặc biệt cần kiểm tra
- Cấu hình đa vùng: S3 bucket ở
ap-southeast-1, CloudFront edge ởus-east-1? Hãy đảm bảo hành vi ký của OAC được đặt thành Sign requests (recommended) — không phải "Do not sign". - Object được mã hóa bằng SSE-KMS: KMS key do khách hàng quản lý yêu cầu thêm một bước. CloudFront cần quyền
kms:Decrypttrong KMS key policy. OAC hỗ trợ điều này, nhưng bạn phải thêm vào một cách tường minh. - Statement OAI còn sót lại: Nếu policy OAI cũ vẫn còn đó, hãy xóa nó đi. Có cả statement OAI lẫn OAC trong cùng một policy không làm hỏng gì, nhưng sẽ gây nhầm lẫn cho mọi người trong team — kể cả chính bạn sau này.

