Bagaimana Saya Membuka Message Broker ke Internet Tanpa Membiarkan Siapa Pun Menyamar Jadi Orang Lain
On this page
- Pendahuluan
- A. Apa itu broker, dan siapa yang berbicara dengannya
- B. Kenapa endpoint publik mengubah segalanya
- C. Jalan pintas yang saya tolak
- D. Tiga belas hambatan yang menghalangi
- Metode
- A. Satu kredensial per pintu masuk
- B. Mengikat token ke nama
- C. Audience yang tepat, dan key yang bisa diambil
- D. Aturan yang tak butuh user password
- E. Mengganti password dashboard
- F. Enkripsi di depan broker
- G. Mulai dari data kosong
- H. Menghapus yang dimiliki container
- I. Identitas baru untuk broker
- J. Konfigurasi di tempat broker membacanya
- K. User yang memang milik project ini
- L. Administrator yang benar-benar dibuat RabbitMQ
- M. Batas disk yang cocok dengan host
- Hasil dan Pembahasan
- A. Apa yang terlihat dari internet
- B. Apa yang ditolak, dan di mana
- C. Di mana ini berhenti
- Simpulan
- Istilah
Pendahuluan
Message broker gampang dijalankan di jaringan privat, tempat semua yang bisa menjangkaunya adalah program yang saya taruh sendiri di sana. Begitu ia harus terjangkau dari internet, oleh browser di satu sisi dan perangkat di sisi lain, setiap koneksi adalah orang asing sampai terbukti sebaliknya. Saya ingin stack broker yang bisa didapat project baru dengan satu perintah dan langsung dibuka ke internet, tanpa ada yang bisa terhubung sebagai orang lain, atau masuk membawa token yang diterbitkan untuk aplikasi lain.
A. Apa itu broker, dan siapa yang berbicara dengannya
Message broker menyampaikan pesan di antara program-program yang tak pernah berbicara langsung satu sama lain: satu program mem-publish ke satu topic, dan siapa pun yang sudah subscribe ke topic itu menerimanya. Stack saya menjalankan dua broker. EMQX berbicara MQTT, protokol publish-subscribe ringan yang dirancang untuk perangkat dan untuk browser yang butuh pembaruan langsung. RabbitMQ berbicara AMQP, protokol yang lebih berat yang dipakai service backend saya di antara mereka sendiri untuk antrean dan event. Database PostgreSQL kecil menyimpan user MQTT beserta aturan aksesnya.
Dua jenis client MQTT datang dengan cara berbeda. Perangkat, atau service di luar server, terhubung lewat TCP dengan username dan password. Browser tak bisa membuka koneksi TCP mentah, jadi ia terhubung lewat WebSocket, dan ia sudah memegang bekal yang lebih baik daripada password: token login yang diterima aplikasinya saat user login. Broker yang melayani keduanya harus menerima keduanya, dan dari situlah kerumitannya mulai.
Setiap project mendapat salinan stack ini sendiri. Generator menanyakan nama project, network Docker-nya, kredensialnya, user MQTT pertama beserta topic yang boleh dipakainya, dan apakah browser perlu login dengan token. Sesudah itu ia menulis folder terpisah dengan broker sendiri, database user sendiri, dan konfigurasi sendiri, supaya client satu project tak pernah berbagi broker, user, atau topic dengan client project lain. Apa pun yang sudah benar di stack ini harus benar lagi di setiap project baru, tanpa ada yang perlu mengingat caranya.
B. Kenapa endpoint publik mengubah segalanya
Di jaringan privat, aturan broker kebanyakan melindungi dari kekeliruan. Di internet, aturan itu melindungi dari orang. Pemeriksaan password di port publik mengundang siapa saja untuk mencoba-coba password. Pemeriksaan token yang menerima token apa pun dari identity provider saya ikut menerima token dari setiap aplikasi yang dilayani provider itu, bukan cuma yang memang ditujukan untuk broker ini. Dan aturan akses yang memercayai nama yang disebut client tentang dirinya sendiri memercayai siapa pun yang mau mengetik nama lain.
Tak satu pun kegagalan ini menghasilkan error. Masing-masing bekerja sempurna dari sudut pandang client yang menyalahgunakannya, dan justru karena itulah semuanya harus ditutup sejak rancangan, bukan ditemukan belakangan di log. Ujian sebenarnya bukan apakah client yang sah bisa terhubung, melainkan apakah client yang tak sah ditolak, dan ditolak sedini mungkin.
C. Jalan pintas yang saya tolak
Rancangan paling sederhana adalah satu metode autentikasi untuk semuanya: setiap client, browser maupun perangkat, menyerahkan username dan password. Rancangan itu saya tolak karena ia menaruh pemeriksaan password di endpoint WebSocket publik dan memaksa browser membawa rahasia kedua di samping token yang sudah dipegangnya. Jalan pintas kedua adalah membuka port MQTT polos milik broker secara langsung dan menunda enkripsi. Itu juga saya tolak: kredensial yang dikirim lewat port tak terenkripsi di internet sama saja dengan kredensial yang diumumkan.
Jalan pintas ketiga paling halus: membiarkan aturan akses broker mencari client berdasarkan username yang dikirimnya saat terhubung. Itulah perilaku bawaannya, itulah yang diperlihatkan setiap contoh, dan di jaringan privat ia tak berbahaya. Di endpoint publik, artinya username menjadi klaim yang tak diperiksa siapa pun. Rancangan yang akhirnya saya pakai memberi tiap jenis client tepat satu jalan masuk, mengikat setiap token ke identitas di dalamnya, dan mengakhiri enkripsi di depan broker, bukan di dalamnya.
D. Tiga belas hambatan yang menghalangi
Gampang dirumuskan, canggung dibangun. Ada tiga belas rintangan di antara broker yang terbuka dan broker yang hanya meloloskan yang berhak: lima soal identitas, satu soal enkripsi, dan tujuh soal membuat broker setiap project menyala sebagai dirinya sendiri, bukan salinan broker project sebelumnya.
Setiap pintu masuk hanya boleh menerima satu jenis kredensial. Secara bawaan, broker menjalankan setiap koneksi lewat rantai authenticator yang sama, jadi client WebSocket masih bisa mencoba password dan client TCP masih bisa mencoba token. Satu rantai untuk semua listener adalah alternatif yang ditolak, karena ia mempertahankan pemeriksaan password di endpoint publik yang semestinya tak punya pemeriksaan semacam itu.
Token yang sah tak boleh cukup untuk menjadi orang lain. Broker mencari aturan akses berdasarkan username di paket connect milik client, bukan berdasarkan identitas di dalam token. Memercayai username itu adalah alternatif yang ditolak; saya membuktikannya lewat tes, ketika client yang memegang token sahnya sendiri bisa memilih nama user lain lalu menerima subscription milik user itu.
Token harus ditujukan untuk broker ini, dan broker harus sanggup memeriksanya. Audience token wajib menyebut broker, bukan aplikasi yang memintanya. Versi broker yang saya pakai di awal membandingkan audience itu sebagai string polos, padahal identity provider saya mengirimnya sebagai list, sehingga setiap token gagal. Dan pengambilan signing key milik provider gagal total sampai broker diberi tahu sertifikat mana yang dipercaya dan nama server mana yang disebutkan.
Enkripsi harus berakhir di depan broker, untuk dua protokol berbeda. WebSocket aman berjalan di atas HTTP, sedangkan MQTT over TLS adalah TCP mentah, yang ditangani web server di blok konfigurasi berbeda dan wajib berada di level paling atas. Membiarkan broker memegang sertifikatnya sendiri adalah alternatif yang ditolak, karena setiap pembaruan sertifikat akan berarti me-restart broker.
User token butuh aturan akses, dan tabel aturannya menolak mereka. Aturan akses merujuk user password lewat foreign key, sedangkan user yang login dengan token tak punya baris password, jadi menambahkan aturan untuknya gagal. Mempertahankan foreign key itu, beserta pembersihan otomatis yang dibawanya, adalah alternatif yang saya lepaskan: tabel aturan kini menjadi gerbangnya sendiri, dan user tanpa aturan ditolak.
Dashboard broker menyala dengan password bawaan image. EMQX tak mengambil password administratornya dari konfigurasi, jadi stack baru akan membuka dashboard manajemennya dengan password yang tercetak di dokumentasi publik. Membiarkannya untuk diganti orang sesudah start pertama adalah alternatif yang ditolak.
Run kedua untuk project yang sama akan diam-diam memakai ulang database lama. Data broker tinggal di path ber-prefix di luar folder output, jadi menimpa output membiarkan database user, antrean, dan state broker yang lama tetap di tempatnya. Membiarkan data itu adalah alternatif yang ditolak, karena stack baru menyala sehat di atas user milik orang lain.
Container meninggalkan file yang hanya bisa dihapus root. Database, RabbitMQ, dan cookie cluster-nya menulis file sebagai user di dalam image masing-masing, yang tak bisa dihapus atau disalin oleh orang yang menjalankan generator. Menjalankan generator sebagai root, atau memakai sudo, adalah alternatif yang ditolak, karena setiap file yang ditulisnya akan menjadi milik root.
Broker hasil salinan membawa identitas node lama. EMQX menyimpan identifier node dan cluster-nya beserta session yang tersimpan di dalam folder datanya. Menyalin data template utuh-utuh adalah alternatif yang ditolak, karena dua project akan berbagi satu identitas broker.
Broker bisa menyala tanpa autentikasi dan tampak sehat sempurna. Broker membaca konfigurasinya dari path ter-mount di bawah prefix data, bukan dari folder output tempat generator menulis. Menyunting konfigurasi di folder output saja adalah alternatif yang ditolak: broker akan menyala dengan konfigurasi template, tanpa pemeriksaan database dan tanpa aturan akses.
User project sebelumnya tertanam di migration. Migration database user berisi user MQTT project lama beserta aturan aksesnya, ditambah satu migration untuk user login milik satu project. Menjalankannya apa adanya adalah alternatif yang ditolak, karena user lama akan tiba di project baru lengkap dengan izin lamanya.
RabbitMQ mengabaikan administrator yang diberikan lewat environment-nya. Begitu RabbitMQ memuat definisinya dari file, ia melewati user bawaan yang disebut di environment variable-nya, jadi administratornya diam-diam tak pernah ada. Mengandalkan variable itu adalah alternatif yang ditolak.
Batas disk bawaan RabbitMQ memblokir publisher di host kecil. Template mengatur batas disk kosong relatif terhadap memori, satu setengah kali RAM, yang di host berdisk kecil langsung memicu alarm disk dan memblokir setiap publisher. Mempertahankan batas relatif itu adalah alternatif yang ditolak.
Urutannya mengikuti satu koneksi dari luar ke dalam, lalu kelahiran stack itu sendiri. Hambatan pertama menentukan pintu mana yang boleh dipakai client. Yang kedua dan ketiga menentukan apakah identitas yang dibawanya ke pintu itu asli dan memang ditujukan untuk broker ini. Yang kelima dan keenam menutup dua jalan masuk tersisa yang tak bergantung pada client: tabel aturan yang tak bisa menampung user token, dan dashboard berpassword publik. Yang keempat menentukan apakah semua itu bisa menyeberangi internet dengan aman, dan ia datang sesudah tiga yang pertama karena baru masuk akal setelah ada yang layak dilindungi di belakangnya. Tujuh yang terakhir menentukan apakah broker project baru benar-benar baru: datanya sendiri, file-nya sendiri, identitasnya sendiri, konfigurasinya sendiri, user-nya sendiri, dan RabbitMQ yang punya administrator dan tak berhenti di disk penuh pertama.
Metode
A. Satu kredensial per pintu masuk
Inilah jawaban atas hambatan pertama: setiap authenticator di rantai broker membawa precondition yang menyebut satu-satunya listener tempat ia berlaku. Pemeriksaan password PostgreSQL hanya berlaku untuk listener TCP, dan pemeriksaan token hanya berlaku untuk listener WebSocket. Browser di endpoint publik tak pernah dimintai password, dan password yang dikirim ke sana tak pernah dicocokkan ke database.
authentication = [
{ mechanism = password_based, backend = postgresql, …
precondition = "str_eq(listener, 'tcp:default')" },
{ mechanism = jwt, use_jwks = true, …
precondition = "str_eq(listener, 'ws:default')" }
]Generator menulis template dengan dua placeholder dan baru mengisinya bila login dengan token diaktifkan. Tanpa itu, kedua placeholder dibuang dan broker kembali ke satu rantai password, jadi template yang sama melayani broker privat maupun broker publik. Template juga menyalakan listener TLS milik broker sendiri, di port 8883 dan 8084 di dalam container, dan tak satu pun precondition menyebutnya; 8883 tak pernah dipublikasikan, dan 8084 hanya dipublikasikan di alamat internal, jadi keduanya tak terjangkau dari internet, tapi mematikannya di template akan menutup celah itu untuk selamanya.
B. Mengikat token ke nama
Inilah jawaban atas hambatan kedua: pemeriksaan token memverifikasi klaim yang mengikat username milik token itu sendiri ke username di paket connect. Aturan akses tetap dicari berdasarkan username di paket connect, tapi kini client hanya bisa mengirim nama yang memang tertera di token-nya.
authorization.sources = [
{ type = postgresql,
query = "SELECT action, permission, topic FROM mqtt_acl WHERE username = ${username}" }
]verify_claims = {
iss = "https://id.example.com/realms/main",
aud = "broker.example.com",
preferred_username = "${username}"
}Sebelum klaim ini dipasang, client yang login sebagai alice lalu terhubung dengan username mallory diberi subscription milik Mallory. Sesudahnya, percobaan yang sama ditolak di tahap connect, sebelum aturan akses mana pun sempat diperiksa. Apa pun yang tak diizinkan secara eksplisit akan ditolak, jadi user tanpa aturan tak menerima apa-apa sama sekali.
C. Audience yang tepat, dan key yang bisa diambil
Inilah jawaban atas hambatan ketiga, dalam tiga bagian. Bagian pertama soal makna: audience adalah pihak yang dituju token, jadi ia menyebut broker. Client identifier aplikasi adalah nilai yang keliru: itu identitas pihak yang meminta, bukan pihak yang menerima. Kini broker hanya meminta tepat tiga nilai — issuer, endpoint signing key, dan audience — dan tak mengambil apa pun dari konfigurasi OAuth2 milik aplikasi, karena konfigurasi itu milik client, bukan milik resource seperti broker.
Bagian kedua soal versi. Identity provider saya menerbitkan audience sebagai list, misalnya broker ditambah service akun. Versi broker yang saya pakai di awal membandingkan audience yang diharapkan dengan list itu sebagai satu string persis, sehingga pemeriksaannya gagal untuk setiap token. Perbaikannya ada di broker itu sendiri, dirilis di versi patch berikutnya, dan template kini mengunci versi tersebut.
Bagian ketiga adalah koneksi yang mengambil signing key milik provider. Dengan verifikasi sertifikat menyala dan tanpa konfigurasi lain, pengambilannya gagal dengan error yang menyatakan sertifikat tepercaya tak terdefinisi. Broker butuh bundle sertifikat untuk dipercaya dan nama server untuk disebutkan, dan generator menurunkan nama itu dari endpoint yang diketik user.
JWKS_SNI=""ssl {
enable = true
verify = verify_peer
cacertfile = "/etc/ssl/certs/ca-certificates.crt"
server_name_indication = "id.example.com"
}D. Aturan yang tak butuh user password
Satu migration membuang foreign key dari aturan akses ke user password dan menambahkan index sebagai gantinya, jadi satu aturan bisa menyebut user yang hanya pernah login dengan token. Tabel aturan menjadi gerbang otorisasi: broker menolak apa pun yang tak diizinkan aturan, jadi token sah tanpa aturan tetap ditolak. Harganya, aturan tak lagi ikut hilang bersama user-nya, jadi aplikasi yang mengelola user menghapusnya sendiri. Aturan yang berubah baru berlaku sesudah cache otorisasi broker dibersihkan, yang dikerjakan script provisioning sesudah setiap perubahan.
-- access rules no longer require a password user
mqtt_acl DROP CONSTRAINT IF EXISTS mqtt_acl_username_fkey;
NOT EXISTS mqtt_acl_username_idx ON mqtt_acl (username);E. Mengganti password dashboard
Begitu EMQX melapor siap, generator memasang password administrator lewat tool command-line milik broker sendiri, mencoba ulang selama semenit, karena perintah itu gagal selagi broker masih menyala.
for; do
&& break
F. Enkripsi di depan broker
Enkripsi ditangani di luar broker: nginx di host mengakhiri TLS untuk kedua protokol, dan broker hanya pernah melihat koneksi polos di alamat internal. WebSocket aman di port 443 adalah location HTTP biasa dengan protocol upgrade. MQTT over TLS di port 8883 adalah proxy TCP, yang hanya diterima nginx di dalam blok stream di level paling atas konfigurasi utamanya — bukan di file site, yang di-include di dalam blok http. Karena itu generator menulis dua file, dan script pemasangnya menaruh file kedua di direktori terpisah yang di-include dari satu blok stream di level teratas.
server {
listen 8883 ssl;
ssl_certificate /etc/letsencrypt/live/broker.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/broker.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
proxy_pass mqtt_backend;
proxy_timeout 7200s;
}Dua detail di blok itu lahir dari kegagalan. Koneksi MQTT tetap terbuka dan diam di antara pesan, dan nginx menutup koneksi stream yang menganggur sesudah sepuluh menit kecuali diatur lain, jadi timeout-nya dinaikkan. Lalu port 8883 tak boleh ikut dipublikasikan oleh container broker: bila ikut, proxy Docker memegang port itu, dan nginx gagal start dengan pesan "address already in use" — bukan saat konfigurasi dites atau di-reload, yang keduanya lolos, melainkan saat restart berikutnya, bisa berjam-jam kemudian. Script pemasang memeriksa hal ini sebelum mengubah apa pun. Ia butuh root khusus untuk pemeriksaan ini, karena tanpa root daftar port memperlihatkan bahwa port terpakai tapi tidak menyebut proses mana yang memegangnya; port yang dipegang nginx sendiri adalah sisa pemasangan sebelumnya dan diizinkan.
Sisi WebSocket punya timeout sendiri: nginx menutup koneksi proxy HTTP yang diam selama enam puluh detik, jadi browser yang tak menerima pesan selama semenit akan terputus; timeout itu dinaikkan ke dua jam yang sama dengan batas idle broker sendiri. Site-nya mendengarkan di port 443 polos, bukan di satu alamat, karena nginx mengirim request ke listener yang paling spesifik untuk satu alamat, dan site lain yang mengklaim alamat itu akan mengambil domain broker. Modul stream wajib dipasang sebagai paket dan tak boleh juga dimuat dengan tangan, kalau tidak nginx memuatnya dua kali dan menolak start. Satu batas perlu diketahui: langkah aktivasi milik generator sendiri hanya memasang site WebSocket; file stream, include-nya di level teratas, dan pemeriksaan port dipasang oleh script pemasang terpisah, jadi MQTT over TLS butuh script itu dijalankan.
line=""
&& continue
holder=""
&& continue
Generator sendiri tak pernah berjalan sebagai root. Kalau iya, setiap file yang ditulisnya — termasuk file environment yang menyimpan password — akan menjadi milik root, dan setiap langkah sesudahnya juga harus berjalan sebagai root. Hak lebih tinggi hanya ia minta untuk beberapa perintah nginx, dan hanya bila saya setuju.
G. Mulai dari data kosong
Sebelum menulis stack baru, generator menghapus data run sebelumnya di path ber-prefix, jadi database user, antrean RabbitMQ, dan state broker semuanya mulai kosong. Komentar di samping langkah itu menyebut alasannya dalam satu baris: tanpanya, database lama diam-diam terpakai ulang.
H. Menghapus yang dimiliki container
Ketika orang yang menjalankan generator tak bisa menghapus file yang ditulis container, container berumur pendek dengan mount yang sama menghapusnya, dan template disalin dengan direktori-direktori itu dikecualikan, jadi tak ada langkah yang butuh root.
|| I. Identitas baru untuk broker
Dari data broker milik template, hanya dua file yang ikut: konfigurasi cluster dan aturan akses berbasis file. Semua yang mengidentifikasi node lama — identifier node dan cluster-nya, session yang tersimpan, dan database-nya — ditinggalkan, jadi broker baru menyala dengan identitasnya sendiri.
J. Konfigurasi di tempat broker membacanya
Sesudah menyunting konfigurasi broker, generator memindahkannya ke path ber-prefix yang di-mount file compose. Tanpa pemindahan itu, broker menyala dengan konfigurasi template: sehat, terjangkau, tanpa pemeriksaan database dan tanpa aturan akses.
K. User yang memang milik project ini
Generator membuang user dan aturan lama dari migration, menghapus migration milik login satu project, lalu menulis migration seed baru untuk user MQTT pertama project ini, dengan hash bcrypt dan migration down pasangannya, jadi database user dibuat dengan tepat satu user beserta aturannya.
L. Administrator yang benar-benar dibuat RabbitMQ
Administrator ditulis ke file definisi RabbitMQ, dengan hash SHA-256 bergaram dalam format yang diharapkan RabbitMQ, bersama permission-nya di virtual host bawaan dan virtual host milik project.
M. Batas disk yang cocok dengan host
Generator menanyakan batas disk kosong yang absolut, dua gigabyte secara bawaan, lalu menuliskannya menggantikan batas relatif.
disk_free_limit.absolute = 2GBHasil dan Pembahasan
A. Apa yang terlihat dari internet
Stack ini dites dari internet, dengan sertifikat publik dan token sungguhan dari identity provider, bukan dari dalam server. Port 8883 menerima MQTT over TLS dengan username dan password. Port 443 menerima MQTT lewat WebSocket aman dengan token. Port MQTT polos sama sekali tak terjangkau dari luar, karena secara bawaan port broker hanya dipublikasikan di alamat internal dan nginx satu-satunya yang mendengarkan secara publik.
| Port | Protokol | Enkripsi | Kredensial | Dari internet |
|---|---|---|---|---|
| 8883 | MQTT over TCP | TLS | username dan password | terbuka |
| 443 | MQTT over WebSocket | TLS | token | terbuka |
| 1883 | MQTT over TCP | tidak ada | — | tertutup |
Dua temuan dari tes itu layak disimpan. Client yang terhubung ke 8883 tanpa TLS tidak mendapat error; ia menggantung sampai timeout, karena server menunggu handshake yang tak pernah datang, dan gejalanya mirip masalah jaringan, bukan penolakan; password yang salah langsung dijawab dengan kode penolakan. Lalu, ini bukan mutual TLS: client memverifikasi sertifikat server dengan trust store sistemnya, dan server tidak meminta sertifikat client, jadi identitas client tetap urusan broker.
B. Apa yang ditolak, dan di mana
Kasus yang paling penting justru yang gagal. Token yang login sebagai satu user tapi terhubung dengan nama lain ditolak di tahap connect. Token sah dari aplikasi lain di identity provider yang sama ditolak di tahap yang sama, karena audience-nya tidak menyebut broker. Keduanya tak sampai ke aturan akses, yang merupakan titik paling awal penolakan bisa terjadi.
C. Di mana ini berhenti
RabbitMQ sengaja tidak menjadi bagian dari permukaan publik. Ia membawa lalu lintas di antara service saya sendiri, port-nya hanya dipublikasikan di alamat internal, dan user-nya, termasuk administrator, dibuat dari definisi yang ditulis generator. Dashboard manajemen kedua broker juga tetap internal. Menambahkan mutual TLS untuk perangkat, atau membuka AMQP ke service luar, akan menjadi rancangan lain dengan hambatan lain.
Simpulan
Membuka broker ke internet ternyata lebih banyak soal identitas ketimbang enkripsi. Kini setiap pintu masuk hanya menerima satu jenis kredensial, setiap token terikat ke nama yang dipakai client-nya dan wajib ditujukan untuk broker ini, dan TLS berakhir di nginx di depannya untuk kedua protokol. Broker setiap project juga menyala sebagai dirinya sendiri: data kosong, identitas node baru, user-nya sendiri, password dashboard yang bukan bawaan, dan RabbitMQ dengan administrator sungguhan serta batas disk yang pas. Generator menulis semua itu dari segelintir jawaban, sehingga project baru mendapat broker publik yang menolak penyusup sejak start pertamanya, bukan sesudah insiden pertamanya.
Istilah
- MQTT
- Protokol pesan publish-subscribe yang ringan, dipakai perangkat dan aplikasi yang butuh pembaruan langsung.
- AMQP
- Protokol pesan untuk antrean dan event yang dirutekan, umumnya dipakai di antara service backend.
- Listener
- Satu port dan protokol tempat broker menerima koneksi, misalnya TCP atau WebSocket.
- JWT
- Token bertanda tangan yang membawa klaim tentang user, seperti namanya, siapa penerbitnya, dan untuk siapa token itu ditujukan.
- JWKS
- Kumpulan public key yang dipublikasikan identity provider untuk menandatangani token-nya, diambil oleh siapa pun yang perlu memverifikasinya.
- Audience
- Klaim di dalam token yang menyebut service tujuan token itu.
- ACL
- Access control list: aturan yang menentukan user mana boleh publish atau subscribe ke topic mana.
- TLS terminator
- Server yang menangani enkripsi atas nama server lain dan meneruskan lalu lintas yang sudah didekripsi kepadanya.
- SNI
- Server Name Indication: nama server yang disebutkan client saat handshake TLS supaya server bisa memilih sertifikat yang tepat.
Technologies covered
- Docker Compose
- EMQX
- nginx
- RabbitMQ
- JWT
- MQTT
- TLS