FHM31052601IBL - tambah runbook implementasi enkripsi PII untuk production
Dokumentasi lengkap urutan eksekusi, field yang dienkripsi, format masking, disk space requirement, dan restore procedure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
223
docs/pdp-encryption-runbook.md
Normal file
223
docs/pdp-encryption-runbook.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# Runbook: Implementasi Enkripsi PII Pasien (UU PDP) — Production
|
||||
|
||||
## Ringkasan
|
||||
|
||||
Enkripsi AES-256-GCM untuk data pribadi pasien dan data medis.
|
||||
Key disimpan di `.env`. Data asli di kolom `_enc`, kolom lama berisi masked value.
|
||||
Search pasien via trigram blind index (nama, HP, DOB, NIK).
|
||||
|
||||
---
|
||||
|
||||
## Urutan Eksekusi di Production
|
||||
|
||||
### 0. Pre-flight
|
||||
|
||||
```bash
|
||||
# Pastikan disk cukup (minimal 10GB free sebelum mulai)
|
||||
df -h /
|
||||
|
||||
# Pastikan MySQL running
|
||||
mysql -e "SELECT 1;"
|
||||
|
||||
# Catat ukuran tabel sebelum
|
||||
mysql -e "SELECT table_name, ROUND((data_length+index_length)/1024/1024,1) MB
|
||||
FROM information_schema.tables WHERE table_schema='one_lab'
|
||||
ORDER BY (data_length+index_length) DESC LIMIT 15;"
|
||||
```
|
||||
|
||||
### 1. Backup Database
|
||||
|
||||
```bash
|
||||
bash scripts/backup_pdp_tables.sh
|
||||
# Backup tersimpan di ~/backup_pdp_YYYY_MM_DD_HHMMSS/
|
||||
```
|
||||
|
||||
### 2. Buat file `.env`
|
||||
|
||||
```bash
|
||||
cat > /path/to/one-api-lab/.env << 'EOF'
|
||||
IBL_ENCRYPT_KEY=<passphrase-enkripsi-kamu>
|
||||
IBL_ENCRYPT_SEARCH_KEY=<passphrase-search-kamu>
|
||||
EOF
|
||||
chmod 600 .env
|
||||
```
|
||||
|
||||
> ⚠️ **WAJIB** simpan passphrase di password manager sebelum lanjut.
|
||||
> Key hilang = data tidak bisa didekripsi.
|
||||
|
||||
### 3. Jalankan SQL Migration (tambah kolom)
|
||||
|
||||
```bash
|
||||
mysql one_lab < sql/manual_changes/2026-05-31-pdp-encrypt-columns.sql
|
||||
mysql one_lab < sql/manual_changes/2026-05-31-pdp-update-triggers-enc.sql
|
||||
|
||||
# Verifikasi kolom terbentuk
|
||||
mysql -e "SHOW COLUMNS FROM one_lab.m_patient LIKE '%_enc';"
|
||||
mysql -e "SHOW COLUMNS FROM one_lab.m_patient LIKE '%_bidx';"
|
||||
```
|
||||
|
||||
### 4. Migration Data — Patient PII
|
||||
|
||||
```bash
|
||||
# Enkripsi m_patient dan m_patientaddress (178K + 133K rows)
|
||||
# Estimasi: 30-60 menit tergantung server
|
||||
php scripts/migrate_encrypt_patient.php
|
||||
|
||||
# Verifikasi
|
||||
mysql -e "SELECT COUNT(*) total, COUNT(M_PatientName_enc) done FROM one_lab.m_patient;"
|
||||
mysql -e "SELECT COUNT(*) total, COUNT(M_PatientAddressDescription_enc) done FROM one_lab.m_patientaddress;"
|
||||
```
|
||||
|
||||
### 5. Migration Data — NIK Bidx
|
||||
|
||||
```bash
|
||||
# Populate search index untuk NIK (dari _enc yang sudah ada)
|
||||
php scripts/migrate_nik_bidx.php
|
||||
```
|
||||
|
||||
### 6. Migration Data — Address Enc
|
||||
|
||||
```bash
|
||||
# Enkripsi alamat (tanpa bidx — hemat disk)
|
||||
php scripts/migrate_address_enc.php
|
||||
```
|
||||
|
||||
### 7. Migration Data — Hasil Lab & Log
|
||||
|
||||
```bash
|
||||
# Enkripsi hasil lab (t_orderdetail, t_orderheader, so_resultentry*, dll)
|
||||
php scripts/migrate_encrypt_results.php
|
||||
|
||||
# Enkripsi t_orderdelivery (email/HP tujuan pengiriman hasil)
|
||||
php scripts/migrate_encrypt_orderdelivery.php
|
||||
```
|
||||
|
||||
### 8. Masking Kolom Plaintext
|
||||
|
||||
```bash
|
||||
# Masking kolom lama agar controller lama tidak expose data lengkap
|
||||
php scripts/mask_patient_plaintext.php
|
||||
|
||||
# Re-masking nama dengan format baru (kata pertama penuh + inisial)
|
||||
php scripts/remask_patient_name.php
|
||||
```
|
||||
|
||||
### 9. Verifikasi Akhir
|
||||
|
||||
```bash
|
||||
# Cek sample data sudah termasking
|
||||
mysql -e "SELECT M_PatientID, M_PatientName, M_PatientHP, M_PatientEmail
|
||||
FROM one_lab.m_patient LIMIT 5;"
|
||||
|
||||
# Pastikan decrypt bisa berjalan
|
||||
php -r "
|
||||
define('BASEPATH', true);
|
||||
\$_ENV['IBL_ENCRYPT_KEY'] = trim(explode('=', file('.env')[0])[1]);
|
||||
\$_ENV['IBL_ENCRYPT_SEARCH_KEY'] = trim(explode('=', file('.env')[1])[1]);
|
||||
require 'application/libraries/Ibl_encryptor.php';
|
||||
\$enc = new Ibl_encryptor();
|
||||
\$row = (new PDO('mysql:host=localhost;dbname=one_lab', 'user', 'pass'))
|
||||
->query('SELECT M_PatientName_enc FROM m_patient LIMIT 1')->fetch();
|
||||
echo \$enc->decrypt(\$row['M_PatientName_enc']) . PHP_EOL;
|
||||
"
|
||||
|
||||
# Cek disk usage setelah
|
||||
df -h /
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Catatan Penting
|
||||
|
||||
### Key Management
|
||||
- Key disimpan di `.env` (JANGAN commit ke git — sudah di `.gitignore`)
|
||||
- Backup key di: password manager + file enkripsi di lokasi terpisah
|
||||
- Jika key hilang: data di `_enc` tidak bisa didekripsi
|
||||
|
||||
### Disk Space
|
||||
- Tambahkan minimal **8GB free** sebelum mulai di production
|
||||
- Kolom `_bidx` untuk nama/HP/DOB/NIK menambah ~500MB-1GB
|
||||
- Kolom `_enc` untuk semua field menambah ~200-300MB
|
||||
- `m_patientaddress` tidak punya `_bidx` (dihapus — hemat disk)
|
||||
|
||||
### Jika Disk Penuh
|
||||
```bash
|
||||
# Cek pemakai disk terbesar
|
||||
du -sh /home/* /tmp/* /var/log/* 2>/dev/null | sort -rh | head -20
|
||||
|
||||
# Bersihkan journal (butuh sudo)
|
||||
sudo journalctl --vacuum-size=300M
|
||||
sudo truncate -s 0 /var/log/btmp
|
||||
```
|
||||
|
||||
### Field yang Dienkripsi
|
||||
|
||||
#### `one_lab.m_patient`
|
||||
| Field | `_enc` | `_bidx` |
|
||||
|-------|--------|---------|
|
||||
| M_PatientName | ✅ | ✅ (search) |
|
||||
| M_PatientHP | ✅ | ✅ (search) |
|
||||
| M_PatientDOB | ✅ | ✅ (search) |
|
||||
| M_PatientNIK | ✅ | ✅ (search) |
|
||||
| M_PatientEmail | ✅ | — |
|
||||
| M_PatientPhone | ✅ | — |
|
||||
| M_PatientPOB | ✅ | — |
|
||||
| M_PatientIDNumber | ✅ | — |
|
||||
| M_PatientNIP | ✅ | — |
|
||||
|
||||
#### `one_lab.m_patientaddress`
|
||||
| Field | `_enc` | `_bidx` |
|
||||
|-------|--------|---------|
|
||||
| M_PatientAddressDescription | ✅ | — (dihapus, hemat disk) |
|
||||
| M_PatientAddressEmail | ✅ | — |
|
||||
| M_PatientAddressPhone | ✅ | — |
|
||||
|
||||
#### Hasil Lab
|
||||
- `t_orderdetail`: `T_OrderDetailResult`, `T_OrderDetailNote`
|
||||
- `t_orderheader`: `T_OrderHeaderDiagnose`
|
||||
- `t_orderdelivery`: `T_OrderDeliveryDestination`
|
||||
- `so_resultentrydetail`, `so_resultentry_fisik_umum`, dll
|
||||
- `mcu_resume_results`: `Mcu_ResumeResultsJSON`
|
||||
|
||||
#### Log
|
||||
- `one_lab_log.log_patient`: `Log_PatientJsonBefore/After`
|
||||
- `one_lab_log.log_fo`: `Log_FoJson`
|
||||
|
||||
### Search Pasien
|
||||
Search parameter via `+` separator:
|
||||
```
|
||||
?search=NAMA+HP+DOB+NIK
|
||||
```
|
||||
- `e[0]` = nama (trigram bidx, min 3 karakter)
|
||||
- `e[1]` = HP (trigram bidx, min 3 karakter)
|
||||
- `e[2]` = DOB format dd-mm-yyyy (trigram bidx)
|
||||
- `e[3]` = NIK (trigram bidx, min 3 karakter)
|
||||
|
||||
### Masking Format
|
||||
| Field | Contoh |
|
||||
|-------|--------|
|
||||
| Nama | `FAJRI H******* M****` |
|
||||
| HP | `0812*****890` |
|
||||
| Email | `fa***@gmail.com` |
|
||||
| NIK/IDNumber | `3201***01` |
|
||||
| POB | `JA***` |
|
||||
| Alamat | `Jl. S***` |
|
||||
|
||||
### Controller yang Sudah Diupdate (Read Full Data)
|
||||
- `mockup/fo/ibl_registration/Patient.php` — FO registration
|
||||
- `mockup/fo/ibl_registration/Order.php` — Order management
|
||||
- `mockup/fo/ibl_registration/Payment.php`
|
||||
- `mockup/fo/ibl_registration/History.php`
|
||||
- `mockup/fo/ibl_registration/Delivery.php`
|
||||
- `mockup/fo/ibl_registration/Order copy.php`
|
||||
- `mockup/masterdata/Patientv4.php` — Masterdata pasien (full data)
|
||||
|
||||
### Controller yang Belum Diupdate (Tampil Data Masked)
|
||||
Semua controller lain (~300+ file) otomatis menampilkan data termasking
|
||||
karena kolom plaintext sudah dimasking. Tidak perlu update satu-satu.
|
||||
|
||||
### Restore jika Ada Masalah
|
||||
```bash
|
||||
mysql one_lab < ~/backup_pdp_YYYY_MM_DD_HHMMSS/one_lab_tables.sql
|
||||
mysql one_lab_log < ~/backup_pdp_YYYY_MM_DD_HHMMSS/one_lab_log_tables.sql
|
||||
```
|
||||
Reference in New Issue
Block a user