Configurando Azure Functions para Acesso a Tabelas do Azure com Padrão Factory e SOLID em TypeScript

Cláudio Rapôso
3 min readJul 15, 2024

Este é o segundo 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). No artigo anterior, abordamos o acesso ao Azure Blob Storage. Neste artigo, focaremos no acesso a tabelas do Azure utilizando o Azure Data Tables.

Passo 1: Configuração do Ambiente

Antes de começar, certifique-se de ter as seguintes dependências instaladas:

npm install @azure/identity @azure/data-tables

OBS: Caso precise ver os Passos 1 ao 3 veja o artigo anterior sobre o tema:

Passo 4: Criando a Fábrica TableServiceClientFactory

Agora vamos criar uma fábrica que utiliza o CredentialProvider para criar instâncias de TableServiceClient.

/**
* Factory for creating instances of TableServiceClient.
*/
class TableServiceClientFactory {
private accountUrl: string;
private credentialProvider: CredentialProvider;

/**
* Creates an instance of TableServiceClientFactory.
* @param {string} accountUrl - The account URL for the TableServiceClient.
* @param {CredentialProvider} credentialProvider - The provider for Azure credentials.
*/
constructor(accountUrl: string, credentialProvider: CredentialProvider) {
this.accountUrl = accountUrl;
this.credentialProvider = credentialProvider;
}

/**
* Creates a TableServiceClient instance.
* @returns {TableServiceClient} The TableServiceClient instance.
*/
createTableServiceClient(): TableServiceClient {
const credential = this.credentialProvider.getCredential();
return new TableServiceClient(this.accountUrl, credential);
}
}

Passo 5: Utilizando a Fábrica em uma Azure Function

Vamos ver como podemos utilizar a fábrica para criar uma instância do TableServiceClient em uma Azure Function. Vamos demonstrar três exemplos: Managed Identity atribuída ao sistema, Managed Identity atribuída ao usuário e Service Principal.

Exemplo 1: Azure Function com Managed Identity Atribuída ao Sistema

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { TableServiceClientFactory } from "./TableServiceClientFactory";
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_STORAGETABLE_RESOURCEENDPOINT;
const credentialProvider = new SystemAssignedManagedIdentityCredentialProvider();
const tableServiceClientFactory = new TableServiceClientFactory(accountUrl, credentialProvider);

const tableServiceClient = tableServiceClientFactory.createTableServiceClient();
const list = await tableServiceClient.listTables();

context.res = {
status: 200,
body: list
};
};

export default httpTrigger;

Exemplo 2: Azure Function com Managed Identity Atribuída ao Usuário

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { TableServiceClientFactory } from "./TableServiceClientFactory";
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_STORAGETABLE_RESOURCEENDPOINT;
const clientId = process.env.AZURE_STORAGETABLE_CLIENTID;
const credentialProvider = new UserAssignedManagedIdentityCredentialProvider(clientId);
const tableServiceClientFactory = new TableServiceClientFactory(accountUrl, credentialProvider);

const tableServiceClient = tableServiceClientFactory.createTableServiceClient();
const list = await tableServiceClient.listTables();

context.res = {
status: 200,
body: list
};
};

export default httpTrigger;

Exemplo 3: Azure Function com Service Principal

import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { TableServiceClientFactory } from "./TableServiceClientFactory";
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_STORAGETABLE_RESOURCEENDPOINT;
const tenantId = process.env.AZURE_STORAGETABLE_TENANTID;
const clientId = process.env.AZURE_STORAGETABLE_CLIENTID;
const clientSecret = process.env.AZURE_STORAGETABLE_CLIENTSECRET;
const credentialProvider = new ServicePrincipalCredentialProvider(tenantId, clientId, clientSecret);
const tableServiceClientFactory = new TableServiceClientFactory(accountUrl, credentialProvider);

const tableServiceClient = tableServiceClientFactory.createTableServiceClient();
const list = await tableServiceClient.listTables();

context.res = {
status: 200,
body: list
};
};

export default httpTrigger;

Conclusão

Neste artigo, mostramos como configurar uma Azure Function para acesso a tabelas do Azure utilizando diferentes métodos de autenticação aplicando os princípios SOLID. Este design modular facilita a adição de novos métodos de autenticação e a manutenção do código.

Referências

--

--

Cláudio Rapôso
Cláudio Rapôso

Written by Cláudio Rapôso

Microsoft MVP | Software Architect | Teacher | Book Author | MCT | 12x Microsoft Certified Connect with me in https://www.linkedin.com/in/cfraposo

No responses yet