Mendesain keamanan sebagai properti arsitektur: threat modeling STRIDE atas flow checkout studi kasus kita, prinsip secure design seperti defense in depth dan least privilege, pengelolaan secrets, serta fondasi zero trust yang diperdalam di episode 18

Setelah di episode 9 kita mengunci API sebagai kontrak — resource-oriented, versioning disiplin, idempotency di jalur uang — pada episode ini kita hadapi dimensi yang tidak bisa ditambah belakangan tanpa membongkar: security architecture.
Mengapa security adalah urusan architect, bukan sekadar checklist tim keamanan? Karena keputusan struktural menentukan permukaan serangan sebelum satu baris kode ditulis. Sistem yang membagi trust boundary dengan ceroboh, menyimpan secret di environment variable yang tersebar, atau menaruh otorisasi hanya di satu lapisan akan tetap rapuh berapa pun banyak security review di akhir. Keamanan yang murah adalah keamanan yang dirancang sejak awal.
Evolusi praktik keamanan industri:
Pen-test akhir proyek → terlambat & mahal
Security review per rilis → lebih baik, masih reaktif
Shift left → desain + CI sejak hari pertama
Security by design → struktur mencegah kelas bug utuhDua fakta yang mendasari pendekatan ini: mayoritas kerentanan lahir dari kesalahan desain (bukan typo kode), dan biaya perbaikan naik eksponensial mendekati produksi. Architect yang memikirkan threat model saat whiteboard sedang bekerja di titik termurah.
Threat modeling menjawab tiga pertanyaan: apa yang kita bangun, apa yang bisa salah, dan apa yang kita lakukan soal itu. Metode paling populer untuk "apa yang bisa salah" adalah STRIDE — enam kategori ancaman:
| Huruf | Ancaman | Properti yang Diserang |
|---|---|---|
| S | Spoofing | Autentikasi — pura-pura jadi orang lain |
| T | Tampering | Integritas — ubah data di transit/at rest |
| R | Repudiation | Audit — menyangkal pernah beraksi |
| I | Information disclosure | Kerahasiaan — bocorkan data |
| D | Denial of service | Availability — lumpuhkan layanan |
| E | Elevation of privilege | Otorisasi — naik jadi admin |
Mari jalankan pada studi kasus kita. Trust boundaries utamanya:
[Browser User] ════boundary 1════▶ [API Server]
[API Server] ════boundary 2════▶ [Payment Gateway]
[API Server] ════boundary 3════▶ [PostgreSQL / Redis]
[Webhook Gateway] ══boundary 4═══▶ [API callback payment]Hasil enumerasi paling penting:
| # | Boundary | Ancaman (STRIDE) | Mitigasi Arsitektural |
|---|---|---|---|
| 1 | Browser→API | S: token dicuri | Access token umur pendek + refresh rotasi |
| 1 | Browser→API | T: harga diubah klien | Harga divalid ulang server-side dari DB, bukan payload |
| 1 | Browser→API | D: spam checkout | Rate limit per IP+user, bot protection di edge |
| 2 | API→Gateway | I: data kartu tersimpan | Tokenisasi — kartu tak pernah menyentuh DB kita |
| 4 | Webhook→API | S: webhook palsu | Verifikasi signature HMAC + timestamp window |
| 3 | API→DB | E: SQL injection | Query parameterized, least-privilege DB user per modul |
| semua | — | R: menyangkal aksi | Audit log append-only siapa-beda-apa-kapan |
Perhatikan pola mitigasi baris kedua — never trust the client adalah prinsip nomor satu: semua input (termasuk harga, diskon, jumlah) divalidasi ulang di server. Payload klien hanyalah niat, bukan kebenaran.
Important
Dokumentasikan threat model bersama kode (misal docs/threat-model.md), perbarui setiap ada fitur baru menyentuh trust boundary. Model yang tertinggal di slide presentasi akan basi; yang hidup di repo ikut direview setiap PR besar.
Tidak ada satu lapisan yang sempurna — susun beberapa yang independen:
Edge : WAF, rate limit, TLS termination
Network : segmentasi subnet, egress policy, no public DB
App : authN/authZ tiap request, validasi input, output encoding
Data : encryption at rest, field-level encryption PII
Ops : least-privilege IAM, audit trail, alert anomaliKunci filosofinya: asumsikan setiap lapisan bisa jebol. Pertanyaannya bukan "apakah WAF cukup", melainkan "jika WAF jebol, apa lapisan berikutnya yang menahan". Contoh konkret: meski attacker lolos ke application layer, database user milik modul ordering tidak punya izin DROP TABLE — kerusakan terkurung.
Untuk aplikasi modern, jangan roll your own: pakai OIDC provider (Keycloak self-host, atau managed). Pola standar:
Otorisasi harus diputuskan di satu tempat yang konsisten, bukan tersebar if di controller:
X-User-Id dari dalam network.Secret (DB password, API key) tidak boleh tinggal di kode, config file repo, atau image layer. Gunakan vault (HashiCorp Vault, AWS Secrets Manager): rotasi otomatis, audit akses, TTL singkat. CI/CD mengambil via identity, bukan file .env yang menyebar antar laptop.
Tip
Uji cepat posture secrets tim: git log -p seluruh riwayat repo — apakah ada credential pernah masuk? Jika ya, anggap bocor permanen dan rotate semuanya. Rotasi lebih murah daripada harapan bahwa tidak ada yang menemukannya.
Model keamanan klasik = kastil dan parit: firewall di depan, percaya semua di dalam. Zero trust membaliknya: never trust, always verify — setiap request diverifikasi identitas dan otorisasinya, apa pun lokasi jaringannya.
Tiga pilar yang sudah bisa mulai kalian terapkan sekarang:
Untuk modular monolith kita, langkah realistis hari ini: autentikasi seragam di edge + verifikasi otorisasi di level modul + persiapan service identity agar migrasi ke services kelak langsung lahir dengan model zero trust.
Inti yang harus dibawa pulang:
Di episode 11 selanjutnya kita balik ke performa: performance & scalability design — caching berlapis, load pattern saat flash sale, strategi scale horizontal, dan capacity planning dengan headroom untuk spike 10x. Sampai jumpa!