Débogage des problèmes de connexion / authentification VerneMQ pour la double authentification avec webhooks et vmq_diversity

TL;DR

https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl

comprend une déclaration qui bloquera l'authentification/autorisation par le biais de tout autre canal si votre script Lua renvoie "false" :

image

conduira à :

image

au lieu d'essayer d'autres plugins, comme vous auriez pu le supposer !

Afin d'éviter ce problème, il suffit de ne rendez rien de votre script Lua, si vous ne voulez pas traiter le message !

image

Débogage

VerneMQ a un outil de traçage intégré, qui vous aidera à voir quels problèmes peuvent survenir. Tout d'abord, affichez les sessions, afin de savoir avec quelles données vos clients essaient de se connecter :

vmq-admin session show

image

Puis lancez une trace :

vmq-admin trace client client-id=000000007eaefc47 -mountpoint=5c61a59ba6b76f558d256f42

Notez que le point de montage par défaut est "" (le point de montage par défaut pour Verne) - si vous ne définissez pas un point de montage personnalisé sur les auditeurs ( comme moi), alors vous pouvez omettre ceci.

image

Initialement, vmq-admin trace signalera qu'aucune session n'est trouvée pour ce client - si votre client n'est pas actuellement connecté.

Connectez votre client, et il y aura plus de résultats.

Il est également utile d'augmenter le niveau de verbosité dans le logger pour le déboguer (pour vernemq.conf) :

log.console.level = debug

image

econnus

Dans mon cas particulier, mon point de terminaison webhook n'était pas en cours d'exécution. Après l'avoir démarré, j'obtiens maintenant (plusieurs tentatives avec des résultats similaires) :

image

Comme vous pouvez le voir, le client est maintenant authentifié, mais n'est pas autorisé à publier. Le client est alors déconnecté (conformément à la spécification MQTT 3.1.1).

Et voici la sortie du journal :

image

Ce qui se passe ici, c'est que le client est authentifié à l'aide d'un webhook, puis il essaie d'être autorisé à l'aide d'un script Lua (autorisation MongoDB).

Je ne sais pas pourquoi auth_on_publish pour le client n'est pas appelé en utilisant un webhook également. Dans tous les cas, ce client est censé être pleinement authentifié par MongoDB.

Je ne vois également que des demandes de registre d'authentification :

image

Pour montrer quels webhooks sont enregistrés, vous pouvez exécuter

vmq-admin webhooks show

image

voir : https://docs.vernemq.com/plugindevelopment/webhookplugins

Tous les webhooks sont appelés avec la méthode POST, et doivent recevoir une réponse avec le code HTTP 200 pour être considérés comme réussis.

Une demande pour le serveur webhook

Voici à quoi ressemblera une requête pour le serveur Webhook :

image

sont passés, avec l'en-tête vernemq-hook réglé sur auth_on_register dans ce cas.

Le corps du message comprendra différentes informations sur le client qui tente de se connecter.

Après avoir utilisé "next" comme réponse du webhook, la publication fonctionne correctement - le client est authentifié par rapport à MongoDB, et ensuite la publication est autorisée, comme souhaité.

Voici à quoi devrait ressembler la réponse du webhook pour transmettre l'authentification au plugin suivant :

{"résultat" : "suivant"}

Et voici à quoi ressemble la trace maintenant :

image

En bas, vous pouvez voir les keepalives pour le client (PINGREQ, PINGRESP).

Donc, un client fonctionne maintenant. On passe au client suivant - qui devrait être authentifié et autorisé en utilisant les webhooks !

Client Webhook

image

Comme vous pouvez le voir, le script Lua de MongoDB réécrit le point de montage de "piclient" à un autre point de montage.

En fait, j'utilise le point de montage sur les écouteurs pour indiquer quelle méthode d'authentification doit être utilisée pour ce client.

Dans la version 2 de VerneMQ, on nous promet qu'il y aura une séparation des Plugins par Listener - donc nous pouvons éviter ces vérifications qui ajoutent de la surcharge à chaque connexion.

image

apparemment, une seule trace peut être exécutée à la fois. J'essaie à nouveau après avoir fermé l'autre trace :

vmq-admin trace client client-id=my_clientid -mountpoint=jsclient

image

image

image

Veuillez noter que le message auth_on_publish debug est imprimé par une instruction supplémentaire que j'ai insérée dans le script Lua :

image

dans auth_commons.lua

Comprendre ce qui doit être renvoyé par le script Lua

Ce que nous voulons, c'est probablement retourner du script Lua que le prochain hook doit être appelé.

"Dans le cas où le plugin ne peut pas valider le message de publication, il est préférable de renvoyer suivant car cela permettrait aux plugins suivants dans la chaîne de valider la demande."

