ASP.NET Core 3.1 - API Gateway Pattern - Ocelot (Parte 16)

Até este momento, sempre que falei em segurança, estava tudo voltado à forma de autorização, para que a API de Pagamento não permitisse o acesso de forma anônima.

No último posto desta série ASP.NET Core 3.1 - Payment API - Anti-Corruption Layer and Façade Pattern (Parte 15) falei sobre o Façade Pattern e neste novo post vou falar desse pattern novamente, mas que ajuda na solução de um outro problema e também dúvidas que podem surgir.

Direct Client to Microservice Communication

Esta é uma forma de se comunicar com a API de Pagamento, de forma direta, ou seja, a aplicação cliente (MVC, SPA, Mobile, etc), realiza o acesso direto à API conforme demonstrado na imagem a seguir. A referência do uso desta imagem pode ser vista aqui.

32-API Gateway-Direct Client to microservice

Nunca esqueça de perguntar a real necessidade de implementar um Gateway em seu projeto, as vezes uma API simples, que possui poucas funcionalidades, que será acessada apenas por uma aplicação web, que não precisa se preocupar com estalabilidade, disponibilidade, etc talvez possa sim ser acessada diretamente.

API Gateway Communication

Com a implementação de microsserviços, as aplicações clientes (MVC, SPA, Mobile, etc), acessam funcionalidades de mais de um serviço. O que aconteceria se sua aplicação cliente precisasse acessar diferentes APIs, em URLs diferentes, hospedadas em distintos lugares do mundo? Dependendo de cada problema, podemos ter impactos diferentes com latência, com a atualização das APIs e por fim o processo de construção ou manutenção se torna muito mais complexo.

O uso de API Gateway coloca uma camada de acesso a mais, centraliza o acesso as funcionalidades das APIs, funcionando como um proxy reverso, isso ajuda na solução de alguns problemas:

  1. Acomplamento direto das aplicações
  2. Melhora a performance por não ter a necessidade de fazer tantas voltas na internet para acessar as APIs
  3. Segurança contra ataques antes de chegar na API propriamente dita e o fato de que as APIs não precisam estar expostas e acessíveis na internet, seu nível de acesso é mais interno.

A imagem a seguir exemplifica o uso de duas API Gateway, neste exemplo há um gateway para chamadas de aplicações mobile e outro para web.
API Gateway Multiple

Se tivessemos apenas um gateway que service aplicações web e mobile precisaríamos aplicar o façade pattern como técnica para separar as chamadas pela origem da requisição, seria o meio mais fácil e o pattern nos ajudaria na solução deste problema também.

Ocelot

Ocelot é um produto para .NET e implementação de microsserviços que possui diversas funcionalidades para API Gateway.

Configuration

O Gateway que eu vou sugerir a criação, possui a configuração para que sempre que uma requisição chegar até ele, já seja autorizada pelo IdentityServer4, para somente depois dessa pré-autenticação a API de Pagamento possa ser acessada de fato, ou seja, para que o Gateway possa realizar o seu trabalho de proxy reverso e levar a chamada adiante através do roteamento que explicarei nas configurações.

Vamos aos passos da configuração do Ocelot:

  1. Crie um projeto do tipo API, eu criei com o nome "WebGateway";
  2. Remova as classes e controllers desnecessárias, que vem no template padrão;
  3. Adicione os pacotes do NuGet Package Ocelot e IdentityServer4.AccessTokenValidation;
  4. Vamos fazer as alterações necessárias no arquivo Program.cs conforme a seguir;

Veja que fiz a referência ao arquivo "ocelot.json", é nele que faremos as configurações necessárias para o Ocelot consiga realizar o seu trabalho. Além disso, a configuração deste arquivo possui o parâmetro reloadOnChange=true, significa que enquanto o projeto está rodando, se você realizar uma alteração no arquivo e salvar, automaticamente haverá um refresh da aplicação para pegar as novas configurações.

  1. No arquivo Startup.cs realizei as configurações necessárias para o funcionamento da autorização do IdentityServer4, adicionei o método de extensão do serviços do Ocelot services.AddOcelot() e no final das configurações adicionei o app.UseOcelot().Wait();, o código pode ser conferido a seguir.
  1. No arquivo appsettings.json, incluí as configurações para o IdentityServer4 apenas, pode ser conferido a seguir. Na ASP.NET Core 3.1 - IdentityServer4 - API de Pagamento (Parte 3) eu explico mais detalhadamente estas configurações.

Ocelot Configuration

Depois de passar as configurações básicas, vou com um pouco mais de atenção aos detalhes do Ocelot e seu funcionamento, o arquivo a seguir mostra de forma sequencial como o Ocelot vai ler as configurações.

Na documentação, você vai perceber que o DownstreamPathTemplate vem antes do UpstreamPathTemplate, na minha visão é um pouco mais difícil de ler desta forma, então eu resolvi inverter para facilitar o sequenciamento das ações na leitura.

GlobalConfiguration > BaseUrl: Esta é a URL de entrada do UpstreamPathTemplate, especificando desta forma, não é necessário informar o caminho completo sempre.

UpstreamPathTemplate: É a [controler]/[action] que você quer acessar de forma simplificada, então aqui eu omiti o /api/, pois ele é o caminho de exposição da API de Pagamento e agora eu quero acessar de outra forma e mais simples.

UpstreamHttpMethod: Aqui vai a configuração dos métodos aceitos pela UpstreamPathTemplate, no meu caso eu apenas aceito o método GET, caso você precise habilitar o método OPTIONS, bastaria colocar ["GET","OPTIONS"].

DownstreamPathTemplate: É o caminho [controler]/[action] oficial da API de Pagamento, este eu não posso mudar, senão o Ocelot não vai encontrar a API.

DownstreamScheme: Qual o protocolo de entrada da API de Pagamento, http OU https

DownstreamHostAndPorts: Configuração do nome do servidor, dns, ip para chegar na API de Pagamento juntamente com a porta.

AuthenticationOptions: Realiza a verificação da chave do provider de configuração dos serviços do Gateway com o escopo permitido pelo IdentityServer4 para acessar a API de Pagamento.

RateLimitOptions: Eu considero esta configuração como mais um ponto de segurança para proteção da API de Pagamento, evita uma série de problemas e dores de cabeça quando se fala em ataques, chamadas assíncronas múltiplas às APIs entre tantas outras situações. Eu sugiro que você explore na documentação as opções, quem sabe alguma delas resolva seu problema.

Testing

Para testar eu segui os passos:

  1. Executei o projeto do IdentityServer4;
  2. Executei o projeto da API de Pagamento;
  3. Executei o projeto do Gateway;

Através do postman, eu peguei um token no IdentityServer4 e fiz a chamada no Gateway usando o caminho da configuração que está no UpstreamPathTemplate. As imagens a seguir exemplificam estes passos.

API Gateway Token IdentityServer4

API Gateway API Payment Invoke

Github

Você pode conferir tudo isso no Github.

Continua em ASP.NET Core 3.1 - API Gateway Pattern - Azure (Parte 17)