Secret Management #

Secret adalah informasi sensitif yang dibutuhkan aplikasi untuk beroperasi — database password, API key pihak ketiga, sertifikat TLS, encryption key, OAuth client secret. Cara kamu menyimpan dan mendistribusikan secret ini adalah salah satu aspek keamanan yang paling sering dilakukan salah, dan konsekuensinya bisa sangat serius. Secret yang bocor di repository publik, hardcoded di kode, atau tersimpan di tempat yang salah adalah sumber dari ribuan insiden keamanan nyata setiap tahun.

Masalah yang Paling Umum #

// ANTI-PATTERN 1: Hardcode di kode sumber
  DATABASE_PASSWORD = "super_secret_password_2024"
  API_KEY = "sk_live_abcdef123456789"
  
  Risiko:
  ✗ Setiap orang yang punya akses ke repository bisa baca secret
  ✗ Secret masuk ke git history — tetap ada bahkan setelah dihapus
  ✗ Secret bocor ke semua environment (dev, staging, prod sama)
  ✗ Jika repository di-fork atau di-push ke public → langsung terbaca

// ANTI-PATTERN 2: Di environment file yang di-commit
  # .env file yang di-commit ke git
  DB_HOST=prod-db.internal
  DB_PASSWORD=prod_password_here
  STRIPE_SECRET_KEY=sk_live_xxxxx
  
  Risiko sama dengan hardcode — .env di-commit = secret di repo

// ANTI-PATTERN 3: Dalam konfigurasi yang di-commit
  # kubernetes/deployment.yaml
  env:
    - name: DB_PASSWORD
      value: "hardcoded_password"  ← INI SALAH

// ANTI-PATTERN 4: Berbagi secret via chat atau email
  Slack: "hei, password database prod adalah XYZ"
  → Chat history = permanent record yang bisa diakses banyak orang
  → Secret tidak pernah bisa di-revoke dari chat history

Konsekuensi Nyata Secret yang Bocor #

Skenario yang sangat umum terjadi:
  
  Developer push code ke GitHub
  Lupa bahwa file konfigurasi berisi AWS credentials
  
  Dalam hitungan menit (bukan jam):
  → Bot scanner otomatis menemukan credentials
  → Bot mulai spin up ratusan instance GPU untuk crypto mining
  → Tagihan AWS melonjak ribuan dolar
  → Developer/perusahaan menerima tagihan mengejutkan
  
  Bahkan setelah credentials di-revoke:
  → Jika secret sudah ada di git history, masih bisa ditemukan
  → Perlu rewrite git history (git filter-branch / BFG) untuk benar-benar
    menghapus dari semua commit

Pelajaran:
  → Anggap setiap secret yang pernah masuk ke git history sebagai
    sudah dikompromikan — revoke dan rotate segera
  → Jangan andalkan "repository private" sebagai satu-satunya proteksi

Managed Secrets Service #

Solusi yang benar adalah menyimpan secret di managed secrets service — sistem yang dirancang khusus untuk menyimpan, mengontrol akses, dan merotasi secret secara aman.

Cara Kerja Managed Secrets Service:

  Secret disimpan di Secrets Manager (terenkripsi at-rest)
      │
      │ Permission: hanya identitas dengan akses eksplisit
      │             yang bisa membaca secret ini
      ▼
  Aplikasi saat startup (atau saat dibutuhkan):
      → Autentikasi ke cloud provider (via instance role)
      → Request secret: GetSecretValue("prod/db/password")
      → Secrets Manager verifikasi permission
      → Kembalikan nilai secret
      → Aplikasi gunakan nilai tersebut

  Yang TIDAK terjadi:
  ✓ Secret tidak ada di kode
  ✓ Secret tidak ada di environment variable yang statis
  ✓ Secret tidak ada di file konfigurasi yang di-commit
  ✓ Secret tidak ada di log

Fitur Utama Managed Secrets Service #

Enkripsi:
  ✓ Secret dienkripsi at-rest dengan encryption key yang dikelola
  ✓ Akses ke encryption key juga dikontrol secara terpisah

Access Control:
  ✓ Setiap secret punya policy tersendiri
  ✓ Hanya identitas yang eksplisit diizinkan yang bisa baca/tulis
  ✓ Audit log: siapa membaca secret apa, kapan

Rotation Otomatis:
  ✓ Secret bisa di-rotate secara otomatis sesuai jadwal
  ✓ Database password di-rotate → Secrets Manager update password di DB
    dan update nilai di Secrets Manager → aplikasi dapat password baru
  ✓ Tidak ada downtime — aplikasi fetch password baru saat diperlukan

Versioning:
  ✓ Riwayat versi secret tersimpan
  ✓ Rollback ke versi sebelumnya jika rotation bermasalah

Dynamic Secrets:
  ✓ Beberapa sistem (seperti Vault) bisa generate credentials
    sementara on-demand — database user dibuat saat diperlukan,
    dihapus setelah expire

