Transmitindo logs para eventos na Azure
Tags: azure, events, log, aad
Published: 2020-05-28 14:34:01

Algumas vezes precisamos executar processos no sistema caso ocorram certos tipos de eventos em nossa aplicação, para citar um caso clássico em grande parte dos softwares *enterprise* imagine a seguinte situação:

> Um usuário com perfil gerencia atribui um permissão especial a um outro usuário da organização. Neste caso, a concessão deste perfil a qualquer usuário deverá ser registrada em banco de dados e notificar um grupo de usuários a tal ação.

Na plataforma da Azure, o cenário acima pode ser executado adicionando um grupo a um usuário cadastrado no Azure Active Directory.

Uma saída simples seria codificar a regra de negócio (registrar a ação no banco de dados e notificação do grupo de usuários) no endpoint que irá realizar a ação de atribuir a permissão, mas isto não é suficiente, pois existem casos que de atribuição de permissão que não são realizadas pelo sistema.

Uma atribuição de grupo a um usuário no AAD pode ser feita programaticamente via [Microsoft Graph API](https://developer.microsoft.com/en-us/graph), script [PowerShell](https://docs.microsoft.com/en-us/powershell/azure/?view=azps-3.1.0) ou diretamente pelo portal [Azure](https://portal.azure.com/). Sendo assim, caso um outro usuário faça destes métodos, sua regra de negócio implementada no endpoint não seria executada ocasionando um problema na sua aplicação.

A solução para cobrir todos estes casos seria inspecionar o LOG de Auditoria do AAD e sensibilizar a execução da regra sempre que um grupo for atribuído.

Para isto iremos utilizar 4 recursos da Azure:

* [Azure Active Directory](https://azure.microsoft.com/en-us/services/active-directory/)
* [Azure Cloud Storage](https://azure.microsoft.com/en-us/free/storage/)
* [Azure Event Hubs](https://azure.microsoft.com/en-us/services/event-hubs/)
* [Azure Functions](https://azure.microsoft.com/en-us/services/functions/)

# Quais são os papéis de cada recurso na solução?
Azure Active Directory, será utilizado para gerenciar o diretório de usuários e grupos da aplicação. É responsável também por manter a aplicação e consequentemente um tenant na Azure.

O Azure Event Hubs será o serviço responsável por guardar e entregar os dados em tempo real em uma fila, de forma simples, confiável e escalável. 

A regra de negócio do sistema será implementada em uma Azure Function, uma forma eficiente de desenvolvimento baseada em eventos em computação sem servidores.

Por fim, o Azure Cloud Storage é um serviço armazenamento de dados altamente seguro, massivo e escalável. Este serviço será utilizado pois é um requisito de configuração ao utilizar o Event Hubs e também o Function.

Fique tranquilo para fazer seus estudos e POCs, todos estes serviços possuem camada grátis na Azure (tier free)

Neste artigo você irá aprender como fazer isto de forma eficiente, inspecionando o LOG de eventos do AAD.

# Como configurar a solução
Utilize o portal da Azure para configurar os 4 serviços conforme descrito nos passos.

## Criar um namespace no event hub
Para armazenar os dados de forma seguro devemos criar um *namespace* no Event hub. Sega os seguintes passos:

1. Acesse: Home > Event Hubs
2. Clique em **Add**
3. Digite um nome único para o namespace
4. Selecione **Basic princing tier**
5. Selecione uma **Subscription**
6. Selecione ou crie um **Resource group**
7. Selecione um **Location**
8. Clique em **Create**

> Um **resource group** (RG) na Azure é uma nova abordagem de agrupar uma coleção de serviçõs/recursos em um grupo lógico. Isto é útil para facilitar, monitorar, controlar acesso e gerenciar custos de suas aplicações

## Criar um hub
Um *hub* deve ser utilizado para segregar os diferentes tipos de mensagens que podem ser entregues ao *namespace* 

1. Acesse: Home > Event Hubs
2. Clique namespace creado anteriormente
3. Dentro da seção _Overview_ clique no ítem **+ Event Hub**
4. Digite um nome único para o hub
5. Clique em **Create**


## Configurar AAD
Para configurar o Azure Active Directory siga os passos abaixo.

1. Acessar: Home > **<seu-diretorio> - Overview Azure Active Directory**
2. Abrir **Audit logs** na seção **Monitoring**
3. Clique em **Export Data Settings**
4. Clique em **+ Add diagnostic setting**
5. Digite um diagnostic settings name único 
6. Ative a opção **Stream to an event hub**
7. Ative a opção **AuditLogs** abaixo da seção LOG
8. Clique em **Configure** abaixo de *Stream to an event hub*
9. Selecione uma **Subscription**
10. Selecione o _namespace_ do event hub criado anteriormente
11. Selecione o _hub_ do event hub criado anteriormente
12. Selecionar o _hub policy name_
13. Clique em **Save**


## Configurar Azure Functions
Implementar a regra de negócio definida é um jeito econômico e eficiente de desenvolver a funcionalidade necessária.

1. Acesse: Home > Function App
2. Clique em **Add**
3. Digite um **App name** único
4. Selecione uma **Subscription**
5. Selecione ou crie um **Resource group**
6. Selecione o sistema operacional **Windows** 
   * Este passo é importante para poder rodar a versão estável do _Azure Functions_
7. Selecione **Comsumption plan** em _Hosting Plan_
8. Selecione um **Location**
9. Selecione **Node.js** em Runtime Stack ou outra de sua preferência
10. Crie ou selecione um **Storage**
11. Mantenha o **Application Insights** habilitado
12. Clique em **Create**


> Recomenda-se utilizar um local (**Location**) o mais próximo possível de onde estarão seus usuários e também seus recursos alocados na Azure.

## Criar a Function
Para implementar a functions utilizando *javascript* siga os passos abaixo.

1. Acesse: Home > Function App
2. Clique na **Function App** criada anteriormente
3. Clique em **Functions** dentro da seção *Function Apps*
4. Clique em **New function***
5. Selecione o template **Azure Event Hub trigger**
    5.1. Na primeira vez que utilizar este recurso, você precisa instalar a extensão  **Microsoft.Azure.WebJobs.Extensions.EventHubs**
    5.2. Clique em **Install** para iniciar a instalação
    5.3. Clique em **Continue** para finalizar este passo
6. Digite um nome único para a *function*
7. Escolhe o Event Hub na aba **Event Hub**
   7.1. Selecione o *Namespace* criado anteriormente
   7.2. Selecione o *Hub* criado anteriormente
   7.3. Select o política padrão **RootManageSharedAccessKey** dentro de *Policy*
   7.4. Clique em **Select**
8. Selecione **$Default** em *Event Hub consumer group*
9. Digite o nome do Hub criado anteriormente na seção **Criar um Hub**
10. Clicar em **Create**

## Configurar a trigger
Agora precisamos configurar o gatilho que irá sensibilizar a trigger para "ouvir" o hub de eventos

1. Acesse: Home > Function App
2. Clique na *Function App* criada anteriormente
3. Clique na *Function* criada anteriormente na seção *Criar a Function*
4. Clique em **View files** para expandir o painel a direita
5. Clique no arquivo **function.json**
6. Modifique o arquivo .json para configurar a trigger
   6.1. Adicione o **namespace** no valor da chave **eventHubName** e adicionar uma "/" antes no nome do **hub**. O valor desta propriedade deve estar no formato: {Event Hub Namespace}/{Event Hub Name}
   6.2. Clique em **Save**

# Vamos testar?
Após todos os passos executados podemos testar nossa solução. Para executar um teste prático siga os seguintes passos.

## Executar uma operação
1. Acesse: Home > <seu-diretorio> - Overview Azure Active Directory
2. Faça qualquer operação de escrita no _Audit Log_ como por exemplo: crie um novo grupo
3. Aguarde o tempo de latência de operações de escrita no *Audit logs*
   3.1. Clique em: **Audit logs** na seção *Activity*
   3.2. Clique em: **Refresh** para atualizar as últimas entradas de log até sua operação de criação de grupo ser listada.
   
> Algumas vezes a Azure demora em torno de 2 minutes para escrever uma linha no Audit Log

## Verificar mensagem recebida no Event Hub
1. Acesse: Home > Event Hubs
2. Clique no *Event Hub namespace* criado
3. Dentro de **Overview** desça o conteúdo e clique no *Hub* criado
4. Dentro de **Overview** procure por *Messages graph* e veja o *Incoming Messages (sum)* o qual é o número de mensagens recebidas

> O Event Hub iniciar somente após a linha ser escrita no Audit Log

## Verificar o log da function
1. Acesse: Home > Function App
2. Clique na *Function App* criada
3. Clique em **Functions** dentro da seção *Function Apps*
4. Clique na *function* criada
5. Clique no ítem **Monitor** e você poderá ver todos os disparos da function que foram capturadas

> Para que possa visualizar os detalhes da execução da function você pode utilizar o método Log no objeto de contexto disponibilizado pela trigger

# Conclusão
Podemos utilizar como padrão de arquitetura a fila de eventos não somente para esta  finalidade mas também para outras que envolvem um número massivo de operações à serem executas em fila, desta forma escalando horizontalmente a aplicação.