Secrets no Kubernetes: o problema e as soluções

1. O problema fundamental: Secrets não são tão secretos

1.1. Codificação Base64 não é criptografia

Muitos desenvolvedores acreditam que os Secrets do Kubernetes são seguros por padrão. A realidade é que o Kubernetes apenas codifica os valores em Base64 — uma transformação reversível instantaneamente. Qualquer pessoa com acesso ao cluster pode decodificá-los:

# Criando um Secret aparentemente "protegido"
kubectl create secret generic db-password --from-literal=password=SuperS3nh@

# Obtendo o valor codificado
kubectl get secret db-password -o jsonpath='{.data.password}'
# Saída: U3VwZXJTM25oQA==

# Decodificando em segundos
echo "U3VwZXJTM25oQA==" | base64 --decode
# Saída: SuperS3nh@

1.2. Acesso indiscriminado ao etcd e ao kube-apiserver

O etcd armazena todos os Secrets em texto puro por padrão. Se um atacante obtiver acesso ao etcd ou ao kube-apiserver, todos os segredos do cluster ficam expostos. Não há criptografia automática em repouso.

1.3. Vazamento em logs, volumes e variáveis de ambiente

Secrets injetados como variáveis de ambiente ou montados como volumes podem vazar facilmente:

# Exemplo de Pod que expõe Secret como variável de ambiente
apiVersion: v1
kind: Pod
metadata:
  name: app-vulneravel
spec:
  containers:
  - name: app
    image: minha-app
    env:
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-password
          key: password

Qualquer processo dentro do container pode ler /proc/self/environ e capturar o segredo. Além disso, logs de aplicação podem inadvertidamente imprimir essas variáveis.

2. Boas práticas de criação e armazenamento de Secrets

2.1. Evitar Secrets hardcoded no YAML e no Git

Nunca versionar Secrets em repositórios Git. Utilize ferramentas como git-secrets ou talisman para bloquear commits acidentais:

# Instalando git-secrets
brew install git-secrets
git secrets --install
git secrets --register-aws

# Escaneando repositório
git secrets --scan

2.2. Uso de namespaces e RBAC para isolar acesso

Crie namespaces dedicados por equipe e aplique RBAC restritivo:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: equipe-a
  name: secret-reader-restrito
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list"]  # Sem permissão de create ou update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: equipe-a
  name: restrito-equipe-a
subjects:
- kind: User
  name: dev-alice
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: secret-reader-restrito
  apiGroup: rbac.authorization.k8s.io

2.3. Rotação periódica e versões de Secrets

Implemente rotação automática com um operador como o Reloader:

# Anotação para reiniciar Pods quando Secret muda
metadata:
  annotations:
    reloader.stakater.com/match: "true"

3. Criptografia em repouso: Encryption at Rest

3.1. Configuração do EncryptionConfiguration no etcd

Ative a criptografia em repouso editando o arquivo de configuração do kube-apiserver:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aesgcm:
          keys:
            - name: key1
              secret: c2VjcmV0LWtleS0zMi1ieXRlcy1sb25nLTEyMzQ1Njc4OTA=
      - identity: {}  # Fallback para Secrets já existentes

3.2. Escolha do provedor de criptografia

Prefira KMS (Key Management Service) em produção para gerenciamento centralizado de chaves:

# Exemplo com AWS KMS
providers:
  - kms:
      name: aws-encryption
      endpoint: https://kms.us-east-1.amazonaws.com
      cachesize: 100
      timeout: 3s

3.3. Testando a criptografia e revogação de chaves

Verifique se a criptografia está ativa:

# Criar Secret de teste
kubectl create secret generic test-secret --from-literal=test=value

# Acessar etcd diretamente (apenas com acesso privilegiado)
ETCDCTL_API=3 etcdctl get /registry/secrets/default/test-secret \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt \
  --key=/etc/kubernetes/pki/etcd/healthcheck-client.key
# Saída: dados criptografados (não legíveis)

4. Gerenciamento externo de Secrets com provedores dedicados

