Codeblox Blog

Controle o acesso a suas Web APIs com Azure APIM

Guilherme
07/12/2021

O Azure API Management(APIM) é um serviço que funciona como uma camada de controle sobre suas APIs. Nele é possível gerenciar o consumo através de assinaturas e produtos.

Vou falar aqui especificamente sobre as necessidades do caso em que estou trabalhando. Nele é preciso:

API com ASP.NET

Para simplificar, vou colocar aqui um exemplo utilizando Minimal Web Apis do .NET6. (no caso real utilizei Controllers)

A API abaixo lista os produtos de uma empresa:

app.MapGet("produtos", 
  (Db db, IHttpContextAccessor accessor) => db.Produtos.Where(p => p.EmpresaId == accessor.HttpContext
                                                                                    .Request
                                                                                    .Headers["X-EmpresaId"]
                                                                                    .First())
);

Repare que realizo o filtro dos dados da empresa através do cabeçalho X-EmpresaId. Esta informação será injetada posteriormente pelo APIM.

Nesta aplicação deixo exposto em produção as definições de OpenApi, vou usar elas depois para realizar a importação no APIM. Além disso, não vou me preocupar com autorização sobre as APIs, pois a aplicação não ficará acessível diretamente na internet, ficando tudo a cargo do APIM.

Protegendo o Backend

Após publicar a aplicação em uma App Service precisamos permitir o acesso apenas pelo APIM, impossibilitanto qualquer outro acesso na internet.

Existem diversas formas de proteger as APIs do seu Backend e não encontrei nenhuma menção na documentação da Microsoft a opção de restrição por IP.

Acredito que seja por que o IP do serviço APIM acabe sendo compartilhado entre vários clientes do Azure e por isso não estaria totalmente protegido.

Neste trabalho especificamente eu preciso simplificar ao máximo a configuração. Por isso decidi utilizar restrição por IP + envio de uma chave secreta em todas as requisições do APIM para as APIs de Backend. (Caso eu tivesse total controle dos recursos de nuvem, provavelmente usaria autenticação Azure AD com a identidade gerenciada do APIM).

Para isso, obtenha o IP público do APIM nas propriedades dentro do serviço:

image

Vá até a opção de Restrição de Acesso na App Service:

image

E adicione uma regra permitindo acesso ao IP do APIM. Ex:

O Azure automaticamente criará outra regra de bloqueio para qualquer outra origem.

Importando as APIs no APIM

Após publicar a aplicação numa App Service precisamos importar as definições no APIM, para isso vamos utilizar a opção de definição OpenApi.

image

Na especificação é possível colocar o endereço da definição OpenApi na App Service ou fazer o upload do arquivo json.

Caso já tenha sido feita a restrição por IP, não será possível utilizar o endereço.

image

Feita a importação suas APIs ficarão listadas no APIM

image

Adicionando assinantes

Nesta aplicação temos uma base de dados com uma tabela de empresas que podem se tornar assinantes das APIs.

Quando uma empresa quiser uma assinatura será necessário ir até o menu “Assinaturas” do APIM e adicionar uma nova.

Neste caso adicionarei da seguinte forma:

Com a assinatura criada, será necessário fornecer a empresa uma chave de acesso:

image

A empresa deverá enviar essa chave em todas as requisições através do cabeçalho Ocp-Apim-Subscription-Key.

Isolando dados por assinante

Como mostrado anteriormente, a aplicação filtra os produtos através do ID da empresa enviado no cabeçalho X-EmpresaId. O ID da empresa também foi utilizado para criar a assinatura (campo Nome).

Dentro do APIM, na opção APIs > Design, pode-se então criar uma política de processamento de Inboud para adicionarmos o cabeçalho X-EmpresaId com base na assinatura de acesso.

image

Como queremos adicionar um cabeçalho, é necessário adicionar uma política do tipo “Set headers”:

image

O valor do ID da empresa é atribuído através da expressão de política @(context.Subscription.Id) onde Subscription.Id é uma das variáveis de contexto do APIM que guarda o Nome que foi atribuído na assinatura.

Também é necessário usar a opção override para evitar que o consumidor final atribua algo neste cabeçalho.

Para complementar a proteção via restrição de acesso por IP, vou adicionar outra política para adicionar um cabeçalho contendo uma chave conhecida apenas entre a aplicação e o APIM. (Esse detalhe não vou mostrar aqui).

Conclusão

Esse caso de uso é bem específico para a necessidade do projeto em que estou atuando. Ainda é possível explorar a opção de Produtos e também tem o Portal do Desenvolvedor para realizar a documentação das APIs e permitir testes interativos aos consumidores.

Caso haja necessidade de gerenciar e monetizar automaticamente as APIs, é possível implementar uma solução customizada utilizado os SDKs do APIM e de algum serviço de pagamentos como o Stripe.

azure
aspnet


Guilherme M. Abdo
Guilherme M. Abdo
Desenvolvedor fullstack .Net/Angular/Azure/GitHub