Páginas filhas
  • DTTALK1-117 - Definir modelo de deploy do API Mirror com Rabbit MQ para acesso externo (TKS)

Introdução

Este documento busca mostrar como deve ser feita a separação dos componentes cloud, para que atendam tanto a mensageria de eventos entre microsserviços, quanto subscrição de comandos. 

Tentamos esclarecer algumas das vantagens do modelo proposto.

Essas são algumas das perguntas que levantaram a necessidade desse Spike:

  • Precisaremos ter ao menos dois brokers (Acesso externo permitido e bloqueado)?
  • Sistemas externos podem se subscrever nas nossas mensagens?
  • A multitenância sempre será tratada como Virtual Hosts? Até mesmo em ambientes compartilhados?
  • APIMirror deve possuir um login único para todos os virtual hosts?

Propostas de Arquitetura

Abaixo segue tabela comparativa entre os benefícios e riscos de cada proposta:


Critério (Broker)Proposta 1 - EconomiaProposta 2 - Robustez
SegurançaAtende TotalmenteAtende Parcialmente
MonitoramentoAtende ParcialmenteAtende Totalmente
IsolamentoAtende ParcialmenteAtende Totalmente
CustomizaçãoAtende ParcialmenteAtende Totalmente
Economia de RecursosAtende TotalmenteNão Atende
Simplicidade de ManutençãoNão AtendeAtende Totalmente

Proposta 1

Existem dois modelos a ser entendidos aqui. Um ocorre quando o cliente opta pelo ambiente exclusivo, e outro compartilhado.

Compartilhado

  • Acesso externo desabilitado, é visível apenas de dentro do cluster. Ambiente mais seguro.
  • Cada API utiliza uma única conexão (compartilham o VHOST "/"), causando menor ônus ao servidor.
    • Cada conexão ao RabbitMQ custa 100kb de memória no server.
    • Pode ser maior que 100kb se TLS estiver habilitado. Nesse ambiente controlado e fechado, pode ser uma vantagem técnica não habilitar o TLS para favorecer a performance e uso de memória.
  • Trafega dados de tenant na mensagem
  • Não permite Arquitetura orientada a Comandos
  • Não permite microsserviços distribuídos de maneira híbrida. Tem que pertencer a um contrato "full cloud".
  • Não permite subscrição de sistemas externos

Figura 1 - Overview de uma arquitetura em um ambiente cloud compartilhado entre clientes +
message broker com acesso externo desabilitado

Exclusivo

  • Acesso externo habilitado
  • Existe um VHOST exclusivo para o tenant, e as APIs devem conectar-se nele
  • Não trafega dados de tenant na mensagem, para evitar brechas de segurança, e por não ser um dado relevante nesse cenário
    • É uma brecha de segurança permitir que nosso cliente saiba como estamos tratando nosso ID de cliente, ou em qual ID ele está.
      • Engenharia Reversa
      • Manipulação de mensagem
    • Todas as mensagens dentro de determinado VHOST pertencem ao mesmo tenant, tornando esse dado irrelevante
  • Permite arquitetura orientada a Comandos
  • Permite microsserviços distribuídos de maneira híbrida
  • Permite subscrição de sistemas externos

Figura 2 - Overview de uma arquitetura em um ambiente cloud exclusivo +
message broker com acesso externo habilitado


Já tínhamos a premissa de que para a subscrição de eventos o RabbitMQ deveria estar exposto para acesso externo. Entretanto, percebemos que essa mesma também pode existir para um cenário de microsserviços, onde o cliente tenha parte destes rodando na sua infraestrutura, e parte em cloud. 

Levamos em consideração também que pode ser bastante vantajoso para o cliente subscrever suas próprias aplicações nos nossos eventos. 

As conexões externas devem ser realizadas através de AMQPS, que nada mais é do que é o protocolo AMQP através de TLS.

Nessa modelagem, existiu também uma proposta sobre como poderia funcionar o modelo de subscrição dos microsserviços.

A base aqui é a arquitetura de publish/subscribe, em sua maneira mais simples, sem utilizar tópicos ou roteamentos mais complexos. Se existir uma necessidade de negócio para justificar uma complexidade maior, essa deveria passar pelo nosso comitê para um entendimento mais aprofundado.

Cada Exchange representa uma informação de eventos realizados que outros sistemas podem vir a se interessar (não necessariamente de CRUD, pode ser um processo que foi realizado). Cada API tem sua fila própria, para aquele evento, e a mesma é subscrita na Exchange.

O escalonamento pode ser feito por N instâncias da mesma API lendo a mesma fila.

