Strategi uji untuk migrasi TLS/PKI tanpa regresi keamanan harus menjawab dua risiko sekaligus: layanan tetap kompatibel dengan klien yang sah, dan posture keamanan tidak turun diam-diam setelah perubahan. Mengganti sertifikat, CA, cipher suite, trust store, atau library kriptografi sering terlihat sederhana, tetapi satu perubahan nama algoritma, format chain, atau default library dapat membuat handshake gagal, fallback ke parameter yang lebih lemah, atau validasi sertifikat tidak berjalan seperti yang diharapkan.

Dalam praktiknya, tim tidak bisa bergantung pada satu tes “koneksi sukses”. Yang dibutuhkan adalah kombinasi compatibility matrix, contract test untuk handshake, negative test untuk mismatch dan downgrade, golden capture untuk memverifikasi parameter yang benar-benar dinegosiasikan, canary rollout, serta observabilitas error handshake setelah rilis. Konteks standardisasi TLS dan varian implementasi algoritma baru menunjukkan bahwa perbedaan penamaan dan perilaku implementasi dapat memicu salah konfigurasi; karena itu workflow verifikasi harus berfokus pada bukti perilaku di wire, bukan asumsi dari konfigurasi semata.

Jenis perubahan yang perlu dianggap berisiko

Tidak semua perubahan TLS/PKI memiliki profil risiko yang sama, tetapi semuanya layak masuk ke jalur uji yang disiplin bila menyentuh parameter handshake atau rantai kepercayaan.

  • Rotasi sertifikat server: perubahan SAN, EKU, issuer, chain intermediate, atau masa berlaku.
  • Migrasi CA atau trust store: root/intermediate baru belum tentu tersedia di semua klien.
  • Perubahan cipher suite atau kelompok key exchange: dapat memutus kompatibilitas dengan klien lama atau menyebabkan negosiasi ke parameter tak diinginkan.
  • Upgrade library kriptografi: default verification path, hostname verification, session resumption, dan daftar algoritma bisa berubah.
  • Perubahan terminasi TLS: misalnya pindah dari application server ke load balancer atau service mesh.
  • Aktivasi mutual TLS: berdampak pada distribusi sertifikat klien, trust anchor, dan validasi chain dua arah.

Kesalahan umum adalah menganggap perubahan ini setara dengan perubahan konfigurasi biasa. Padahal, regresi sering muncul bukan karena layanan mati total, melainkan karena sebagian klien gagal, sebagian koneksi turun ke parameter lebih lemah, atau observability tidak cukup rinci untuk melihat pola gagal.

Prinsip dasar workflow verifikasi migrasi TLS/PKI

1. Verifikasi perilaku, bukan hanya file konfigurasi

Konfigurasi dapat terlihat benar tetapi hasil negosiasi berbeda karena default library, urutan prioritas cipher, atau chain yang dikirim server. Karena itu, validasi harus memeriksa apa yang benar-benar terjadi di handshake.

2. Pisahkan uji kompatibilitas dan uji keamanan

Keduanya berbeda. Uji kompatibilitas menjawab: “klien yang sah masih bisa terhubung?” Uji keamanan menjawab: “klien atau parameter yang tidak diizinkan tetap ditolak?” Sering terjadi tim hanya menguji jalur sukses dan melewatkan pengujian jalur tolak.

3. Gunakan artefak yang bisa dibandingkan antar-rilis

Contohnya: hasil negosiasi TLS, metadata sertifikat, fingerprint chain, dan daftar error handshake per kategori. Ini memudahkan deteksi regresi halus pada pipeline CI dan saat canary.

4. Hindari ketergantungan pada satu tool

Output satu tool dapat dipengaruhi default lokal. Gabungkan pengujian dari sisi klien aplikasi, tool CLI, dan bila perlu packet capture singkat untuk memastikan hasil konsisten.

Menyusun test matrix kompatibilitas client-server

Test matrix adalah fondasi. Tujuannya bukan menguji semua kombinasi tak terbatas, melainkan memetakan kombinasi yang benar-benar mewakili risiko produksi.

Dimensi minimum yang sebaiknya diuji

  • Jenis klien: browser, mobile app, service internal, job batch, SDK pihak ketiga.
  • Runtime/library TLS: misalnya variasi OpenSSL, BoringSSL, JDK, Go runtime, atau platform mobile. Tidak perlu menyebut versi yang tak relevan, tetapi identifikasi keluarga runtime yang berbeda.
  • Mode koneksi: TLS biasa, mTLS, via proxy, via ingress, session resumption bila dipakai.
  • Target environment: staging, canary, production subset.
  • Parameter yang berubah: sertifikat, CA chain, cipher suite, key exchange group, ALPN, hostname verification.

