Mengapa kredensial palsu test/test diterima begitu saja, bagaimana evaluasi policy IAM dasar bekerja di LocalStack, penggunaan resource-based policy, dan batasan emulasi IAM yang wajib kalian tahu.

Di episode 13 sebelumnya kita mengarahkan SDK dan CLI ke http://localhost:4566 lewat endpoint injection dan awslocal. Namun masih ada pertanyaan yang mengganjal: AWS CLI selalu menuntut kredensial, tapi LocalStack tidak pernah menolak. Bagaimana autentikasi sebenarnya bekerja di emulator? Episode ini menjawabnya: kredensial palsu test/test, variabel AWS_ACCESS_KEY_ID dan AWS_SECRET_ACCESS_KEY, cara LocalStack mengevaluasi policy IAM, resource-based policy, dan batasan emulasi yang perlu kalian tahu sebelum membawa asumsi produksi ke lokal.
Default LocalStack tidak memverifikasi kredensial. Semua kombinasi access key dan secret key diterima, selama formatnya valid. Ini sengaja dilakukan agar SDK dan CLI produksi berjalan tanpa modifikasi selain endpoint URL. Pasangan paling umum adalah test/test dengan region us-east-1 — persis yang dipakai awslocal secara otomatis.
Kita bisa membuktikannya lewat AWS CLI yang diarahkan ke emulator:
aws --endpoint-url=http://localhost:4566 sts get-caller-identityLocalStack menjawab dengan identitas default account 000000000000:
{
"UserId": "AKIAIOSFODNN7EXAMPLE",
"Account": "000000000000",
"Arn": "arn:aws:iam::000000000000:root"
}Sekali lagi: LocalStack tidak memeriksa apakah AKIAIOSFODNN7EXAMPLE benar-benar milik kalian. Account 000000000000 adalah akun default yang dipakai semua resource lokal.
Untuk SDK dan CLI, cara paling bersih adalah variabel lingkungan:
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test
export AWS_DEFAULT_REGION=us-east-1
export AWS_ENDPOINT_URL=http://localhost:4566Setelah ini, kode produksi apa pun berjalan apa adanya — tidak ada perubahan baris selain endpoint.
Boto3 (Python) memakai kombinasi env var di atas tanpa perlu menyebutkan kredensial eksplisit:
import boto3
s3 = boto3.client(
"s3",
region_name="us-east-1",
endpoint_url="http://localhost:4566",
aws_access_key_id="test",
aws_secret_access_key="test",
)
print(s3.list_buckets())Perhatikan: aws_access_key_id="test" hanyalah nilai formalitas. Nilai yang sama di SDK lain (aws-sdk-js, aws-sdk-go) juga diterima.
Tip
Simpan kredensial palsu ini di .env yang ikut versioned, bukan di secret store. Karena LocalStack tidak memverifikasinya, ia aman dibagikan antar developer — justru ini keuntungan utamanya dibanding kredensial sungguhan.
LocalStack meniru model allow-by-default: selama tidak ada policy yang menolak, akses diperbolehkan. Namun LocalStack tetap bisa mengevaluasi policy yang menempel pada user, group, dan role. Mari kita coba: buat user, lampirkan policy read-only S3, lalu periksa.
awslocal iam create-user --user-name dev
awslocal iam attach-user-policy \
--user-name dev \
--policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
awslocal iam list-attached-user-policies --user-name devKita juga bisa membuat policy kustom dengan dokumen JSON dan melampirkannya:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": ["arn:aws:s3:::assets/*"]
}
]
}Policy di atas disimpan lewat awslocal iam create-policy lalu di-attach ke user dev. Hasilnya, operasi s3:PutObject yang tidak tercantum bisa ditolak di sebagian service — inilah dasar emulasi otorisasi di LocalStack.
Selain policy yang menempel pada identitas (identity-based), AWS punya resource-based policy yang menempel pada resource — paling umum pada S3 bucket. LocalStack mengevaluasinya secara terbatas. Contoh bucket policy yang memberi akses s3:GetObject ke user dev:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::000000000000:user/dev"},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::assets/*"
}
]
}Terapkan dengan perintah berikut:
awslocal s3 mb s3://assets
awslocal s3api put-bucket-policy \
--bucket assets --policy file://bucket-policy.jsonPenting untuk tahu apa yang tidak disimulasikan. Jangan menaruh kepercayaan keamanan pada emulator:
| Aspek IAM | Status di LocalStack | Catatan |
|---|---|---|
| Validasi kredensial | Tidak diperiksa | Semua kredensial diterima |
| Evaluasi policy | Sebagian | Sangat bergantung pada service |
| Deny precedence | Terbatas | Logika allow default mendominasi |
| STS assume-role | Mock | Sesi dibuat tanpa kebijakan sesi sungguhan |
| SCP & Organizations | Tidak didukung | Tidak ada policy level organisasi |
| KMS key policy | Sebagian | Hanya layanan tertentu |
Implikasinya: gunakan emulasi IAM untuk menguji alur kode (flow), bukan untuk menguji keamanan. Otorisasi sebenarnya harus tetap diverifikasi di akun AWS nyata pada staging atau environment yang mendekati produksi.
Warning
Jangan pernah menganggap hasil evaluasi policy di LocalStack sebagai bukti aman. Karena bersifat allow-by-default, akses yang seharusnya ditolak bisa tetap lolos di emulator lalu tertolak di AWS asli — atau sebaliknya.
Episode ini membuka kotak hitam autentikasi LocalStack:
test/test dengan region us-east-1 adalah default yang bisa dipakai bebas.AWS_ACCESS_KEY_ID dan AWS_SECRET_ACCESS_KEY cukup diarahkan lewat env var, endpoint lewat AWS_ENDPOINT_URL.Saat kredensial dan policy sudah dipahami, pertanyaan berikutnya adalah keamanan environment itu sendiri: di mana menyimpan data, bagaimana memisahkan state antar developer, dan bagaimana memperlakukan PERSISTENCE. Di episode 15 selanjutnya kita membahas Security & Best Practice — prinsip agar LocalStack nyaman dipakai tanpa menciptakan risiko produksi. Sampai jumpa!