← Semua pembelajaran / Go Nol → Enterprise
Fase 10 · Deploy di AWS

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 secrets di 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 ManagerParameter Store (SSM)
BiayaPer rahasia per bulan + per panggilanStandard: gratis
Rotasi otomatisYa, terintegrasi RDSTidak
EnkripsiSelalu (KMS)Opsional (SecureString)
VersiYaYa
UntukKredensial database, kunci APIKonfigurasi, 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

JanganKenapa
Rahasia di environment, bukan secretsTerlihat di describe-task-definition oleh siapa pun yang punya akses baca
Rahasia di dalam imageLapisan image bertahan selamanya di ECR
Rahasia di CloudFormation/Terraform stateState tersimpan di S3, sering terbaca lebih luas
Rahasia di logPakai tipe yang menyensor dirinya (Fase 5)
Rahasia yang sama di staging dan produksiSatu kebocoran mengenai keduanya
Rahasia ter-commit lalu dihapus dari riwayatPutar 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.