Pola Implementasi #

Environment Variable dari Secrets Manager #

// Pola yang umum: inject secret sebagai env var saat startup
// Lebih baik dari hardcode, tapi masih ada risiko:
// env var bisa terbaca dari /proc/PID/environ di Linux

// Lebih aman: fetch langsung dari secrets manager saat dibutuhkan

// Python example (pseudocode):
import boto3
import json

def get_db_config():
    client = boto3.client('secretsmanager', region_name='ap-southeast-1')
    response = client.get_secret_value(SecretId='prod/app/database')
    secret = json.loads(response['SecretString'])
    return {
        'host': secret['host'],
        'username': secret['username'],
        'password': secret['password'],
        'database': secret['dbname']
    }

# Fetch saat aplikasi startup, bukan hardcode
db_config = get_db_config()

Kubernetes Secrets Integration #

Kubernetes secrets native vs Secrets Manager:

  Kubernetes Secret (kurang aman jika tidak dikonfigurasi dengan benar):
    → Disimpan di etcd (butuh enkripsi etcd at-rest)
    → Bisa di-base64 decode oleh siapa saja yang punya akses kubectl
    → Tidak ada audit log built-in
    → Tidak ada rotation otomatis

  Integrasi dengan managed secrets service (lebih aman):
    → Secrets Manager menyimpan secret
    → CSI Secret Store Driver atau external-secrets operator
      sync secret ke Kubernetes Secret
    → Pod mengakses Kubernetes Secret seperti biasa
    → Rotation di Secrets Manager otomatis tersinkronisasi

  Atau: inject langsung ke pod tanpa Kubernetes Secret
    → Init container atau sidecar yang fetch secret dari Secrets Manager
    → Mount sebagai file di /secrets/ atau inject ke environment
    → Secret tidak pernah tersimpan di Kubernetes etcd

Secret Rotation — Kebiasaan yang Sering Diabaikan #

Mengapa rotation penting:
  → Secret yang tidak pernah di-rotate = window of exposure permanen
  → Jika secret bocor tapi tidak diketahui → attacker punya akses selamanya
  → Regular rotation membatasi window bahkan untuk breach yang tidak terdeteksi

Jenis rotation:
  Rotation teratur (scheduled):
    → Database password di-rotate setiap 30/60/90 hari
    → API key di-rotate setiap 90 hari
    → Otomatis dengan managed secrets service

  Rotation on-demand (setelah insiden):
    → Segera rotate jika ada kecurigaan secret bocor
    → Rotate semua secret yang mungkin terekspos dalam scope insiden

  Zero-downtime rotation:
    Langkah yang aman:
    1. Tambahkan credentials baru di sistem target (DB user baru)
    2. Update Secrets Manager dengan credentials baru
    3. Aplikasi ambil credentials baru saat refresh berikutnya
    4. Verifikasi aplikasi berjalan normal dengan credentials baru
    5. Hapus credentials lama dari sistem target

Pre-commit Hook — Cegah Secret Masuk ke Repository #

Tools untuk mendeteksi secret sebelum commit:
  → git-secrets (AWS)
  → truffleHog
  → detect-secrets (Yelp)
  → gitleaks

Cara kerja:
  Developer menjalankan git commit
      │
      ▼
  Pre-commit hook aktif
      │
      ▼
  Scan perubahan untuk pattern secret:
  → AWS access key pattern
  → Private key header
  → Password dalam config file
  → API key format yang dikenal
      │
      ├── Tidak ditemukan → commit diizinkan
      └── Ditemukan → commit dibatalkan, tampilkan peringatan

Setup di CI/CD juga (defense in depth):
  Bahkan jika pre-commit hook dibypass,
  CI/CD scan bisa menangkap sebelum merge ke main branch

Ringkasan #

  • Secret di repository = secret yang sudah bocor — anggap setiap secret yang masuk ke git history sebagai dikompromikan, bahkan jika dihapus kemudian.
  • Managed secrets service adalah standar industri — enkripsi at-rest, access control per-secret, audit log, dan rotation otomatis dalam satu layanan.
  • Fetch secret di runtime, bukan di build time — aplikasi ambil secret saat dibutuhkan, bukan di-embed ke container image atau konfigurasi statis.
  • Rotation teratur membatasi window of exposure — secret yang di-rotate setiap 30 hari hanya memberi attacker window 30 hari jika bocor tanpa diketahui.
  • Pre-commit hook sebagai safety net — cegah secret masuk ke repository sejak awal, sebelum terlanjur ter-commit.
  • Kubernetes native secret tidak aman by default — gunakan integrasi dengan managed secrets service atau enkripsi etcd at-rest untuk keamanan yang lebih baik.

← Sebelumnya: Authentication vs Authorization   Berikutnya: Zero Trust →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact