Certificate & Key Management: Mengelola Keystore dan Truststore di Kafka #

Keamanan berbasis kriptografi kunci publik (Public Key Infrastructure atau PKI) adalah fondasi utama dari enkripsi lalu lintas data dan otentikasi timbal balik (Mutual TLS) pada Apache Kafka. Di lingkungan kluster terdistribusi, setiap broker dan klien harus dapat membuktikan identitasnya secara kriptografis menggunakan sertifikat digital standar x509 yang ditandatangani oleh pihak tepercaya (Certificate Authority / CA).

Namun, mengelola sertifikat digital di Java Virtual Machine (JVM)—runtime tempat Apache Kafka berjalan—sering kali membingungkan bagi pengembang maupun tim operasi. Kita harus berurusan dengan konsep Keystore, Truststore, perintah Java keytool yang rumit, serta strategi rotasi sertifikat agar kluster tidak mendadak mati ketika masa berlaku sertifikat habis.

Artikel ini akan mengupas tuntas perbedaan konseptual antara Keystore dan Truststore, memberikan panduan praktis langkah-demi-langkah (step-by-step) pembuatan Certificate Authority (CA) internal menggunakan OpenSSL dan keytool, serta memaparkan strategi rotasi sertifikat produksi tanpa menyebabkan downtime pada kluster kita.


Memahami Perbedaan Konseptual: Keystore vs Truststore #

Dalam dunia Java Security, sertifikat dan kunci privat (private key) disimpan di dalam repositori khusus berbentuk file biner terenkripsi. Dua jenis file penyimpanan yang digunakan di Kafka adalah Keystore dan Truststore. Secara teknis, kedua file ini dapat menggunakan format yang sama (seperti .jks untuk Java KeyStore standar, atau .p12 untuk format standar industri PKCS12). Namun, tujuan fungsional keduanya di dalam arsitektur keamanan sangatlah berbeda.

flowchart LR
    subgraph JVM ["ARSITEKTUR MEMORI JVM"]
        direction LR
        Keystore["KEYSTORE (Siapa saya?)<br/>- Kunci Privat Broker (Private Key)<br/>- Sertifikat Publik Broker<br/>- Rantai Sertifikat Terpenuhi"]
        Truststore["TRUSTSTORE (Siapa saja yang saya percayai?)<br>- Sertifikat Root CA Publik<br>- Sertifikat Intermediate CA"]
    end

1. Keystore: Pembuktian Identitas Diri (“Siapa Saya?”) #

Keystore digunakan untuk menyimpan kredensial identitas pribadi dari entitas tempat ia berjalan (baik broker maupun klien).

  • Isi Keystore: Kunci privat (private key) yang harus dirahasiakan rapat-rapat, sertifikat kunci publik (public key certificate) milik entitas tersebut, dan rantai sertifikat (certificate chain) yang menghubungkannya ke Root CA.
  • Fungsi: Ketika broker atau klien ingin membuka koneksi aman, ia akan menggunakan isi Keystore ini untuk membuktikan identitasnya kepada pihak lain.
  • Analogi: Keystore mirip dengan Paspor Pribadi Kita. Paspor tersebut berisi data diri kita dan hanya kita yang berhak memegangnya (karena di dalamnya ada kunci privat kita).

2. Truststore: Daftar Kepercayaan (“Siapa Saja yang Saya Percayai?”) #

Truststore digunakan untuk memverifikasi keabsahan sertifikat yang disodorkan oleh entitas luar yang mencoba terhubung dengan kita.

  • Isi Truststore: Hanya berisi sertifikat kunci publik (public certificates) dari pihak ketiga tepercaya, terutama sertifikat Root CA dan sertifikat Intermediate CA. Truststore tidak boleh menyimpan kunci privat (private key) apa pun.
  • Fungsi: Ketika entitas luar menyodorkan sertifikatnya untuk membuktikan diri, kita akan mencocokkan tanda tangan pada sertifikat tersebut dengan daftar sertifikat CA tepercaya yang tersimpan di dalam Truststore kita. Jika sertifikat tersebut ditandatangani oleh salah satu CA di Truststore kita, koneksi diizinkan.
  • Analogi: Truststore mirip dengan Daftar Instansi Pemerintah Resmi yang diakui oleh negara kita untuk memvalidasi apakah paspor orang asing yang masuk ke wilayah kita sah atau palsu.

