Skip to main content

Visão Geral

Secrets são objetos do Kubernetes para armazenar dados sensíveis como tokens, chaves, senhas e certificados.

Tipos de Secrets

Opaque (generic)

apiVersion: v1
kind: Secret
metadata:
  name: app-secrets
type: Opaque
stringData:
  DB_PASSWORD: "postgres123"
  API_KEY: "sk-live-xxxxx"

TLS Secret

apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
  tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t...

Docker Registry Secret

apiVersion: v1
kind: Secret
metadata:
  name: registry-secret
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4...

SSH Auth

apiVersion: v1
kind: Secret
metadata:
  name: ssh-key
type: kubernetes.io/ssh-auth
data:
  ssh-privatekey: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t...
  ssh-publickey: c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFB...

Criar Secrets

# De literals
kubectl create secret generic db-creds \
  --from-literal=username=admin \
  --from-literal=password='secret123!'

# De arquivo
kubectl create secret generic tls-cert \
  --from-file=tls.crt=./server.crt \
  --from-file=tls.key=./server.key

# De .env file
kubectl create secret generic app-env \
  --from-env-file=./.env

# Docker registry
kubectl create secret docker-registry my-registry \
  --docker-server=https://index.docker.io \
  --docker-username=user \
  --docker-password=token \
  --docker-email=email@example.com

# TLS shorthand
kubectl create secret tls my-tls \
  --cert=./server.crt \
  --key=./server.key

Usar Secrets

Variáveis de Ambiente

env:
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: db-creds
        key: password
        optional: false

Todas as variáveis

envFrom:
  - secretRef:
      name: db-creds

Volume

volumeMounts:
  - name: secrets
    mountPath: /etc/secrets
    readOnly: true
volumes:
  - name: secrets
    secret:
      secretName: db-creds
      defaultMode: 0640
      optional: true
      items:
        - key: password
          path: db-pass

file mode (0777, base10 ou 0777)

volumes:
  - name: secrets
    secret:
      secretName: db-creds
      items:
        - key: password
          path: password
          mode: 0400

ServiceAccount Secrets

apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
secrets:
  - name: app-sa-token-xyz

Kubernetes External Secrets

apiVersion: external-secrets.io/v1beta1
kind: ClusterSecretStore
metadata:
  name: aws-secrets-manager
spec:
  provider:
    aws:
      service: SecretsManager
      region: us-east-1
      auth:
        secretRef:
          accessKeyIDSecretRef:
            name: aws-creds
            key: access-key
          secretAccessKeySecretRef:
            name: aws-creds
            key: secret-key
---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-external-secrets
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: app-secrets
    creationPolicy: Owner
  data:
    - secretKey: DB_PASSWORD
      remoteRef:
        key: /production/database
        property: password
    - secretKey: API_KEY
      remoteRef:
        key: /production/app
        property: api_key
        metadata:
          conversionStrategy: Default
          decodingStrategy: None

Vault Integration

Agent Injector

apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
  namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: vault-auth-delegator
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
  - kind: ServiceAccount
    name: app-sa
    namespace: production
---
apiVersion: v1
kind: Pod
metadata:
  name: app
  annotations:
    vault.hashicorp.com/agent-inject: "true"
    vault.hashicorp.com/role: "app"
    vault.hashicorp.com/agent-inject-secret-db: "database/creds/app"
    vault.hashicorp.com/agent-inject-template-db: |
      {{- with secret "database/creds/app" -}}
      DB_PASSWORD={{ .Data.password }}
      DB_USER={{ .Data.username }}
      {{- end }}

Sealed Secrets (Bitnami)

# Instalar controller
kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/latest/download/controller.yaml

# Criar sealed secret (criptografado)
kubectl create secret generic db-creds \
  --dry-run=client \
  --from-literal=password=secret \
  -o json | kubeseal --cert pub-cert.pem -o yaml > sealed-secret.yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-creds
  namespace: production
spec:
  encryptedData:
    password: AgA...
  target:
    kind: Secret
    apiVersion: v1
    metadata:
      name: db-creds

Best Practices

  1. Encrypt etcd com chaves KMS
  2. RBAC - Limitar acesso a secrets
  3. Auditar acesso a secrets
  4. Rotacionar segredos regularmente
  5. Usar External Secrets para integração com vault/SM
  6. Não commitar secrets no Git
  7. Usar short-lived tokens via ServiceAccount

Encrypt Secrets at Rest

# /etc/kubernetes/encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded-32-byte-key>
      - identity: {}
# Editar kube-apiserver
KUBEADM_FLAGS="--encryption-provider-config=/etc/kubernetes/encryption-config.yaml"

Comandos Úteis

# Listar secrets
kubectl get secrets -A

# Ver secret decoded
kubectl get secret my-secret -o jsonpath='{.data.password}' | base64 -d

# Listar com detalhes
kubectl describe secret my-secret

# Ver todos os secrets de um namespace
kubectl get secrets -n production -o wide

# Check if secrets are encrypted
kubectl get secret <secret-name> -o yaml | grep -i "kubernetes.io/encrypted"