Cara memilih kombinasi yang bernilai tinggi

Prioritaskan kombinasi berdasarkan dampak bisnis dan keragaman stack. Misalnya:

  1. Klien dengan trafik terbesar.
  2. Klien paling tua atau paling sulit di-upgrade.
  3. Integrasi eksternal yang trust store-nya tidak Anda kontrol.
  4. Jalur mTLS, karena gagal handshake di sini biasanya lebih sulit didiagnosis.

Buat hasil matrix dalam bentuk tabel internal dengan status must pass, nice to have, dan known incompatible. Status terakhir penting agar tim tidak salah menafsirkan kegagalan yang memang sudah diharapkan dan didokumentasikan.

Contoh isi matrix

  • Service A (Go client) → Ingress TLS baru: harus lolos, verifikasi hostname aktif, chain issuer sesuai.
  • Batch legacy → Endpoint baru: harus ditinjau, kemungkinan gagal karena trust store lama.
  • Mobile app lama → API gateway: validasi apakah sertifikat/intermediate baru masih diterima.
  • mTLS partner eksternal → BFF: verifikasi trust anchor klien, EKU, dan subject mapping.

Contract test handshake: apa yang harus dianggap “benar”

Contract test untuk handshake adalah tes yang memverifikasi sekumpulan properti keamanan dan kompatibilitas yang harus tetap benar setelah migrasi. Bukan hanya “socket connect berhasil”.

Properti yang layak dijadikan kontrak

  • Negosiasi menggunakan versi TLS minimum yang diizinkan.
  • SNI mengarah ke sertifikat yang benar.
  • Hostname verification berhasil untuk nama host yang sah dan gagal untuk nama lain.
  • Chain sertifikat lengkap dan urutannya dapat divalidasi klien target.
  • ALPN sesuai kebutuhan, misalnya HTTP/2 tidak hilang tanpa sengaja.
  • Cipher/key exchange/group yang dinegosiasikan termasuk daftar yang diizinkan.
  • Untuk mTLS, sertifikat klien yang sah diterima dan yang tidak sah ditolak.

Jika tim Anda punya service-to-service estate yang besar, kontrak ini sebaiknya dibungkus sebagai test helper bersama, agar seluruh service memeriksa properti yang sama saat endpoint TLS berubah.

Contoh pemeriksaan dengan OpenSSL

Perintah CLI tidak menggantikan automated test, tetapi sangat berguna untuk membuat kontrak eksplisit dan mudah direproduksi di CI atau saat debugging.

openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts -verify_return_error

Gunakan output tersebut untuk memeriksa:

  • sertifikat leaf dan intermediate yang benar-benar dikirim,
  • apakah verifikasi chain sukses,
  • protokol dan cipher yang dinegosiasikan,
  • apakah nama host sesuai dengan SAN sertifikat.

Untuk pengujian yang lebih deterministik, parsing output sebaiknya dilakukan oleh skrip internal yang hanya mengambil field penting dan membandingkannya dengan ekspektasi yang telah ditetapkan.

Contoh skrip verifikasi sederhana

#!/usr/bin/env bash
set -euo pipefail

HOST="api.example.com"
PORT="443"
OUT=$(openssl s_client -connect "${HOST}:${PORT}" -servername "${HOST}" -verify_return_error </dev/null 2>/dev/null)

echo "$OUT" | grep -q "Verify return code: 0 (ok)"
echo "$OUT" | grep -q "Protocol  : TLS"
echo "$OUT" | grep -q "Cipher    :"

echo "Handshake dasar valid untuk ${HOST}:${PORT}"

Skrip seperti ini belum cukup untuk seluruh kebutuhan, tetapi berguna sebagai lapisan cepat untuk mendeteksi kegagalan chain atau negosiasi dasar.

Negative test untuk downgrade, mismatch, dan salah konfigurasi

Regresi keamanan sering lolos karena tim hanya menguji jalur yang sukses. Negative test memastikan sistem menolak kondisi yang seharusnya ditolak.

Skenario negative test yang wajib dipertimbangkan

  • Downgrade protocol: klien yang memaksa versi TLS di bawah kebijakan harus gagal.
  • Cipher mismatch: bila hanya cipher tertentu yang diizinkan, kombinasi di luar daftar harus ditolak.
  • Hostname mismatch: koneksi ke nama host yang tidak ada di SAN harus gagal verifikasi.
  • Unknown CA: sertifikat dari CA yang tidak dipercaya harus ditolak.
  • Incomplete chain: server yang lupa mengirim intermediate harus terdeteksi.
  • mTLS invalid client cert: sertifikat klien tanpa EKU yang sesuai, kedaluwarsa, atau signed by CA yang salah harus ditolak.
  • SNI salah: endpoint multi-tenant harus mengembalikan sertifikat yang benar atau gagal secara aman, bukan diam-diam melayani dengan sertifikat default yang tidak sesuai.

