Common Security Mistakes: 8 Kesalahan Fatal Keamanan Kafka di Produksi #

Membangun sistem terdistribusi yang aman menuntut perhatian konseptual yang sangat menyeluruh. Pada Apache Kafka, satu celah kecil saja pada konfigurasi jaringan, sertifikat, atau Access Control Lists (ACL) dapat meruntuhkan seluruh pertahanan yang telah kita bangun dengan susah payah. Di lingkungan produksi, kesalahan-kesalahan ini tidak hanya menyebabkan potensi kebocoran data sensitif, tetapi juga sering kali menjadi penyebab utama downtime kluster yang tidak direncanakan.

Banyak tim operasional yang merasa kluster mereka sudah “aman” hanya karena telah mengaktifkan SSL dan SASL. Namun, setelah diteliti lebih dalam, kita sering menemukan celah keamanan serius seperti membiarkan port JMX terbuka tanpa otentikasi, memberikan izin wildcard penuh pada ACL yang terlalu longgar, atau melupakan pemantauan masa aktif sertifikat broker.

Dalam panduan mendalam ini, kita akan mengupas tuntas 8 kesalahan fatal (security anti-patterns) dalam mengamankan kluster Kafka di produksi, menganalisis konsekuensi teknis di balik kegagalan tersebut, menyediakan perbandingan konfigurasi buruk (bad config) vs konfigurasi aman (good config), menyusun skrip otomasi pendeteksi sertifikat kedaluwarsa, serta menyediakan Production Readiness Security Checklist yang komprehensif.

Analisis Mendalam: 8 Kesalahan Fatal Keamanan Kafka #

Berikut adalah rincian 8 kesalahan keamanan paling kritis yang sering terjadi di kluster Kafka produksi beserta skenario kegagalannya:

+---------------------------------------------------------------------------------+
|                        8 KESALAHAN FATAL KEAMANAN KAFKA                         |
|                                                                                 |
|   1. PLAINTEXT di Jaringan Terbuka  ==>  Data disadap & dimanipulasi            |
|   2. Hardcode Password di Config    ==>  Kredensial bocor via Git               |
|   3. Wildcard ACL Berlebihan (*)    ==>  Hak akses terlalu luas (Over-privilege)|
|   4. Lupa Rotasi Sertifikat SSL     ==>  Kluster mati saat cert expired         |
|   5. Port Campuran Client-Broker    ==>  Resource port internal disedot klien   |
|   6. Metadata Quorum Terbuka        ==>  Metadata KRaft rentan dimanipulasi     |
|   7. Tanpa Connection Rate Limit    ==>  Rentan terhadap DoS / Connection Leak  |
|   8. allow.everyone...=true         ==>  Mematikan asas Zero-Trust (Bawaan)     |
+---------------------------------------------------------------------------------+

1. Membiarkan Protokol PLAINTEXT Berjalan di Jaringan Terbuka #

  • Kesalahan: Mengaktifkan listener PLAINTEXT (port 9092) di interface jaringan publik (0.0.0.0) atau membiarkannya dapat diakses tanpa enkripsi melintasi jaringan antar-data center (cross-DC). Hal ini sering dilakukan agar tim developer dapat terhubung dengan cepat tanpa kerumitan mengelola sertifikat TLS.
  • Dampak: Pihak ketiga yang berada di jalur jaringan yang sama dapat melakukan penyadapan paket (packet sniffing) menggunakan perangkat seperti Wireshark atau tcpdump. Karena data dikirim dalam bentuk teks polos, informasi rahasia seperti payload transaksi, data personal pengguna (PII), hingga kredensial otentikasi yang kurang aman dapat dibaca dengan mudah. Lebih berbahaya lagi, penyerang dapat melancarkan serangan Man-in-the-Middle (MitM) untuk menyuntikkan atau mengubah payload pesan yang dikirim ke topik-topik krusial, yang berujung pada kerusakan logika aplikasi hilir (downstream apps).
  • Mitigasi: Matikan listener PLAINTEXT sepenuhnya di lingkungan produksi. Konfigurasikan semua listener luar dan inter-broker untuk menggunakan protokol terenkripsi seperti SSL atau SASL_SSL.

