S3 Access Denied Meski Objek Sudah Publik: Cara Kerja Block Public Access dan Cara Memperbaikinya
Kamu upload gambar ke S3, set ACL-nya ke public-read, lalu buka URL-nya di browser — dan yang muncul malah Access Denied. Ini salah satu sumber frustrasi paling umum di S3, dan hampir selalu disebabkan oleh satu hal: Block Public Access di level bucket atau akun sedang aktif, dan itu menimpa semua izin yang kamu set di level objek.
TL;DR: Kenapa S3 Access Denied Terjadi Meski Objek Sudah Publik
| Kondisi | Hasil Akses Publik |
|---|---|
| Block Public Access aktif di akun atau bucket | Access Denied — semua ACL/policy publik diabaikan |
| Block Public Access nonaktif, tapi tidak ada ACL atau bucket policy | Access Denied — default S3 private |
Block Public Access nonaktif, objek punya ACL public-read | Akses publik berhasil |
Block Public Access nonaktif, bucket policy mengizinkan s3:GetObject untuk * | Akses publik berhasil |
| Object Ownership = BucketOwnerEnforced | ACL dinonaktifkan — public-read tidak berlaku |
Bagaimana S3 Public Access Benar-Benar Bekerja
Banyak yang mengira izin S3 itu satu lapis: set objek ke publik, selesai. Kenyataannya ada tiga lapis kontrol yang harus semuanya 'mengizinkan' sebelum request anonim bisa berhasil. Block Public Access adalah lapisan paling atas, dan ia bersifat override — bukan additive.
- Block Public Access (BPA) — dievaluasi pertama. Jika aktif, request publik langsung ditolak tanpa melihat ACL atau bucket policy sama sekali.
- Bucket Policy — dievaluasi setelah BPA. Jika ada
Denyeksplisit, request ditolak. Jika adaAllowuntuk principal*, akses publik diizinkan (asalkan BPA tidak menghalangi). - Object ACL — dievaluasi terakhir.
public-readhanya berlaku jika BPA tidak aktif dan Object Ownership tidak disetel keBucketOwnerEnforced.
Analoginya seperti gedung dengan tiga pintu berurutan. Block Public Access adalah pintu pertama yang dikunci dari luar. Tidak peduli kunci pintu kedua dan ketiga ada di tanganmu — kalau pintu pertama terkunci, kamu tidak akan pernah sampai ke sana.
Satu hal yang sering terlewat: Block Public Access bisa aktif di dua level berbeda — level akun (S3 Account Settings) dan level bucket. Keduanya independen, dan keduanya bisa memblokir akses. Kamu bisa sudah menonaktifkan BPA di bucket, tapi kalau di level akun masih aktif, hasilnya tetap Access Denied.
Empat Setting Block Public Access yang Perlu Kamu Pahami
BPA bukan satu toggle — ada empat pengaturan terpisah, dan masing-masing punya efek berbeda.
| Setting | Apa yang Diblokir |
|---|---|
BlockPublicAcls | Mencegah penambahan ACL publik baru pada bucket atau objek |
IgnorePublicAcls | Mengabaikan semua ACL publik yang sudah ada — ini yang paling sering jadi penyebab masalah |
BlockPublicPolicy | Mencegah penambahan bucket policy yang mengizinkan akses publik |
RestrictPublicBuckets | Membatasi akses ke bucket yang punya policy publik — hanya AWS service dan akun yang diotorisasi yang bisa akses |
Dalam kasus upload gambar yang tiba-tiba Access Denied, IgnorePublicAcls adalah tersangka utama. Kamu sudah set public-read di objek, tapi S3 secara diam-diam mengabaikannya.
Diagnosis S3 Access Denied: Langkah per Langkah
Langkah 1: Cek Block Public Access di Level Akun
Mulai dari sini karena ini yang paling sering terlewat. Banyak tim mengira mereka sudah 'fix' masalah di bucket, padahal blokade sebenarnya ada di level akun. Kalau level akun masih memblokir, perubahan apapun di bucket tidak akan berpengaruh.
aws s3control get-public-access-block \
--account-id 123456789012
Output yang perlu diperhatikan:
{
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"IgnorePublicAcls": true,
"BlockPublicPolicy": true,
"RestrictPublicBuckets": true
}
}
Jika salah satu atau semua bernilai true dan kamu memang butuh akses publik, kamu perlu menonaktifkannya di level akun terlebih dahulu.
Langkah 2: Cek Block Public Access di Level Bucket
Setelah level akun bersih, cek level bucket. Keduanya independen — menonaktifkan di akun tidak otomatis menonaktifkan di bucket.
aws s3api get-public-access-block \
--bucket nama-bucket-kamu
Struktur output-nya sama dengan level akun. Perhatikan nilai IgnorePublicAcls dan RestrictPublicBuckets — keduanya yang paling sering memblokir akses publik via ACL.
Langkah 3: Cek Object Ownership Setting
Ini sering jadi 'hidden gotcha'. Sejak AWS memperkenalkan Object Ownership, bucket baru secara default menggunakan BucketOwnerEnforced — yang berarti ACL sepenuhnya dinonaktifkan. Kamu bisa set public-read seribu kali, tidak akan ada efeknya.
aws s3api get-bucket-ownership-controls \
--bucket nama-bucket-kamu
Jika output menunjukkan BucketOwnerEnforced, ACL tidak berlaku. Kamu harus menggunakan bucket policy sebagai gantinya untuk mengizinkan akses publik.
Langkah 4: Verifikasi ACL Objek
Setelah memastikan BPA tidak aktif dan Object Ownership mengizinkan ACL, baru cek apakah ACL objek benar-benar sudah ter-set dengan benar. Langkah ini tidak berguna sebelum tiga langkah di atas bersih — itulah kenapa urutannya penting.
aws s3api get-object-acl \
--bucket nama-bucket-kamu \
--key path/ke/gambar.jpg
Cari grant dengan URI: http://acs.amazonaws.com/groups/global/AllUsers dan permission READ. Jika tidak ada, ACL belum ter-set dengan benar.
Langkah 5: Cek Bucket Policy
Jika kamu memilih menggunakan bucket policy daripada ACL (yang direkomendasikan untuk bucket baru), pastikan policy-nya benar dan tidak ada Deny eksplisit yang menimpa Allow.
aws s3api get-bucket-policy \
--bucket nama-bucket-kamu
Jika tidak ada policy sama sekali, command ini akan mengembalikan error NoSuchBucketPolicy — bukan output kosong.
Solusi: Dua Pendekatan untuk Mengizinkan Akses Publik S3
Pendekatan A: Menggunakan Bucket Policy (Direkomendasikan)
Ini pendekatan yang lebih modern dan tidak bergantung pada ACL. Cocok untuk bucket baru dengan BucketOwnerEnforced.
Langkah 1: Nonaktifkan Block Public Access yang relevan di bucket
aws s3api put-public-access-block \
--bucket nama-bucket-kamu \
--public-access-block-configuration \
'BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false'
Jika level akun juga memblokir, nonaktifkan di sana dulu:
aws s3control put-public-access-block \
--account-id 123456789012 \
--public-access-block-configuration \
'BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false'
Langkah 2: Buat bucket policy yang mengizinkan s3:GetObject untuk semua principal
🔽 Klik untuk melihat bucket policy
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::nama-bucket-kamu/*"
}
]
}
aws s3api put-bucket-policy \
--bucket nama-bucket-kamu \
--policy file://bucket-policy.json
Pendekatan B: Menggunakan Object ACL (Untuk Bucket dengan ACL Aktif)
Gunakan pendekatan ini hanya jika Object Ownership bucket kamu disetel ke BucketOwnerPreferred atau ObjectWriter — bukan BucketOwnerEnforced.
Langkah 1: Pastikan IgnorePublicAcls dan BlockPublicAcls dinonaktifkan (sama seperti Pendekatan A, Langkah 1).
Langkah 2: Set ACL objek ke public-read
aws s3api put-object-acl \
--bucket nama-bucket-kamu \
--key path/ke/gambar.jpg \
--acl public-read
Atau saat upload:
aws s3 cp gambar.jpg s3://nama-bucket-kamu/path/ke/gambar.jpg \
--acl public-read
Pola Kegagalan Nyata: Misdiagnosis yang Sering Terjadi
Skenario yang paling sering terjadi: developer baru bergabung ke tim, membuat bucket S3 baru, upload gambar, set public-read, dan bingung kenapa URL-nya tetap Access Denied. Mereka cek bucket-level BPA — sudah dinonaktifkan. Mereka cek ACL objek — sudah public-read. Semua terlihat benar.
Yang terlewat: account-level Block Public Access masih aktif. Tim security mengaktifkannya sebagai baseline di seluruh akun, tapi tidak ada yang mendokumentasikannya. Bucket-level BPA yang sudah dinonaktifkan tidak ada artinya karena account-level BPA menimpa segalanya.
Fix-nya satu command:
aws s3control get-public-access-block --account-id 123456789012
Dan terlihat semua empat setting bernilai true. Inilah kenapa diagnosis selalu harus dimulai dari level akun, bukan level bucket.
Ada satu lagi yang lebih subtle: bucket dibuat setelah April 2023, ketika AWS mengubah default Object Ownership menjadi BucketOwnerEnforced. Developer yang terbiasa dengan bucket lama mengasumsikan ACL masih bekerja. Mereka set public-read, BPA sudah nonaktif, tapi akses tetap gagal — karena ACL sudah sepenuhnya dinonaktifkan di level bucket. Tidak ada error message yang menjelaskan ini secara eksplisit. S3 hanya mengembalikan Access Denied.
Pertimbangan Keamanan Sebelum Membuat Bucket Publik
Block Public Access ada karena alasan yang bagus. Sebelum menonaktifkannya, pastikan kamu memang butuh akses publik anonim — bukan sekadar akses dari aplikasi atau user tertentu.
- Jika konten hanya perlu diakses oleh user yang sudah login, gunakan pre-signed URL daripada membuat bucket publik.
- Jika konten perlu diakses secara publik tapi dengan kontrol lebih, pertimbangkan CloudFront dengan Origin Access Control (OAC) — bucket tetap private, CloudFront yang mengakses S3.
- Jangan pernah menonaktifkan BPA di level akun hanya untuk satu bucket. Nonaktifkan di level bucket saja.
- Audit bucket publik secara berkala menggunakan S3 Storage Lens atau AWS Config rule
s3-bucket-public-read-prohibited.
Wrap-Up: Checklist S3 Access Denied dan Langkah Selanjutnya
Ketika menghadapi S3 Access Denied pada objek yang seharusnya publik, urutan diagnosis yang benar adalah: account-level BPA → bucket-level BPA → Object Ownership → ACL atau bucket policy. Melewati urutan ini adalah alasan utama kenapa masalah ini butuh waktu lama untuk di-debug.
Untuk setup baru, gunakan bucket policy daripada ACL — lebih eksplisit, lebih mudah di-audit, dan tidak terpengaruh oleh perubahan default Object Ownership di masa depan.
Referensi resmi yang relevan:
- AWS Docs: Blocking public access to your Amazon S3 storage
- AWS Docs: Controlling object ownership
- AWS Docs: Using bucket policies
Glosarium
| Istilah | Penjelasan |
|---|---|
| Block Public Access (BPA) | Fitur S3 yang memblokir akses publik di level akun atau bucket, menimpa ACL dan bucket policy |
| Object ACL | Access Control List pada level objek individual, mengontrol siapa yang bisa membaca atau menulis objek tersebut |
| Bucket Policy | Dokumen JSON yang mendefinisikan izin akses ke bucket dan objek di dalamnya menggunakan IAM policy language |
| Object Ownership | Setting bucket yang mengontrol apakah ACL diaktifkan dan siapa yang memiliki objek yang diupload ke bucket |
| Pre-signed URL | URL sementara yang memberikan akses ke objek S3 private tanpa membuat bucket publik |
Komentar
Posting Komentar