Panduan Langkah-Demi-Langkah Pembuatan CA Internal dan Sertifikat Broker #

Karena kluster Apache Kafka biasanya berada di dalam jaringan privat internal perusahaan dan tidak diakses langsung oleh masyarakat umum melalui internet, kita tidak perlu membeli sertifikat dari CA publik (seperti DigiCert atau GlobalSign). Kita juga tidak bisa menggunakan layanan gratisan seperti Let’s Encrypt dengan mudah karena verifikasi DNS/HTTP menuntut eksposur internet.

Pendekatan standar industri adalah dengan membuat Certificate Authority (CA) internal sendiri (self-signed Root CA), lalu menggunakan root CA tersebut untuk menandatangani semua sertifikat broker dan klien di lingkungan kita.

Berikut adalah alur kerja lengkap pembuatan sertifikat menggunakan program openssl dan Java keytool (disarankan menggunakan format .p12 / PKCS12 yang modern):

flowchart TD
    subgraph CA_Server ["1. Otoritas Sertifikat (CA Server)"]
        CA_Key["Root CA Private Key (ca-key)"]
        CA_Cert["Root CA Certificate (ca-cert)"]
        CA_Key --> CA_Cert
    end

    subgraph Broker_Server ["2. Server Kafka Broker"]
        B_Keystore["Broker Keystore (kafka.server.keystore.p12)"]
        B_CSR["Certificate Signing Request (CSR)"]
        B_Keystore -->|Generate Keypair| B_CSR
    end

    B_CSR -->|3. Kirim CSR| CA_Cert
    CA_Cert & CA_Key -->|4. Tanda Tangani Sertifikat| B_Cert["Signed Certificate (cert-signed)"]
    
    B_Cert -->|5. Impor| B_Keystore
    CA_Cert -->|6. Impor Trust Chain| B_Keystore
    CA_Cert -->|7. Buat| B_Truststore["Broker Truststore (kafka.server.truststore.p12)"]

Mari kita eksekusi perintahnya satu per satu di terminal:

Langkah 1: Membuat Root CA Internal #

Jalankan perintah ini di server aman yang difungsikan sebagai CA server (pisahkan server ini dari broker Kafka di produksi untuk menjaga keamanan):

# 1. Generate Kunci Privat Root CA (panjang kunci 4096 bit)
openssl genrsa -out ca-key.pem 4096

# 2. Buat Sertifikat Publik Root CA yang berlaku selama 10 tahun (3650 hari)
openssl req -new -x509 -key ca-key.pem -out ca-cert.pem -days 3650 \
  -subj "/CN=Kafka-Internal-Root-CA/OU=IT Security/O=Badri Creative Tech/C=ID"

Langkah 2: Membuat Keystore untuk Broker Kafka #

Jalankan perintah ini di server broker Kafka. Kita membuat keystore biner berformat PKCS12 (deststoretype pkcs12 adalah default Java modern):

# Generate keypair (kunci privat & publik) langsung di dalam file keystore
keytool -keystore kafka.broker.keystore.p12 \
  -alias localhost \
  -validity 365 \
  -genkey -keyalg RSA -keysize 2048 \
  -dname "CN=kafka-broker-1.internal,OU=Data Platform,O=Badri Creative Tech,C=ID" \
  -storepass broker-keystore-secret-pass

Langkah 3: Membuat Certificate Signing Request (CSR) #

CSR adalah berkas permohonan yang berisi kunci publik broker beserta data identitasnya, yang akan kita kirimkan ke server CA untuk ditandatangani.

