Client Authentication: Mengamankan Akses Klien ke Kafka Broker #

Otentikasi klien (client authentication) adalah gerbang pertahanan pertama dalam mengamankan kluster Apache Kafka. Tanpa mekanisme otentikasi yang jelas, broker Kafka tidak akan pernah tahu siapa sebenarnya entitas yang sedang mengirim atau menarik pesan. Akibatnya, kita tidak akan pernah bisa menerapkan kebijakan otorisasi tingkat lanjut (Access Control Lists atau ACL) karena kita tidak dapat mencocokkan identitas pemanggil dengan hak aksesnya.

Apache Kafka menyediakan dua metode utama untuk mengotentikasi klien: Mutual TLS (mTLS) yang berbasis sertifikat digital, dan SASL (Simple Authentication and Security Layer) yang mendukung berbagai mekanisme verifikasi seperti username/password, tiket Kerberos, dan token OAuth2.

Artikel ini akan membedah secara mendalam konfigurasi teknis dari kedua metode otentikasi tersebut, menjelaskan cara kerja Principal Mapping Rules pada mTLS, membedah berkas konfigurasi JAAS (Java Authentication and Authorization Service), serta memberikan contoh berkas properti siap pakai untuk klien Java SDK.


Otentikasi Berbasis Mutual TLS (mTLS) #

Ketika kita mengaktifkan enkripsi SSL/TLS di Kafka, jabat tangan (handshake) default bersifat satu arah (one-way). Broker menyodorkan sertifikatnya ke klien untuk membuktikan identitasnya dan mengenkripsi jalur komunikasi. Namun, broker tidak menanyakan siapa identitas klien tersebut.

Untuk mengubahnya menjadi Mutual TLS (mTLS), kita menyetel parameter keamanan broker berikut di server.properties:

# Mengatur broker agar secara wajib meminta dan memverifikasi sertifikat dari klien
ssl.client.auth=required

1. Pembentukan Principal Klien dari Sertifikat x509 #

Saat jabat tangan mTLS sukses, broker Kafka akan mengekstrak nama subjek dari sertifikat x509 klien (Distinguished Name / DN) dan menggunakannya sebagai nama pengguna (Principal). Secara default, Kafka menggunakan DN lengkap subjek tersebut.

Sebagai contoh, jika sertifikat klien kita dibuat dengan perintah: keytool -dname "CN=payment-service,OU=Finance,O=Badri Creative Tech,C=ID"

Maka, broker Kafka secara otomatis akan mengenali klien tersebut sebagai principal: User:CN=payment-service,OU=Finance,O=Badri Creative Tech,C=ID

2. Menyederhanakan Principal via Principal Mapping Rules #

Format DN lengkap di atas sangat panjang dan merepotkan ketika kita harus menulis regulasi ACL (Access Control Lists). Kita tentu lebih menyukai nama principal yang ringkas seperti User:payment-service.

Untuk mengonversinya secara dinamis, Kafka menyediakan parameter ssl.principal.mapping.rules. Parameter ini menggunakan sintaks berbasis ekspresi reguler (Regex) untuk mengekstrak bagian tertentu dari DN sertifikat.

Berikut adalah contoh aturan pemetaan di server.properties broker:

# Menerjemahkan Distinguished Name (DN) menjadi nama pengguna tunggal (simple principal)
ssl.principal.mapping.rules=RULE:^CN=([^,]*)(,.*|$)/$1/,DEFAULT

Cara Kerja Aturan Di Atas:

  1. Aturan akan mencocokkan string DN sertifikat yang diawali dengan CN=.
  2. Kelompok penangkap pertama ([^/]*) (atau ([^,]*)) akan mengambil nilai karakter setelah CN= hingga menemui tanda koma , pertama (dalam contoh kita, akan mengekstrak string payment-service).
  3. Nilai tersebut digantikan oleh $1 (hasil ekstrak), sehingga principal akhir yang dikenali oleh Kafka Authorizer adalah: User:payment-service.
  4. Jika DN tidak cocok dengan aturan tersebut, ia akan menggunakan aturan bawaan DEFAULT (DN lengkap).

3. Aturan Pemetaan Kompleks (Advanced Mapping Rules) #

Kafka mendukung penyusunan beberapa aturan pemetaan yang dipisahkan oleh tanda koma, dan dievaluasi secara berurutan dari kiri ke kanan (atau atas ke bawah) hingga ditemukan kecocokan pertama. Sintaks umum aturan pemetaan adalah sebagai berikut: RULE:pattern/replacement/[L|U]

  • pattern: Ekspresi reguler Java yang digunakan untuk mencocokkan string DN subjek sertifikat.
  • replacement: String pengganti yang mendukung ekspresi rujukan kelompok penangkap (seperti $1, $2).
  • L / U: Modifikator opsional untuk mengubah hasil akhir menjadi huruf kecil semua (lowercase / L) atau huruf besar semua (uppercase / U).