2. Menulis Kredensial Secara Hardcode di Berkas Konfigurasi #

  • Kesalahan: Menulis username/password SASL, password keystore/truststore, atau kunci enkripsi secara langsung (hardcode) di dalam berkas konfigurasi server.properties, berkas JAAS client, atau berkas konfigurasi JSON untuk Kafka Connect.
  • Dampak: Berkas konfigurasi ini sering kali tanpa sengaja terdorong (pushed) ke dalam repositori Git internal atau publik perusahaan. Penyerang menggunakan pemindai otomatis (Git scanning tools seperti GitGuardian atau Trufflehog) untuk mendeteksi rahasia ini dalam hitungan detik. Sekali kredensial ini bocor, penyerang dapat menyusup ke kluster dari mana saja.
  • Mitigasi: Gunakan pustaka Config Providers bawaan Apache Kafka. Kita dapat menyetel agar Kafka membaca rahasia secara aman dari variabel lingkungan, berkas lokal terisolasi yang dienkripsi, atau layanan pengelola rahasia pihak ketiga seperti AWS Secrets Manager, HashiCorp Vault, atau Google Secret Manager pada saat startup kluster.

3. Menggunakan Wildcard * Secara Berlebihan pada Aturan ACL #

  • Kesalahan: Untuk menghemat waktu saat tim developer meminta akses, administrator memberikan izin wildcard penuh (misalnya memberikan akses All pada topik * kepada principal tertentu).
  • Dampak: Kebijakan ini melanggar prinsip hak akses terendah (principle of least privilege). Jika satu aplikasi klien (misalnya payment-service) berhasil disusupi oleh penyerang, penyerang tersebut mewarisi hak akses wildcard tersebut. Mereka dapat dengan bebas membaca data dari topik-topik sensitif lainnya (seperti hr-records), memanipulasi konfigurasi kluster, membuat ribuan topik kosong untuk memakan memori, atau menghapus topik produksi penting.
  • Mitigasi: Terapkan ACL secara granular per topik dengan nama spesifik (Literal). Jika membutuhkan fleksibilitas, gunakan pencocokan awalan (Prefixed Pattern) secara disiplin (misal: hanya mengizinkan akses ke topik dengan awalan payment-) alih-alih memberikan wildcard global *.

4. Mengabaikan Siklus Hidup Sertifikat SSL dan Lupa Melakukan Rotasi #

  • Kesalahan: Membuat sertifikat SSL broker dengan masa berlaku standar (misalnya 1 tahun), tetapi tidak memasang sistem pemantauan (monitoring) dan tidak merancang runbook rotasi sertifikat.
  • Dampak: Saat sertifikat kedaluwarsa (expired), JVM broker akan menolak jabat tangan SSL (SSL handshake) dengan broker lain dan dengan klien. Replikasi data antar-broker langsung terhenti, memicu partisi under-replicated, dan klien Java SDK akan melontarkan error SSLHandshakeException secara massal. Kluster akan mengalami kegagalan fungsi total secara mendadak.
  • Mitigasi: Pasang sistem pemantauan otomatis (seperti skrip diagnostik berbasis openssl) untuk melacak sisa masa aktif sertifikat broker. Manfaatkan fitur pemuatan ulang SSL dinamis (dynamic SSL reloading) via perintah alter configs di Kafka Admin API untuk memperbarui keystore/truststore tanpa perlu mematikan proses JVM broker.

