3 poin oleh GN⁺ 2023-07-06 | 1 komentar | Bagikan ke WhatsApp
  • suc adalah Simple Unix Chat yang mengimplementasikan sebagian fitur inti ala Slack·Mattermost dengan kombinasi blok dasar UNIX dan Bash; loop intinya terdiri dari 5 baris, tetapi skrip sebenarnya lebih panjang
  • Pesan dibaca satu baris demi satu dari standar input, lalu diberi tanggal dan nama pengguna sebelum ditambahkan ke file kanal di /var/lib/suc/, sementara autentikasi dan kontrol akses diserahkan ke SSH dan model izin UNIX
  • Berbeda dengan server Mattermost yang memiliki sekitar 500 ribu baris kode Go saja, suc menekankan bahwa perilaku inti serupa dapat dibuat dengan kode yang jauh lebih kecil
  • usuc menggabungkan tail -f, rlwrap, pygmentize, dan awalan perintah : untuk menangani pembacaan kanal, keluaran bergaya Markdown, dan berbagi hasil perintah
  • Karena kanal hanyalah file teks sederhana, ia mudah dirangkai dengan alat UNIX seperti grep, tail, bat, lnav, hook Git, dan skrip bot

Kompleksitas yang ingin dikurangi oleh suc

  • suc adalah singkatan dari Simple Unix Chat; fiturnya lebih sedikit daripada Slack, Mattermost, dan IRC, dan jumlah baris totalnya memang lebih dari 5, tetapi loop inti untuk menulis pesan disusun dalam 5 baris Bash
  • Fitur yang dituju adalah obrolan rich text waktu nyata, berbagi file, kontrol akses yang rinci, otomatisasi dan integrasi alat eksternal, enkripsi saat transmisi, enkripsi opsional saat penyimpanan, serta autentikasi pengguna
  • Implementasi yang kecil dimungkinkan karena memanfaatkan blok dasar yang konsisten dan dapat dikombinasikan yang disediakan implementasi UNIX modern
  • Sebagai perbandingan, server Mattermost memiliki sekitar 500 ribu baris kode Go, dan suc menilai dirinya dapat mengimplementasikan fitur inti Mattermost dengan 0,005% dari jumlah kode tersebut

Loop penulisan pesan 5 baris

  • Loop Bash inti suc membaca satu baris dari standar input, menambahkan tanggal dan nama pengguna sebenarnya, lalu menambahkannya ke file /var/lib/suc/"$1"
  • Skrip sebenarnya lebih panjang karena prapemrosesan keamanan dan perhitungan warna nama pengguna, tetapi perilaku inti untuk menulis riwayat obrolan dapat diringkas menjadi tiga hal
    • membaca satu baris dari standar input
    • menambahkan tanggal dan nama pengguna sebenarnya
    • menambahkan ke file kanal di bawah /var/lib/suc/
  • Autentikasi, kontrol akses, enkripsi, dan rich text ditangani bukan oleh kode internal suc, melainkan oleh SSH, API kontrol akses UNIX, dan modularitas berbasis teks

SSH menangani autentikasi

  • Proses suc dijalankan oleh pengguna yang sudah diautentikasi, jadi suc sendiri tidak memiliki kode autentikasi
  • Autentikasi jarak jauh ditangani oleh ssh seperti pada server UNIX pada umumnya
    • rahasia bersama seperti kata sandi
    • tantangan kriptografis
    • perangkat pembuat kata sandi sekali pakai (OTP)
    • MFA yang menggabungkan beberapa metode
  • ssh juga mengautentikasi server kepada klien untuk mencegah serangan man-in-the-middle, dan mengenkripsi semua data antara klien dan server
  • Instalasi suc bergantung pada host UNIX dan konfigurasi server ssh
    • pengguna harus ada di sistem
    • server ssh harus mengizinkan login jarak jauh untuk pengguna tersebut
  • Di GNU Guix, pengguna dan kunci SSH dapat ditambahkan dalam satu baris dengan konfigurasi deklaratif, dan jika baris konfigurasi itu dihapus maka pengguna akan dihapus saat proses rekonfigurasi

