Files
BE_IBL/docs/pdp-encryption-runbook.md
sas.fajri f744a25be8 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>
2026-05-31 15:24:24 +07:00

6.3 KiB

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

# 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 scripts/backup_pdp_tables.sh
# Backup tersimpan di ~/backup_pdp_YYYY_MM_DD_HHMMSS/

2. Buat file .env

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)

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

# 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

# Populate search index untuk NIK (dari _enc yang sudah ada)
php scripts/migrate_nik_bidx.php

6. Migration Data — Address Enc

# Enkripsi alamat (tanpa bidx — hemat disk)
php scripts/migrate_address_enc.php

7. Migration Data — Hasil Lab & Log

# 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

# 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

# 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

# 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

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