Secrets Manager & IAM untuk task
Kode Go-mu tidak berubah sedikit pun: ia tetap membaca environment variable. Yang berubah hanya dari mana nilainya datang — dan siapa yang berhak membacanya.
Intisari
- Blok
secretsdi task definition menyuntikkan nilai dari Secrets Manager atau SSM sebagai environment variable. - Yang membacanya adalah execution role, bukan aplikasimu — jadi task role tidak perlu izin Secrets Manager sama sekali.
- Nilainya dibaca sekali saat task mulai. Rotasi rahasia berarti deployment baru.
- Parameter Store (SSM) jauh lebih murah untuk nilai non-rahasia; Secrets Manager untuk yang berputar.
- Task role harus sesempit mungkin: bucket tertentu, antrean tertentu — bukan
s3:*.
Menyuntikkan rahasia
aws secretsmanager create-secret \
--name prod/toko/database-url \
--secret-string "postgres://app:[email protected]:5432/toko?sslmode=verify-full"
// Task definition
"secrets": [
{ "name": "DATABASE_URL",
"valueFrom": "arn:aws:secretsmanager:ap-southeast-1:123456789012:secret:prod/toko/database-url-AbC123" },
// Satu field dari rahasia berbentuk JSON
{ "name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:...:secret:prod/toko/db-AbC123:password::" },
// Parameter Store — untuk nilai yang tidak berputar
{ "name": "API_KEY_PIHAK_KETIGA",
"valueFrom": "arn:aws:ssm:ap-southeast-1:123456789012:parameter/toko/api-key" }
]
// Kodemu tetap sama persis seperti di Fase 5.
cfg.DSN = Rahasia(wajib("DATABASE_URL"))
Inilah nilai dari memisahkan konfigurasi sejak awal. Aplikasi yang membaca environment
variable bekerja identik di laptop (dari .env), di CI (dari secrets repositori), dan di
produksi (dari Secrets Manager) — tanpa satu pun cabang kode yang membedakan lingkungan.
Dua peran, dua izin
executionRole — dipakai AGEN ECS, sebelum container jalan
ecr:GetAuthorizationToken, ecr:BatchGetImage
logs:CreateLogStream, logs:PutLogEvents
secretsmanager:GetSecretValue ← HANYA untuk ARN rahasia yang dipakai
kms:Decrypt ← kalau rahasianya dienkripsi CMK
taskRole — dipakai APLIKASIMU
s3:GetObject, s3:PutObject pada arn:aws:s3:::toko-media/*
sqs:SendMessage, sqs:ReceiveMessage, sqs:DeleteMessage pada antrean tertentu
(TIDAK perlu izin Secrets Manager — nilainya sudah disuntikkan)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue"],
"Resource": [
"arn:aws:secretsmanager:ap-southeast-1:123456789012:secret:prod/toko/*"
]
}
]
}
Kesalahan yang paling umum: memberi task role izin membaca semua rahasia. Aplikasimu tidak
perlu membacanya — agen ECS yang melakukannya sebelum proses dimulai. Kalau task role punya
secretsmanager:GetSecretValue pada *, maka satu kerentanan eksekusi kode di
aplikasimu berubah jadi akses ke seluruh rahasia akun.
Secrets Manager versus Parameter Store
| Secrets Manager | Parameter Store (SSM) | |
|---|---|---|
| Biaya | Per rahasia per bulan + per panggilan | Standard: gratis |
| Rotasi otomatis | Ya, terintegrasi RDS | Tidak |
| Enkripsi | Selalu (KMS) | Opsional (SecureString) |
| Versi | Ya | Ya |
| Untuk | Kredensial database, kunci API | Konfigurasi, endpoint, flag |
Aturan pembagian yang praktis: apa pun yang berputar atau bisa dipakai untuk masuk ke sistem
lain → Secrets Manager. Sisanya — nama bucket, endpoint, level log, batas — → Parameter Store, atau
bahkan environment biasa. Puluhan rahasia di Secrets Manager yang isinya bukan rahasia
adalah biaya bulanan yang tidak perlu.
Rotasi
Secrets Manager memutar kredensial RDS otomatis (mis. tiap 30 hari).
Task yang SUDAH BERJALAN tetap memegang nilai lama — ia dibaca sekali
saat start.
Tiga cara menanganinya:
A. Rotasi memicu deployment ECS baru (paling sederhana)
→ task baru membaca nilai baru; task lama berhenti rapi
B. Strategi dua pengguna: rahasia menyimpan kredensial LAMA dan BARU;
keduanya sah selama masa transisi
C. Aplikasi memuat ulang rahasia berkala dan membangun ulang pool
→ paling rumit; jarang sepadan
Yang tidak boleh terjadi
| Jangan | Kenapa |
|---|---|
Rahasia di environment, bukan secrets | Terlihat di describe-task-definition oleh siapa pun yang punya akses baca |
| Rahasia di dalam image | Lapisan image bertahan selamanya di ECR |
| Rahasia di CloudFormation/Terraform state | State tersimpan di S3, sering terbaca lebih luas |
| Rahasia di log | Pakai tipe yang menyensor dirinya (Fase 5) |
| Rahasia yang sama di staging dan produksi | Satu kebocoran mengenai keduanya |
| Rahasia ter-commit lalu dihapus dari riwayat | Putar rahasianya dulu — ia sudah ada di klon orang lain |
IMDSv2 dan SSRF
Endpoint metadata (169.254.169.254) memberikan kredensial task role.
Kalau aplikasimu punya endpoint yang mengambil URL pilihan pengguna
(SSRF, Fase 6), penyerang bisa mengarahkannya ke sana.
Pertahanan berlapis:
• daftar putih host di aplikasi; tolak alamat privat dan link-local
• paksa IMDSv2 (butuh token PUT dulu — permintaan GET sederhana gagal)
• task role sesempit mungkin, supaya kredensial yang bocor pun terbatas
Latihan: pindahkan DATABASE_URL aplikasimu dari environment ke
secrets, lalu jalankan aws ecs describe-task-definition dan buktikan nilainya
tidak lagi terlihat. Lalu hapus izin secretsmanager:GetSecretValue dari execution role dan
amati bagaimana task gagal start — bukan gagal saat melayani permintaan.
Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.