Kontrol akses ditangani model izin UNIX

  • suc tidak hanya tidak menyertakan kode autentikasi, tetapi juga tidak menyertakan kode kontrol akses; pendekatan ini disebut security agnosticism
  • Kernel UNIX mengetahui pengguna, grup, proses, dan file, lalu menentukan izin baca-tulis file berdasarkan pemilik efektif (effective owner) dari proses
  • File kanal di /var/lib/suc dimiliki oleh pengguna suc, dan diatur agar pengguna bisa membaca kanal tertentu melalui izin baca per grup
  • Pengguna biasa tidak menulis langsung ke file, melainkan menjalankan suc, dan pencocokan serta pemblokiran izin ditangani oleh kernel
  • Dalam komunitas yang lebih ketat, biner setuid per grup bisa disediakan
    • misalnya, suc_blue dimiliki oleh pengguna blue dan hanya bisa dijalankan oleh grup blue
    • pengguna dalam grup blue dapat menulis ke kanal blue melalui suc_blue
    • pengguna grup red tidak dapat membaca atau menulis kanal blue
  • Skrip pembantu pembuatan kanal suc_channel.sh panjangnya sekitar 80 baris, dan pengguna GNU Guix dapat membuat biner setuid, pengguna, grup, dan file kanal yang diperlukan hanya dengan satu baris (suc-private-channel "red" "red")
  • Pembaruan transaksional GNU Guix menjamin perubahan konfigurasi diterapkan sepenuhnya atau tidak sama sekali, dan dapat di-rollback ke keadaan kerja sebelumnya

Rich text dan usuc

  • Banyak aplikasi chat merender teks dengan mesin HTML, dan klien desktop Mattermost menggunakan Electron
  • suc menggunakan satu file teks per kanal, dan pengguna dapat melihatnya dengan alat baris perintah seperti tail atau cat
  • Dengan memanfaatkan kode escape ANSI terminal dan dukungan UTF-8, pengalaman warna, emoji, dan rich text dasar dapat dibuat
  • suc hanya menulis ke file kanal, sedangkan pembacaan ditangani oleh usuc
    • suc adalah biner berizin khusus, jadi logika dan dependensi eksternalnya harus diminimalkan
    • usuc dijalankan dengan izin pengguna pemanggil, sehingga fitur bisa ditambahkan dengan lebih bebas
  • usuc merangkai beberapa alat kecil untuk berperan sebagai klien chat
    • menyediakan riwayat dan pengeditan baris dengan rlwrap
    • memilih biner suc setuid yang sesuai berdasarkan pemilik file kanal
    • menampilkan 20 baris terakhir dan baris yang ditambahkan setelahnya dengan tail -f -n 20
    • memeriksa apakah baris input diawali :
    • memproses teks yang dimasukkan pengguna dengan pygmentize
  • pygmentize membaca standar input sebagai Markdown lalu mengeluarkan teks berwarna ANSI, sehingga markup seperti **bold** dapat didukung hanya dengan satu baris kode

Perintah chat dan integrasi shell

  • Jika pesan diawali :, usuc tidak mengirimkannya sebagai pesan biasa, melainkan menjalankan perintah tersebut lalu mengirim hasil keluarannya melalui suc
  • Misalnya, menjalankan gum style --border=rounded --bold --foreground=#F00 "Hello World !" akan membuat teks dengan bingkai dan gaya muncul di kanal
  • Perintah dijalankan dalam namespace pengguna yang memanggil usuc, sehingga pengguna dapat memiliki makro chat sendiri tanpa memengaruhi pengguna lain
  • Di the dam, ini digunakan saat RPG meja untuk melempar dadu dengan perintah seperti roll 2d6

Integrasi pipa teks dan alat eksternal

  • Alih-alih memakai fitur eksekusi perintah usuc, pengguna juga bisa langsung mengalirkan keluaran perintah dari shell ke suc
  • Jika keluaran berwarna dari bat dikirim ke suc, potongan kode dapat dibagikan ke kanal dengan sintaks yang sudah diberi highlight
  • make test > testlog || (suc devops < testlog ; exit 1) adalah contoh one-liner Bash yang mengirim log ke kanal devops saat pengujian gagal
  • One-liner ini dapat dimasukkan ke hook update pada repositori Git untuk menjalankan tes saat push, menolak pembaruan jika gagal, lalu memberi tahu tim DevOps
  • Pekerjaan yang setara dengan fitur integrasi di Slack atau Mattermost dapat disusun dengan pipa teks UNIX dan skrip