5. Mencampur Port Komunikasi Broker (Inter-Broker) dengan Port Klien #

  • Kesalahan: Menggunakan satu port listener SSL/SASL yang sama (misalnya port 9093) untuk melayani koneksi dari aplikasi klien luar dan lalu lintas replikasi internal antar-broker.
  • Dampak: Jika port klien dibanjiri oleh jutaan koneksi baru dari aplikasi klien yang mengalami kebocoran koneksi (client connection leak atau badai koneksi pasca-downtime), seluruh thread jaringan broker akan habis digunakan untuk melayani jabat tangan SSL klien luar. Akibatnya, thread replikasi internal antar-broker tidak kebagian alokasi thread (socket queue starvation). Broker-broker akan kehilangan koneksi satu sama lain, partisi menjadi tidak sinkron (out-of-sync), dan node pengawas (controller) akan menganggap broker yang sibuk tersebut mati, memicu proses failover berantai yang memperparah degradasi performa kluster.
  • Mitigasi: Selalu pisahkan port listener untuk koordinasi internal inter-broker (misal: port 9092 via SSL) dengan port listener untuk aplikasi klien luar (misal: port 9093 via SASL_SSL).

6. Membiarkan Jalur Metadata (KRaft Quorum) Tanpa Enkripsi dan Otentikasi #

  • Kesalahan: Beranggapan bahwa lalu lintas KRaft Controller Quorum aman karena berada di jaringan privat VPC, sehingga membiarkan port controller (misalnya port 9094) berjalan tanpa enkripsi SSL dan tanpa otentikasi.
  • Dampak: KRaft mengontrol seluruh metadata kluster seperti kepemimpinan partisi (partition leadership), konfigurasi topik, dan penambahan broker baru. Jika port controller dibiarkan terbuka tanpa otentikasi di jaringan lokal, penyerang yang berhasil masuk ke dalam salah satu server di VPC yang sama dapat mengirimkan paket metadata palsu ke quorum controller. Penyerang dapat merebut kepemimpinan partisi, mengubah alokasi replika, atau menyebabkan split-brain di kluster Kafka kita.
  • Mitigasi: Aktifkan enkripsi SSL dan otentikasi timbal balik (mTLS) yang ketat khusus pada listener controller (controller.listener.names=CONTROLLER). Batasi akses port controller hanya untuk sesama anggota KRaft controller melalui aturan firewall (Security Groups) yang ketat.

7. Absennya Batasan Laju Koneksi (Connection Rate Limiting) #

  • Kesalahan: Tidak menyetel batas pembuatan koneksi baru per detik di tingkat broker.
  • Dampak: Broker JVM dapat kehabisan memori heap (Out of Memory - OOM) dan kehabisan alokasi berkas deskriptor (file descriptor) OS jika diserang dengan jutaan koneksi TCP baru secara beruntun oleh server klien yang salah dalam mengelola siklus hidup koneksi produser/konsumennya (misalnya, membuat instansiasi produser baru untuk setiap pesan yang dikirim). Ini adalah bentuk serangan Denial of Service (DoS) yang tidak disengaja.
  • Mitigasi: Konfigurasikan parameter max.connection.creation.rate secara ketat pada broker (terutama pada listener yang terhubung ke klien luar) untuk menahan badai koneksi. Setel juga batas koneksi maksimum per alamat IP menggunakan max.connections.per.ip.

8. Membiarkan allow.everyone.if.no.acl.found=true Aktif di Produksi #

  • Kesalahan: Mengaktifkan modul otorisasi (Authorizer) di broker tetapi membiarkan parameter otorisasi default Kafka tetap bernilai true.
  • Dampak: Setiap topik baru yang tidak memiliki aturan ACL terdaftar akan dibiarkan terbuka untuk diakses oleh siapa saja (read/write bebas). Kebijakan ini mematikan asas dasar pertahanan Zero-Trust (Deny-by-Default). Kluster kita menjadi tidak aman karena perlindungan hanya berlaku untuk topik yang secara eksplisit telah diberi ACL.
  • Mitigasi: Setel allow.everyone.if.no.acl.found=false di berkas server.properties produksi secara mutlak. Dengan setelan ini, jika tidak ada aturan ACL yang cocok, akses akan langsung ditolak secara instan.