4.1. Integração com HashiCorp Vault e CSI Driver

Instale o CSI Driver e monte Secrets diretamente do Vault:

apiVersion: secrets-store.csi.x-k8s.io/v1
kind: SecretProviderClass
metadata:
  name: vault-db
spec:
  provider: vault
  parameters:
    vaultAddress: "https://vault.exemplo.com:8200"
    roleName: "app-role"
    objects: |
      - objectName: "db-password"
        secretPath: "secret/data/db"
        secretKey: "password"

4.2. AWS Secrets Manager / Azure Key Vault / GCP Secret Manager

Exemplo com AWS Secrets Manager e External Secrets Operator:

apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: aws-db-secret
spec:
  refreshInterval: "1h"
  secretStoreRef:
    name: aws-secretstore
    kind: SecretStore
  target:
    name: db-credentials
  data:
  - secretKey: password
    remoteRef:
      key: production/db/password

4.3. Sincronização automática com External Secrets Operator

O External Secrets Operator sincroniza automaticamente Secrets de provedores externos para o Kubernetes, mantendo-os atualizados.

5. Soluções nativas e ferramentas para injeção segura

5.1. Sealed Secrets: criptografia declarativa com GitOps

Com Sealed Secrets, você pode versionar Secrets criptografados no Git:

# Criar SealedSecret a partir de um Secret comum
kubeseal --controller-namespace sealed-secrets \
  --controller-name sealed-secrets \
  --format yaml < db-secret.yaml > sealed-db-secret.yaml

# O SealedSecret pode ser commitado no Git com segurança
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-secret
spec:
  encryptedData:
    password: AgBy3i4F5g6H7j8K9l0...

5.2. Mozilla SOPS + Helm Secrets para templates criptografados

Criptografe valores de Helm charts com SOPS e chave PGP ou KMS:

# Criptografar valores sensíveis
sops --encrypt --pgp FINGERPRINT values.yaml > values.enc.yaml

# Instalar com Helm usando o plugin secrets
helm secrets install minha-app ./chart -f values.enc.yaml

5.3. Fluxo de trabalho com ArgoCD e repositórios seguros

Configure ArgoCD para usar Sealed Secrets ou SOPS, garantindo que o Git nunca contenha Secrets em texto puro.

6. Monitoramento e auditoria de acesso a Secrets

6.1. Audit logging do kube-apiserver para acesso a Secrets

Ative audit logging e filtre por operações em Secrets:

apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
  resources:
  - group: ""
    resources: ["secrets"]
  verbs: ["get", "list", "watch"]

6.2. Ferramentas de detecção de vazamento

Use trivy para escanear imagens e kubectl scan para detectar Secrets expostos:

# Escanear cluster com trivy
trivy k8s --report summary --severity HIGH,CRITICAL cluster

# Detectar Secrets em logs
kubectl logs pod-name | grep -E '(password|secret|token|key)'

6.3. Políticas de segurança com OPA/Gatekeeper e Kyverno

Imponha políticas para evitar práticas inseguras:

# Kyverno policy: proibir envFrom com todos os Secrets
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: block-envfrom-secrets
spec:
  validationFailureAction: enforce
  rules:
  - name: block-envfrom-all
    match:
      resources:
        kinds:
        - Pod
    validate:
      message: "Não use envFrom com todos os Secrets"
      pattern:
        spec:
          containers:
          - (envFrom):
            - secretRef:
                name: "*"

7. Mitigação de riscos em ambientes multi-tenant

7.1. Isolamento com namespaces e NetworkPolicies

Isole namespaces e restrinja tráfego de rede para limitar exfiltração de Secrets.

7.2. Pod Security Standards (Baseline/Restricted)

Aplique padrões de segurança em nível de Pod:

apiVersion: v1
kind: Namespace
metadata:
  name: tenant-restrito
  labels:
    pod-security.kubernetes.io/enforce: restricted

7.3. Limitação de montagem de Secrets por ServiceAccount

Associe ServiceAccounts específicas a roles restritas e evite montagens desnecessárias de Secrets.


Referências