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:
zal leiden tot:
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!
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
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.
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
econnrefused
In mijn specifieke geval, draaide mijn webhook endpoint niet. Na het opstarten, krijg ik nu (meerdere pogingen met vergelijkbare output):
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:
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:
Om te laten zien welke webhooks geregistreerd zijn, kunt u
vmq-admin webhooks show
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:
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:
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
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.
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
Merk op dat het bericht auth_on_publish debug wordt afgedrukt door een extra statement dat ik in het Lua script heb ingevoegd:
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):
vmq-admin trace client client-id=my_clientid -mountpoint=jsclient
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
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:
Terug naar Erlang
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
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:
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:
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
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.
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.
In dit geval wordt de auth_on_publish hook aangeroepen met behulp van webhooks:
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:
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).
Laat wat extra Lua scripting zien voor VerneMQ diversiteit.