Como usar o Vault Agent para injetar segredos em pods Kubernetes

1. Fundamentos do Vault Agent e sua integração com Kubernetes

O Vault Agent é um componente do HashiCorp Vault projetado para automatizar a autenticação e injeção de segredos em aplicações. Quando integrado ao Kubernetes, ele opera como um sidecar dentro do pod, interceptando requisições de inicialização e injetando segredos diretamente no sistema de arquivos do contêiner principal.

A arquitetura da integração envolve três componentes principais:

  • Vault Server: responsável por armazenar e gerenciar segredos, políticas e métodos de autenticação
  • Vault Agent Injector: um mutating admission webhook que modifica dinamicamente as especificações dos pods
  • Pods Kubernetes: que recebem os segredos injetados sem necessidade de alterações no código da aplicação

As vantagens sobre abordagens tradicionais são significativas. Enquanto variáveis de ambiente estáticas expõem segredos em texto plano e Secrets nativos do Kubernetes exigem gerenciamento manual de rotação, o Vault Agent oferece:

  • Renovação automática de segredos dinâmicos
  • Políticas granulares de acesso
  • Auditoria completa de acessos
  • Sem exposição de segredos em manifestos YAML

2. Pré-requisitos e configuração inicial do ambiente

Para começar, é necessário ter um cluster Kubernetes funcional e o Helm instalado. A instalação do Vault Server pode ser feita com:

helm repo add hashicorp https://helm.releases.hashicorp.com
helm install vault hashicorp/vault --set "server.dev.enabled=true"

Após a instalação, configure o Kubernetes Auth Method no Vault:

vault auth enable kubernetes

vault write auth/kubernetes/config \
    token_reviewer_jwt="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
    kubernetes_host="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT" \
    kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

Crie uma política e role de acesso para os pods:

vault policy write app-policy - <<EOF
path "secret/data/app/*" {
  capabilities = ["read"]
}
EOF

vault write auth/kubernetes/role/app-role \
    bound_service_account_names=app-sa \
    bound_service_account_namespaces=default \
    policies=app-policy \
    ttl=1h

3. Instalação e configuração do Vault Agent Injector

O Vault Agent Injector é um webhook que modifica pods automaticamente. Instale-o com:

helm install vault-agent-injector hashicorp/vault-agent-injector \
    --set "agentImage.repository=hashicorp/vault" \
    --set "agentImage.tag=1.15.0"

Para habilitar a injeção em um deployment, adicione annotations ao manifesto:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
  namespace: default
spec:
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "app-role"
    spec:
      serviceAccountName: app-sa
      containers:
      - name: app-container
        image: nginx:latest

Os parâmetros essenciais são:

  • vault.hashicorp.com/agent-inject: ativa o sidecar do Vault Agent
  • vault.hashicorp.com/role: define qual role do Kubernetes Auth Method será usada

4. Injeção de segredos estáticos em volumes de arquivos

Para injetar segredos estáticos, utilize as annotations específicas:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  template:
    metadata:
      annotations:
        vault.hashicorp.com/agent-inject: "true"
        vault.hashicorp.com/role: "app-role"
        vault.hashicorp.com/agent-inject-secret-db-creds: "secret/data/app/database"
        vault.hashicorp.com/agent-inject-template-db-creds: |
          {{- with secret "secret/data/app/database" -}}
          {{ .Data.data.username }}:{{ .Data.data.password }}
          {{- end -}}

O segredo será injetado em /vault/secrets/db-creds dentro do contêiner principal. O template personalizado permite formatar os dados conforme necessário.

Exemplo prático de injeção de credenciais de banco de dados:

vault kv put secret/data/app/database username=admin password=Str0ngP@ss

O arquivo gerado no pod conterá admin:Str0ngP@ss, pronto para ser lido pela aplicação.

5. Injeção de segredos dinâmicos com Vault Agent

Para segredos dinâmicos, configure o database secrets engine no Vault:

vault secrets enable database

vault write database/config/postgres-db \
    plugin_name=postgresql-database-plugin \
    allowed_roles="db-role" \
    connection_url="postgresql://{{username}}:{{password}}@postgres:5432/mydb" \
    username="vault-admin" \
    password="admin-password"

vault write database/roles/db-role \
    db_name=postgres-db \
    creation_statements="CREATE USER \"{{name}}\" WITH PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
    default_ttl="1h" \
    max_ttl="24h"

Configure o template no deployment para renovação automática:

vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/db-role"
vault.hashicorp.com/agent-inject-template-db-creds: |
  {{- with secret "database/creds/db-role" -}}
  {{ .Data.username }}:{{ .Data.password }}
  {{- end -}}

O Vault Agent renovará automaticamente as credenciais antes do lease expirar, garantindo acesso contínuo ao banco de dados.

6. Estratégias de segurança e boas práticas

Para limitar permissões, crie políticas granulares:

vault policy write app-policy - <<EOF
path "secret/data/app/*" {
  capabilities = ["read"]
  allowed_parameters = {
    "username" = []
    "password" = []
  }
}
EOF

Utilize vault.hashicorp.com/agent-run-as-user para executar o sidecar com usuário não-root:

vault.hashicorp.com/agent-run-as-user: "1000"

Combine com securityContext no contêiner principal:

securityContext:
  runAsUser: 1000
  runAsGroup: 1000
  fsGroup: 1000

Monitore leases e renove tokens automaticamente configurando vault.hashicorp.com/agent-extra-secret para tokens de renovação.

7. Troubleshooting e depuração da injeção de segredos

Verifique logs do sidecar para diagnosticar problemas:

kubectl logs <pod-name> -c vault-agent

Teste conectividade entre pod e Vault Server:

kubectl exec <pod-name> -c vault-agent -- vault status

Erros comuns incluem:

  • Falha de autenticação: verifique se o service account está corretamente vinculado à role
  • Template malformado: valide a sintaxe Go template com vault read manual
  • Políticas ausentes: confirme se a política permite acesso ao caminho do segredo

Para depurar, inspecione o webhook:

kubectl describe mutatingwebhookconfiguration vault-agent-injector-cfg

8. Casos de uso avançados e integração com ecossistema

Para injeção em múltiplos contêineres no mesmo pod, especifique annotations por contêiner:

vault.hashicorp.com/agent-inject-secret-container1: "secret/data/app1"
vault.hashicorp.com/agent-inject-secret-container2: "secret/data/app2"

Combine com service mesh como Istio para segurança adicional:

annotations:
  sidecar.istio.io/inject: "true"
  vault.hashicorp.com/agent-inject: "true"

Estratégias de rotação sem reinicialização de pods podem ser implementadas com:

  • vault.hashicorp.com/agent-inject-command: executa comando pós-injeção
  • vault.hashicorp.com/agent-inject-command-period: define período de verificação

Exemplo de rotação automática:

vault.hashicorp.com/agent-inject-command: "/bin/sh -c 'kill -HUP 1'"
vault.hashicorp.com/agent-inject-command-period: "30m"

Isso envia SIGHUP para o processo principal a cada 30 minutos, forçando recarga de configurações sem reinicializar o pod.

Referências