Berikut adalah contoh konfigurasi multi-rule yang umum digunakan di lingkungan enterprise:

# Aturan 1: Ekstrak CN dan OU, gabungkan keduanya, dan ubah menjadi huruf kecil (L)
# Format input: CN=Payment-App,OU=Finance,O=Badri Creative Tech,C=ID
# Format output: User:payment-app-finance
ssl.principal.mapping.rules=RULE:^CN=([^,]*),OU=([^,]*),O=.*$/$1-$2/L,\
                            RULE:^CN=([^,]*)(,.*|$)/$1/L,\
                            DEFAULT

Dengan menerapkan aturan bertingkat di atas:

  • Koneksi dengan sertifikat yang memuat unit organisasi (OU) Finance akan dipetakan dengan rapi ke User:payment-app-finance secara otomatis dalam huruf kecil, meminimalkan sensitivitas huruf besar/kecil (case-sensitivity).
  • Koneksi yang hanya memuat CN akan dipetakan ke User:<cn> dalam huruf kecil.
  • Koneksi lainnya yang tidak memenuhi pola regex akan menggunakan identitas DN lengkap sebagai cadangan (DEFAULT).

Otentikasi Berbasis SASL (Simple Authentication and Security Layer) #

Jika organisasi kita lebih menyukai otentikasi berbasis kredensial daripada mendistribusikan sertifikat SSL klien ke ratusan server aplikasi, maka SASL adalah pilihan yang tepat.

Di lingkungan Java (termasuk Kafka), otentikasi SASL dikonfigurasi melalui modul JAAS (Java Authentication and Authorization Service). Modul ini mendefinisikan pustaka mana yang akan digunakan untuk memverifikasi kredensial.

Mari kita bedah detail konfigurasi untuk masing-masing mekanisme SASL utama:

1. SASL/PLAIN: Username & Password Statis #

Mekanisme SASL/PLAIN adalah yang paling sederhana. Kita mendefinisikan kredensial di berkas konfigurasi JAAS broker.

Berkas JAAS Broker (kafka_server_jaas.conf):

KafkaServer {
    org.apache.kafka.common.security.plain.PlainLoginModule required
    username="admin"
    password="admin-secure-password"
    user_producer_app="producer-app-secret-pass"
    user_consumer_app="consumer-app-secret-pass";
};

Pada konfigurasi di atas, pengguna admin bertindak sebagai user internal yang digunakan oleh broker untuk saling berkoordinasi, sedangkan producer_app dan consumer_app adalah kredensial yang dapat digunakan oleh klien luar untuk terhubung ke broker.

2. SASL/SCRAM: Tantangan Hash yang Dinamis #

Mekanisme SASL/SCRAM jauh lebih aman karena password tidak dikirim ke broker (menggunakan skema Salted Challenge Response). Kredensial tidak di-hardcode di file, melainkan disimpan di metadata cluster.

Berkas JAAS Broker (kafka_server_jaas.conf):

KafkaServer {
    org.apache.kafka.common.security.scram.ScramLoginModule required;
};

Untuk mendaftarkan user baru di runtime tanpa restart broker, jalankan perintah CLI berikut:

kafka-configs.sh --bootstrap-server localhost:9093 \
  --entity-type users --entity-name transaction_service \
  --alter --add-config 'SCRAM-SHA-512=[password=tx_secure_pass_123]'

3. SASL/GSSAPI (Kerberos Enterprise) #

Untuk integrasi otentikasi terpusat berskala enterprise (Single Sign-On), Kerberos adalah standarnya.

Berkas JAAS Broker (kafka_server_jaas.conf):

KafkaServer {
    com.sun.security.auth.module.Krb5LoginModule required
    useKeyTab=true
    storeKey=true
    keyTab="/etc/kafka/secrets/kafka.keytab"
    principal="kafka/[email protected]";
};
  • useKeyTab=true: Memberi tahu JVM untuk menggunakan berkas kredensial keytab terenkripsi daripada menanyakan password interaktif.
  • principal: Nama principal identitas broker di server KDC Kerberos.

Alur Handshake Otentikasi SASL/SCRAM di Kafka #

Untuk memperjelas perbedaan penanganan otentikasi di jaringan, berikut adalah alur pertukaran informasi (handshake) ketika klien mencoba masuk menggunakan mekanisme SASL/SCRAM-SHA-256:

sequenceDiagram
    autonumber
    participant Client as "Klien Kafka"
    participant Broker as "Kafka Broker"
    participant Metadata as "KRaft / ZooKeeper Metadata"

    Note over Client, Broker: Prasyarat: Jalur koneksi aman SSL/TLS aktif (SASL_SSL)
    Client->>Broker: Koneksi awal & negosiasi SASL Mechanism (SCRAM-SHA-256)
    Broker-->>Client: Konfirmasi mekanisme disetujui
    
    Client->>Broker: SASL First Message (Kirim Username: user_app & client_nonce)
    Note over Broker: Broker membaca salt & iterasi user_app dari Metadata
    Broker->>Metadata: Ambil salt & iterasi untuk user_app
    Metadata-->>Broker: Kembalikan salt & iterasi hash
    
    Broker->>Client: SASL Server First Message (Kirim server_nonce, salt, iterasi)
    Note over Client: Klien menghitung SaltedPassword & ClientProof menggunakan password asli
    Client->>Broker: SASL Client Final Message (Kirim ClientProof)
    
    Note over Broker: Broker memvalidasi ClientProof secara kriptografis
    Broker-->>Client: SASL Server Final Message (Sukses, Kirim ServerSignature)
    Note over Client: Klien memverifikasi ServerSignature (Validasi timbal balik)

Berkas Konfigurasi Siap Pakai untuk Aplikasi Klien Java #

Berikut adalah contoh lengkap properti konfigurasi yang harus dipasang di sisi kode aplikasi klien Java SDK (Producer maupun Consumer) untuk masing-masing protokol:

1. Properti Klien untuk Mutual TLS (mTLS) #

Aplikasi klien membutuhkan berkas keystore miliknya sendiri yang berisi sertifikat yang telah ditandatangani oleh root CA kluster.

# Menentukan protokol keamanan mTLS
security.protocol=SSL

# Konfigurasi lokasi truststore (sertifikat root CA untuk memverifikasi broker)
ssl.truststore.location=/var/private/ssl/client.truststore.p12
ssl.truststore.password=client-truststore-pass
ssl.truststore.type=PKCS12

# Konfigurasi lokasi keystore (sertifikat identitas klien untuk diverifikasi broker)
ssl.keystore.location=/var/private/ssl/client.keystore.p12
ssl.keystore.password=client-keystore-pass
ssl.keystore.type=PKCS12

2. Properti Klien untuk SASL/SCRAM (Salted Password) #

Aplikasi klien mengirimkan kredensial password dengan aman menggunakan hashing SCRAM. Kredensial dikonfigurasi melalui parameter inline JAAS sasl.jaas.config.

# Menggabungkan otentikasi SASL dengan enkripsi data SSL
security.protocol=SASL_SSL
sasl.mechanism=SCRAM-SHA-512

# Lokasi Truststore (Wajib diisi untuk enkripsi SSL)
ssl.truststore.location=/var/private/ssl/client.truststore.p12
ssl.truststore.password=client-truststore-pass
ssl.truststore.type=PKCS12

# Konfigurasi JAAS Klien secara inline (tanpa menggunakan file terpisah)
sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
  username="transaction_service" \
  password="tx_secure_pass_123";

3. Properti Klien untuk SASL/PLAIN #

Jika cluster Anda terpaksa menggunakan mekanisme PLAIN, pastikan parameter sasl.jaas.config merujuk pada PlainLoginModule.

security.protocol=SASL_SSL
sasl.mechanism=PLAIN

ssl.truststore.location=/var/private/ssl/client.truststore.p12
ssl.truststore.password=client-truststore-pass
ssl.truststore.type=PKCS12

# JAAS Klien menggunakan PlainLoginModule
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
  username="producer_app" \
  password="producer-app-secret-pass";

3. Properti Klien untuk SASL/PLAIN #

Jika cluster Anda terpaksa menggunakan mekanisme PLAIN, pastikan parameter sasl.jaas.config merujuk pada PlainLoginModule.

security.protocol=SASL_SSL
sasl.mechanism=PLAIN

ssl.truststore.location=/var/private/ssl/client.truststore.p12
ssl.truststore.password=client-truststore-pass
ssl.truststore.type=PKCS12

# JAAS Klien menggunakan PlainLoginModule
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
  username="producer_app" \
  password="producer-app-secret-pass";

Integrasi SASL/OAUTHBEARER & Kerberos Tingkat Lanjut #

Untuk lingkungan berskala enterprise yang mengutamakan otomatisasi tanpa batas (seamless automation), otentikasi menggunakan OAuthbearer atau Kerberos menawarkan keamanan tinggi tanpa intervensi manual. Namun, penerapannya menuntut konfigurasi runtime JVM dan handler callback yang presisi.

1. Token Refresh pada SASL/OAUTHBEARER #

JWT (JSON Web Token) yang diterbitkan oleh server otentikasi (IdP) biasanya berumur sangat pendek (misal: 15 menit s.d. 1 jam) demi meminimalisasi risiko keamanan jika token dicuri. Jika token kedaluwarsa, koneksi klien ke Kafka akan terputus.