Perbandingan Arsitektur: Vulnerable vs Secured #

Mari kita visualisasikan perbedaan desain arsitektur antara kluster yang dikonfigurasi secara buruk (Vulnerable) dengan kluster yang dikonfigurasi secara aman (Secured):

flowchart TD
    subgraph VulnerableCluster ["ARSITEKTUR VULNERABLE (TIDAK AMAN)"]
        direction TB
        ClientV["Aplikasi Klien"] -->|Port 9092: PLAINTEXT| BrokerV["Kafka Broker"]
        BrokerV -->|Hardcode Password di Git| GitV[("Git Repositori")]
        JMXV["JMX Port 9999 (No Auth)"] -->|Terbuka Bebas| InternetV["Internet / Local Network"]
        ACL_V{"allow.everyone... = true"} -.->|Akses Tanpa Batas| BrokerV
    end

    subgraph SecuredCluster ["ARSITEKTUR SECURED (AMAN & KOKOH)"]
        direction TB
        ClientS["Aplikasi Klien"] -->|Port 9093: SASL_SSL / SCRAM| BrokerS["Kafka Broker"]
        BrokerS -->|"ConfigProvider (Secrets)"| SecretStore[("Vault / Secure Local Disk")]
        JMXS["JMX Exporter (HTTP 7071)"] -->|Hanya Izinkan IP Scraping| Prometheus["Prometheus Server"]
        ACL_S{"allow.everyone... = false"} -->|Deny by Default| AuthCheck{"Standard Authorizer (ACL)"}
        AuthCheck -->|Hanya Principal yang Diizinkan| BrokerS
    end

Bad Config vs Good Config #

Untuk membantu kita melakukan audit berkas konfigurasi, berikut adalah contoh perbandingan langsung antara praktik buruk yang sering kita jumpai dan cara memperbaikinya dengan konfigurasi yang aman:

1. Penanganan Kredensial: Hardcoded Password vs FileConfigProvider #

Menyimpan password sensitif di dalam server.properties sangat berbahaya karena berkas ini sering kali masuk ke sistem kontrol versi (Git).

Praktik Buruk (Hardcoded Kredensial) #

# server.properties - BAD CONFIGURATION
ssl.keystore.password=SangatRahasia123!
ssl.key.password=SangatRahasia123!
ssl.truststore.password=TrustPasswordSecure99

# Konfigurasi JAAS untuk SASL SCRAM-SHA-512
listener.name.client.scram-sha-512.sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \
  username="admin" \
  password="SuperSecretAdminPassword123";

Praktik Baik (Menggunakan FileConfigProvider) #

Untuk memperbaikinya, kita harus mengaktifkan FileConfigProvider bawaan Kafka. Layanan ini akan membaca nilai password dari berkas eksternal yang diisolasi dengan hak akses sistem operasi yang ketat (misalnya chmod 600 /etc/kafka/secrets.properties).

Pertama, daftarkan config provider di server.properties:

# server.properties - GOOD CONFIGURATION
config.providers=file
config.providers.file.class=org.apache.kafka.common.config.provider.FileConfigProvider

Kemudian, rujuk berkas eksternal tersebut di dalam konfigurasi utama menggunakan sintaks ${file:path:key}:

# server.properties - GOOD CONFIGURATION (Lanjutan)
ssl.keystore.password=${file:/etc/kafka/secrets.properties:keystore_password}
ssl.key.password=${file:/etc/kafka/secrets.properties:key_password}
ssl.truststore.password=${file:/etc/kafka/secrets.properties:truststore_password}

# Rujuk JAAS config yang disimpan di file rahasia luar
listener.name.client.scram-sha-512.sasl.jaas.config=${file:/etc/kafka/secrets.properties:jaas_client_config}

