Debuggen van VerneMQ connectie / authenticatie problemen voor dubbele authenticatie met webhooks en vmq_diversity

TL;DR

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

bevat een verklaring die authenticatie / autorisatie via andere kanalen zal blokkeren als je Lua script "false" retourneert:

afbeelding

zal leiden tot:

afbeelding

in plaats van andere plugins te proberen, zoals je misschien verondersteld had!

Om dit probleem te vermijden, volstaat het niets teruggeven uit je Lua script, als je het bericht niet wilt afhandelen!

afbeelding

Debuggen

VerneMQ heeft een ingebouwd traceer-gereedschap, waarmee je kunt zien welke problemen zich kunnen voordoen. Laat eerst de sessies zien, om uit te vinden met welke gegevens je clients proberen te verbinden:

vmq-admin sessie tonen

afbeelding

Dan een opsporing:

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

Merk op dat het mount-punt standaard op "" staat (het standaard mount-punt voor Verne) - als u geen aangepast mount-punt op de luisteraars instelt (zoals ik), dan kunt u dit weglaten.

afbeelding

Initieel zal vmq-admin trace melden dat er geen sessies gevonden zijn voor deze client - als je client momenteel niet verbonden is.

Verbind uw cliënt, en er zal meer output zijn.

Het is ook nuttig om het verbosity level in de logger te verhogen naar debug (voor vernemq.conf):

log.console.level = debug

afbeelding

econnrefused

In mijn specifieke geval, draaide mijn webhook endpoint niet. Na het opstarten, krijg ik nu (meerdere pogingen met vergelijkbare output):

afbeelding

Zoals je kunt zien, wordt de client nu wel geauthenticeerd, maar niet gemachtigd om te publiceren. De verbinding met de client wordt vervolgens verbroken (volgens de MQTT 3.1.1 spec).

En dit is de log output:

afbeelding

wat hier gebeurt, is dat de client is geauthenticeerd met behulp van een webhook, en dan probeert te worden geautoriseerd met behulp van een Lua script ( MongoDB autorisatie).

Ik ben niet zeker waarom auth_on_publish voor de client niet wordt aangeroepen met behulp van een webhook ook. Deze client in ieder geval wordt verondersteld volledig te worden geauthenticeerd met behulp van MongoDB.

Ik zie ook alleen maar aanvragen voor auth-on register:

afbeelding

Om te laten zien welke webhooks geregistreerd zijn, kunt u

vmq-admin webhooks show

afbeelding

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

Alle webhooks worden aangeroepen met de methode POST, en moeten worden beantwoord met de HTTP-code 200 om als succesvol te worden beschouwd.

Een verzoek voor de webhook server

Hier is hoe een verzoek eruit zal zien voor de Webhook server:

afbeelding

headers worden doorgegeven, met de header vernemq-hook ingesteld op auth_on_register in dit geval.

Het bericht zal verschillende informatie bevatten over de client die probeert te verbinden.

Na het gebruik van "volgende" als een antwoord van de webhook, de publicatie werkt correct - de client is geverifieerd tegen de MongoDB, en daarna de publicatie is geautoriseerd, zoals gewenst.

Hier is hoe het antwoord van de webhook eruit moet zien om de authenticatie door te geven aan de volgende plugin:

{"resultaat": "volgende"}

En hier is hoe het spoor er nu uitziet:

afbeelding

Onderaan zie je de keepalives voor de client (PINGREQ, PINGRESP).

Dus, één client werkt nu. Op naar de volgende client - die moet worden geauthenticeerd en geautoriseerd met behulp van webhooks!

Webhook cliënt

afbeelding

Zoals je kunt zien, wordt het mountpoint trouwens herschreven van "piclient" naar een ander mountpoint door het MongoDB Lua script.

In principe gebruik ik het mountpoint op de listeners om aan te geven welke authenticatie methode gebruikt moet worden voor deze client.

In versie 2 van VerneMQ, zo is ons beloofd, zal er een scheiding zijn van Plugins per Listener - daardoor kunnen we deze controles vermijden die overhead toevoegen aan elke verbinding.

afbeelding

Blijkbaar kan er maar één spoor tegelijk lopen. Ik probeer het opnieuw nadat ik het andere spoor heb uitgezet:

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

afbeelding

afbeelding

afbeelding

Merk op dat het bericht auth_on_publish debug wordt afgedrukt door een extra statement dat ik in het Lua script heb ingevoegd:

afbeelding

in auth_commons.lua

Begrijpen wat er terug moet komen van het Lua script

Wat we willen is waarschijnlijk dat het Lua script teruggeeft dat de volgende hook moet worden aangeroepen.

"In het geval dat de plugin het publiceer bericht niet kan valideren is het het beste om te retourneren volgende omdat dit volgende plugins in de keten in staat zou stellen het verzoek te valideren."

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

Ik nam aan dat het terugsturen vals dat zou impliceren, maar blijkbaar niet?

Laten we eens kijken in de Erlang broncode van vernemq

https://github.com/vernemq/vernemq

Dit is een testsuite voor de auth_cache voor vmq_diversity (waar de Lua scripts staan):

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

afbeelding

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

afbeelding

Ik voeg wat extra debugging toe voor het bericht in Lua:

functie auth_on_publish(pub)
     print("***auth_on_publish debug*** (LUA)")
     voor k,v in paren(pub) doe
         print(k .. " " .. v)
     einde
     print(pub)
     terugzenden
einde

afbeelding

Merk op dat de code fout lijkt te zijn (false kan blijkbaar niet aaneengeschakeld worden met .. in Lua - OK.)

In ieder geval hebben we in de Lua tabel, die wordt doorgegeven als "pub", de volgende parameters:

  • cliënt_id
  • koppelpunt
  • laadvermogen
  • qos

nu kunnen we controleren of het mountpoint "jsclient" is (die geauthenticeerd zou moeten worden met webhooks), en voor nu force true:

functie auth_on_publish(pub)
     print("***auth_on_publish debug*** (LUA)")
     als pub["mountpoint"] == "jsclient" dan
         waar teruggeven
     anders
         terugzenden
     einde
einde

Hier is hoe een spoor eruit ziet voor deze kunstmatige toestand:

afbeelding

Terug naar Erlang

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

afbeelding

wanneer auth_on_publish wordt aangeroepen voor de vmq_diversity_plugin.erl zal de resultaatwaarde als volgt worden verkregen:

  • Als vmq_diversity_cache:match_publish_acl true teruggeeft, zal het "ok" zijn.
  • als het vals teruggeeft, zal het een fout werpen
  • indien het no_cache teruggeeft, zal het resultaat afhankelijk zijn van de all_till_ok functie (aangeroepen met auth_on_publish)

zoals je kunt zien zijn hier de waarden die aan ons Lua script worden doorgegeven, inclusief het mountpoint

conv_res zal het teruggegeven resultaat wijzigen:

afbeelding

Als u niet bekend bent met Erlang, raad ik u aan mijn vorige artikel te lezen, https://pi3g.com/2019/05/12/understanding-erlang-lua-luerl-for-vernemq-mongodb-auth_on_register-hook/

In principe, als {error, lua_script_returned_false} niet overeenkomt binnen de resultaten, voor elke (_) naam en elke Other, zal het resultaat Other zijn - simpelweg de resultaten van all_till_ok doorgeven aan de aanroepende functie.

Voor de naam lua_script_returned_falsezal de foutmelding "not_authorized" zijn.

Ik ben er niet helemaal zeker van of dit vmq_plugin_helper.erl is waar de belangrijkste controlerende logica (van het doorgeven van de volgende) zit:

afbeelding

in ieder geval wordt waarschijnlijk "volgende" terug verwacht.

Hier, in vmq_diversity_plugin.erl is all_till_ok gedefinieerd:

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

afbeelding

Zoals u kunt zien, wordt de terugkeerwaarde op "ok" gezet als het script "true" terugstuurt.

Als "false" wordt teruggezonden van het script, wordt de eerder genoemde fout teruggezonden, en stopt de uitvoering -> niet geautoriseerd.

afbeelding

Dit betekent dat als je false teruggeeft in de Lua scripts, er geen andere plugins zullen worden aangeroepen!

als alternatief kunnen modifiers worden teruggegeven.

De truc is om niets terug te geven, voor het geval u het verzoek niet wilt afhandelen:

functie auth_on_publish(pub)
     print("***auth_on_publish debug*** (LUA)")
     als pub["mountpoint"] == "jsclient" dan
         print("*** jsclient gedetecteerd ***")
         print("niets terugkerend")
         - waar teruggeven
    anders
         print("+++ andere client gedetecteerd +++")
         terugzenden
     einde
einde

Merk op dat - (twee streepjes) een commentaar is in Lua.

afbeelding

In dit geval wordt de auth_on_publish hook aangeroepen met behulp van webhooks:

afbeelding

afbeelding

afbeelding

Bonus

Fout bij het genereren van de configuratie met inktvis:

Dit kan verder worden gedebugged door het commando in docker-compose.yml in te stellen op:

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

en de container naar boven te halen (merk op dat ik een .local bestand heb gemaakt, zodat bepaalde instellingen niet meer overschreven worden).

De foutmelding die ik krijg is:

jalpine_morpheus | escript: uitzonderingsfout: geen functieclausule die overeenkomt
jalpine_morpheus | lists:unzip([[ws,ws],
jalpine_morpheus | {["log", "console", "bestand"],"./log/console.log"},

Blijkbaar heeft dit te maken met inktvissen die zich verslikken in lijnen die alleen een spatie bevatten:

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

door te drukken Alt + P in nano zal de weergave van spaties inschakelen - goed voor het debuggen van dit specifieke probleem.

De problematische sectie in mijn configuratie ziet er als volgt uit:

afbeelding

hier zijn er twee tabbladen (?) waar er niets zou moeten zijn.

Het verwijderen van de problematische regel zorgt ervoor dat VerneMQ weer kan starten.

Verdere lectuur

Dit kan ook nuttig zijn:

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

Changelog van VerneMQ:

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

NB: in versie 1.8 is een interessante nieuwe plugin de vmq_pulse plugin, die cluster informatie naar een pulse backend zal pushen via HTTP(S).

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

Laat wat extra Lua scripting zien voor VerneMQ diversiteit.