Não perca a cabeça configurando Typescript Azure Functions para Acesso ao Azure Key Vault e Identidades Gerenciadas
Bem-vindo ao quarto artigo da nossa série focada em configurar Azure Functions para acessar serviços do Azure com base nos princípios SOLID. Nos artigos anteriores, exploramos como interagir com Azure Blob Storage e Azure Data Tables e Azure Storage Queue. Neste artigo, vamos aprofundar o acesso ao Azure Key Vault utilizando o SDK do Azure Key Vault.
Passo 1: Configuração do Ambiente
Antes de começar, certifique-se de ter as seguintes dependências instaladas:
npm install @azure/identity @azure/keyvault-secrets
OBS: Caso precise ver os Passos 2 ao 3 veja o artigo anterior sobre o tema:
Passo 4: Configurando a Fábrica para Clientes de Segredos
Agora vamos criar uma fábrica que utiliza o CredentialProvider
para instanciar o SecretClient
.
import { SecretClient } from "@azure/keyvault-secrets";
/**
* Factory class for creating instances of SecretClient for Azure Key Vault.
*/
class SecretClientFactory {
private vaultUrl: string;
private credentialProvider: CredentialProvider;
/**
* Creates an instance of SecretClientClientFactory.
* @param {string} accountUrl - The account URL for the SecretClientClient.
* @param {CredentialProvider} credentialProvider - The provider for Azure credentials.
*/
constructor(accountUrl: string, credentialProvider: CredentialProvider) {
this.accountUrl = accountUrl;
this.credentialProvider = credentialProvider;
}
/**
* Creates a SecretClient instance.
* @returns {SecretClient} The SecretClient instance.
*/
createSecretClient(): SecretClient {
const credential = this.credentialProvider.getCredential();
return new SecretClient(this.vaultUrl, credential);
}
}
Passo 5: Implementando na Azure Function
Vamos agora ver como podemos integrar esta estrutura em uma Azure Function, demonstrando cada um dos métodos de autenticação.
Exemplo 1: Azure Function com Managed Identity Atribuída ao Sistema
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { SecretClientFactory } from "./SecretClientFactory";
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 vaultUrl = process.env.AZURE_KEYVAULT_RESOURCEENDPOINT;
const credentialProvider = new SystemAssignedManagedIdentityCredentialProvider();
const secretClientFactory = new SecretClientFactory(vaultUrl, credentialProvider);
const secretClient = secretClientFactory.createSecretClient()
const secret = await secretClient.getSecret("secretName");
context.res = {
status: 200,
body: { secret }
};
};
export default httpTrigger;
Exemplo 2: Azure Function com Managed Identity Atribuída ao Usuário
import { AzureFunction, Context, HttpRequest } from "@azure/functions";
import { SecretClientFactory } from "./SecretClientFactory";
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 vaultUrl = process.env.AZURE_KEYVAULT_RESOURCEENDPOINT;
const clientId = process.env.AZURE_KEYVAULT_CLIENTID;
const credentialProvider = new UserAssignedManagedIdentityCredentialProvider(clientId);
const secretClientFactory = new SecretClientFactory(vaultUrl, credentialProvider);
const secretClient = secretClientFactory.createSecretClient()
const secret = await secretClient.getSecret("secretName");
context.res = {
status: 200,
body: { secret }
};
};
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 vaultUrl = process.env.AZURE_KEYVAULT_RESOURCEENDPOINT;
const tenantId = process.env.AZURE_KEYVAULT_TENANTID;
const clientId = process.env.AZURE_KEYVAULT_CLIENTID;
const clientSecret = process.env.AZURE_KEYVAULT_CLIENTSECRET;
const credentialProvider = new ServicePrincipalCredentialProvider(tenantId, clientId, clientSecret);
const secretClientFactory = new SecretClientFactory(vaultUrl, credentialProvider);
const secretClient = secretClientFactory.createSecretClient()
const secret = await secretClient.getSecret("secretName");
context.res = {
status: 200,
body: { secret }
};
};
export default httpTrigger;
Conclusão
Neste artigo, mostramos como configurar Azure Functions para acessar o Azure Key Vault com métodos de autenticação variados, criando um Factory Pattern. Esta abordagem não só facilita a manutenção e extensão do código, mas também garante uma implementação robusta e escalável.