keytool -keystore kafka.broker.keystore.p12 \
  -alias localhost \
  -certreq -file broker.csr \
  -storepass broker-keystore-secret-pass

Langkah 4: Menandatangani Sertifikat Broker menggunakan Root CA #

Pindahkan berkas broker.csr ke server CA, lalu jalankan penandatanganan sertifikat. Kita membuat masa berlaku sertifikat broker selama 1 tahun (365 hari):

openssl x509 -req -CA ca-cert.pem -CAkey ca-key.pem \
  -in broker.csr -out broker-cert-signed.pem \
  -days 365 -CAcreateserial

Langkah 5: Mengimpor Sertifikat Root CA ke Keystore Broker #

Sebelum mengimpor sertifikat broker yang telah ditandatangani, keystore harus mengenali root CA yang menandatanganinya terlebih dahulu untuk membentuk rantai kepercayaan (trust chain).

keytool -keystore kafka.broker.keystore.p12 \
  -alias CARoot \
  -import -file ca-cert.pem \
  -storepass broker-keystore-secret-pass -noprompt

Langkah 6: Mengimpor Sertifikat Broker yang Telah Ditandatangani ke Keystore #

Sekarang, impor kembali sertifikat signed yang telah kita dapatkan dari CA ke dalam keystore di bawah alias yang sama dengan tempat keypair dibuat (localhost):

keytool -keystore kafka.broker.keystore.p12 \
  -alias localhost \
  -import -file broker-cert-signed.pem \
  -storepass broker-keystore-secret-pass

Langkah 7: Membuat Truststore Broker #

Terakhir, buat berkas truststore yang hanya berisi sertifikat root CA tepercaya agar broker dapat memvalidasi koneksi dari klien:

keytool -keystore kafka.broker.truststore.p12 \
  -alias CARoot \
  -import -file ca-cert.pem \
  -storepass broker-truststore-secret-pass -noprompt

Konfigurasi Parameter SSL pada Broker Kafka #

Setelah berkas kafka.broker.keystore.p12 dan kafka.broker.truststore.p12 berhasil dibuat dan diletakkan di folder konfigurasi broker (misalnya /etc/kafka/secrets/), kita perlu memperbarui konfigurasi berkas server.properties broker:

# Mengaktifkan listener SSL di port 9093
listeners=PLAINTEXT://:9092,SSL://:9093
advertised.listeners=PLAINTEXT://kafka-broker-1.internal:9092,SSL://kafka-broker-1.internal:9093

# Menentukan protokol komunikasi antar broker (inter-broker) menggunakan SSL
security.inter.broker.protocol=SSL

# Konfigurasi Keystore
ssl.keystore.location=/etc/kafka/secrets/kafka.broker.keystore.p12
ssl.keystore.password=broker-keystore-secret-pass
ssl.keystore.type=PKCS12

# Konfigurasi Truststore
ssl.truststore.location=/etc/kafka/secrets/kafka.broker.truststore.p12
ssl.truststore.password=broker-truststore-secret-pass
ssl.truststore.type=PKCS12

# Menyalakan Mutual Authentication (mTLS) agar broker menuntut sertifikat dari klien
ssl.client.auth=required

Strategi Rotasi Sertifikat Tanpa Downtime di Produksi #

Salah satu kesalahan paling umum yang dijumpai dalam operasional Kafka adalah membiarkan sertifikat kedaluwarsa. Ketika masa berlaku sertifikat habis (misalnya setelah 365 hari), broker Kafka akan menolak koneksi SSL baru dan memutuskan koneksi yang sedang berjalan. Kluster akan mengalami pemadaman total (outage).

Untuk mencegah hal tersebut, kita harus merancang strategi rotasi sertifikat secara berkala. Kabar baiknya, sejak Apache Kafka versi 2.0.0, kita dapat merotasi sertifikat SSL tanpa perlu me-restart proses broker Kafka (zero-downtime certificate rotation).