Untuk mengatasinya, klien Kafka Java memiliki mekanisme internal untuk memperbarui token secara otomatis sebelum masa berlakunya habis. Hal ini dikonfigurasi menggunakan kelas Login Callback Handler.

Sejak Kafka 3.0.0, Kafka menyediakan implementasi bawaan yang kokoh untuk mengotomatiskan siklus ini:

# Menggunakan protokol OAUTHBEARER
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER

# Mendaftarkan Callback Handler bawaan Kafka untuk OAuth2
sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler

# Parameter untuk berkomunikasi langsung ke server OAuth2 Identity Provider (IdP)
sasl.oauthbearer.token.endpoint.url=https://keycloak.internal/auth/realms/kafka/protocol/openid-connect/token
sasl.oauthbearer.client.id=payment_service_app
sasl.oauthbearer.client.secret=my-client-secret-key-from-keycloak

# Konfigurasi JAAS Klien
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required;

Cara Kerja: OAuthBearerLoginCallbackHandler akan menghubungi endpoint URL Token OAuth2, mengirimkan client_id dan client_secret untuk mendapatkan token JWT baru, lalu mengirimkannya ke broker Kafka. Menjelang token tersebut kedaluwarsa, handler ini akan secara otomatis melakukan request ulang ke IdP untuk mendapatkan token baru dan memperbarui sesi di broker tanpa memutuskan koneksi TCP yang sedang aktif (zero disconnect).

2. Rotasi Tiket Kerberos & Perbedaan JVM #

Saat menerapkan SASL/GSSAPI (Kerberos), kita sering kali menghadapi masalah kompabilitas akibat perbedaan vendor JVM yang digunakan di server aplikasi klien.

A. Perbedaan Modul Login JAAS #

Pustaka modul login Kerberos berbeda antara Oracle JDK / OpenJDK dengan IBM JDK (sering digunakan di server enterprise WebSphere/AIX):

  • Oracle JDK / OpenJDK:
    # Menggunakan kelas Krb5LoginModule dari Oracle/Sun
    sasl.jaas.config=com.sun.security.auth.module.Krb5LoginModule required \
      useKeyTab=true \
      storeKey=true \
      keyTab="/etc/security/keytabs/client.keytab" \
      principal="[email protected]";
    
  • IBM JDK:
    # Menggunakan kelas Krb5LoginModule dari IBM
    sasl.jaas.config=com.ibm.security.auth.module.Krb5LoginModule required \
      useKeytab=true \
      credsType=both \
      keytab="/etc/security/keytabs/client.keytab" \
      principal="[email protected]";
    

B. Parameter Rotasi Tiket Otomatis (Ticket Renewal) #

Tiket Kerberos memiliki masa berlaku terbatas (misal: 24 jam). Jika tiket kedaluwarsa, klien tidak akan dapat melakukan koneksi baru. Klien Kafka menyediakan parameter untuk mengatur bagaimana thread latar belakang (background thread) memperbarui tiket sebelum kedaluwarsa:

  • sasl.kerberos.ticket.renew.window.factor: Menentukan persentase dari sisa waktu hidup tiket sebelum thread mulai mencoba memperbaruinya (Default: 0.80, artinya jika tiket berumur 10 jam, proses pembaruan dimulai pada jam ke-8).
  • sasl.kerberos.ticket.renew.jitter: Menambahkan nilai acak (jitter) pada waktu pembaruan untuk mencegah seluruh instansi klien di ribuan server menyerang server KDC Kerberos secara bersamaan (thundering herd problem, Default: 0.05).

Ringkasan #

  • mTLS vs SASL — mTLS sangat direkomendasikan jika infrastruktur Anda telah mengadopsi otomatisasi manajemen sertifikat (Kubernetes/Vault). SASL cocok untuk integrasi dinamis tanpa mendistribusikan file kunci publik/privat ke server klien.
  • Enkripsi itu Wajib — SASL tidak melakukan enkripsi biner lalu lintas data. Pengoperasian SASL di produksi harus selalu digabungkan dengan SSL (SASL_SSL) untuk melindungi kebocoran data.
  • Dynamic Config SCRAM — Gunakan SASL/SCRAM daripada SASL/PLAIN agar manajemen kredensial bersifat dinamis via metadata cluster tanpa memerlukan restart berkala pada broker.
  • Principal Mapping — Atur parameter ssl.principal.mapping.rules di broker agar nama principal yang diekstrak dari sertifikat x509 rapi dan mudah diatur di regulasi ACL.

← Sebelumnya: Certificate & Key Management   Berikutnya: Access Control Lists (ACL) →

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