🔐 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
- ✅ Segurança: Segredos encriptados e versionados
- ✅ Auditoria: Logs de acesso e modificações
- ✅ Rotação: Suporte para rotação automática de segredos
- ✅ Controle de Acesso: Permissões granulares por ambiente
- ✅ Integração CI/CD: Acesso controlado em pipelines
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:
POST /auth/social/googlePOST /auth/social/facebook
| 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
Azure CLI instalado e autenticado
az loginPermissões Azure para criar Key Vaults
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á:
- Criar o Key Vault no Azure
- Configurar políticas de acesso
- Criar todos os segredos necessários
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:
AZURE_TENANT_IDAZURE_CLIENT_IDAZURE_CLIENT_SECRET
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
Criar Variable Group:
- Pipeline → Library → Variable Groups
- Nome:
audissey-keyvault-secrets - Adicionar variáveis:
AZURE_KEY_VAULT_URLAZURE_TENANT_IDAZURE_CLIENT_IDAZURE_CLIENT_SECRET(marcar como secret)
Ligar ao Pipeline:
variables: - group: 'audissey-keyvault-secrets'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
- Criar nova versão do segredo no Key Vault
- A aplicação usa automaticamente a versão mais recente
- 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
- Nunca commitar credenciais do Service Principal
- Usar Managed Identity em produção sempre que possível
- Rotacionar segredos regularmente
- Limitar permissões ao mínimo necessário
- 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:
- Acessos falhados
- Modificações de segredos
- Acessos fora de horário
Ambientes
Desenvolvimento
- Key Vault:
audissey-kv-dev - Autenticação: Azure CLI ou Service Principal
- Secrets: Valores de teste
Staging
- Key Vault:
audissey-kv-staging - Autenticação: Service Principal (CI/CD)
- Secrets: Valores semelhantes a produção
Produção
- Key Vault:
audissey-kv-production - Autenticação: Managed Identity
- Secrets: Valores reais
- Acesso: Restrito e auditado
Custos
Azure Key Vault pricing:
- Standard tier: ~$0.03 por 10,000 operações
- Premium tier: ~$1/mês por chave + operações
Para a maioria dos casos, o custo é < $5/mês.
Recursos Adicionais
Última Atualização: 25 de dezembro de 2025