Mengapa negative test penting saat nama standar/algoritma berubah

Pada migrasi algoritma atau library, perubahan nama kelompok algoritma, representasi konfigurasi, atau pemetaan default dapat menyebabkan dua jenis bug: fail-open dan accidental fallback. Tes negatif membantu memastikan sistem tidak diam-diam menerima konfigurasi yang salah lalu turun ke jalur lebih lemah atau tak terduga.

Contoh pengujian kegagalan yang terkontrol

# Contoh konsep: paksa parameter yang tidak didukung dan pastikan handshake gagal.
openssl s_client -connect api.example.com:443 -servername api.example.com \
  -cipher 'INVALID_OR_UNSUPPORTED' 

Format parameter yang tersedia bergantung pada tool dan runtime yang dipakai. Poin utamanya: Anda perlu test yang menyatakan dengan jelas bahwa parameter di luar kebijakan memang ditolak, bukan hanya tidak pernah dipakai pada jalur sukses.

Golden capture untuk verifikasi parameter handshake

Golden capture adalah snapshot referensi dari handshake yang dianggap benar. Ini bisa berupa ringkasan field penting dari packet capture, hasil tool inspeksi, atau metadata handshake yang disimpan sebagai artefak CI.

Apa yang sebaiknya disimpan sebagai golden reference

  • Versi TLS yang dinegosiasikan.
  • ALPN hasil negosiasi.
  • Cipher suite atau parameter kriptografi yang diharapkan.
  • Subject, issuer, SAN, dan fingerprint sertifikat leaf.
  • Fingerprint intermediate bila chain berubah.
  • Status apakah mutual authentication diminta dan berhasil, jika mTLS aktif.

Jangan menyimpan artefak yang terlalu rapuh, misalnya byte-for-byte seluruh transcript jika nilainya berubah karena nonce acak. Simpan field yang memang menjadi kontrak.

Kenapa golden capture efektif

Perubahan konfigurasi TLS sering tidak terlihat di level aplikasi. Dengan golden capture, tim bisa membandingkan sebelum dan sesudah migrasi secara obyektif. Ini sangat membantu ketika upgrade library mengubah default secara diam-diam.

Catatan: simpan golden reference dalam bentuk yang mudah dibaca mesin dan manusia, misalnya JSON hasil ekstraksi field penting, bukan screenshot atau catatan manual.

Contoh struktur artefak golden

{
  "server_name": "api.example.com",
  "tls_version": "expected-min-or-better",
  "alpn": "h2",
  "certificate": {
    "subject_cn": "api.example.com",
    "san_contains": ["api.example.com"],
    "issuer_contains": "Example Intermediate CA"
  },
  "mtls": false
}

Nilai di atas sengaja generik. Di implementasi nyata, isi dengan field yang benar-benar Anda kontrol dan ingin pertahankan antar-rilis.

Canary rollout dan observability saat migrasi

Pengujian pre-release penting, tetapi tidak cukup. Banyak kegagalan TLS baru terlihat saat berhadapan dengan keragaman klien produksi. Karena itu, migrasi TLS/PKI sebaiknya selalu memakai canary rollout dan metrik handshake yang dapat dipantau.

Strategi canary yang aman

  1. Rilis ke subset endpoint, subset instance, atau subset traffic yang bisa diisolasi.
  2. Aktifkan observability handshake sebelum canary dimulai.
  3. Bandingkan error rate dan distribusi negotiated parameters antara baseline dan canary.
  4. Siapkan rollback yang cepat, termasuk sertifikat/chain/config lama yang masih valid.

Metrik yang sebaiknya dikumpulkan

  • Handshake success/failure count.
  • Error reason: unknown_ca, bad_certificate, handshake_failure, protocol_version, certificate_expired, hostname mismatch, atau kategori setara yang tersedia di stack Anda.
  • Negotiated TLS version.
  • Negotiated ALPN.
  • Distribusi cipher/group bila dapat diakses dari terminator TLS.
  • Session resumption success rate bila relevan untuk performa.

Jika stack Anda tidak mengekspos semua detail dari sisi aplikasi, pertimbangkan pengumpulan di reverse proxy, load balancer, ingress controller, atau service mesh tempat terminasi TLS terjadi.

Prinsip penting observability

Jangan hanya mencatat “SSL error”. Anda perlu pengelompokan error yang berguna untuk diagnosis. Misalnya, lonjakan unknown_ca mengarah ke masalah trust store atau chain, sedangkan lonjakan protocol_version mengarah ke klien lawas yang tidak kompatibel dengan kebijakan baru.

