🔐

Azure Key Vault Setup

🔐 Azure Key Vault Integration

Sistema de gestão segura de segredos usando Azure Key Vault para armazenar credenciais sensíveis.

Visão Geral

O Azure Key Vault é usado para armazenar e gerir segredos de forma segura, eliminando a necessidade de armazenar credenciais em ficheiros .env ou código.

Benefícios

Arquitetura

┌─────────────────┐
│  Application    │
│  (Nest.js)      │
└────────┬────────┘
         │
         │ 1. Initialize KeyVault
         │    (on bootstrap)
         ▼
┌─────────────────┐
│  KeyVault       │
│  Service        │
└────────┬────────┘
         │
         │ 2. Authenticate
         │    (Managed Identity
         │     or Service Principal)
         ▼
┌─────────────────┐
│  Azure          │
│  Key Vault      │
└────────┬────────┘
         │
         │ 3. Load secrets
         │    into process.env
         ▼
┌─────────────────┐
│  ConfigModule   │
│  validates env  │
└─────────────────┘

Segredos Geridos

Obrigatórios

Secret Name Environment Variable Descrição
mongo-root-username MONGO_ROOT_USERNAME Utilizador root do MongoDB
mongo-root-password MONGO_ROOT_PASSWORD Password do MongoDB
jwt-secret JWT_SECRET Chave secreta para assinatura JWT
podcast-index-api-key PODCAST_INDEX_API_KEY API Key do Podcast Index
podcast-index-api-secret PODCAST_INDEX_API_SECRET API Secret do Podcast Index

Opcionais

Secret Name Environment Variable Descrição
mongo-uri MONGO_URI URI completa do MongoDB (alternativa)
redis-connection-string REDIS_CONNECTION_STRING String de conexão Redis
analytics-api-key ANALYTICS_API_KEY API Key de Analytics
ml-service-api-key ML_SERVICE_API_KEY API Key do serviço ML
ml-service-endpoint ML_SERVICE_ENDPOINT Endpoint do serviço ML

Social Auth (Opcionais)

Necessários apenas se fores usar os endpoints:

Secret Name Environment Variable Descrição
google-oauth-client-ids GOOGLE_OAUTH_CLIENT_IDS CSV de OAuth Client IDs (Web) aceites como audience para validar Google ID tokens
google-server-client-id GOOGLE_SERVER_CLIENT_ID Fallback (1 client id)
facebook-app-id FACEBOOK_APP_ID Facebook App ID
facebook-app-secret FACEBOOK_APP_SECRET Facebook App Secret (sensível)

Set secrets via Azure CLI

# 1) Login
az login

# 2) Definir variáveis locais (não commitar)
export AZURE_KEY_VAULT_NAME="audissey-kv-dev"
export GOOGLE_OAUTH_CLIENT_IDS="<client-id-web-1>,<client-id-web-2>"
export GOOGLE_SERVER_CLIENT_ID="<optional-single-client-id>"  # opcional
export FACEBOOK_APP_ID="<facebook-app-id>"
export FACEBOOK_APP_SECRET="<facebook-app-secret>"

# 3) Criar/atualizar secrets
az keyvault secret set --vault-name "$AZURE_KEY_VAULT_NAME" --name "google-oauth-client-ids" --value "$GOOGLE_OAUTH_CLIENT_IDS"
az keyvault secret set --vault-name "$AZURE_KEY_VAULT_NAME" --name "google-server-client-id" --value "$GOOGLE_SERVER_CLIENT_ID"  # opcional
az keyvault secret set --vault-name "$AZURE_KEY_VAULT_NAME" --name "facebook-app-id" --value "$FACEBOOK_APP_ID"
az keyvault secret set --vault-name "$AZURE_KEY_VAULT_NAME" --name "facebook-app-secret" --value "$FACEBOOK_APP_SECRET"

Alternativa: usar o script do repo:

export AZURE_KEY_VAULT_NAMES="audissey-kv-dev,audissey-kv-staging,audissey-kv-production"
export GOOGLE_OAUTH_CLIENT_IDS="<client-id-web-1>,<client-id-web-2>"
export FACEBOOK_APP_ID="<facebook-app-id>"

# O script pede o FACEBOOK_APP_SECRET em modo oculto (não fica no histórico do terminal)
./scripts/keyvault/set-social-auth-secrets.sh --prompt

Setup

Pré-requisitos

  1. Azure CLI instalado e autenticado

    az login
    
  2. Permissões Azure para criar Key Vaults

  3. jq instalado (para scripts)

    # macOS
    brew install jq
    
    # Ubuntu/Debian
    sudo apt-get install jq
    

1. Criar Key Vault

Execute o script de setup:

./scripts/setup-keyvault.sh

O script irá:

Exemplo de execução:

Enter environment name (dev/staging/production): dev
Enter Azure resource group name: audissey-rg
Enter Azure region (e.g., westeurope): westeurope

Configuration:
  Environment: dev
  Resource Group: audissey-rg
  Key Vault Name: audissey-kv-dev
  Location: westeurope

Continue with this configuration? (y/n): y

✓ Key Vault setup completed successfully!

2. Criar Service Principal (para CI/CD)

./scripts/create-service-principal.sh audissey-kv-dev

Guarde as credenciais retornadas:

3. Configurar Aplicação

Desenvolvimento Local

Adicione ao .env:

AZURE_KEY_VAULT_ENABLED=true
AZURE_KEY_VAULT_URL=https://audissey-kv-dev.vault.azure.net/