Membaca kanal, notifikasi, dan bot

  • Kanal suc adalah file teks yang terus diperbarui, sehingga baris baru dapat dibaca dan diproses dengan tail -f
  • Saat pesan baru masuk, pipeline dapat dibuat untuk mengirim notifikasi dengan notify-send, dan grep bisa dipakai untuk memfilter hanya nama tertentu atau kata kunci seperti “build failure”
  • Untuk menggabungkan beberapa kanal menjadi satu feed, tail -f /var/lib/suc/* dapat digunakan
  • Dengan lnav, pengguna dapat memanfaatkan pengingatan posisi baca, bookmark, warna per kanal, parsing tanggal/nama pengguna/field khusus, filtering, dan kueri SQL
  • Bot dapat dibuat selama ia bisa membaca dan menulis ke kanal sekaligus
    • contohnya mencari ekspresi panjang seperti 33000 ft di kanal
    • mengubahnya ke meter dengan perintah units
    • lalu menulis balasan seperti [metric_bot] 33000 ft is 10058.4 meters. ke kanal yang sama

Perbandingan dan kesimpulan

  • Perbandingan yang dipakai mencakup sistem besar seperti Slack, Mattermost, dan Discord, tetapi menurut penulis pembanding yang lebih adil juga mencakup IRC, talk, dan write
  • IRC dinilai memiliki fitur lebih sedikit daripada suc karena memerlukan bouncer untuk membaca riwayat chat lama
  • Disebutkan bahwa talk, ytalk, dan wall tidak berhasil dibuat berjalan di distribusi Linux modern
  • suc menyerahkan autentikasi ke SSH, kontrol akses dan komposabilitas ke UNIX, serta mempertahankan kanal sebagai file teks
  • Alat-alatnya bisa ditulis dalam bahasa apa pun selama dapat membaca dan menulis teks

1 komentar

 
GN⁺ 2023-07-06
Komentar Hacker News
  • Langsung teringat pada “Master Foo and the Ten Thousand Lines”: http://catb.org/~esr/writings/unix-koans/ten-thousand.html
    Ini kisah ketika Master Foo berkata kepada programmer yang berkunjung, “satu baris shell script mengandung lebih banyak hakikat Unix daripada 10 ribu baris C”

  • Jika fungsi inti baku dari sesuatu bisa direplikasi dengan terlalu mudah dan sepele, mungkin fungsi itu bukan inti atau sumber nilai yang sebenarnya
    Jadi penasaran berapa banyak bagian dari pengembangan UI sejak 1980-an yang sudah diserap dan diotomatisasi oleh rekayasa perangkat lunak, atau apakah itu masih wilayah seni manusia murni

    • Benar juga. Misalnya, nilai tambah utama Slack bukanlah “mengirim pesan antar pengguna yang terautentikasi”
      Bahkan sebelum Slack muncul dan menyingkirkan yang lain, sudah ada puluhan aplikasi—baik komersial maupun open source—yang melakukan hal itu
      Nilai utama Slack ada di langkah berikutnya. Slack menyediakan UI/UX yang enak dilihat dan sangat intuitif, sehingga hampir siapa pun bisa langsung duduk dan memakainya tanpa belajar, konfigurasi, manual, atau pelatihan. Tidak perlu pengetahuan teknis, dan tanpa perlu memahami apa pun selain “masukkan nama pengguna dan kata sandi”, sisanya terasa jelas dengan sendirinya
    • Sudut pandang yang sangat tajam. Kalau begitu, nilai Slack adalah kemudahan bagi pengguna, dan suc jelas bukan untuk pengguna umum
      Tapi lalu muncul pertanyaan yang lebih sulit. Dibandingkan alternatif untuk melatih pengguna lebih jauh agar bisa melakukan pemanggilan command line yang sangat dasar, apakah harga Slack memang sepadan? Bagaimana jika juga mempertimbangkan bahwa Slack menahan data dan tidak mengembalikannya? Seberapa mahal biaya untuk keluar dari Slack?
      Memang suc tidak nyaman, tetapi rasanya bisa saja mengerucut ke sesuatu yang kurang bengkak dan kurang tertutup dibanding Slack
  • Saya suka hasil akhirnya. Menarik melihat apa yang bisa dibuat dengan komposabilitas
    Hanya saja, membandingkannya dengan Slack dan sejenisnya terasa kurang kena. Tidak ada engineer yang ingin bertanggung jawab di production untuk sesuatu yang dirangkai begini dari sana-sini. Bagaimana rekrut talent-nya, bagaimana testing dan debugging-nya, bagaimana logging dan analytics-nya?
    Tulisan ini memang menyalin sebagian fungsi chat dari aplikasi ala Slack, tetapi fitur chat bukan 100% dari aplikasi seperti itu. Keduanya dibuat dalam lingkungan yang sepenuhnya berbeda, jadi menyerang keadaan saat ini sebagai sesuatu yang bengkak terasa seperti tafsiran yang dipelintir ala Stockton Rush. Memang ada kebengkakan dalam software, tetapi “Lihat, Bu, saya bikin kapal selam dari barang rongsokan. Jadi kapal selam mahal itu bodoh” tidak terdengar seperti bantahan yang sebenarnya dimaksud penulis

    • Intinya, kalau permukaan codebase mengecil, banyak dari hal-hal itu jadi kurang penting
      Utilitas individual biasanya lebih mudah dipahami, diuji, dan di-debug sebagai unit terpisah, logging juga sudah ada di sistem. Bukankah ada syslog? Dan kenapa analytics dibutuhkan?
    • Saat membaca saya juga melihatnya begitu. Rekayasa teknisnya hebat dan menyenangkan untuk dibaca, tetapi akan lebih jujur kalau dibandingkan bukan dengan Slack melainkan dengan IRC
      Meski begitu, saya benar-benar penasaran seperti apa jadinya jika alat seperti Slack secara agresif memprioritaskan kesederhanaan ketimbang fitur baru. Rasanya kapitalisme secara keseluruhan tidak mendorong pengembangan seperti ini, jadi tidak banyak contoh software enterprise yang sesederhana mungkin secara masuk akal. Tetap saja ini eksperimen pemikiran yang menarik
  • Mirip dengan itu, ada juga ii yang berjalan langsung di atas IRC: https://tools.suckless.org/ii/
    Ia memakai satu file standar untuk semua percakapan, autentikasi dan kontrol akses langsung ditangani jaringan IRC, dan UI-nya sudah banyak. Seperti pada tulisan ini, plugin bisa berupa apa saja yang membaca suatu file dan menulis ke file lain

  • Seperti diagram craigslist, akan seru kalau ada diagram spawn of unix yang mengumpulkan startup-startup yang memotong celah di antara fungsi-fungsi Unix
    https://thegongshow.tumblr.com/post/345941486/the-spawn-of-craigslist-like-most-vcs-that-focus
    ftp/rsync => Dropbox
    suc => Slack
    ...

  • Jika judulnya terlihat seperti clickbait sehingga Anda ingin melewatinya, memang ada sedikit unsur clickbait, tetapi sebenarnya ini tulisan yang cukup bagus
    Tulisan ini membahas utilitas suc (Simple Unix Chat), yang mengimplementasikan fungsi server seperti Slack atau Discord dengan basis kode yang sangat kecil
    Hal yang baru adalah ia memanfaatkan alat dan metodologi Unix yang sudah ada, alih-alih menciptakannya ulang. Autentikasi ditangani oleh SSH, channel hanyalah file biasa, dan kontrol admin/moderator ditangani dengan grup pengguna serta izin file. Hal seperti teks berformat atau unggah file juga bisa dilakukan dengan menulis data yang diinginkan ke channel lalu membiarkan klien menafsirkannya. Bot juga sangat mudah, cukup hubungkan pipe ke file channel
    Anda memang tidak bisa membuat klon Slack yang sempurna hanya dengan 5 baris untuk menulis pesan ke channel seperti di artikel itu, tetapi tetap sangat mengesankan seberapa jauh Anda bisa melangkah hanya dengan alat Unix yang benar-benar sederhana

    • Platform chat yang ada bukan “menciptakan ulang” alat Unix, melainkan tidak memakainya karena memang tidak cocok dibangun di atasnya
      Ada alasan mengapa hampir tidak ada sistem produksi besar yang ditulis dengan paradigma “everything is a file” dan shell script. Untuk sistem yang tidak sepele dan benar-benar akan dipakai di dunia nyata, pendekatan itu tidak bisa diterima
    • Bagi kebanyakan pengguna akhir, Slack adalah klien
      Di dalamnya ada UI admin, UI manajemen pengguna, skalabilitas, webhook, dan sebagainya. “Semua orang login ke kotak itu lalu bisa chat dengan pengguna lain di Linux” tidak menangani satu pun dari hal-hal ini. Semua fitur itu sudah ada di semua *nix jauh sebelum kebanyakan pembaca di sini lahir
    • Sepertinya append-only file akan sangat cocok di sini. Karena itu bisa menjamin pengguna biasa dan bot tidak dapat mengubah kiriman orang lain
      Sayangnya, fitur Plan 9 ini masih belum dipindahkan ke Linux. Ini semacam bit izin seperti “read” atau “write”, tetapi jauh lebih spesifik
    • “Memanfaatkan alat dan metodologi Unix yang ada” hampir selalu berarti “mengimplementasikan X dengan jumlah baris kode yang nyaris tak masuk akal sedikitnya”
      Bukan menyalahkan penulisnya, dan artikelnya sendiri juga sangat jujur tentang hal ini
  • Slack dan Discord punya berbagi layar dan chat suara. Ini bukan fitur tambahan, melainkan fitur yang cukup menentukan dalam dominasi pasar

    • Menentukan, tetapi rasanya kualitasnya makin menurun
  • Tulisan blog ini memang tentang suc dan sejak awal juga jujur mengakui bahwa judulnya bisa sedikit menyesatkan, tetapi pada akhirnya ada pesan penting yang tidak berhubungan langsung dengan suc
    Hampir semua perangkat lunak modern sangat bengkak. Gagasan bahwa server chat kaya fitur membutuhkan 1,7 juta baris terasa tidak masuk akal. Meminjam gaya Bill Gates, rasanya saya pun tidak akan bisa “menghabiskan” sebanyak itu baris kode hanya untuk server chat, sekeras apa pun saya berusaha
    Saya mengapresiasi bahwa tulisan ini bukan sekadar menyoroti masalah atau menawarkan alternatif, tetapi juga mengingatkan bahwa kita tidak perlu menciptakan ulang roda. Mengimplementasikan sesuatu dengan cerdik menggunakan sifat dari sistem dan subsistem yang ada, misalnya memakai SSH untuk autentikasi dan enkripsi, meskipun bukan untuk tujuan persis seperti yang mula-mula dibayangkan tetapi tetap sejalan dengan maksud dari sifat-sifat itu, adalah contoh bagus dari semangat hacker
    Saya berharap dunia perangkat lunak bisa banyak belajar dari konsep ini. Biaya yang lebih rendah, waktu pengembangan yang lebih singkat, dan berkurangnya waktu engineering yang terbuang untuk menulis ulang kode yang secara fungsional sama akan baik bagi developer, perusahaan, pengguna akhir, dan pada akhirnya umat manusia. Saya ingin melihat lebih banyak lagi penghancuran kreatif seperti ini ke depan, dan saya juga ingin mencoba menerapkan teknik cerdas seperti ini di proyek-proyek saya berikutnya

    • Sebagai catatan, sebagian besar baris kode TypeScript ada di tes E2E[0] dan direktori webapp[1]. Seperti terlihat dari namanya, webapp berisi “kode klien untuk aplikasi web Mattermost”
      Jadi sebenarnya lebih tepat menghitung hanya baris kode Go
      [0] https://github.com/mattermost/mattermost/tree/master/e2e-tests
      [1] https://github.com/mattermost/mattermost/tree/master/webapp
    • Saya pernah ada di rapat untuk memilih framework autentikasi web untuk dipakai di suatu situs, tetapi rapatnya terlalu panjang karena bikeshedding, jadi saat rapat masih berlangsung saya langsung mengimplementasikannya sendiri berbasis fitur autentikasi yang sudah disediakan HTTP, lalu bahkan sempat mendemokannya sebelum rapat selesai
    • Secara prinsip saya setuju, tetapi sebagian besar kebengkakan muncul karena mencoba mendukung banyak platform dengan satu basis kode
      Ini biasanya ide yang bagus karena mempercepat peluncuran dan mengurangi ukuran organisasi. Namun ada trade-off besar berupa kompleksitas dan abstraksi. Makin tinggi tingkat abstraksi, sering kali makin buruk hasilnya. Jadi bukan berarti tanpa alasan sama sekali
  • Saat ini, sebagian besar distribusi memblokir pembuatan skrip bash setuid demi alasan keamanan
    Namun, efek yang hampir sama bisa diperoleh dengan entri sudoers tertentu

    • Sebenarnya ini berlaku bukan hanya untuk bash, tetapi hampir semua skrip shebang, dengan pengecualian seperti skrip Perl. Perl otomatis mengaktifkan taint mode saat uid != euid
      https://perldoc.perl.org/perlsec#Taint-mode
      Di beberapa sistem mungkin ada race condition yang mendasar:
      https://perldoc.perl.org/perlsec#Shebang-Race-Condition
      Penggunaan sudo -T juga layak dilihat:
      https://perldoc.perl.org/perlsec#Using-Sudo
      Cukup disayangkan taint mode baru-baru ini dihapus dari Ruby. Pelacakan taint adalah mekanisme kuat yang bisa melampaui sekadar skrip. Misalnya, jika #html_safe di Rack/Rails ditangani dengan pelacakan taint, perilakunya bisa jauh lebih ketat: saat string pengguna yang terkontaminasi digabungkan/diinterpolasi/diformat ke dalam fragmen SQL, eksekusi bisa langsung gagal, sehingga satu kelas SQL injection dapat dicegah sejak level desain
      Dulu juga ada orang-orang yang menggunakan pelacakan taint dengan sangat efektif di CGI/mod_perl. Ini jelas bukan solusi ajaib untuk semuanya, tetapi tetap alat yang cukup efektif
    • Gunakan wrapper C yang memanggil skrip shell. Memang terlihat jelek dan skripnya perlu sedikit lebih diperkuat, tetapi ini berfungsi :)
      https://gitlab.com/edouardklein/suc/-/blob/master/suc_wrapper.c
    • Memangnya ada distribusi yang mengizinkan hal seperti itu? Saat saya coba cari tahu sendiri, semua yang saya baca mengatakan setuid tidak akan diterapkan. Karena yang dieksekusi bukan file itu sendiri, melainkan target yang tertulis di shebang
      Sebelum melihat file wrapper di repositori GitLab, saya membacanya sambil berharap memang ada caranya
  • Ini topik lain, tapi agak mengejutkan talk(1) tidak disebut: https://man.netbsd.org/talk.1

    • Atau ada juga write(2)[1]. Saya langsung teringat ntalk, karena terakhir kali saya memakai hal seperti itu adalah saat itu, pada mesin yang sama. Waktu itu IRC tidak terenkripsi
      Nilai plusnya adalah penerimaan bisa dibatasi hanya secara lokal, sehingga akun pengguna di mesin tersebut menjadi syarat. Karena itu, ini cocok untuk tempat seperti SDF atau klaster yang lebih besar. Autentikasi tidak perlu ditangani sendiri, cukup serahkan ke PAM atau BSD_Auth. Socket maupun enkripsi juga tidak perlu ditangani sendiri, cukup serahkan ke TLS. Anda juga bisa masuk ke shell aman lewat SSH lalu memakai tmux dan (n)talk
      Tentu saja, karena (n)talk ditulis dalam C, ini bukan 5 baris bash
      [1] https://man7.org/linux/man-pages/man2/write.2.html