Isi dari berkas eksternal /etc/kafka/secrets.properties (pastikan hanya dapat dibaca oleh user proses kafka):

keystore_password=SangatRahasia123!
key_password=SangatRahasia123!
truststore_password=TrustPasswordSecure99
jaas_client_config=org.apache.kafka.common.security.scram.ScramLoginModule required username="admin" password="SuperSecretAdminPassword123";

2. Konfigurasi Otorisasi: Wildcard ACL vs Prefixed & Specific ACL #

Menggunakan wildcard * global memberikan akses ke seluruh sumber daya kluster. Kita harus mendefinisikan aturan akses secara ketat berdasarkan nama topik atau awalan nama topik (Prefixed).

Praktik Buruk (Wildcard ACL Global) #

Perintah di bawah ini memberikan hak akses penuh kepada pengguna payment-service untuk melakukan operasi apa pun di topik apa saja di dalam kluster.

# BAD CONFIGURATION - Memberikan izin tak terbatas
kafka-acls.sh --bootstrap-server localhost:9093 \
  --command-config /etc/kafka/client.properties \
  --add \
  --allow-principal User:payment-service \
  --operation All \
  --topic *

Praktik Baik (Granular & Prefixed ACL) #

Sebagai gantinya, kita harus membatasi agar pengguna payment-service hanya dapat membaca dari topik yang memiliki awalan payment- dan hanya dapat mempublikasikan pesan ke topik spesifik transactions-incoming.

# GOOD CONFIGURATION - Batasi hanya membaca dari topik berawalan "payment-"
kafka-acls.sh --bootstrap-server localhost:9093 \
  --command-config /etc/kafka/client.properties \
  --add \
  --allow-principal User:payment-service \
  --operation Read \
  --topic payment- \
  --resource-pattern-type prefixed

# GOOD CONFIGURATION - Batasi hanya mempublikasikan ke topik "transactions-incoming" secara spesifik
kafka-acls.sh --bootstrap-server localhost:9093 \
  --command-config /etc/kafka/client.properties \
  --add \
  --allow-principal User:payment-service \
  --operation Write \
  --topic transactions-incoming \
  --resource-pattern-type literal

3. Expose Metrics: Remote JMX Tanpa Otentikasi vs Prometheus JMX Exporter #

Mengaktifkan remote JMX secara mentah di port publik merupakan ancaman keamanan yang sangat besar karena membuka peluang eksekusi kode jarak jauh (Remote Code Execution - RCE) melalui kerentanan Java deserialization.

Praktik Buruk (Remote JMX Terbuka) #

# BAD CONFIGURATION - Menyetel parameter JVM di kafka-run-class.sh / environment
export KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote \
                       -Dcom.sun.management.jmxremote.port=9999 \
                       -Dcom.sun.management.jmxremote.authenticate=false \
                       -Dcom.sun.management.jmxremote.ssl=false"

Praktik Baik (Menggunakan Prometheus JMX Exporter Agent) #

Untuk memantau metrik internal Kafka dengan aman, kita sebaiknya menggunakan Java Agent Prometheus JMX Exporter. Agent ini berjalan di dalam proses JVM Kafka yang sama dan mengekspor metrik internal dalam format teks HTTP ramah-Prometheus di port lokal yang terisolasi.

Langkah perbaikan:

  1. Unduh file jmx_prometheus_javaagent.jar.
  2. Buat file konfigurasi /etc/kafka/jmx_exporter.yaml untuk memfilter metrik yang dibutuhkan saja.
  3. Konfigurasikan Kafka untuk menjalankan agent ini pada interface localhost (127.0.0.1) di port 7071:
# GOOD CONFIGURATION - Jalankan JMX Exporter yang terikat ke localhost
export KAFKA_OPTS="-javaagent:/usr/share/jmx-exporter/jmx_prometheus_javaagent.jar=7071:/etc/kafka/jmx_exporter.yaml"

