DevOps Admin

Como Usar Gerenciamento de Secrets em Produção: Vault, AWS Secrets Manager e SOPS em Produção Já leu

O Problema Real: Por Que Gerenciar Secrets? Quando você trabalha em produção, inevitavelmente precisa lidar com informações sensíveis: chaves de API, senhas de banco de dados, certificados SSL, tokens de autenticação. A tentação inicial é armazenar tudo em variáveis de ambiente ou, pior ainda, commitar no repositório Git. Ambas as abordagens são vulneráveis e violam princípios básicos de segurança. O desafio aumenta conforme sua aplicação cresce: múltiplos ambientes (dev, staging, produção), rotação automática de credenciais, auditoria de acesso, distribuição segura entre servidores. Gerenciar secrets manualmente não escala. É exatamente aqui que entram ferramentas especializadas como Vault, AWS Secrets Manager e SOPS. Cada uma resolve o problema de forma diferente, com trade-offs distintos. Meu objetivo nesta aula é você entender quando usar cada uma. HashiCorp Vault: O Padrão Agnóstico em Nuvem Conceitos Fundamentais O Vault é um software open-source que centraliza o gerenciamento de secrets de forma agnóstica à nuvem. Ele funciona como um "cofre" digital: você o instancia (on-premise ou

O Problema Real: Por Que Gerenciar Secrets?

Quando você trabalha em produção, inevitavelmente precisa lidar com informações sensíveis: chaves de API, senhas de banco de dados, certificados SSL, tokens de autenticação. A tentação inicial é armazenar tudo em variáveis de ambiente ou, pior ainda, commitar no repositório Git. Ambas as abordagens são vulneráveis e violam princípios básicos de segurança.

O desafio aumenta conforme sua aplicação cresce: múltiplos ambientes (dev, staging, produção), rotação automática de credenciais, auditoria de acesso, distribuição segura entre servidores. Gerenciar secrets manualmente não escala. É exatamente aqui que entram ferramentas especializadas como Vault, AWS Secrets Manager e SOPS. Cada uma resolve o problema de forma diferente, com trade-offs distintos. Meu objetivo nesta aula é você entender quando usar cada uma.

HashiCorp Vault: O Padrão Agnóstico em Nuvem

Conceitos Fundamentais

O Vault é um software open-source que centraliza o gerenciamento de secrets de forma agnóstica à nuvem. Ele funciona como um "cofre" digital: você o instancia (on-premise ou em nuvem), e todas as suas aplicações fazem requisições HTTP para recuperar credenciais sob demanda. O Vault autentica a aplicação, verifica permissões, registra o acesso em logs de auditoria, e entrega o secret criptografado.

Um conceito crucial do Vault é a identidade dinâmica. Em vez de armazenar uma senha estática, o Vault pode gerar credenciais temporárias para bancos de dados, AWS, etc., com TTL (Time To Live) configurável. Se uma credencial é comprometida, ela expira automaticamente em minutos. Isso reduz drasticamente o dano de uma breach.

Instalação e Configuração Básica

Para demonstrar, vou instalar Vault localmente em modo de desenvolvimento (nunca faça isso em produção):

# Download e extração (macOS/Linux)
wget https://releases.hashicorp.com/vault/1.15.0/vault_1.15.0_linux_amd64.zip
unzip vault_1.15.0_linux_amd64.zip
sudo mv vault /usr/local/bin/

# Iniciar em modo dev (apenas para aprendizado)
vault server -dev

# Em outro terminal, autenticar com o token dev
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='s.XXXXXXXXXXXXXXXX'  # Token exibido no console anterior

# Verificar status
vault status

Pronto. Vault está rodando. Agora vamos armazenar um secret:

# Armazenar uma credencial no caminho kv/database
vault kv put kv/database username=admin password=supersecret

# Recuperar a credencial
vault kv get kv/database

# Output esperado:
# ====== Secret Path ======
# kv/database
#
# ====== Metadata ======
# Key                Value
# ---                -----
# created_time       2024-01-15T10:30:00.123456Z
# custom_metadata    <nil>
# deletion_time      n/a
# destroyed          false
# version            1
#
# ====== Data ======
# Key         Value
# ---         -----
# password    supersecret
# username    admin

Integração com Aplicação Python

Agora a parte prática: sua aplicação precisa ler esse secret. Aqui está um exemplo real em Python:

import hvac
import os

class VaultClient:
    def __init__(self, vault_addr: str, vault_token: str):
        self.client = hvac.Client(url=vault_addr, token=vault_token)

    def get_database_credentials(self) -> dict:
        """
        Recupera credenciais de banco de dados do Vault.
        Lança exceção se o Vault estiver indisponível ou token inválido.
        """
        try:
            response = self.client.secrets.kv.read_secret_version(
                path='database'
            )
            return response['data']['data']
        except hvac.exceptions.InvalidPath:
            raise Exception("Secret não encontrado no Vault")
        except hvac.exceptions.Unauthorized:
            raise Exception("Token do Vault expirou ou é inválido")

    def get_dynamic_db_credentials(self, db_role: str, ttl: str = '1h'):
        """
        Gera credenciais dinâmicas (temporárias) para PostgreSQL.
        O Vault criará usuário no banco com TTL de 1 hora.
        """
        try:
            response = self.client.secrets.database.generate_credentials(
                name=db_role
            )
            creds = response['data']
            return {
                'username': creds['username'],
                'password': creds['password'],
                'ttl': creds['ttl']  # Quanto tempo até expirar
            }
        except Exception as e:
            raise Exception(f"Erro ao gerar credenciais dinâmicas: {e}")

# Uso na aplicação
if __name__ == '__main__':
    vault = VaultClient(
        vault_addr='http://vault.internal:8200',
        vault_token=os.getenv('VAULT_TOKEN')
    )

    # Credenciais estáticas
    db_creds = vault.get_database_credentials()
    print(f"Conectando ao banco com usuário: {db_creds['username']}")

    # Credenciais dinâmicas (recomendado para produção)
    dynamic_creds = vault.get_dynamic_db_credentials(db_role='postgres-prod')
    print(f"Credencial temporária válida por: {dynamic_creds['ttl']}")

Para isso funcionar, instale a biblioteca cliente:

pip install hvac

Quando Usar Vault

Use Vault quando você precisa de controle total sobre secrets, quer implementar rotação automática, ou sua infraestrutura é multi-cloud. Vault é especialmente poderoso para credenciais dinâmicas em bancos de dados, mas requer que você mantenha uma instância do Vault (ou use Vault Cloud).

AWS Secrets Manager: Simplicidade Integrada à AWS

Conceitos Fundamentais

Se sua infraestrutura é totalmente AWS, o Secrets Manager oferece uma solução nativa mais simples que Vault. Você armazena secrets no serviço AWS, e suas aplicações (EC2, Lambda, ECS) obtêm acesso via IAM roles, sem precisar gerenciar tokens. O AWS Secrets Manager integra-se profundamente com outros serviços: rotaciona credenciais de RDS automaticamente, gera credenciais temporárias para bancos, e oferece replicação multi-região.

A grande vantagem é a integração IAM: você não precisa injetar tokens em containers ou variáveis de ambiente. Uma EC2 instance com a role correta simplesmente faz a chamada à API, e o AWS verifica permissões automaticamente. Isso elimina toda uma classe de vulnerabilidades.

Criando e Acessando Secrets

Vamos criar um secret via AWS CLI:

# Criar um secret com dados arbitrários
aws secretsmanager create-secret \
    --name prod/database/postgres \
    --description "Credenciais do RDS PostgreSQL em produção" \
    --secret-string '{"username":"admin","password":"MySecure#Pass123","host":"prod-db.c1234567890.us-east-1.rds.amazonaws.com","port":5432}'

# Output esperado:
# {
#     "ARN": "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/database/postgres-AbCdEf",
#     "Name": "prod/database/postgres",
#     "VersionId": "a1b2c3d4-e5f6-47ab-8c9d-0e1f2a3b4c5d"
# }

# Recuperar o secret
aws secretsmanager get-secret-value \
    --secret-id prod/database/postgres \
    --query SecretString \
    --output text

Integração com Aplicação Python

Aqui está como sua aplicação acessa o secret (assumindo que a role IAM tem permissão):

import boto3
import json
from typing import Dict

class AWSSecretsClient:
    def __init__(self, region: str = 'us-east-1'):
        self.client = boto3.client('secretsmanager', region_name=region)

    def get_secret(self, secret_name: str) -> Dict:
        """
        Recupera um secret do AWS Secrets Manager.
        A autenticação acontece via IAM role da instância/função.
        """
        try:
            response = self.client.get_secret_value(SecretId=secret_name)
            # Se for string JSON, fazer parse
            if 'SecretString' in response:
                return json.loads(response['SecretString'])
            # Se for arquivo binário
            else:
                return response['SecretBinary']
        except self.client.exceptions.ResourceNotFoundException:
            raise Exception(f"Secret '{secret_name}' não encontrado")
        except self.client.exceptions.InvalidRequestException:
            raise Exception("Requisição inválida ao Secrets Manager")

    def list_secrets(self, filters: Dict = None) -> list:
        """Lista todos os secrets (com filtros opcionais)."""
        try:
            response = self.client.list_secrets(
                Filters=filters or []
            )
            return [s['Name'] for s in response['SecretList']]
        except Exception as e:
            raise Exception(f"Erro ao listar secrets: {e}")

# Uso na aplicação
if __name__ == '__main__':
    secrets = AWSSecretsClient(region='us-east-1')

    # Recuperar credenciais de banco
    db_creds = secrets.get_secret('prod/database/postgres')
    print(f"Conectando a {db_creds['host']} com usuário {db_creds['username']}")

    # Listar todos os secrets (útil para debug)
    all_secrets = secrets.list_secrets()
    print(f"Secrets disponíveis: {all_secrets}")

Para isso funcionar, instale boto3:

pip install boto3

Configurando Rotação Automática

Uma feature poderosa do AWS Secrets Manager é a rotação automática de credenciais RDS:

# Criar um secret para RDS com rotação automática
aws secretsmanager create-secret \
    --name prod/rds/master \
    --description "Master credentials for RDS rotation" \
    --secret-string '{"username":"admin","password":"InitialPass123"}'

# Ativar rotação automática a cada 30 dias
aws secretsmanager rotate-secret \
    --secret-id prod/rds/master \
    --rotation-rules AutomaticallyAfterDays=30 \
    --rotation-lambda-arn arn:aws:lambda:us-east-1:123456789012:function:SecretsManagerRotation

Quando Usar AWS Secrets Manager

Use quando sua infraestrutura é majoritariamente AWS e você quer máxima simplicidade com integração IAM. Perfeito para aplicações serverless (Lambda), RDS, e ECS. Desvantagem: lock-in com AWS e menos flexibilidade que Vault para cenários multi-cloud.

SOPS: Segredos em Repositório (Com Criptografia)

Conceitos Fundamentais

SOPS (Secrets Operations) inverte a lógica: em vez de centralizar secrets em um serviço, você os armazena criptografados no repositório Git da sua aplicação. Quando alguém precisa do valor real, SOPS descriptografa usando chaves KMS (AWS, GCP, Azure) ou GPG. É particularmente útil para Infrastructure as Code (Terraform, Kubernetes) onde você quer versionamento de secrets junto com infraestrutura.

A filosofia do SOPS é: "criptografe apenas os valores sensíveis, deixe o resto do arquivo legível". Isso facilita code review: você vê qual secret foi modificado sem expor o valor. O trade-off é que você precisa de acesso às chaves de criptografia (IAM para KMS, chave GPG) para descriptografar.

Instalação e Setup com KMS

Vou demonstrar SOPS com AWS KMS (mais seguro que GPG em produção):

# Instalar SOPS (macOS com Homebrew)
brew install sops

# Ou baixar direto (Linux)
wget https://github.com/mozilla/sops/releases/download/v3.8.1/sops-v3.8.1.linux.amd64
chmod +x sops-v3.8.1.linux.amd64
sudo mv sops-v3.8.1.linux.amd64 /usr/local/bin/sops

# Verificar instalação
sops --version

Agora crie uma chave KMS na AWS:

# Criar chave KMS para SOPS
aws kms create-key \
    --description "SOPS encryption key for prod secrets" \
    --region us-east-1

# Output:
# {
#     "KeyMetadata": {
#         "KeyId": "12345678-1234-1234-1234-123456789012",
#         "Arn": "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
#     }
# }

# Criar um alias para facilitar referência
aws kms create-alias \
    --alias-name alias/sops-prod \
    --target-key-id 12345678-1234-1234-1234-123456789012

Criando e Descriptografando Secrets

Crie um arquivo com seus secrets:

# secrets.yaml (conteúdo original em texto plano)
database:
  host: prod-db.c1234567890.us-east-1.rds.amazonaws.com
  username: admin
  password: MySecure#Pass123
  port: 5432

api:
  key: sk-1234567890abcdefghijklmnopqrstuvwxyz
  secret: super_secret_value_12345

Agora criptografe com SOPS:

# Criptografar usando KMS
sops --encrypt \
    --kms arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012 \
    secrets.yaml > secrets.enc.yaml

# Visualizar arquivo criptografado
cat secrets.enc.yaml
# Output (dados sensíveis criptografados, mas metadata legível):
# database:
#     host: prod-db.c1234567890.us-east-1.rds.amazonaws.com
#     password: ENC[AES256_GCM,data:abcdef123456...,iv:xyz...,tag:...,type:str]
#     port: 5432
#     username: ENC[AES256_GCM,data:1234567890...,iv:abc...,tag:...,type:str]
# sops:
#     kms:
#     - arn: arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012
#       created_at: '2024-01-15T10:30:00Z'
#       enc: AQIDAHg...
#       aws_profile: ''
#     lastmodified: '2024-01-15T10:30:05Z'
#     mac: ENC[AES256_GCM,data:5678...,iv:def...,tag:...,type:str]
#     version: 3.8.1

# Descriptografar para usar
sops --decrypt secrets.enc.yaml

# Editar arquivo criptografado (SOPS descriptografa temporariamente)
sops secrets.enc.yaml
# Seu editor padrão abre com valores descriptografados
# Ao salvar e fechar, SOPS re-criptografa automaticamente

Integração em Pipeline CI/CD

Na prática, você versionaria secrets.enc.yaml no Git, mas nunca secrets.yaml:

# .gitignore
secrets.yaml        # Nunca commitar valores em texto plano
*.decrypted.yaml

# secrets.enc.yaml é commitado normalmente (está criptografado)

Em um pipeline Kubernetes com ArgoCD, você decodifica secrets assim:

#!/bin/bash
# deploy.sh - script executado no CI/CD com credenciais KMS

# Descriptografar secrets e aplicar ao cluster
sops --decrypt secrets.enc.yaml | kubectl apply -f -

# Ou usar o plugin Kustomize do SOPS
kustomize build . | sops --encrypt /dev/stdin > kustomization.enc.yaml

Programaticamente com Python

Para aplicações que precisam ler secrets criptografados em tempo de execução:

import subprocess
import json
import yaml

class SOPSClient:
    def __init__(self, encrypted_file_path: str):
        self.file_path = encrypted_file_path

    def get_decrypted_config(self) -> dict:
        """
        Executa sops para descriptografar e retorna o config como dict.
        Requer que as credenciais KMS estejam disponíveis (AWS_PROFILE, IAM role, etc)
        """
        try:
            result = subprocess.run(
                ['sops', '--decrypt', self.file_path],
                capture_output=True,
                text=True,
                check=True
            )

            # Parseando YAML descriptografado
            config = yaml.safe_load(result.stdout)
            return config
        except subprocess.CalledProcessError as e:
            raise Exception(f"Erro ao descriptografar com SOPS: {e.stderr}")
        except FileNotFoundError:
            raise Exception("SOPS não encontrado no PATH")

# Uso
if __name__ == '__main__':
    sops = SOPSClient('/app/config/secrets.enc.yaml')
    config = sops.get_decrypted_config()

    db_password = config['database']['password']
    api_key = config['api']['key']

    print(f"Conectando com senha: {db_password[:10]}...")

Quando Usar SOPS

Use SOPS quando seus secrets fazem parte da Infrastructure as Code (Terraform, Kubernetes manifests) e você quer versionamento completo no Git. Excelente para DevOps e GitOps workflows. Desvantagem: não há rotação automática de credenciais, e requer acesso às chaves KMS em tempo de deploy.

Comparação Prática: Qual Ferramenta Escolher?

Aspecto Vault AWS Secrets Manager SOPS
Rotação Automática Sim (dinâmica para DB) Sim (para RDS) Não
Multi-Cloud Sim Apenas AWS Suporta KMS/GCP/Azure
Integração IAM Não Sim (nativa) Sim (via KMS)
Versionamento Git Não Não Sim
Complexidade Setup Alta Baixa Média
Melhor Para Multi-cloud, credenciais dinâmicas Apps AWS puro IaC + versionamento
Custo Self-hosted ou Vault Cloud ~$0.40 por 10k requisições Custo KMS apenas

Cenários recomendados:

  • Startup com tudo em AWS + Lambda/RDS: AWS Secrets Manager
  • Empresa multi-cloud (AWS + GCP + On-premise): Vault
  • Time DevOps com Kubernetes + GitOps: SOPS
  • Aplicação legada com múltiplos ambientes: Vault
  • Segurança máxima com rotação DB: Vault + SOPS em conjunto

Boas Práticas Universais

Independente da ferramenta escolhida, algumas práticas nunca devem ser quebradas:

1. Princípio do Menor Privilégio: Uma aplicação nunca deve ter acesso a todos os secrets. Use roles, policies, ou RBAC para limitar. Uma Lambda que só precisa de credenciais de S3 não deve ter acesso a senhas de RDS.

2. Auditoria Completa: Log todo acesso (quem, quando, qual secret). Isso é crítico para investigações de segurança pós-breach.

3. Rotação Regular: Mesmo com credenciais estáticas, altere-as a cada 90 dias no mínimo. Com credenciais dinâmicas (Vault), faça TTL curto (1-24 horas).

4. Nenhum Secret em Logs: Nunca print ou log um valor de secret. Isso inclui exceções e stack traces. Use mascaramento.

# ❌ ERRADO
except Exception as e:
    logger.error(f"Failed with password: {db_password}", exc_info=True)

# ✅ CORRETO
except Exception as e:
    logger.error("Failed to connect to database", exc_info=True)
    # Investigar logs de auditoria do serviço de secrets, não da app

5. Secrets em Variáveis de Ambiente com Cuidado: Se você usa env vars, elas passam por processos filhos e podem vazar em logs de sistema. Prefira ler diretamente do serviço de secrets.

Conclusão

Gerenciar secrets em produção é uma tarefa que não tolera atalhos. As três ferramentas apresentadas —Vault, AWS Secrets Manager e SOPS— resolvem o mesmo problema com filosofias distintas. Vault oferece máxima flexibilidade e credenciais dinâmicas, ideal para arquiteturas complexas. AWS Secrets Manager é a escolha pragmática para quem já está no ecossistema AWS. SOPS é o campeão do versionamento e GitOps, permitindo secrets criptografados no repositório. O grande aprendizado é que não existe ferramenta única: você deve escolher baseado em sua arquitetura, constraints de operação e necessidades de compliance. Na minha experiência, o mais comum em startups é começar simples (Secrets Manager ou variáveis de ambiente), e escalar para Vault conforme a complexidade cresce.

Referências


Artigos relacionados