Keamanan Partner Service
Dokumen ini mencatat keunggulan keamanan yang telah diimplementasikan pada partner_service (port 8086).
Keamanan & Hardening
Semua item di bawah telah diimplementasikan dan diverifikasi per audit keamanan 2026-05-29–2026-06-05.
Input Validation & Body Limits
-
Global body limit via middleware:
withBodyLimitmiddleware 1 MB dipasang membungkus seluruh mux diserver.go, sehingga semua 20+ POST handler (termasuk/api/partner/v1/auth/tokendan seluruh endpoint admin) terlindungi dari request body berlebihan tanpa perluMaxBytesReaderindividual di setiap handler. Ini mencegah serangan DoS berbasis memory exhaustion dari credential holder maupun pihak tidak dikenal. -
Validasi UUID sebelum query database: handler
handleInternalCredentialByKey/handleInternalPartnerLookupNamesmemvalidasi format UUID setiap elemen query parameter (isValidUUID) sebelum diteruskan ke storeLookupPartnerNamesByIDs, yang mencocokkan viaid::text = ANY(string_to_array($1, ',')). String non-UUID tidak pernah mencapai layer database, mencegah potensi injeksi via invalid cast.
Authentication & Authorization
-
Fail-fast pada konfigurasi JWT:
MakeAuthMiddlewaremelakukanlog.FatalsaatJWT_SECRETkosong di semua environment non-local (staging, production, dll). Tidak ada fallback bypass untuk environment selain local — sistem tidak mau berjalan dengan konfigurasi auth yang tidak lengkap. -
Ownership bypass via nil claims ditutup:
handlePartnerScopedmengembalikan 401 saat JWT claims bernilai nil, sehingga mode dev tanpa JWT tidak bisa melewati pengecekan kepemilikan partner. Kondisiif claims == nil || claims.PartnerID != partnerIDmenjamin nil claims selalu ditolak. -
Auth middleware aktif di semua partner API endpoint: Seluruh 5 non-auth routes di bawah
/api/partner/v1/sekarang dibungkusm.auth(handler)diroutes.go. Tidak ada endpoint partner API yang dapat diakses tanpa token JWT valid. -
Global scope fail-closed: Mode global scope yang memungkinkan akses lintas-merchant sekarang mencatat
slog.Warnaudit dilistGlobaldanCanAccessMerchant. Dev mode bypass telah diubah darireturn true, nilmenjadireturn false, nil— sistem memilih tolak daripada izinkan saat terjadi ambiguitas. Empat credential placeholder global telah dinonaktifkan di database.
SSRF Prevention
- Validasi webhook URL blokir jaringan internal:
validateWebhookURL()helper memastikan URL webhook yang dikonfigurasi wajib menggunakan HTTPS dan memblokir semua loopback address serta private IP range vianet.ParseIP().IsLoopback()dan.IsPrivate(). Webhook dispatcher tidak akan pernah mengirim request ke jaringan internal meskipun admin menyimpan URL internal ke database.
Credential Security & Audit Trail
-
Scope resolution berbasis credential level:
ScopeResolvermembacaCOALESCE(credential.access_scope_mode, partner.access_scope_mode)sehingga credential yang dikonfigurasi restricted benar-benar dibatasi aksesnya, meskipun partner induknya memiliki scope global. Sebelumnya, scope level credential diabaikan sepenuhnya. -
Scope credential dipropagasi ke JWT:
partnerJWTClaimsmenyertakan fieldAccessScopeModeyang di-populate dari credential aktif. Downstream scope resolution di setiap request menghormati scope level credential, bukan hanya scope level partner. -
Audit log lifecycle credential: Operasi
RotateCredential,RevokeCredentialByID, danCreateHMACCredentialmencatat event kepartner.api_audit_logs. Forensik post-incident dapat menentukan kapan dan oleh siapa credential di-rotate atau di-revoke. -
Audit log akses global scope ke database:
CanAccessMerchantdalam mode global menulis kepartner.api_audit_logs(sebelumnya hanyaslog.Warnin-memory). Setiap akses lintas-merchant tercatat secara persisten untuk kebutuhan audit dan deteksi anomali. -
Upgrade transparan SHA-256 ke bcrypt: Credential lama yang tersimpan sebagai SHA-256 secara otomatis di-upgrade ke bcrypt pada saat verifikasi berhasil. Ini mengeliminasi timing oracle antara dua hash type secara bertahap tanpa membutuhkan migrasi massal atau downtime.
-
Endpoint credential sensitif dibatasi ke high-privilege key:
GET /internal/credentials/by-keyhanya dapat diakses oleh internal key bereputasi tinggi yang terpisah.hmac_secret_encryptedtidak bocor ke semua internal key holder, membatasi radius blast jika sebuah internal key dikompromikan.
Ringkasan Postur Keamanan
| Area | Status |
|---|---|
| Body limit global (DoS prevention) | Aktif |
| JWT fail-fast semua env non-local | Aktif |
| Auth middleware semua partner API routes | Aktif |
| Global scope fail-closed + audit log | Aktif |
| SSRF prevention via webhook URL validation | Aktif |
| Credential-level scope resolution | Aktif |
| Audit log lifecycle credential | Aktif |
| Upgrade hash SHA-256 → bcrypt transparan | Aktif |
| Pembatasan endpoint credential sensitif | Aktif |
| UUID validation sebelum DB query | Aktif |