Configurando Azure Functions para Acesso Eficiente a Filas do Azure com SOLID e Padrão Factory em TypeScript
Este é o terceiro artigo de uma série sobre como configurar Azure Functions para acesso a serviços do Azure utilizando os princípios SOLID (Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion). Nos artigos anteriores, abordamos o acesso ao Azure Blob Storage e às tabelas do Azure. Neste artigo, focaremos no acesso a filas do Azure utilizando o Azure Storage Queue. Caso sinta vontade de entender como integrar o Azure Table Storage veja o artigo abaixo:
Passo 1: Configuração do Ambiente
Antes de começar, certifique-se de ter as seguintes dependências instaladas:
npm install @azure/identity @azure/storage-queue
OBS: Caso precise ver os Passos 1 ao 3 veja o artigo anterior sobre o tema:
Passo 4: Criando a Fábrica QueueServiceClientFactory
Implementaremos uma fábrica para criar instâncias de QueueServiceClient
com base no provedor de credenciais selecionado.
import { QueueServiceClient } from "@azure/storage-queue";
/**
* Factory for creating instances of QueueServiceClient.
*/
class QueueServiceClientFactory {
private accountUrl: string;
private credentialProvider: CredentialProvider;
/**
* Creates an instance of QueueServiceClientFactory.
* @param {string} accountUrl - The account URL for the QueueServiceClient.
* @param {CredentialProvider} credentialProvider - The provider for Azure credentials.
*/
constructor(accountUrl: string, credentialProvider: CredentialProvider) {
this.accountUrl = accountUrl;
this.credentialProvider = credentialProvider;
}
/**
* Creates a QueueServiceClient instance.
* @returns {QueueServiceClient} The QueueServiceClient instance.
*/
createQueueServiceClient(): QueueServiceClient {
const credential = this.credentialProvider.getCredential();
return new QueueServiceClient(this.accountUrl, credential);
}
}
Passo 5: Utilizando a Fábrica em uma Azure Function
Vamos aplicar nossa fábrica dentro de Azure Functions para acesso seguro e eficiente às filas do Azure.
Exemplo 1: Azure Function com Managed Identity Atribuída ao Sistema
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { QueueServiceClientFactory } from "./QueueServiceClientFactory";
import { SystemAssignedManagedIdentityCredentialProvider } from "./SystemAssignedManagedIdentityCredentialProvider";
/**
* Azure Function triggered by an HTTP request.
* @param {Context} context - The Azure Function context object.
* @param {HttpRequest} req - The HTTP request object.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const accountUrl = process.env.AZURE_STORAGEQUEUE_RESOURCEENDPOINT;
const credentialProvider = new SystemAssignedManagedIdentityCredentialProvider();
const queueServiceClientFactory = new QueueServiceClientFactory(accountUrl, credentialProvider);
const queueServiceClient = queueServiceClientFactory.createQueueServiceClient();
const queueClient = queueServiceClient.getQueueClient(queueName);
await queueClient.sendMessage("Hello World!");
context.res = {
status: 200,
body: { text: "menssage sent" }
};
};
export default httpTrigger;
Exemplo 2: Azure Function com Managed Identity Atribuída ao Usuário
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { QueueServiceClientFactory } from "./QueueServiceClientFactory";
import { UserAssignedManagedIdentityCredentialProvider } from "./UserAssignedManagedIdentityCredentialProvider";
/**
* Azure Function triggered by an HTTP request.
* @param {Context} context - The Azure Function context object.
* @param {HttpRequest} req - The HTTP request object.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const accountUrl = process.env.AZURE_STORAGEQUEUE_RESOURCEENDPOINT;
const clientId = process.env.AZURE_STORAGEQUEUE_CLIENTID;
const credentialProvider = new UserAssignedManagedIdentityCredentialProvider(clientId);
const queueServiceClientFactory = new QueueServiceClientFactory(accountUrl, credentialProvider);
const queueServiceClient = queueServiceClientFactory.createQueueServiceClient();
const queueClient = queueServiceClient.getQueueClient(queueName);
await queueClient.sendMessage("Hello World!");
context.res = {
status: 200,
body: { text: "menssage sent" }
};
};
export default httpTrigger;
Exemplo 3: Azure Function com Service Principal
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { QueueServiceClientFactory } from "./QueueServiceClientFactory";
import { ServicePrincipalCredentialProvider } from "./ServicePrincipalCredentialProvider";
/**
* Azure Function triggered by an HTTP request.
* @param {Context} context - The Azure Function context object.
* @param {HttpRequest} req - The HTTP request object.
*/
const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
const accountUrl = process.env.AZURE_STORAGEQUEUE_RESOURCEENDPOINT;
const tenantId = process.env.AZURE_STORAGEQUEUE_TENANTID;
const clientId = process.env.AZURE_STORAGEQUEUE_CLIENTID;
const clientSecret = process.env.AZURE_STORAGEQUEUE_CLIENTSECRET;
const credentialProvider = new ServicePrincipalCredentialProvider(tenantId, clientId, clientSecret);
const queueServiceClientFactory = new QueueServiceClientFactory(accountUrl, credentialProvider);
const queueServiceClient = queueServiceClientFactory.createQueueServiceClient();
const queueClient = queueServiceClient.getQueueClient(queueName);
await queueClient.sendMessage("Hello World!");
context.res = {
status: 200,
body: { text: "menssage sent" }
};
};
export default httpTrigger;
Conclusão
Neste artigo, discutimos como configurar e utilizar Azure Functions para interação com filas do Azure, seguindo os princípios SOLID utilizando Factory Pattern. Ao modularizar a obtenção de credenciais e a criação de clientes de serviço, facilitamos a manutenção e expansão do código em cenários de autenticação diversificados.