(voir https://docs.vernemq.com/plugindevelopment/publishflow )

J'ai supposé que le retour faux impliquerait cela, mais apparemment non ?

Regardons dans la source Erlang de vernemq

https://github.com/vernemq/vernemq

C'est une suite de tests pour le auth_cache de vmq_diversity (où se trouvent les scripts Lua) :

https://github.com/vernemq/vernemq/blob/c8b92f398e76d6ce4b8cca5e438e8ae1e717d71c/apps/vmq_diversity/test/vmq_diversity_auth_cache_SUITE.erl

image

vmq-admin trace client client-id=my_clientid -mountpoint=jsclient

image

Ajout d'un débogage supplémentaire pour le message en Lua :

fonction auth_on_publish(pub)
     print("***auth_on_publish debug*** (LUA)")
     pour k,v dans paires(pub) faire
         print(k .. " " .. v)
     fin
     print(pub)
     retournez à la case départ
fin

image

Notez que le code semble être défectueux (les faux ne peuvent apparemment pas être concaténés en utilisant .. en Lua - OK.)

Quoi qu'il en soit, dans le tableau Lua, qui est transmis en tant que "pub", nous avons les paramètres suivants :

  • client_id
  • point de montage
  • charge utile
  • qos

maintenant nous pourrions vérifier si le point de montage est "jsclient" (qui devrait être authentifié en utilisant les webhooks), et pour l'instant forcer true :

fonction auth_on_publish(pub)
     print("***auth_on_publish debug*** (LUA)")
     si pub["mountpoint"] == "jsclient" alors
         retourner vrai
     sinon
         retournez à la case départ
     fin
fin

Voici à quoi ressemble une trace pour cette condition artificielle :

image

Retour à Erlang

https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl

image

lorsque auth_on_publish est appelé pour le vmq_diversity_plugin.erl la valeur du résultat sera obtenue comme ceci :

  • si vmq_diversity_cache:match_publish_acl renvoie vrai, ce sera "ok".
  • si elle renvoie false, elle lancera une erreur
  • si elle retourne no_cache, le résultat dépendra de la fonction all_till_ok (appelée avec auth_on_publish).

Comme vous pouvez le voir, voici les valeurs transmises à notre script Lua, y compris le point de montage.

conv_res modifiera le résultat retourné :

image

Si vous n'êtes pas familier avec Erlang, je vous recommande vivement de lire mon article précédent, https://pi3g.com/2019/05/12/understanding-erlang-lua-luerl-for-vernemq-mongodb-auth_on_register-hook/

En gros, si {error, lua_script_returned_false} ne correspond pas aux résultats, pour tout nom (_) et tout autre, le résultat sera Autre - en passant simplement les résultats de all_till_ok à la fonction appelante.

Pour le nom lua_script_returned_falsel'erreur sera not_authorized.

Je ne suis pas tout à fait sûr que ce vmq_plugin_helper.erl soit l'endroit où se trouve la logique de contrôle principale (du passage au suivant) :

image

dans tous les cas, on s'attend probablement à ce que "next" soit retourné.

Ici, dans vmq_diversity_plugin.erl all_till_ok est défini :

https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl

image

Comme vous pouvez le voir, si le script renvoie "true", la valeur de retour est fixée à "ok".

Si "false" est renvoyé par le script, l'erreur mentionnée précédemment est renvoyée, et l'exécution s'arrête -> non autorisé.

image

Cela signifie que si vous renvoyez false dans les scripts Lua, aucun autre plugin ne sera appelé !

des modificateurs peuvent également être renvoyés.

L'astuce est de ne rien rendre, dans le cas où vous ne voulez pas traiter la demande :

fonction auth_on_publish(pub)
     print("***auth_on_publish debug*** (LUA)")
     si pub["mountpoint"] == "jsclient" alors
         print("*** jsclient detected ***")
         print("ne renvoie rien")
         - retourner vrai
    sinon
         print("+++ autre client détecté +++")
         retournez à la case départ
     fin
fin

Notez que - (deux tirets) est un commentaire en Lua.

image

Dans ce cas, le hook auth_on_publish est appelé à l'aide de webhooks :

image

image

image

Bonus

Erreur de génération de la configuration avec la seiche :

Cela peut être débogué davantage en définissant la commande dans docker-compose.yml comme :

commande : "vernemq config generate -l debug /vernemq/etc/vernemq.conf.local"

et faire apparaître le conteneur (notez que j'ai créé un fichier .local, de sorte que certains paramètres ne sont plus écrasés).

Le message d'erreur que je reçois est le suivant :

jalpine_morpheus | escript : exception error : no function clause matching
jalpine_morpheus | lists:unzip([[ws,ws],
jalpine_morpheus | {["log", "console", "file"], "./log/console.log"},

apparemment, cela est lié au fait que les seiches s'étouffent avec des lignes qui ne contiennent qu'un espace :

https://github.com/basho/cuttlefish/issues/222

en appuyant sur Alt + P dans nano activera l'affichage des espaces - ce qui est utile pour déboguer ce problème particulier.

La section problématique dans ma configuration ressemble à ceci :

image

ici il y a deux onglets ( ?) là où il ne devrait rien y avoir.

La suppression de la ligne problématique permettra à VerneMQ de redémarrer.

Autres lectures

Cela pourrait également être utile :

http://www.steves-internet-guide.com/mqtt-protocol-messages-overview/

Changelog de VerneMQ :

https://github.com/vernemq/vernemq/blob/fe514561cbeebb2ac4f7c98a87c64d766587c1d7/changelog.md

NB : dans la version 1.8, un nouveau plugin intéressant est le plugin vmq_pulse, qui va pousser les informations du cluster vers un backend pulse via HTTP(S).

https://github.com/vernemq/vernemq/blob/c8b92f398e76d6ce4b8cca5e438e8ae1e717d71c/apps/vmq_diversity/test/cache_test.lua

Présentation de quelques scripts Lua supplémentaires pour la diversité VerneMQ.