Dengan konfigurasi ini, port JMX internal JVM tidak perlu dibuka ke jaringan luar. Layanan Prometheus dapat mengambil metrik dengan aman melalui port HTTP 7071 yang dilindungi oleh firewall.


Skrip Diagnostik Otomatis: Monitoring Kedaluwarsa Sertifikat SSL #

Untuk mencegah padamnya kluster Kafka akibat sertifikat SSL yang habis masa berlakunya, kita dapat menggunakan skrip Bash otomatis di bawah ini. Skrip ini memiliki dua kapabilitas:

  1. Memeriksa sertifikat broker dari jarak jauh melalui koneksi jaringan TLS (openssl s_client).
  2. Memeriksa isi file Keystore lokal Java JKS (keytool) secara langsung pada server broker.

Skrip Bash: check-kafka-certs.sh #

Kita dapat membuat berkas skrip ini pada server pemantauan atau server broker, menyetel variabel lingkungan yang sesuai, dan mengaturnya berjalan secara berkala menggunakan cron job.

#!/usr/bin/env bash
# ==============================================================================
# check-kafka-certs.sh
# Skrip Otomasi Pemantauan Masa Berlaku Sertifikat SSL Apache Kafka
# Kriteria Alert: Sisa masa berlaku sertifikat kurang dari atau sama dengan 30 hari.
# ==============================================================================

# Konfigurasi Batas Hari Peringatan (Alert Threshold)
ALERT_DAYS=30

# Mode 1: Pemeriksaan Jaringan Jarak Jauh (Remote TLS Inspection)
CHECK_REMOTE=true
REMOTE_HOST="localhost"
REMOTE_PORT="9093"

# Mode 2: Pemeriksaan Keystore Lokal JKS (Local Keystore Inspection)
CHECK_LOCAL_KEYSTORE=false
KEYSTORE_PATH="/var/private/ssl/kafka.server.keystore.jks"
KEYSTORE_PASS="SangatRahasia123!"
KEY_ALIAS="caroot"

# Inisialisasi status error
EXIT_STATUS=0

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Memulai pemeriksaan sertifikat Kafka..."

# --- FUNGSI UTAMA: Evaluasi Sisa Hari Sertifikat ---
evaluate_expiry() {
    local expiry_date_str="$1"
    local source_desc="$2"

    # Konversi tanggal kedaluwarsa ke format epoch seconds
    # Mendukung format tanggal dari openssl dan keytool
    if [[ "$OSTYPE" == "darwin"* ]]; then
        # OS macOS
        expiry_epoch=$(date -j -f "%b %d %T %Y %Z" "$expiry_date_str" "+%s" 2>/dev/null)
        if [ -z "$expiry_epoch" ]; then
            expiry_epoch=$(date -j -f "%Y-%m-%d" "$expiry_date_str" "+%s" 2>/dev/null)
        fi
    else
        # OS Linux
        expiry_epoch=$(date -d "$expiry_date_str" "+%s" 2>/dev/null)
    fi

    if [ -z "$expiry_epoch" ]; then
        echo "[ERROR] Gagal mem-parsing tanggal kedaluwarsa: '$expiry_date_str' pada $source_desc"
        EXIT_STATUS=1
        return
    fi

    current_epoch=$(date '+%s')
    diff_seconds=$((expiry_epoch - current_epoch))
    diff_days=$((diff_seconds / 86400))

    echo "Sertifikat [$source_desc]:"
    echo "  - Tanggal Kedaluwarsa : $expiry_date_str"
    echo "  - Sisa Masa Berlaku   : $diff_days hari"

    if [ "$diff_days" -le 0 ]; then
        echo "[CRITICAL] SERTIFIKAT TELAH KEDALUWARSA PADA $source_desc!"
        EXIT_STATUS=2
    elif [ "$diff_days" -le "$ALERT_DAYS" ]; then
        echo "[WARNING] SERTIFIKAT AKAN KEDALUWARSA DALAM $diff_days HARI PADA $source_desc!"
        # Di sini kita dapat menambahkan integrasi webhook Slack/Discord/PagerDuty
        # curl -X POST -H 'Content-type: application/json' --data '{"text":"Warning: Cert expired in '$diff_days' days!"}' https://hooks.slack.com/services/...
        EXIT_STATUS=1
    else
        echo "[OK] Sertifikat aman. Masa berlaku lebih dari $ALERT_DAYS hari."
    fi
}