API Mirror

Na arquitetura proposta acima, o API Mirror só existe dentro do modelo exclusivo, e por isso somente necessita um login (O do VHOST do tenant a qual pertence).

Se existir alguma mudança, e ele precisar ter um acesso no modelo compartilhado, continua sendo ainda apenas a conexão com o VHOST default ("/").
Supondo ainda que precisasse acessar N VHOSTS, aí faria sentido ele ter um login com perfil de administrador, com acesso a todos, que muda sua senha periodicamente.

Proposta 2

Essa proposta busca uma arquitetura mais simplificada do que a apresentada anteriormente, porém mais robusta, buscando unificar o mesmo desenho para cenários compartilhados e exclusivos.

Isso garante que, até mesmo no ambiente compartilhado, teremos um nível maior de isolamento.

Conseguiremos, também, monitorar exatamente o que está acontecendo para cada cliente. 

O ponto negativo é um número maior de conexões abertas, o que pode acarretar em uma necessidade de maior escalonamento, horizontal ou vertical. Consequentemente, maior custo de infraestrutura Cloud. Como contra ponto disso, podemos pensar que essas conexões vão "abrir e fechar", e em um cenário que temos muitas simultâneas quer dizer que provavelmente está sendo lucrativo para a companhia.

  • Acesso externo habilitado
  • Existe um VHOST exclusivo para o tenant, e as APIs devem conectar-se nele
  • Não trafega dados de tenant na mensagem por ser irrelevante, visto que cada tenant está isolado em seu próprio VHOST
  • Permite arquitetura orientada a Comandos
  • Permite microsserviços distribuídos de maneira híbrida
  • Permite subscrição de sistemas externos

Figura 3 - Overview de uma arquitetura simplificada com a coexistência ambiente cloud compartilhado e exclusivo seguindo as
mesmas regras para o message broker (acesso externo habilitado)

API Mirror

Na arquitetura proposta acima, o API Mirror utilizará um login único, que possui os acessos aos VHOSTS necessários.

Essa mesma ideia se aplica à conexão dos microsserviços com o broker: Um login que possui os acessos devidos.

O consumidor, para se conectar externamente ao broker, tem um login separado que acessa apenas o seu próprio VHOST

Segurança

Autenticação e Autorização 

No RabbitMQ, a autenticação é feita com base no usuário e senha de um determinado VHOST que se deseja conectar.

Ele possui dois níveis de autorização, sendo que isso é facilmente configurável através do console de administração. 

Níveis:

  1. VHost (Rejeita conexões de quem não tem a permissão de acesso)
  2. Operações em recursos: Exchanges, Queues, e outras entidades.
    1. Leitura, Escrita, Configuração

Integração com IDPs externos

É possível cadastrar os chamados "Alternative Authentication and Authorisation Backends". Isso é feito através de plugins do Rabbit.

O Plugin rabbitmq-auth-backend-http é o oficial para isso, e ele exige que o server para o qual aponta respeite o padrão especifico de autenticação do Rabbit.

Eles também possuem o plugin rabbitmq-auth-backend-oauth2 para trabalhar com IDPs no padrão Oauth 2.0. Existe uma nota informando que o mesmo ainda está em um estágio experimental, e, no momento de escrita desse documento, existem testes unitários quebrando na master.

Não encontrei plugins específicos para o formato esperado pelo RAC (OpenID).

Customizações nos comportamentos dos plugins exige conhecimento de Erlang.

Detalhes na implementação ou utilização de ambos plugins exigem um estudo/spike mais aprofundado voltado para tal.

Referências

https://www.rabbitmq.com/access-control.html

https://www.rabbitmq.com/tutorials/tutorial-two-dotnet.html

https://www.rabbitmq.com/tutorials/tutorial-three-dotnet.html

https://www.rabbitmq.com/ssl.html

https://www.cloudamqp.com/blog/2017-12-29-part1-rabbitmq-best-practice.html

https://github.com/rabbitmq/rabbitmq-auth-backend-http

https://github.com/rabbitmq/rabbitmq-auth-backend-oauth2

Elaboração

 

Apresentação

 

Implementação

 

Issue JIRA

DTTALK1-117 - Obtendo detalhes do item... STATUS


  • Sem rótulos

1 comentário

  1. Francisco, em relação a suprimir o tenantId da mensagem, de quem seria esta responsabilidade? Do aplicativo?

    Conforme definido na reunião do comitê de  e documentado aqui, o tenantId é obrigatório nas mensagens trafegadas entre os microsserviços.