Chat Unix simple
(the-dam.org)suces Simple Unix Chat, una implementación de algunas funciones clave de un chat estilo Slack o Mattermost usando componentes básicos de UNIX y Bash; el bucle central tiene 5 líneas, aunque el script real es más largo- Los mensajes se leen línea por línea desde la entrada estándar, se les agrega la fecha y el nombre de usuario, y luego se anexan al archivo del canal en
/var/lib/suc/; la autenticación y el control de permisos se delegan a SSH y al modelo de permisos de UNIX - A diferencia del servidor de Mattermost, que solo en código Go tiene alrededor de 500 mil líneas,
sucdestaca que puede lograr un comportamiento central similar con mucho menos código usuccombinatail -f,rlwrap,pygmentizey el prefijo de comando:para manejar la lectura de canales, la salida con estilo tipo Markdown y el intercambio de resultados de comandos- Como los canales son archivos de texto simples, se integran fácilmente con herramientas UNIX como
grep,tail,bat,lnav, hooks de Git y scripts de bots
La complejidad que suc busca reducir
sucsignifica Simple Unix Chat; tiene menos funciones que Slack, Mattermost o IRC, y su total de líneas supera las 5, pero el bucle central para escribir mensajes está compuesto por 5 líneas de Bash- Las funciones objetivo son chat en tiempo real con texto enriquecido, intercambio de archivos, control de acceso detallado, automatización e integración con herramientas externas, cifrado en tránsito, cifrado opcional del almacenamiento y autenticación de usuarios
- La implementación pequeña es posible porque aprovecha componentes básicos consistentes y combinables que ofrecen las implementaciones modernas de UNIX
- En contraste, el servidor de Mattermost tiene unas 500 mil líneas solo en Go, y
succonsidera que puede implementar las funciones centrales de Mattermost con el 0.005% de ese código
El bucle de 5 líneas para escribir mensajes
- El bucle principal en Bash de
suclee una línea desde la entrada estándar, le agrega la fecha y el nombre de usuario real, y luego la anexa al archivo/var/lib/suc/"$1" - El script real es más largo por el preprocesamiento de seguridad y el cálculo del color del nombre de usuario, pero la acción central de escribir el historial del chat se resume en tres pasos
- Leer una línea desde la entrada estándar
- Agregar la fecha y el nombre de usuario real
- Anexarla al archivo del canal bajo
/var/lib/suc/
- La autenticación, el control de acceso, el cifrado y el texto enriquecido no los maneja código interno de
suc, sino SSH, las API de control de acceso de UNIX y la modularidad basada en texto
La autenticación corre por cuenta de SSH
- El proceso
suclo ejecuta un usuario que ya fue autenticado, así quesucen sí no tiene código de autenticación - La autenticación remota la maneja
ssh, como en un servidor UNIX normal- Secretos compartidos, como contraseñas
- Desafíos criptográficos
- Dispositivos para generar contraseñas de un solo uso (OTP)
- MFA combinando varios métodos
sshtambién autentica al servidor ante el cliente para evitar ataques de intermediario y cifra todos los datos entre cliente y servidor- La instalación de
sucdepende del host UNIX y de la configuración del servidorssh- El usuario debe existir en el sistema
- El servidor
sshdebe permitir el inicio de sesión remoto de ese usuario
- En GNU Guix, con configuración declarativa se pueden agregar usuarios y claves SSH en una sola línea, y si esa línea desaparece, el usuario se elimina durante la reconfiguración
El control de acceso corre por cuenta del modelo de permisos de UNIX
sucno incluye código ni para autenticación ni para control de acceso, y a este enfoque lo llama agnosticismo de seguridad- El kernel de UNIX conoce usuarios, grupos, procesos y archivos, y decide los permisos de lectura y escritura de archivos según el propietario efectivo del proceso
- Los archivos de canal en
/var/lib/sucpertenecen al usuariosuc, y se configuran permisos de lectura por grupo para que los usuarios puedan leer ciertos canales - Los usuarios normales no escriben directamente en los archivos: ejecutan
suc, y el kernel se encarga de hacer coincidir o bloquear permisos - En comunidades más restrictivas se pueden usar binarios
setuidpor grupo- Por ejemplo,
suc_bluepertenece al usuariobluey solo lo puede ejecutar el grupoblue - Los usuarios del grupo
bluepueden escribir en el canalbluemediantesuc_blue - Los usuarios del grupo
redno pueden leer ni escribir en el canalblue
- Por ejemplo,
- El script auxiliar para crear canales
suc_channel.shtiene unas 80 líneas, y los usuarios de GNU Guix pueden crear el binariosetuid, el usuario, el grupo y el archivo del canal necesarios con una sola línea:(suc-private-channel "red" "red") - Las actualizaciones transaccionales de GNU Guix garantizan que un cambio de configuración se aplique por completo o no se aplique en absoluto, y permiten volver al estado anterior
Texto enriquecido y usuc
- Muchas apps de chat renderizan texto con motores HTML, y el cliente de escritorio de Mattermost usa Electron
sucusa un archivo de texto por canal, y los usuarios pueden verlo con herramientas de línea de comandos comotailocat- Aprovechando los códigos de escape ANSI y el soporte de UTF-8 del terminal, se puede crear una experiencia básica de texto enriquecido con colores y emojis
sucsolo escribe en el archivo del canal; la lectura la manejausucsuces un binario con privilegios, así que su lógica y sus dependencias externas deben mantenerse al mínimousucse ejecuta con los permisos del usuario que lo invoca, por lo que puede incorporar funciones con más libertad
usucune varias herramientas pequeñas para funcionar como cliente de chatrlwrapaporta historial y edición de línea- Selecciona el binario
succonsetuidapropiado según el propietario del archivo del canal - Usa
tail -f -n 20para mostrar las últimas 20 líneas y las que se agreguen después - Verifica si la línea de entrada empieza con
: - Procesa el texto ingresado por el usuario con
pygmentize
pygmentizetrata la entrada estándar como Markdown y genera texto ANSI con color, así que permite soportar marcado como**bold**con una sola línea de código
Comandos de chat e integración con el shell
- Si un mensaje en
usucempieza con:, no se envía como mensaje normal; en su lugar, se ejecuta ese comando y luego se envía su salida mediantesuc - Por ejemplo, si se ejecuta
gum style --border=rounded --bold --foreground=#F00 "Hello World !", en el canal aparecerá un texto con borde y estilo - Los comandos se ejecutan en el espacio de nombres del usuario que invocó
usuc, así que cada persona puede tener sus propias macros de chat sin afectar a los demás - En the dam se usa, por ejemplo, para lanzar dados en partidas de RPG de mesa con comandos como
roll 2d6
Pipes de texto e integración con herramientas externas
- En lugar de usar la función de ejecución de comandos de
usuc, el usuario puede hacer pipe directamente desde el shell haciasuccon la salida de un comando - Si se envía a
sucla salida con color debat, se pueden compartir fragmentos de código en el canal con resaltado de sintaxis make test > testlog || (suc devops < testlog ; exit 1)es un ejemplo de una sola línea en Bash que envía el log al canaldevopscuando fallan las pruebas- Esa línea puede ir dentro del hook
updatede un repositorio Git para ejecutar pruebas al hacer push, rechazar la actualización si fallan y avisar al equipo de DevOps - Tareas equivalentes a las integraciones de Slack o Mattermost pueden construirse con pipes de texto y scripts de UNIX
Lectura de canales, notificaciones y bots
- Como los canales de
sucson archivos de texto que se actualizan continuamente, se pueden leer y procesar líneas nuevas contail -f - Se puede construir un pipeline que muestre notificaciones con
notify-sendcuando llegue un mensaje nuevo, y usargreppara filtrar solo nombres o palabras clave como “build failure” - Para combinar varios canales en un solo feed se puede usar
tail -f /var/lib/suc/* - Con lnav se puede recordar la posición de lectura, usar marcadores, colores por canal, parsear fecha, nombre de usuario y campos personalizados, además de aplicar filtros y consultas SQL
- Un bot puede implementarse si puede leer y escribir en un canal al mismo tiempo
- El ejemplo busca expresiones de longitud como
33000 ften el canal - Las convierte a metros con el comando
units - Luego escribe en el mismo canal una respuesta como
[metric_bot] 33000 ft is 10058.4 meters.
- El ejemplo busca expresiones de longitud como
Comparaciones y conclusión
- Se mencionan como punto de comparación sistemas grandes como Slack, Mattermost o Discord, pero se considera que comparaciones más justas incluirían también IRC,
talkywrite - Se evalúa que IRC tiene menos funciones que
suc, ya que necesita un bouncer para leer historial de chat anterior - Se dice que no se logró hacer funcionar
talk,ytalkywallen distribuciones modernas de Linux sucdelega la autenticación a SSH, el control de acceso y la componibilidad a UNIX, y mantiene los canales como archivos de texto- Mientras una herramienta pueda leer y escribir texto, puede desarrollarse en cualquier lenguaje
1 comentarios
Opiniones de Hacker News
Inmediatamente me hizo pensar en “Master Foo and the Ten Thousand Lines”: http://catb.org/~esr/writings/unix-koans/ten-thousand.html
Es la historia en la que Master Foo le dice a un programador visitante que “una sola línea de script de shell contiene más naturaleza Unix que diez mil líneas de C”
Si la función central definida de algo se puede reproducir de forma demasiado fácil y trivial, entonces esa función podría no ser el núcleo ni la fuente real de su valor
Me hace preguntarme cuánto del desarrollo de UI desde los años 80 ha sido absorbido y automatizado por la ingeniería de software, o si todavía sigue siendo territorio del arte humano puro
Incluso antes de que apareciera Slack y desplazara a otras cosas, ya había docenas de apps, tanto comerciales como de código abierto, que hacían eso
El valor central de Slack está en el siguiente nivel. Ofrece una UI/UX visualmente atractiva y muy intuitiva, de modo que casi cualquiera puede sentarse y usarla de inmediato sin estudio, configuración, manuales ni capacitación. No hace falta conocimiento técnico y no necesitas entender nada más allá de “introduce tu nombre de usuario y contraseña”; el resto resulta evidente
Pero eso plantea una pregunta más difícil. Comparado con la alternativa de capacitar un poco más a usuarios que ya saben hacer una invocación muy básica de línea de comandos, ¿vale lo que cuesta Slack? ¿Y qué pasa si además consideras que Slack retiene los datos y no te los devuelve? ¿Qué tan caro es salir de Slack?
Es cierto que suc es incómodo, pero parece posible converger hacia algo menos voluminoso y menos propietario que Slack
Me gusta el logro en sí. Es genial ver lo que se puede hacer con la composabilidad
Dicho eso, la comparación con Slack y similares no me convence mucho. Ningún ingeniero querría hacerse responsable en producción de algo armado así a base de unir piezas. ¿Cómo harías la contratación de talento, las pruebas y la depuración, y los logs y la analítica?
Este artículo replica parte de la funcionalidad de chat de apps tipo Slack, pero la función de chat no es el 100% de estas apps. Son cosas construidas en contextos completamente distintos, así que atacar el estado actual por voluminoso parece una interpretación retorcida al estilo Stockton Rush. Claro que existe software inflado, pero “mamá, mira, hice un submarino con cachivaches; por lo tanto, los submarinos caros son tontos” no suena como la refutación que el autor pretendía
Las utilidades individuales suelen ser fáciles de entender, probar y depurar por separado, y el logging ya viene integrado en el sistema. ¿Acaso no existe syslog? Y además, ¿por qué haría falta la analítica?
Aun así, sí me da mucha curiosidad cómo se vería una herramienta tipo Slack si priorizara agresivamente la simplicidad por encima de las funciones nuevas. Parece que el capitalismo en su conjunto no fomenta este tipo de desarrollo, así que no hay muchos ejemplos de software empresarial tan simple como razonablemente podría ser. De todos modos, es un experimento mental interesante
De forma parecida, también existe ii, que funciona directamente sobre IRC: https://tools.suckless.org/ii/
Usa un único archivo estándar para todas las conversaciones, y la autenticación y el control de acceso los gestiona directamente la red IRC, además de que ya existen muchas UI. Igual que en este artículo, un plugin puede ser cualquier cosa que lea ciertos archivos y escriba en otros
Como el diagrama de craigslist, sería divertido hacer un diagrama de spawn of unix reuniendo startups que recortan nichos de funcionalidad de Unix
https://thegongshow.tumblr.com/post/345941486/the-spawn-of-craigslist-like-most-vcs-that-focus
ftp/rsync => Dropbox
suc => Slack
...
Si ibas a saltártelo porque el título parece clickbait, sí tiene algo de eso, pero en realidad fue un artículo bastante bueno
Trata sobre una utilidad llamada “suc” (Simple Unix Chat), que implementa funciones de servidor como las de Slack o Discord con una base de código diminuta
Lo novedoso es que aprovecha herramientas y metodologías Unix existentes en lugar de reinventarlas. SSH se encarga de la autenticación, los canales son simplemente archivos, y el control de administradores/moderadores se maneja con grupos de usuarios y permisos de archivos. Cosas como texto con formato o subida de archivos se pueden resolver escribiendo los datos que quieras en el canal y dejando que el cliente los interprete. Los bots también son facilísimos si conectas un pipe al archivo del canal
Con solo las 5 líneas para escribir mensajes al canal que salen en el artículo no vas a crear un clon perfecto de Slack, pero impresiona bastante hasta dónde se puede llegar con herramientas Unix realmente simples
Hay una razón por la que casi no existen sistemas de producción grandes escritos con el paradigma de “todo es un archivo” y scripts de shell. Para sistemas no triviales que realmente se usarían en el mundo real, ese enfoque es inaceptable
Incluye UI de administración, UI de gestión de usuarios, extensibilidad, webhooks, etc. Decir “si todos inician sesión en esa máquina pueden chatear con otros usuarios en Linux” no resuelve nada de eso. Todas las variantes de *nix ya tenían eso desde antes de que naciera la mayoría de los lectores de aquí
Lamentablemente, esta función de Plan 9 todavía no se ha portado a Linux. Son bits de permisos parecidos a “lectura” o “escritura”, pero mucho más específicos
No culpo al autor, y de hecho el artículo lo reconoce con bastante honestidad
Slack y Discord tienen compartir pantalla y chat de voz. Eso no son extras, sino funciones bastante decisivas para su dominio del mercado
Aunque el post del blog trata sobre suc y desde el inicio reconoce con honestidad que el título puede llevar un poco a confusión, al final deja un mensaje importante que no tiene relación directa con suc
Casi todo el software moderno está horriblemente inflado. La idea de que un servidor de chat completo necesite 1.7 millones de líneas es absurda. Parafraseando a Bill Gates, siento que ni esforzándome podría “gastar” tantas líneas de código en un servidor de chat
No solo por poner el problema sobre la mesa o proponer una alternativa, sino también por recordar que no hace falta reinventar la rueda, merece aplausos. Implementar de forma ingeniosa aprovechando propiedades de sistemas y subsistemas existentes —por ejemplo, usar SSH para autenticación y cifrado— aunque sea para fines distintos de los imaginados originalmente, pero respetando la intención de esas propiedades, es un muy buen ejemplo del espíritu hacker
Ojalá el mundo del software pudiera aprender mucho más de esta idea. Menores costos, tiempos de desarrollo más cortos y menos horas de ingeniería desperdiciadas reescribiendo código funcionalmente equivalente benefician a desarrolladores, empresas, usuarios finales y, en última instancia, a toda la humanidad. Me gustaría ver más destrucción creativa de este tipo, y también probar técnicas así de ingeniosas en proyectos futuros
Así que en realidad lo correcto sería contar solo las líneas de código Go
[0] https://github.com/mattermost/mattermost/tree/master/e2e-tests
[1] https://github.com/mattermost/mattermost/tree/master/webapp
Eso normalmente es una buena idea porque acelera la salida al mercado y reduce el tamaño de la organización. Pero implica un gran trade-off de complejidad y abstracción. Cuanto mayor es el nivel de abstracción, peor puede ponerse. Así que tampoco es que no haya ninguna razón
Actualmente, la mayoría de las distribuciones impiden crear scripts bash setuid por razones de seguridad.
Pero con una entrada específica en sudoers se puede lograr casi el mismo efecto.
https://perldoc.perl.org/perlsec#Taint-mode
Algunos sistemas pueden tener una condición de carrera fundamental:
https://perldoc.perl.org/perlsec#Shebang-Race-Condition
También vale la pena ver el uso de
sudo -T:https://perldoc.perl.org/perlsec#Using-Sudo
Da pena que en Ruby hayan eliminado recientemente el modo taint. El seguimiento de contaminación es un mecanismo potente que puede ir mucho más allá de los scripts. Por ejemplo, si en Rack/Rails
#html_safese hubiera manejado con seguimiento de contaminación, habría funcionado de forma más rigurosa y podría haber hecho fallar en el momento en que una cadena de usuario contaminada se concatenara/interpolara/formateara dentro de un fragmento SQL, bloqueando por diseño una clase de inyección SQL.Antes también había gente que usaba el seguimiento de contaminación con mucha eficacia en CGI/mod_perl. No es una solución mágica ni de lejos, pero sigue siendo una herramienta bastante efectiva.
https://gitlab.com/edouardklein/suc/-/blob/master/suc_wrapper.c
Hasta ver el archivo wrapper en el repositorio de GitLab, mientras leía esperaba que hubiera alguna forma de hacerlo.
Esto ya es otro tema, pero me sorprende que no se haya mencionado talk(1): https://man.netbsd.org/talk.1
Lo bueno es que se puede hacer que solo reciba localmente, y entonces hace falta una cuenta de usuario en esa máquina. Por eso encaja bien en lugares como SDF o en clústeres más grandes. La autenticación no hace falta implementarla uno mismo: se la puedes dejar a PAM o BSD_Auth. Tampoco hace falta encargarse uno mismo de los sockets ni del cifrado: se lo puedes dejar a TLS. También se puede entrar a un shell seguro por SSH y luego usar tmux y (n)talk.
Claro, (n)talk está escrito en C, así que no son 5 líneas de bash.
[1] https://man7.org/linux/man-pages/man2/write.2.html