Gerenciamento de Identidades Cloud-Native com SPIFFE e SPIRE: Implementação Prática

O Problema da Identidade em Ambientes Distribuídos

Em sistemas distribuídos, especialmente em ambientes kubernetes e cloud-native, a autenticação e autorização entre serviços tornam-se um desafio crítico. Soluções tradicionais, como credenciais estáticas ou certificados TLS manuais, não escalam e introduzem riscos de segurança. O spiffe (Secure Production Identity Framework for Everyone) surge como um padrão aberto para definir identidades de workloads, enquanto o SPIRE (SPIFFE Runtime Environment) implementa esse framework de forma prática.

Arquitetura SPIFFE: Conceitos Fundamentais

O SPIFFE define uma identidade única para cada workload, representada por um SPIFFE ID no formato spiffe://trust-domain/path/to/workload. Essa identidade é atestada por um SPIFFE Verifiable Identity Document (SVID), geralmente um certificado X.509 de curta duração. O SPIRE atua como a autoridade de certificação (CA) e o agente de atestação, emitindo e renovando SVIDs automaticamente.

Componentes do SPIRE

O SPIRE consiste em dois componentes principais:

  • SPIRE Server: Gerencia o trust domain, emite SVIDs e valida atestações de workloads.
  • SPIRE Agent: Executa em cada nó (node) do cluster, atestando workloads e distribuindo SVIDs.

Deploy do SPIRE em Kubernetes

Para implementar o SPIRE em um cluster Kubernetes, utilize o Helm chart oficial. Primeiro, adicione o repositório:

helm repo add spire https://spiffe.io/spire
helm repo update

Em seguida, instale o SPIRE Server e Agent com um namespace dedicado:

kubectl create namespace spire
helm install spire spire/spire -n spire

O deployment inclui um ClusterIP para o Server e um DaemonSet para os Agents, garantindo cobertura em todos os nós.

Configuração de Trust Domains e Entries

O trust domain é a raiz de confiança do SPIFFE. No SPIRE, ele é definido no arquivo de configuração do Server (server.conf):

trust_domain = "example.org"

server {
  bind_address = "0.0.0.0"
  bind_port = "8081"
  trust_domain = "example.org"
  data_dir = "/run/spire/data"
  log_level = "DEBUG"
}

Para registrar workloads, crie entries no SPIRE Server. Por exemplo, para um pod Kubernetes:

kubectl exec -n spire spire-server-0 -- 
  /opt/spire/bin/spire-server entry create 
  -parentID spiffe://example.org/spire/agent/k8s_psat/cluster/ns/spire/sa/spire-agent 
  -spiffeID spiffe://example.org/ns/default/sa/my-service 
  -selector k8s:ns:default 
  -selector k8s:sa:my-service 
  -node

Integração com Workloads: Sidecar e SDKs

Workloads podem consumir SVIDs de duas formas:

  1. SPIRE Agent API: O workload se conecta ao Unix Domain Socket do Agent (/tmp/spire-agent/public/api.sock) para obter SVIDs.
  2. Workload API: Uma sidecar (como o spire-agent) gerencia a comunicação com o SPIRE Agent.

Exemplo de código em Go para obter um SVID via Workload API:

package main

import (
  "crypto/tls"
  "log"
  "net/http"
  
  "github.com/spiffe/go-spiffe/v2/workloadapi"
)

func main() {
  ctx := context.Background()
  
  // Conecta à Workload API
  client, err := workloadapi.New(ctx, workloadapi.WithAddr("unix:///tmp/spire-agent/public/api.sock"))
  if err != nil {
    log.Fatal(err)
  }
  defer client.Close()
  
  // Obtém o SVID
  svid, err := client.FetchX509SVID(ctx)
  if err != nil {
    log.Fatal(err)
  }
  
  // Configura TLS com o SVID
  tlsConfig := &tls.Config{
    Certificates: []tls.Certificate{svid.Default()},
  }
  
  httpClient := &http.Client{Transport: &http.Transport{TLSClientConfig: tlsConfig}}
  resp, err := httpClient.Get("https://target-service:8443")
  // ...
}

Automação com SPIFFE Federation

Em ambientes multi-cluster ou híbridos, a federação SPIFFE permite estabelecer confiança entre trust domains. Configure a federação no SPIRE Server:

bundle_endpoint {
  address = "0.0.0.0"
  port = 8443
}

federation {
  bundle_endpoint_url = "https://spire-server-other-cluster:8443"
  trust_domain = "other-cluster.example"
}

Os bundles são trocados periodicamente para validar SVIDs entre clusters.

Monitoramento e Debugging

O SPIRE expõe métricas Prometheus no endpoint /metrics. Configure um ServiceMonitor para integração com o Prometheus Operator:

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: spire-server
  namespace: spire
spec:
  selector:
    matchLabels:
      app: spire-server
  endpoints:
  - port: metrics
    interval: 30s

Para debugging, verifique logs do Agent e Server:

kubectl logs -n spire -l app=spire-server --tail=50
kubectl logs -n spire -l app=spire-agent --tail=50

Casos de Uso Avançados

Além da autenticação mTLS, o SPIFFE/SPIRE pode ser integrado com:

  • Istio: Para políticas de autorização baseadas em SPIFFE IDs.
  • Envoy: Como fonte de identidade para filtros de rede.
  • Vault: Para emissões de tokens JWT com identidades SPIFFE.

Exemplo de política Istio usando SPIFFE IDs:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: allow-spiffe-ids
spec:
  rules:
  - from:
    - source:
        principals: ["spiffe://example.org/ns/default/sa/allowed-service"]