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":

imagem

vai levar a..:

imagem

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!

imagem

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

imagem

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.

imagem

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

imagem

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):

imagem

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:

imagem

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:

imagem

Para mostrar quais ganchos web estão registrados, você pode executar

vmq-admin webhooks show

imagem

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:

imagem

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:

imagem

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

imagem

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.

imagem

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

imagem

imagem

imagem

Por favor note que a mensagem auth_on_publish debug é impressa por uma declaração adicional que eu inseri no script Lua:

imagem

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):

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

imagem

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

imagem

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

imagem

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:

imagem

Voltar para Erlang

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

imagem

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:

imagem

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):

imagem

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

imagem

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.

imagem

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.

imagem

Neste caso, o gancho auth_on_publish é chamado usando ganchos web:

imagem

imagem

imagem

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:

imagem

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).

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

Mostrando alguns scripts Lua adicionais para a diversidade VerneMQ.