Mengurangi flaky test TLS di CI

Test TLS di CI sering flaky karena bergantung pada jaringan eksternal, waktu sistem, DNS, entropy, atau sertifikat yang mendekati masa kedaluwarsa. Flaky test berbahaya karena membuat tim mengabaikan alarm yang valid.

Penyebab umum flaky test

  • Mengakses host publik yang kondisinya berubah di luar kontrol tim.
  • Sertifikat uji punya masa berlaku terlalu pendek tanpa mekanisme rotasi yang konsisten.
  • Pengujian bergantung pada DNS atau clock yang tidak stabil.
  • Session cache/resumption membuat hasil antar-run tidak identik.
  • Environment CI berbagi port atau resource sehingga terminator TLS belum siap saat test dimulai.

Cara membuat test lebih deterministik

  • Jalankan server TLS lokal atau ephemeral di pipeline, bukan endpoint publik.
  • Gunakan CA uji internal dan generate sertifikat fixture yang masa berlakunya cukup panjang untuk pipeline.
  • Matikan variabel yang tidak relevan untuk test tertentu, misalnya session resumption, bila itu bukan objek yang diuji.
  • Pin input: hostname, chain, trust store, dan port harus tetap.
  • Tunggu readiness sebelum menjalankan test handshake.
  • Pisahkan test unit parsing/validation dari test integrasi TLS penuh agar kegagalan lebih mudah dilokalisasi.

Contoh readiness check sederhana

for i in $(seq 1 30); do
  if openssl s_client -connect 127.0.0.1:8443 -servername test.local </dev/null >/dev/null 2>&1; then
    echo "TLS endpoint siap"
    break
  fi
  sleep 1
done

Readiness check sederhana seperti ini sering cukup untuk menghilangkan race condition ketika container server TLS baru dinyalakan di CI.

Checklist rilis migrasi TLS/PKI

Bagian ini bisa langsung dipakai sebagai dasar release checklist.

Sebelum rilis

  • Inventaris semua klien dan jalur traffic yang terkena dampak.
  • Definisikan kontrak handshake: versi minimum, chain, hostname validation, ALPN, mTLS, parameter yang diizinkan.
  • Siapkan compatibility matrix dan tandai kombinasi prioritas tinggi.
  • Jalankan positive dan negative test terhadap environment staging yang merepresentasikan terminasi TLS produksi.
  • Buat golden capture dan bandingkan hasil sebelum-sesudah.
  • Pastikan sertifikat lama dan konfigurasi rollback masih tersedia dan valid selama jendela rilis.

Saat canary

  • Rilis ke subset traffic atau instance yang bisa diisolasi.
  • Pantau error handshake per kategori, bukan hanya total error.
  • Bandingkan negotiated parameters antara baseline dan canary.
  • Verifikasi klien prioritas tinggi secara aktif, bukan menunggu error masuk.

Setelah rilis penuh

  • Tinjau distribusi error dan kompatibilitas 24-48 jam pertama sesuai pola traffic Anda.
  • Hapus konfigurasi fallback sementara hanya setelah yakin tidak dibutuhkan.
  • Perbarui dokumentasi trust chain, proses rotasi, dan artefak golden untuk baseline baru.

Kesalahan yang paling sering terjadi

  • Mengirim chain tidak lengkap dan baru ketahuan pada klien tertentu.
  • Mengandalkan hasil dari satu runtime lalu mengira semua klien akan berperilaku sama.
  • Tidak menguji hostname verification, terutama pada endpoint internal dengan banyak alias.
  • Tidak punya observability yang granular, sehingga semua kegagalan terlihat sama.
  • Melewatkan negative test, padahal regresi keamanan sering muncul sebagai jalur tolak yang berubah jadi jalur terima.
  • Membuat golden reference terlalu rapuh sehingga sering berubah untuk alasan yang tidak relevan.

Penutup

Migrasi TLS/PKI yang aman tidak ditentukan oleh satu sertifikat baru atau satu file konfigurasi yang tampak benar, melainkan oleh kemampuan tim membuktikan bahwa handshake tetap kompatibel dan kebijakan keamanan tetap tegak. Pendekatan yang paling efektif adalah menggabungkan test matrix client-server, contract test handshake, negative test untuk downgrade dan mismatch, golden capture untuk parameter penting, canary rollout, serta observability error handshake yang rinci.

Jika Anda ingin mengurangi regresi, mulailah dari hal yang paling operasional: definisikan kontrak handshake, otomatisasi verifikasinya di CI, simpan artefak golden yang stabil, lalu jadikan checklist rilis TLS/PKI sebagai bagian wajib dari proses deploy. Dengan cara itu, perubahan nama standar, varian implementasi, atau default library tidak langsung berubah menjadi insiden produksi.