Mekanisme Pengisian Ulang SSL Dinamis (Dynamic SSL Throttling & Reloading) #

Kafka menyediakan konfigurasi tingkat lanjut yang dapat diperbarui secara dinamis pada saat kluster sedang berjalan (runtime). Kita dapat menggunakan API alter configs (melalui perintah CLI kafka-configs.sh) untuk memaksa broker memuat ulang berkas keystore dan truststore baru dari disk.

Berikut adalah runbook operasional untuk melakukan rotasi sertifikat broker tanpa downtime:

Langkah 1: Siapkan Keystore Baru di Server Broker #

Buat keystore PKCS12 baru yang berisi sertifikat yang diperbarui (misalnya, masa berlaku diperpanjang 1 tahun ke depan). Tempatkan file tersebut di folder broker dengan nama yang berbeda atau timpa file lama. Sangat disarankan untuk menimpa file keystore lama di lokasi yang sama untuk kesederhanaan, misalnya /etc/kafka/secrets/kafka.broker.keystore.p12.

Langkah 2: Jalankan Perintah Dynamic Reload #

Setelah file keystore baru siap di disk server broker, jalankan perintah CLI berikut untuk memicu pemuatan ulang sertifikat di memori JVM broker secara instan:

# Memaksa broker ID 1 memuat ulang konfigurasi SSL keystore dari disk
kafka-configs.sh --bootstrap-server kafka-broker-1.internal:9093 \
  --entity-type brokers --entity-name 1 \
  --alter --add-config 'listener.name.SSL.ssl.keystore.location=/etc/kafka/secrets/kafka.broker.keystore.p12'

[!TIP] Ketika perintah di atas dieksekusi, thread jaringan (network threads) di broker Kafka akan menutup koneksi SSL yang ada secara bertahap dan memuat keystore baru ke dalam memori. Klien produser dan konsumen akan secara otomatis melakukan koneksi ulang (reconnect) dan melakukan jabat tangan SSL menggunakan sertifikat baru secara transparan tanpa terjadi kegagalan pemrosesan data.

Langkah 3: Verifikasi Sertifikat Baru menggunakan OpenSSL #

Untuk memastikan bahwa broker telah benar-benar menyodorkan sertifikat baru yang sudah diperbarui, kita dapat memindai port SSL broker menggunakan tool client OpenSSL s_client:

openssl s_client -connect kafka-broker-1.internal:9093 -showcerts | openssl x509 -noout -dates

Perintah di atas akan menampilkan rentang tanggal validitas sertifikat (notBefore dan notAfter). Pastikan tanggal kedaluwarsa telah bergeser ke masa depan sesuai dengan sertifikat baru kita.


Troubleshooting & Diagnostik Kesalahan SSL Handshake di Kafka #

Mengoperasikan Kafka berbasis SSL sering kali mempertemukan kita dengan kegagalan jabat tangan (SSL Handshake failure). Ketika koneksi gagal, klien biasanya hanya menerima pesan error generik seperti Connection closed by peer tanpa detail apa pun. Untuk mendiagnosis masalah, kita harus masuk ke server broker dan memeriksa log broker (server.log) atau mengaktifkan debugging JVM.

1. Mengaktifkan Logging Detail JVM SSL #

Untuk melihat alur jabat tangan SSL byte-demi-byte, kita dapat menambahkan opsi JVM berikut pada skrip startup Kafka broker atau aplikasi klien:

# Daftarkan variabel lingkungan KAFKA_OPTS sebelum menjalankan Kafka
export KAFKA_OPTS="-Djavax.net.debug=ssl,handshake"

Ketika opsi ini aktif, JVM akan mencetak seluruh isi sertifikat yang dipertukarkan, cipher suites yang ditawarkan, dan titik kegagalan persis dari jabat tangan SSL ke berkas Standard Output (stdout).

2. Tiga Kesalahan Klasik SSL Kafka & Solusinya #