# Service Principal (apenas se não usar Azure CLI local)
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret

Produção (Azure App Service)

Configure Managed Identity:

# Enable system-assigned managed identity
az webapp identity assign \
  --name audissey-api \
  --resource-group audissey-rg

# Grant access to Key Vault
az keyvault set-policy \
  --name audissey-kv-production \
  --object-id <managed-identity-object-id> \
  --secret-permissions get list

Configure variáveis de ambiente:

az webapp config appsettings set \
  --name audissey-api \
  --resource-group audissey-rg \
  --settings \
    AZURE_KEY_VAULT_ENABLED=true \
    AZURE_KEY_VAULT_URL=https://audissey-kv-production.vault.azure.net/

Configuração CI/CD

Azure DevOps

  1. Criar Variable Group:

    • Pipeline → Library → Variable Groups
    • Nome: audissey-keyvault-secrets
    • Adicionar variáveis:
      • AZURE_KEY_VAULT_URL
      • AZURE_TENANT_ID
      • AZURE_CLIENT_ID
      • AZURE_CLIENT_SECRET (marcar como secret)
  2. Ligar ao Pipeline:

    variables:
      - group: 'audissey-keyvault-secrets'
    
  3. Usar nas steps:

    - script: npx nx build api
      env:
        AZURE_KEY_VAULT_ENABLED: true
        AZURE_KEY_VAULT_URL: $(AZURE_KEY_VAULT_URL)
        AZURE_TENANT_ID: $(AZURE_TENANT_ID)
        AZURE_CLIENT_ID: $(AZURE_CLIENT_ID)
        AZURE_CLIENT_SECRET: $(AZURE_CLIENT_SECRET)
    

GitHub Actions

name: Deploy

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install dependencies
        run: npm ci
      
      - name: Build
        env:
          AZURE_KEY_VAULT_ENABLED: true
          AZURE_KEY_VAULT_URL: ${{ secrets.AZURE_KEY_VAULT_URL }}
          AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
          AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
          AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
        run: npx nx build api

Uso na Aplicação

Automático (Recomendado)

Os segredos são carregados automaticamente no bootstrap da aplicação:

// main.ts
async function bootstrap() {
  // Loads secrets into process.env
  await initializeKeyVault();
  
  const app = await NestFactory.create(AppModule);
  // ...
}

Manual (Avançado)

Se precisar aceder diretamente ao KeyVaultService:

import { KeyVaultService } from './config/keyvault';

// Initialize
const keyVault = new KeyVaultService({
  enabled: true,
  vaultUrl: 'https://audissey-kv-dev.vault.azure.net/',
});

// Get individual secret
const jwtSecret = await keyVault.getSecret('jwt-secret');

// Get multiple secrets
const secrets = await keyVault.getSecrets([
  'mongo-root-username',
  'mongo-root-password'
]);

// Health check
const isHealthy = await keyVault.healthCheck();

Gestão de Segredos

Adicionar Novo Segredo

az keyvault secret set \
  --vault-name audissey-kv-production \
  --name "new-api-key" \
  --value "secret-value"

Atualizar Segredo

# Creates a new version (old versions are retained)
az keyvault secret set \
  --vault-name audissey-kv-production \
  --name "jwt-secret" \
  --value "new-secret-value"

Listar Segredos

az keyvault secret list \
  --vault-name audissey-kv-production \
  --output table

Ver Valor de Segredo

az keyvault secret show \
  --vault-name audissey-kv-production \
  --name "jwt-secret" \
  --query value \
  --output tsv

Rotação de Segredos

  1. Criar nova versão do segredo no Key Vault
  2. A aplicação usa automaticamente a versão mais recente
  3. Reiniciar a aplicação ou esperar pela próxima deployment

Troubleshooting

Error: Unauthorized

Problema: Não tem permissões para aceder ao Key Vault

Solução:

# Verificar acesso
az keyvault show --name audissey-kv-production

# Adicionar permissões
az keyvault set-policy \
  --name audissey-kv-production \
  --upn your-email@domain.com \
  --secret-permissions get list

Error: Secret not found

Problema: Segredo não existe no Key Vault

Solução:

# Listar segredos existentes
az keyvault secret list --vault-name audissey-kv-production

# Criar segredo em falta
az keyvault secret set \
  --vault-name audissey-kv-production \
  --name "missing-secret" \
  --value "value"

Fallback para .env

Se Key Vault falhar, a aplicação usa automaticamente variáveis de ambiente:

// Fallback behavior
const jwtSecret = await keyVault.getSecret(
  'jwt-secret',
  process.env.JWT_SECRET  // fallback value
);

Debug Mode

Ativar logs detalhados:

LOG_LEVEL=debug

Segurança

Best Practices

  1. Nunca commitar credenciais do Service Principal
  2. Usar Managed Identity em produção sempre que possível
  3. Rotacionar segredos regularmente
  4. Limitar permissões ao mínimo necessário
  5. Monitorizar acessos através dos logs do Key Vault

Auditoria

Visualizar logs de acesso:

az monitor activity-log list \
  --resource-group audissey-rg \
  --resource-type Microsoft.KeyVault/vaults \
  --output table

Alertas

Configurar alertas para:

Ambientes

Desenvolvimento

Staging

Produção

Custos

Azure Key Vault pricing:

Para a maioria dos casos, o custo é < $5/mês.

Recursos Adicionais


Última Atualização: 25 de dezembro de 2025