Depuración de problemas de conexión / autenticación de VerneMQ para la autenticación dual con webhooks y vmq_diversity
TL;DR
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
incluye una declaración que bloqueará la autenticación / autorización a través de cualquier otro canal si su script Lua devuelve "false":
llevará a:
en lugar de probar otros plugins, como podría haber supuesto.
Para evitar este problema, basta con no devuelva nada ¡de su script Lua, si no quiere manejar el mensaje!
Depuración
VerneMQ tiene una herramienta de rastreo incorporada, que le ayudará a ver qué problemas pueden ocurrir. En primer lugar, visualiza las sesiones, para saber con qué datos intentan conectarse tus clientes:
vmq-admin session show
Entonces, ejecuta un rastreo:
vmq-admin trace client client-id=000000007eaefc47 -mountpoint=5c61a59ba6b76f558d256f42
Tenga en cuenta que el punto de montaje por defecto es "" (el punto de montaje por defecto para Verne) - si no está configurando un punto de montaje personalizado en las escuchas (como yo), entonces puede omitir esto.
Inicialmente vmq-admin trace reportará que no se encuentran sesiones para este cliente - si su cliente no está conectado actualmente.
Conecte su cliente y habrá más salida.
También es útil aumentar el nivel de verbosidad en el registrador para depurar (para vernemq.conf):
log.console.level = debug
econnrefused
En mi caso particular, mi punto final de webhook no se estaba ejecutando. Después de ponerlo en marcha, ahora obtengo (múltiples intentos con una salida similar):
Como puede ver, el cliente está siendo autenticado, pero no está autorizado a publicar. El cliente se desconecta entonces (según la especificación MQTT 3.1.1).
Y esta es la salida del registro:
Lo que ocurre aquí, es que el cliente se autentifica mediante un webhook, y luego intenta autorizarse mediante un script Lua (autorización de MongoDB).
No estoy seguro de por qué auth_on_publish para el cliente no se llama usando un webhook también. Este cliente, en cualquier caso, se supone que debe ser autenticado completamente usando MongoDB.
También veo sólo solicitudes de registro de autenticidad:
Para mostrar qué webhooks están registrados, puede ejecutar
vmq-admin webhooks show
ver: https://docs.vernemq.com/plugindevelopment/webhookplugins
Todos los webhooks son llamados con el método POST, y necesitan ser respondidos con el código HTTP 200 para ser considerados exitosos.
Una solicitud para el servidor de webhooks
Este es el aspecto de una solicitud para el servidor Webhook:
se pasan las cabeceras, con la cabecera vernemq-hook establecida en auth_on_register en este caso.
El cuerpo del mensaje incluirá diferente información sobre el cliente que intenta conectarse.
Después de usar "next" como respuesta del webhook, la publicación funciona correctamente - el cliente se autentifica contra el MongoDB, y después la publicación se autoriza, como se desea.
Así es como debería ser la respuesta del webhook para pasar la autenticación al siguiente plugin:
{"resultado": "siguiente"}
Y así es como se ve el rastro ahora:
En la parte inferior puedes ver los keepalives para el cliente (PINGREQ, PINGRESP).
Así que, un cliente está trabajando ahora. A continuación, el siguiente cliente, que debería estar autenticado y autorizado mediante webhooks.
Cliente Webhook
Como puedes ver, por cierto, el punto de montaje se reescribe de "piclient" a un punto de montaje diferente por el script Lua de MongoDB.
Básicamente estoy usando el punto de montaje en las escuchas para indicar qué método de autenticación se debe utilizar para este cliente.
En la versión 2 de VerneMQ, nos han prometido, habrá una separación de Plugins por Listener - por lo tanto podemos evitar estas comprobaciones que añaden sobrecarga a cada conexión.
aparentemente sólo se puede ejecutar una traza a la vez. Intentando de nuevo después de cerrar la otra traza:
vmq-admin trace client client-id=my_clientid -mountpoint=jsclient
Tenga en cuenta que el mensaje auth_on_publish debug es impreso por una declaración adicional que inserté en el script Lua:
en auth_commons.lua
Comprender lo que debe devolver el script Lua
Lo que queremos es, probablemente, que el script Lua devuelva que el siguiente gancho debe ser llamado.
"En caso de que el plugin no pueda validar el mensaje de publicación es mejor devolver siguiente
ya que esto permitiría a los siguientes plugins de la cadena validar la solicitud".
(ver https://docs.vernemq.com/plugindevelopment/publishflow )
Supuse que devolver falso implicaría eso, pero aparentemente no?
Busquemos en el código fuente Erlang de vernemq
https://github.com/vernemq/vernemq
Este es un conjunto de pruebas para el auth_cache de vmq_diversity (donde viven los scripts de Lua):
vmq-admin trace client client-id=my_clientid -mountpoint=jsclient
Añadiendo algo de depuración adicional para el mensaje en Lua:
function auth_on_publish(pub)
print("***auth_on_publish debug*** (LUA)")
para k,v en pares(pub) hacer
print(k .. " " .. v)
fin
print(pub)
devolver falso
fin
Obsérvese que el código parece ser defectuoso (aparentemente no se puede concatenar falsos usando .. en Lua - OK.)
En cualquier caso, en la tabla Lua, que se pasa como "pub", tenemos los siguientes parámetros:
- client_id
- punto de montaje
- carga útil
- qos
ahora podríamos comprobar si el punto de montaje es "jsclient" (que debería ser autentificado usando webhooks), y por ahora forzar true:
function auth_on_publish(pub)
print("***auth_on_publish debug*** (LUA)")
si pub["mountpoint"] == "jsclient" entonces
devolver true
si no
devolver falso
fin
fin
Este es el aspecto de un rastro para esta condición artificial:
Volver a Erlang
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
cuando se llame a auth_on_publish para el vmq_diversity_plugin.erl el valor del resultado se obtendrá así:
- si vmq_diversity_cache:match_publish_acl devuelve true, será "ok".
- si devuelve false, lanzará un error
- si devuelve no_cache, el resultado dependerá de la función all_till_ok (llamada con auth_on_publish)
como puedes ver aquí están los valores pasados a nuestro script Lua, incluyendo el punto de montaje
conv_res modificará el resultado devuelto:
Le recomiendo encarecidamente que si no está familiarizado con Erlang lea mi artículo anterior, https://pi3g.com/2019/05/12/understanding-erlang-lua-luerl-for-vernemq-mongodb-auth_on_register-hook/
Básicamente, si {error, lua_script_returned_false} no coincide dentro de los resultados, para cualquier nombre (_) y cualquier Otro, el resultado será Otro - simplemente pasando los resultados de all_till_ok a la función que llama.
Para el nombre lua_script_returned_falseel error será not_authorized.
No estoy del todo seguro si este vmq_plugin_helper.erl es donde está la lógica principal de control (de pasar a lo siguiente):
en cualquier caso, probablemente se espera que se devuelva "next".
Aquí, en vmq_diversity_plugin.erl se define all_till_ok:
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
Como puede ver, si el script devuelve "true", el valor de retorno se establece en "ok".
Si se devuelve "false" del script, se devuelve el error mencionado anteriormente, y se detiene la ejecución -> no autorizada.
Esto significa que si devuelve false en los scripts Lua, ¡no se llamará a ningún otro plugin!
alternativamente se pueden devolver los modificadores.
El truco es para no devolver nada, en caso de que no quiera gestionar la solicitud:
function auth_on_publish(pub)
print("***auth_on_publish debug*** (LUA)")
si pub["mountpoint"] == "jsclient" entonces
print("*** jsclient detectado ***")
print("no devuelve nada")
- devolver true
si no
print("+++ otro cliente detectado +++")
devolver falso
fin
fin
Tenga en cuenta que - (dos guiones) es un comentario en Lua.
En este caso, el gancho auth_on_publish se llama utilizando webhooks:
Bono
Error al generar la configuración con la sepia:
Esto puede ser depurado aún más estableciendo el comando en docker-compose.yml a:
comando: "vernemq config generate -l debug /vernemq/etc/vernemq.conf.local"
y haciendo aparecer el contenedor (nótese que he creado un archivo .local, por lo que ciertas configuraciones ya no se sobrescriben).
El mensaje de error que recibo es:
jalpine_morpheus | escript: error de excepción: no coincide la cláusula de la función
jalpine_morpheus | lists:unzip([[ws,ws],
jalpine_morpheus | {["log", "console", "file"],"./log/console.log"},
Al parecer, esto está relacionado con la asfixia de la sepia en las líneas que sólo contienen un espacio:
https://github.com/basho/cuttlefish/issues/222
presionando Alt + P en nano habilitará la visualización de espacios en blanco - bueno para depurar este problema en particular.
La sección problemática en mi configuración se ve así:
aquí hay dos pestañas (?) donde no debería haber nada.
Eliminar la línea problemática permitirá que VerneMQ se inicie de nuevo.
Más información
Esto también puede ser útil:
http://www.steves-internet-guide.com/mqtt-protocol-messages-overview/
Registro de cambios de VerneMQ:
https://github.com/vernemq/vernemq/blob/fe514561cbeebb2ac4f7c98a87c64d766587c1d7/changelog.md
NB: en la versión 1.8 un nuevo e interesante plugin es el vmq_pulse, que enviará la información del cluster a un backend de pulsos vía HTTP(S).
Mostrando algunos scripts Lua adicionales para la diversidad de VerneMQ.