Episode ini membahas pemasangan sertifikat TLS server dengan chain dan SAN yang benar, pengujian handshake memakai openssl s_client, serta penerapan mutual TLS dengan client certificate untuk autentikasi dua arah pada API internal dan service mesh.

Di episode 6 sebelumnya kalian sudah menguasai revocation: membangkitkan CRL, menjalankan OCSP responder, dan memahami apa yang terjadi ketika sertifikat revoked muncul di handshake. Fondasi kepercayaan sudah lengkap — sekarang saatnya yang lebih menyenangkan: memasang sertifikat ke server sungguhan dan melihat TLS bekerja di dunia nyata.
Sampai titik ini, kita hanya menguji sertifikat di lab. Episode 7 adalah episode transisi menuju produksi. Kalian akan belajar konfigurasi sertifikat TLS server dengan chain dan SAN yang benar, menguji hasil konfigurasi dengan openssl s_client, lalu naik satu level: mutual TLS (mTLS) yang memverifikasi klien dengan client certificate.
Roadmap episode ini: pertama kita rapikan file dan chain sertifikat, kedua kita konfigurasi Nginx dan HAProxy, ketiga kita uji dengan openssl s_client, dan terakhir kita bangun mTLS untuk autentikasi dua arah beserta skenario penerapannya di API internal dan service mesh.
Sertifikat server tidak berdiri sendiri. Ia berada di ujung rantai kepercayaan yang dimulai dari root CA, lalu satu atau lebih intermediate CA, dan berakhir di leaf certificate milik server. Klien harus bisa menelusuri rantai ini dari leaf sampai root yang sudah ada di trust store.
Karena itu, server tidak cukup diberi file leaf saja. Praktik terbaik adalah menyediakan fullchain: leaf certificate digabung dengan semua intermediate CA dalam satu file, mengikuti urutan dari leaf menuju root. Kunci privat disimpan terpisah dan harus dijaga dengan permission yang ketat.
ls -l /etc/ssl/private/api-server.key
ls -l /etc/ssl/certs/fullchain.pem
cat fullchain.pemPerintah cat fullchain.pem di atas menampilkan isi fullchain. Kalian akan melihat leaf certificate di bagian atas, diikuti intermediate CA di bawahnya. Root CA tidak wajib ada di fullchain — pemroses sudah punya root di trust store, dan menambahkannya justru bisa menimbulkan warning tentang kelebihan sertifikat.
Sebagian besar konfigurasi server gagal bukan karena kriptografinya, melainkan karena Subject Alternative Name (SAN). Peramban modern dan library TLS mengabaikan Common Name dan hanya memeriksa SAN untuk mencocokkan nama host. Jika SAN tidak memuat nama yang dipakai klien, koneksi ditolak meski sertifikatnya valid.
SAN bisa berupa nama DNS, wildcard, maupun alamat IP langsung. Untuk service internal yang sering diakses lewat IP, pastikan IP address ikut dicantumkan. Berikut cara menambahkan SAN saat membuat CSR.
openssl req -new -key /etc/ssl/private/api-server.key \
-addext "subjectAltName = DNS:api.internal,DNS:api.internal.local,IP:10.0.5.12" \
-out api-server.csrPerhatikan -addext yang menyisipkan SAN langsung ke CSR. Setelah sertifikat diterbitkan, periksa kembali apakah SAN-nya benar sebelum dipasang ke server, karena kesalahan kecil di sini berarti downtime untuk semua klien.
Nginx adalah pilihan paling umum untuk TLS termination. Yang perlu diperhatikan adalah menunjuk fullchain di ssl_certificate dan kunci privat di ssl_certificate_key. Jangan tertukar: menunjuk leaf saja akan membuat klien yang tidak punya intermediate gagal memverifikasi rantai.
server {
listen 443 ssl;
server_name api.internal;
ssl_certificate /etc/ssl/certs/fullchain.pem;
ssl_certificate_key /etc/ssl/private/api-server.key;
ssl_protocols TLSv1.2 TLSv1.3;
}Setelah menulis konfigurasi, uji sintaks lalu reload. Nginx memuat perubahan tanpa memutus koneksi yang sedang berjalan.
nginx -t
nginx -s reloadOutput nginx -t akan mengonfirmasi bahwa file konfigurasi valid, termasuk sertifikat yang bisa dibaca dengan benar. Jika ada error, periksa path file dan izin baca pada kunci privat.
HAProxy adalah alternatif yang banyak dipakai sebagai load balancer dan TLS termination. Berbeda dengan Nginx, HAProxy menerima sertifikat dalam satu file PEM yang memuat leaf, intermediate, dan kunci privat sekaligus.
frontend fe_https
bind :443 ssl crt /etc/haproxy/certs/api.pem
default_backend be_apiUrutan isi file api.pem untuk HAProxy: kunci privat, lalu leaf certificate, lalu intermediate. Gabungkan dengan urutan itu dan pastikan permission file hanya bisa dibaca oleh proses HAProxy.
Sebelum memberi tahu semua orang bahwa service sudah aman, uji dulu handshake-nya. openssl s_client adalah alat paling serbaguna untuk keperluan ini. Ia membuat koneksi TLS ke server dan menampilkan detail sertifikat serta jalur verifikasinya.
openssl s_client -connect api.internal:443 \
-servername api.internal -showcertsOpsi -servername mengirim SNI supaya server memilih sertifikat yang tepat saat ada banyak virtual host. -showcerts menampilkan seluruh rantai yang dikirim server. Periksa bagian Certificate chain: semua sertifikat harus muncul, dan bagian Verify return code harus berbunyi ok.
Untuk menguji dengan trust store spesifik, misalnya hanya mempercayai root CA internal kalian, gunakan -CAfile.
openssl s_client -connect api.internal:443 \
-servername api.internal -CAfile /etc/ssl/root-ca.crtJika Verify return code bukan ok, cek lagi fullchain, SAN, dan tanggal kedaluwarsa. openssl s_client adalah teman terbaik saat debugging TLS — biasakan menggunakannya sebelum menambahkan lapisan otomatisasi.
Info
Handshake yang menampilkan Verify return code bukan ok sering diabaikan karena koneksi tetap berhasil dibuat. Ini keliru: banyak library hanya memperingatkan, tapi beberapa aplikasi strict akan menolak. Selalu pastikan verifikasi benar-benar ok sebelum menandai konfigurasi selesai.
TLS standar hanya memverifikasi satu arah: klien memverifikasi identitas server. Server tidak peduli siapa kliennya selama handshake berhasil. Mutual TLS (mTLS) membalik logika itu: server juga meminta dan memverifikasi sertifikat dari klien, sehingga kedua belah pihak saling mengenali.
Client certificate pada dasarnya sama dengan sertifikat server, hanya saja diterbitkan untuk entitas klien seperti service, mesin, atau manusia, dan biasanya memuat Extended Key Usage client auth. Server memeriksa sertifikat itu terhadap CA yang dipercaya — yang bisa jadi CA yang sama dengan pembuat sertifikat server, atau CA terpisah yang khusus untuk klien.
Skenario paling umum adalah API internal yang hanya boleh diakses oleh service tertentu. Tanpa mTLS, siapa pun yang bisa menjangkau jaringan bisa memanggil API itu. Dengan mTLS, server menolak setiap koneksi yang tidak membawa client certificate valid.
Di Nginx, fitur ini diaktifkan lewat ssl_verify_client. Saat diatur ke on, klien tanpa sertifikat valid akan ditolak di level handshake.
server {
listen 443 ssl;
ssl_certificate /etc/ssl/certs/fullchain.pem;
ssl_certificate_key /etc/ssl/private/api-server.key;
ssl_client_certificate /etc/ssl/certs/client-ca.pem;
ssl_verify_client on;
}ssl_client_certificate menunjuk CA yang diizinkan menerbitkan client certificate. Sebaiknya CA ini terpisah dari CA server, supaya pencabutan atau kepercayaan untuk klien bisa dikelola tanpa memengaruhi sertifikat server. Client certificate yang dicabut akan ditolak sesuai mekanisme CRL dan OCSP yang kita bahas di episode 6.
Mengelola client certificate manual untuk ratusan service jelas tidak masuk akal. Di sinilah service mesh berperan. Teknologi seperti Istio atau Linkerd menanamkan identitas berbasis sertifikat ke setiap workload secara otomatis lewat sidecar, mengelola rotasi, dan menegakkan policy mTLS di seluruh mesh.
Perbedaannya dengan konfigurasi manual: kalian tidak menyentuh kode aplikasi sama sekali. Sidecar yang menangani handshake mTLS untuk pod, sementara aplikasi tetap berkomunikasi lewat localhost. Policy menentukan mode mTLS: permissive saat migrasi, dan strict ketika semua workload sudah siap.
Selain Nginx, hampir semua server TLS punya mekanisme serupa. Di HAProxy, verifikasi klien diatur lewat kata kunci verify pada baris bind.
frontend fe_internal_api
bind :8443 ssl crt /etc/haproxy/certs/api.pem \
verify required ca-file /etc/haproxy/certs/client-ca.pem
default_backend be_apiNilai required pada verify membuat handshake gagal bila klien tidak mengirim sertifikat yang valid. Ini setara dengan ssl_verify_client on di Nginx. Pastikan kebijakan diperkuat di level aplikasi juga, karena TLS hanya menjawab pertanyaan identitas, bukan pertanyaan otorisasi.
Untuk menguji konfigurasi mTLS, gunakan curl dengan opsi --cert dan --key.
curl -s --cacert /etc/ssl/root-ca.crt \
--cert /etc/ssl/certs/billing-client.pem \
--key /etc/ssl/private/billing-client.key \
https://api.internal/healthJika kalian mengirim request tanpa client certificate, koneksi akan ditolak dengan alert bad certificate atau error TLS dari server. Inilah bukti bahwa mTLS benar-benar menegakkan identitas, bukan sekadar dekorasi.
Info
Client certificate membuktikan identitas, tapi tidak otomatis berarti otorisasi. Dua service yang sama-sama punya sertifikat valid tetap bisa memiliki hak yang berbeda. Petakan identitas sertifikat ke peran atau izin di aplikasi, misalnya lewat atribut pada sertifikat, supaya akses bisa dibedakan secara halus.
Episode 7 membawa kalian dari lab ke produksi. Kalian belajar menyusun fullchain dengan benar, menambahkan SAN yang mencakup nama dan IP, mengonfigurasi Nginx dan HAProxy, menguji handshake dengan openssl s_client, lalu membangun mTLS yang memverifikasi identitas klien di level TLS.
Inti yang harus dibawa pulang:
openssl s_client adalah alat utama untuk memverifikasi handshake, chain, dan SAN sebelum dipakai produksi.ssl_verify_client on di Nginx dan verify required di HAProxy memaksa klien membawa sertifikat.Sampai episode ini, semua sertifikat masih diurus secara manual atau semi-manual. Di episode 8, kita akan membuang cara lama itu: kalian akan belajar ACME Protocol dari RFC 8555 — alur order hingga issuance, tiga tipe challenge, External Account Binding — lalu menerapkannya dengan Let's Encrypt dan certbot. Sampai jumpa!