A. Kesalahan Sandi Kunci Kustom (UnrecoverableKeyException) #

  • Gejala: Broker gagal dinyalakan dan menampilkan stack trace berisi java.security.UnrecoverableKeyException: Cannot recover key.
  • Penyebab: Di format Java Keystore (JKS) klasik, kata sandi untuk berkas keystore (ssl.keystore.password) dan kata sandi untuk kunci privat individual di dalamnya (key password) bisa berbeda. Jika keduanya berbeda dan kita tidak menyetel ssl.key.password secara spesifik, JVM tidak dapat membuka kunci privat broker.
  • Solusi: Tambahkan parameter ssl.key.password di berkas server.properties dengan kata sandi kunci privat Anda, atau saat membuat keystore PKCS12 modern, pastikan password keystore dan password private key disamakan.

B. Kesalahan Nama Alternatif Subjek (Subject Alternative Name - SAN Missing) #

  • Gejala: Klien Java gagal terhubung ke broker dengan pesan error: java.security.cert.CertificateException: No subject alternative DNS name matching kafka-broker-1.internal found.
  • Penyebab: Secara default, klien Kafka melakukan verifikasi apakah hostname broker yang dituju cocok dengan identitas yang tertulis di dalam sertifikat broker. Jika sertifikat broker hanya menggunakan CN=localhost atau CN=kafka-broker-1.internal tanpa mendefinisikannya di bagian ekstensi Subject Alternative Name (SAN), pencocokan hostname (endpoint identification) Java akan menolaknya.
  • Solusi: Kita dapat mematikan verifikasi ini di sisi klien (sangat tidak direkomendasikan untuk produksi) dengan menyetel ssl.endpoint.identification.algorithm=. Solusi terbaiknya adalah dengan membuat ulang CSR broker dengan menyertakan opsi ekstensi SAN yang lengkap menggunakan keytool:
    keytool -keystore kafka.broker.keystore.p12 -alias localhost \
      -genkey -keyalg RSA -keysize 2048 \
      -ext SAN=dns:kafka-broker-1.internal,ip:192.168.1.10
    

C. Kesalahan Rantai Kepercayaan Tidak Dikenal (Unknown CA / CertificateUnknown) #

  • Gejala: Log broker menampilkan javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown.
  • Penyebab: Broker atau klien menyodorkan sertifikat yang ditandatangani oleh CA yang tidak terdaftar di dalam Truststore pihak penerima. Hal ini sering terjadi jika kita lupa mengimpor sertifikat Root CA ke dalam berkas truststore milik klien, atau sebaliknya saat mTLS aktif, sertifikat klien tidak dikenali oleh truststore broker.
  • Solusi: Periksa isi berkas truststore menggunakan perintah daftar keytool:
    keytool -keystore kafka.broker.truststore.p12 -list -v
    
    Pastikan sertifikat CA penerbit (issuer) dari sertifikat klien/broker sudah tercantum di dalamnya dengan status trustedCertEntry.

Ringkasan #

  • Keystore — Berisi kunci privat (private key) dan sertifikat publik milik broker/klien itu sendiri. Digunakan sebagai bukti identitas diri.
  • Truststore — Hanya berisi sertifikat root/intermediate CA publik yang dipercayai. Digunakan untuk memvalidasi keaslian sertifikat entitas lain.
  • PKCS12 Format — Format biner .p12 adalah standar industri modern yang sangat direkomendasikan menggantikan format bawaan Java .jks yang lama.
  • CA Internal — Kluster internal wajib menggunakan Root CA buatan sendiri (self-signed Root CA) untuk efisiensi biaya dan kontrol penuh atas otentikasi cluster.
  • Rotasi Dinamis — Jangan pernah me-restart broker hanya untuk merotasi sertifikat. Manfaatkan fitur dynamic config reload via kafka-configs.sh untuk menjamin ketersediaan sistem 100%.

← Sebelumnya: PLAINTEXT vs SSL vs SASL   Berikutnya: Client Authentication →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact