Depuração de problemas de conexão / autenticação VerneMQ para autenticação dupla com ganchos web e vmq_diversity
TL;DR
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
inclui uma declaração que irá bloquear a autenticação / autorização através de quaisquer outros canais se o seu script Lua retornar "falso":
vai levar a..:
em vez de tentar outros plugins, como você poderia ter suposto!
A fim de evitar este problema, simplesmente não devolver nada do seu roteiro Lua, se você não quer lidar com a mensagem!
Depuração
A VerneMQ tem uma ferramenta de rastreamento integrada, que o ajudará a ver quais problemas podem ocorrer. Primeiro, exiba as sessões, a fim de descobrir com quais dados os seus clientes estão tentando se conectar:
vmq-admin sessão show
Então, rastreia:
vmq-admin trace client client-id=000000007eaefc47 -mountpoint=5c61a59ba6b76f558d256f42
Note que o ponto de montagem padrão é "" (o ponto de montagem padrão para Verne) - se você não estiver definindo um ponto de montagem personalizado nos ouvintes ( como eu), então você pode omitir isso.
Inicialmente o vmq-admin trace irá reportar que nenhuma sessão é encontrada para este cliente - se o seu cliente não está actualmente ligado.
Ligue o seu cliente, e haverá mais resultados.
Também é útil aumentar o nível de verbosidade no logger para depuração (para vernemq.conf):
log.console.nível = debug
econnrefused
No meu caso em particular, o meu ponto final do gancho da web não estava funcionando. Depois de o iniciar, eu agora recebo (múltiplas tentativas com saída semelhante):
Como você pode ver, o cliente agora está sendo autenticado, mas não está sendo autorizado a publicar. O cliente é então desconectado (conforme especificação MQTT 3.1.1).
E esta é a saída do registo:
o que está acontecendo aqui, é que o cliente é autenticado usando um webhook, e então ele tenta se tornar autorizado usando um script Lua (autorização MongoDB).
Eu não tenho certeza porque auth_on_publish para o cliente não é chamado usando um webhook também. Este cliente em qualquer caso é suposto ser autenticado totalmente usando o MongoDB.
Eu também só vejo pedidos de registro automático:
Para mostrar quais ganchos web estão registrados, você pode executar
vmq-admin webhooks show
Vê: https://docs.vernemq.com/plugindevelopment/webhookplugins
Todos os ganchos da web são chamados com o método POST, e precisam ser respondidos com o código HTTP 200 para serem considerados bem sucedidos.
Um pedido para o servidor webhook
Aqui está como será um pedido para o servidor Webhook:
Os cabeçalhos são passados, com o gancho de cabeça vernemq-hook definido para auth_on_register neste caso.
O corpo do correio incluirá informações diferentes sobre o cliente que está tentando se conectar.
Depois de usar "next" como resposta do webhook, a publicação funciona corretamente - o cliente é autenticado contra o MongoDB, e depois a publicação é autorizada, como desejado.
Aqui está como a resposta do webhook deve parecer para passar a autenticação para o próximo plugin:
{\an8}"resultado": "seguinte"}
E aqui está o aspecto do vestígio agora:
No fundo você pode ver os keepalives para o cliente (PINGREQ, PINGRESP).
Então, um cliente está a trabalhar agora. Avance para o próximo cliente - que deve ser autenticado e autorizado através de ganchos web!
Cliente Webhook
Como você pode ver, a propósito, o ponto de montagem é reescrito de "picliente" para um ponto de montagem diferente pelo roteiro de MongoDB Lua.
Basicamente estou usando o ponto de montagem nos ouvintes para indicar qual método de autenticação deve ser usado para este cliente.
Na versão 2 do VerneMQ, estamos prometidos, haverá uma separação de Plugins por Ouvinte - portanto podemos evitar estas verificações que adicionam despesas gerais a cada conexão.
aparentemente apenas um traço pode ser executado de cada vez. Tentando novamente depois de desligar o outro vestígio:
vmq-admin trace client client-id=my_clientid -mountpoint=jsclient
Por favor note que a mensagem auth_on_publish debug é impressa por uma declaração adicional que eu inseri no script Lua:
em auth_commons.lua
Entendendo o que retornar do roteiro de Lua
O que nós queremos é provavelmente voltar do roteiro Lua que o próximo gancho deve ser chamado.
"Caso o plugin não possa validar a mensagem de publicação, é melhor retornar próximo
pois isso permitiria que os plugins subsequentes na cadeia validassem o pedido".
(ver https://docs.vernemq.com/plugindevelopment/publishflow )
Presumi que o regresso falso implicaria isso, mas aparentemente não?
Vamos procurar na fonte Erlang de vernemq
https://github.com/vernemq/vernemq
Esta é uma suite de teste para o auth_cache para vmq_diversity (onde vivem os scripts Lua):
vmq-admin trace client client-id=my_clientid -mountpoint=jsclient
Adicionando algumas depurações adicionais para a mensagem em Lua:
função auth_on_publish(pub)
print("***auth_on_publish debug*** (LUA)")
para k,v em pares(pub) do
imprimir(k ... " ... " ... v)
final
imprimir(pub)
devolver falsas
final
Note que o código parece estar com defeito (falso aparentemente não pode ser concatenado usando ... em Lua - OK.)
Em qualquer caso, na tabela Lua, que é passada como "pub", temos os seguintes parâmetros:
- client_id
- ponto de montagem
- carga útil
- qos
agora podemos verificar se o ponto de montagem é "jsclient" (que deve ser autenticado usando ganchos web), e por enquanto forçar a verdade:
função auth_on_publish(pub)
print("***auth_on_publish debug*** (LUA)")
se pub["mountpoint"] == "jsclient" então
retornar verdadeiro
além disso
devolver falsas
final
final
Aqui está como se parece um vestígio para esta condição artificial:
Voltar para Erlang
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
quando auth_on_publish é chamado para o vmq_diversity_plugin.erl o valor do resultado será obtido desta forma:
- se vmq_diversity_cache:match_publish_acl voltar a ser verdade, será "ok".
- se ele retornar falso, ele vai lançar um erro
- se não_cache retorna, o resultado será dependente da função all_till_ok (chamada com auth_on_publish)
como você pode ver aqui estão os valores passados ao nosso roteiro Lua, incluindo o ponto de montagem
conv_res irá modificar o resultado devolvido:
Recomendo vivamente que se não estiver familiarizado com Erlang leia o meu artigo anterior, https://pi3g.com/2019/05/12/understanding-erlang-lua-luerl-for-vernemq-mongodb-auth_on_register-hook/
Basicamente se {error, lua_script_returned_false} não for igualado dentro dos resultados, para qualquer (_) nome e qualquer Outro, o resultado será Outro - simplesmente passando os resultados de all_till_ok para a função de chamada.
Para o nome lua_script_retorned_falseo erro não será_autorizado.
Eu não estou totalmente certo se este vmq_plugin_helper.erl é onde está a lógica principal de controle (de passar adiante):
em qualquer caso, provavelmente "próximo" é esperado que seja devolvido.
Aqui, em vmq_diversity_plugin.erl all_till_ok está definido:
https://github.com/vernemq/vernemq/blob/master/apps/vmq_diversity/src/vmq_diversity_plugin.erl
Como você pode ver, se "true" é retornado pelo script, o valor de retorno é definido como "ok".
Se "falso" for retornado do script, o erro mencionado anteriormente é retornado, e a execução pára -> não autorizada.
Isto significa que se você retornar falsos nos scripts Lua, nenhum outro plugin será chamado!
alternativamente, os modificadores podem ser devolvidos.
O truque é para não devolver nada, para o caso de não querer tratar do pedido:
função auth_on_publish(pub)
print("***auth_on_publish debug*** (LUA)")
se pub["mountpoint"] == "jsclient" então
print("*** jsclient detectado ***")
imprimir("não devolver nada")
- retornar verdadeiro
além disso
imprimir("++++ outro cliente detectado +++")
devolver falsas
final
final
Note que - (dois traços) é um comentário em Lua.
Neste caso, o gancho auth_on_publish é chamado usando ganchos web:
Bónus
Configuração geradora de erros com cuttlefish:
Isto pode ser depurado ainda mais definindo o comando em docker-compose.yml para:
...o comando: "vernemq config generate -l debug /vernemq/etc/vernemq.conf.local".
e trazer o container para cima (note que eu criei um arquivo .local, então certas configurações não são mais sobrescritas).
A mensagem de erro que eu recebo é:
jalpine_morpheus | escript: erro de excepção: sem correspondência de cláusula de função
jalpine_morpheus | lists:unzip([[ws,ws],
jalpine_morpheus | {["log", "console", "arquivo"],"./log/console.log"},
aparentemente isto está relacionado com chocos a sufocar em linhas que contêm apenas um espaço:
https://github.com/basho/cuttlefish/issues/222
prensagem Alt + P em nano vai permitir a exibição do espaço em branco - bom para depurar este problema em particular.
A secção problemática na minha configuração parece-se com isto:
aqui há duas abas (?) onde não devem ser nada.
A remoção da linha problemática permitirá que a VerneMQ recomece.
Leitura adicional
Isto também pode ser útil:
http://www.steves-internet-guide.com/mqtt-protocol-messages-overview/
Changelog de VerneMQ:
https://github.com/vernemq/vernemq/blob/fe514561cbeebb2ac4f7c98a87c64d766587c1d7/changelog.md
NB: na Versão 1.8 um novo plugin interessante é o vmq_pulse plugin, que irá empurrar as informações do cluster para um backend de pulso via HTTP(S).
Mostrando alguns scripts Lua adicionais para a diversidade VerneMQ.