# --- AKSI 1: Pemeriksaan Remote SSL ---
if [ "$CHECK_REMOTE" = true ]; then
    echo "Memeriksa port remote TLS $REMOTE_HOST:$REMOTE_PORT..."
    
    # Mengambil tanggal kedaluwarsa menggunakan openssl s_client
    cert_info=$(echo | openssl s_client -connect "$REMOTE_HOST:$REMOTE_PORT" -servername "$REMOTE_HOST" 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null)
    
    if [ -n "$cert_info" ]; then
        # Ekstrak string tanggal setelah "notAfter="
        raw_date=$(echo "$cert_info" | cut -d= -f2)
        evaluate_expiry "$raw_date" "Remote Port $REMOTE_HOST:$REMOTE_PORT"
    else
        echo "[ERROR] Gagal terhubung ke port remote TLS $REMOTE_HOST:$REMOTE_PORT atau port tidak merespon jabat tangan SSL."
        EXIT_STATUS=1
    fi
fi

# --- AKSI 2: Pemeriksaan Keystore Lokal JKS ---
if [ "$CHECK_LOCAL_KEYSTORE" = true ]; then
    echo "Memeriksa berkas keystore lokal $KEYSTORE_PATH..."
    
    if [ ! -f "$KEYSTORE_PATH" ]; then
        echo "[ERROR] Berkas keystore tidak ditemukan di path: $KEYSTORE_PATH"
        EXIT_STATUS=1
    else
        # Menggunakan keytool untuk membaca tanggal kedaluwarsa alias tertentu
        # Mengambil baris yang mengandung 'Valid from' dan memfilter tanggal kedaluwarsa 'until'
        cert_info=$(keytool -list -v -keystore "$KEYSTORE_PATH" -storepass "$KEYSTORE_PASS" -alias "$KEY_ALIAS" 2>/dev/null | grep "Valid from")
        
        if [ -n "$cert_info" ]; then
            # Ekstrak tanggal setelah kata "until:"
            raw_date=$(echo "$cert_info" | sed -E 's/.*until: (.*)/\1/')
            # Contoh format keytool: Mon Aug 17 14:32:01 WIB 2026
            # Kita bersihkan format timezone lokal (seperti WIB/WIT/WITA) jika mempersulit parsing
            clean_date=$(echo "$raw_date" | sed -E 's/ (WIB|WIT|WITA|WET|CET|EST|PST|UTC|GMT) / /')
            evaluate_expiry "$clean_date" "Local Keystore Alias [$KEY_ALIAS]"
        else
            echo "[ERROR] Gagal membaca alias '$KEY_ALIAS' di dalam keystore atau password salah."
            EXIT_STATUS=1
        fi
    fi
fi

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Pemeriksaan selesai dengan kode keluar: $EXIT_STATUS"
exit $EXIT_STATUS

Konfigurasi Jadwal Otomatisasi (Cron Job) #

Untuk menjalankan skrip ini secara otomatis setiap hari pada pukul 03:00 pagi dan mencatat hasilnya ke file log, kita dapat menambahkannya ke tabel cron (crontab) server pemantau:

  1. Jalankan perintah edit crontab:
    crontab -e
    
  2. Tambahkan baris jadwal berikut:
    0 3 * * * /usr/local/bin/check-kafka-certs.sh >> /var/log/kafka/cert-check.log 2>&1
    

