Kenapa Harus Pakai Secrets Manager, Bukan Hardcode Password di Kode?
Satu pertanyaan yang hampir selalu muncul di code review: 'repo-nya private kok, kenapa tidak boleh hardcode password DB-nya langsung di kode?' Pertanyaan ini masuk akal di permukaan, tapi model ancaman yang mendasarinya salah — dan Secrets Manager hadir bukan hanya untuk menyembunyikan string, melainkan untuk menyelesaikan masalah operasional yang jauh lebih dalam dari sekadar visibilitas kode.
TL;DR — Secrets Manager vs Hardcoding
| Aspek | Hardcoding di Kode | AWS Secrets Manager |
|---|---|---|
| Rotasi password | Manual, rawan downtime | Otomatis via Lambda rotation function |
| Audit akses | Tidak ada jejak siapa membaca secret | Setiap GetSecretValue tercatat di CloudTrail |
| Scope paparan | Semua yang bisa baca kode, bisa baca secret | Dikontrol IAM per resource, per principal |
| Revoke akses | Harus deploy ulang seluruh aplikasi | Rotasi secret, akses lama langsung invalid |
| Risiko git history | Secret tersimpan permanen di commit history | Tidak ada credential di repository |
| Multi-environment | Rawan salah env, sulit diaudit | Secret berbeda per environment, path terpisah |
Bagaimana AWS Secrets Manager Bekerja
Sebelum masuk ke alasan operasional, penting untuk memahami mekanisme dasarnya. Secrets Manager menyimpan secret sebagai pasangan key-value terenkripsi menggunakan AWS KMS. Aplikasi tidak pernah memegang credential secara statis — setiap kali butuh password, aplikasi memanggil API GetSecretValue dan mendapat nilai terkini.
- Aplikasi memanggil GetSecretValue — request dikirim ke Secrets Manager endpoint regional.
- IAM authorization — Secrets Manager memverifikasi apakah IAM role aplikasi memiliki izin
secretsmanager:GetSecretValuepada ARN secret tersebut. - KMS decrypt — Secret yang tersimpan dalam bentuk terenkripsi didekripsi menggunakan KMS key yang dikonfigurasi.
- Nilai dikembalikan — Aplikasi menerima nilai secret saat ini, bukan nilai yang di-cache dari waktu deploy.
- CloudTrail mencatat — Setiap pemanggilan GetSecretValue menghasilkan event audit di CloudTrail secara otomatis.
Kenapa Repo Private Bukan Jaminan Keamanan
Asumsi 'repo private = aman' mengabaikan beberapa vektor serangan nyata yang sering terjadi di lingkungan produksi.
Pertama, git history tidak bisa dihapus dengan mudah. Kalau password pernah di-commit, bahkan satu kali, nilai itu tersimpan di seluruh clone lokal yang pernah ada. Force-push atau git filter-branch tidak menjamin semua salinan lokal developer sudah bersih.
Kedua, scope akses repo tidak sama dengan scope akses yang seharusnya. Developer yang butuh baca kode frontend tidak seharusnya otomatis bisa baca password database produksi. Tapi kalau keduanya ada di repo yang sama, itulah yang terjadi. Dengan Secrets Manager, akses ke secret dikontrol IAM secara terpisah dari akses ke kode.
Ketiga, CI/CD pipeline sering menjadi titik bocor. Build log, artifact, environment variable yang di-print saat debugging — semua ini bisa mengekspos credential yang hardcoded tanpa disadari.
Analogi yang tepat: menyimpan kunci rumah di bawah keset depan pintu. Semua orang yang 'tahu caranya' bisa masuk. Secrets Manager lebih seperti brankas dengan log siapa yang membukanya dan kapan.
Rotasi Password Otomatis — Ini yang Sering Diabaikan
Fitur rotasi otomatis Secrets Manager adalah alasan operasional terkuat untuk migrasi dari hardcoding, dan ini yang paling sering diremehkan tim engineering.
(simpan nilai baru) Lambda->>DB: Verifikasi koneksi dengan password baru DB-->>Lambda: Koneksi berhasil Lambda-->>SM: Rotasi selesai App->>SM: GetSecretValue (request berikutnya) SM-->>App: Password baru (otomatis)
- Rotation schedule terpicu — Secrets Manager memanggil Lambda rotation function sesuai jadwal yang dikonfigurasi (misalnya setiap 30 hari).
- Lambda membuat password baru — Rotation function membuat credential baru di database target (RDS, Redshift, dll.) menggunakan API database yang sesuai.
- Secret diperbarui — Nilai baru disimpan di Secrets Manager. Versi lama tetap tersedia sementara dengan label
AWSPREVIOUS. - Verifikasi — Lambda memverifikasi credential baru berfungsi sebelum menandai rotasi sebagai selesai.
- Aplikasi otomatis pakai nilai baru — Karena aplikasi selalu memanggil GetSecretValue (bukan membaca nilai statis), credential baru langsung digunakan tanpa deploy ulang.
Dengan hardcoding, rotasi password berarti: update kode → commit → deploy → restart aplikasi. Setiap langkah adalah peluang downtime dan kesalahan manusia. Dengan Secrets Manager, aplikasi yang memanggil GetSecretValue setiap koneksi (atau dengan TTL cache yang pendek) akan otomatis mengambil credential baru.
Implementasi Praktis — Migrasi dari Hardcode ke Secrets Manager
Berikut langkah konkret untuk menyimpan dan mengambil secret database menggunakan AWS CLI dan kode aplikasi.
Langkah 1: Simpan Secret ke Secrets Manager
Buat secret baru yang menyimpan credential database. Format JSON direkomendasikan untuk secret yang berisi beberapa field.
aws secretsmanager create-secret \
--name 'prod/myapp/db-credentials' \
--description 'Kredensial database produksi untuk MyApp' \
--secret-string '{"username":"dbadmin","password":"P@ssw0rd-contoh","host":"mydb.cluster-xyz.us-east-1.rds.amazonaws.com","port":"5432","dbname":"myappdb"}' \
--region us-east-1
Langkah 2: Buat IAM Policy untuk Aplikasi
Aplikasi hanya perlu izin membaca secret spesifik — bukan semua secret di akun. Prinsip least privilege diterapkan di level ARN secret.
🔽 Klik untuk lihat IAM Policy JSON
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowReadAppSecret",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"secretsmanager:DescribeSecret"
],
"Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp/db-credentials-*"
},
{
"Sid": "AllowKMSDecrypt",
"Effect": "Allow",
"Action": [
"kms:Decrypt"
],
"Resource": "arn:aws:kms:us-east-1:123456789012:key/your-kms-key-id"
}
]
}
Perhatikan wildcard -* di akhir ARN secret — Secrets Manager menambahkan suffix acak 6 karakter saat secret dibuat, sehingga ARN eksak perlu dicek dengan describe-secret atau wildcard digunakan untuk policy.
Langkah 3: Verifikasi Akses dari CLI
Sebelum deploy ke aplikasi, verifikasi bahwa role yang benar bisa membaca secret.
aws secretsmanager get-secret-value \
--secret-id 'prod/myapp/db-credentials' \
--region us-east-1 \
--query 'SecretString' \
--output text
Langkah 4: Ambil Secret di Kode Aplikasi (Python)
Contoh ini menggunakan boto3. Pola yang direkomendasikan adalah mengambil secret saat startup koneksi, bukan di-cache selamanya — ini memungkinkan rotasi bekerja tanpa restart.
🔽 Klik untuk lihat contoh kode Python
import boto3
import json
from botocore.exceptions import ClientError
def get_db_credentials(secret_name: str, region_name: str) -> dict:
client = boto3.client('secretsmanager', region_name=region_name)
try:
response = client.get_secret_value(SecretId=secret_name)
except ClientError as e:
# Tangani error spesifik sesuai kebutuhan aplikasi
raise e
secret = json.loads(response['SecretString'])
return secret
# Penggunaan
creds = get_db_credentials(
secret_name='prod/myapp/db-credentials',
region_name='us-east-1'
)
connection = connect_to_db(
host=creds['host'],
port=int(creds['port']),
user=creds['username'],
password=creds['password'],
database=creds['dbname']
)
Langkah 5: Aktifkan Rotasi Otomatis
Untuk RDS, Secrets Manager menyediakan managed rotation function yang bisa diaktifkan langsung. Pastikan Lambda rotation function sudah ada di akun (bisa di-deploy via AWS console atau SAR).
aws secretsmanager rotate-secret \
--secret-id 'prod/myapp/db-credentials' \
--rotation-rules '{"AutomaticallyAfterDays": 30}' \
--rotation-lambda-arn 'arn:aws:lambda:us-east-1:123456789012:function:SecretsManagerRDSPostgreSQLRotationSingleUser' \
--region us-east-1
Pola Kesalahan yang Sering Terjadi — Diagnosis Lapangan
Ini skenario nyata yang sering muncul saat tim pertama kali migrasi ke Secrets Manager.
Gejala: Aplikasi berjalan normal di lokal tapi gagal di ECS dengan error AccessDeniedException saat memanggil GetSecretValue.
Diagnosis awal yang salah: Tim langsung curiga ke VPC endpoint atau network connectivity, karena aplikasi 'tidak bisa reach' Secrets Manager.
Penyebab sebenarnya: ECS task role tidak memiliki izin secretsmanager:GetSecretValue pada ARN secret yang spesifik. Di lokal, developer menggunakan AWS credentials pribadi yang memiliki akses lebih luas. Dua identity yang berbeda, dua set izin yang berbeda.
Fix: Verifikasi identity yang digunakan task ECS, lalu pastikan policy terpasang di task role yang benar — bukan execution role.
# Cek task role yang digunakan ECS task
aws ecs describe-tasks \
--cluster nama-cluster-anda \
--tasks arn:aws:ecs:us-east-1:123456789012:task/nama-cluster-anda/task-id-anda \
--region us-east-1 \
--query 'tasks[0].taskDefinitionArn'
# Cek task definition untuk melihat taskRoleArn
aws ecs describe-task-definition \
--task-definition nama-task-definition:versi \
--region us-east-1 \
--query 'taskDefinition.taskRoleArn'
Perbedaan antara taskRoleArn (identity yang digunakan kode aplikasi) dan executionRoleArn (identity yang digunakan ECS agent untuk pull image dan push log) adalah sumber kebingungan yang hampir universal di tim yang baru mulai pakai ECS.
Audit Trail — Siapa Mengakses Secret dan Kapan
Setiap panggilan GetSecretValue menghasilkan event di CloudTrail. Ini bukan fitur opsional — ini terjadi secara otomatis selama CloudTrail aktif di region tersebut.
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=GetSecretValue \
--region us-east-1 \
--query 'Events[*].{Time:EventTime,User:Username,Source:EventSource}' \
--output table
Dengan hardcoding, tidak ada cara untuk tahu siapa yang 'menggunakan' password tersebut setelah kode di-deploy. Dengan Secrets Manager, setiap akses tercatat dengan identity, timestamp, dan source IP — informasi yang krusial saat investigasi insiden.
Wrap-Up dan Langkah Selanjutnya
Menyimpan credential di kode bukan hanya masalah keamanan — ini masalah operasional. Rotasi manual, audit yang tidak ada, dan scope akses yang terlalu luas adalah utang teknis yang akan jatuh tempo saat paling tidak nyaman: di tengah insiden produksi.
Langkah konkret berikutnya:
- Audit semua credential yang saat ini hardcoded menggunakan tools seperti git-secrets atau Amazon Inspector.
- Mulai migrasi dari secret yang paling sensitif (credential database produksi) ke Secrets Manager.
- Aktifkan rotasi otomatis segera setelah migrasi selesai — jangan tunda ini.
- Baca dokumentasi resmi: AWS Secrets Manager User Guide dan Rotating Secrets.
Glosarium
| Istilah | Penjelasan |
|---|---|
| Secret Rotation | Proses otomatis mengganti nilai credential (password, API key) secara berkala tanpa intervensi manual. |
| GetSecretValue | API action Secrets Manager untuk mengambil nilai secret saat ini. Setiap panggilan dicatat di CloudTrail. |
| KMS CMK | Customer Managed Key di AWS Key Management Service — kunci enkripsi yang digunakan Secrets Manager untuk mengenkripsi secret. |
| Task Role (ECS) | IAM role yang diasosiasikan dengan ECS task, digunakan oleh kode aplikasi untuk memanggil AWS API. Berbeda dari execution role. |
| AWSPREVIOUS | Label versi secret di Secrets Manager yang menandai credential sebelum rotasi terakhir — tersedia sementara untuk backward compatibility. |
Komentar
Posting Komentar