Production Readiness Security Checklist #

Sebelum kita merilis kluster Apache Kafka ke lingkungan produksi, tim administrator dan IT Security wajib melakukan audit kepatuhan (compliance audit) berdasarkan checklist berikut untuk memastikan tidak ada celah keamanan yang terlewat:

No Kategori Audit Item Kepatuhan (Compliance Item) Status Metode Verifikasi
1 Encryption Protokol PLAINTEXT dinonaktifkan di seluruh broker. [ ] Periksa konfigurasi listeners dan advertised.listeners di server.properties di setiap node broker.
2 Encryption Lalu lintas data klien luar wajib menggunakan enkripsi SSL/TLS. [ ] Lakukan pemindaian eksternal ke port broker klien menggunakan openssl s_client -connect broker:port.
3 Encryption Komunikasi inter-broker dikonfigurasi menggunakan port SSL terisolasi yang terpisah. [ ] Pastikan parameter security.inter.broker.protocol=SSL atau SASL_SSL diaktifkan di broker.
4 Authentication Otentikasi klien aktif secara wajib menggunakan mTLS atau SASL (SCRAM/OAuthbearer). [ ] Coba lakukan koneksi klien tanpa sertifikat klien atau kredensial yang valid; broker harus menolak koneksi.
5 Authentication Kredensial, token, dan password keystore tidak ditulis secara hardcode di file properti Git. [ ] Jalankan pemindaian statis repositori dengan grep atau GitGuardian untuk memeriksa string password.
6 Authorization Modul Authorizer aktif dengan kebijakan penolakan bawaan (Deny-by-Default). [ ] Pastikan parameter allow.everyone.if.no.acl.found=false disetel di berkas server.properties.
7 Authorization Aturan ACL dikonfigurasi secara granular per nama aplikasi/principal (tanpa wildcard * global). [ ] Jalankan perintah kafka-acls.sh --bootstrap-server broker:port --list secara berkala dan audit hasilnya.
8 Infrastructure Port internal sensitif (KRaft controller 9094, JMX 9999) ditutup dari jaringan luar oleh firewall. [ ] Lakukan pemindaian port (port scanning) menggunakan nmap dari luar subnet VPC untuk memastikan port tertutup.
9 Infrastructure Rate limiter pembuatan koneksi TCP dikonfigurasi pada broker untuk mencegah kebanjiran koneksi. [ ] Pastikan parameter max.connection.creation.rate disetel ke nilai logis di broker.
10 Operations Sistem rotasi sertifikat SSL otomatis telah diuji dan berfungsi tanpa menyebabkan downtime. [ ] Lakukan pengujian rotasi sertifikat menggunakan Admin API dinamis untuk memicu reload keystore broker.

Ringkasan #

  • Terapkan Zero-Trust — Selalu matikan listener PLAINTEXT dan ubah setelan otorisasi bawaan menjadi allow.everyone.if.no.acl.found=false untuk mengadopsi prinsip pertahanan deny-by-default.
  • Gunakan Config Provider — Hindari menaruh rahasia/password di Git. Manfaatkan FileConfigProvider untuk merujuk file password eksternal yang diisolasi dengan ketat di sistem operasi.
  • Pantau Sertifikat SSL — Pasang skrip pemantauan otomatis berbasis openssl atau keytool untuk mendeteksi sertifikat broker yang akan habis masa berlakunya dalam kurun waktu kurang dari 30 hari.
  • Gunakan JMX Exporter — Tutup port remote JMX JVM dari jaringan dan gunakan Prometheus JMX Exporter agent yang terikat pada host lokal (127.0.0.1) agar metrik internal dapat dikikis secara aman.

← Sebelumnya: Top-Level Security   Berikutnya: Encryption in Transit →

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