Claude Platform Docs
AdministraçãoProvedores de identidade

Usar WIF com SPIFFE

Autentique workloads SPIFFE na Claude API usando JWT-SVIDs do SPIRE ou de qualquer outro emissor compatível com SPIFFE.

SPIFFE é o padrão da CNCF para emissão de identidade para workloads (cargas de trabalho). SPIRE é sua implementação de referência de código aberto, e vários produtos comerciais também emitem identidades compatíveis com SPIFFE. A Anthropic federa com qualquer implementação SPIFFE que emita JWT-SVIDs compatíveis com OIDC. Para uma lista atualizada de implementações, consulte Commercial software that implements SPIFFE no site do projeto SPIFFE.

A federação funciona por meio de um documento de descoberta OIDC em uma URL HTTPS pública (modo discovery, sujeito às restrições de URL) ou registrando o JWKS diretamente (modo inline).

A especificação JWT-SVID define sub como o SPIFFE ID do workload, e a SPIFFE Workload API exige que o chamador forneça aud no momento da obtenção, portanto essas claims são as mesmas em todas as implementações. A Anthropic exige adicionalmente iss e iat, nenhuma das quais a especificação JWT-SVID torna obrigatória, então configure sua implementação para preencher ambas (no SPIRE, iss é a configuração de servidor jwt_issuer e iat é definida automaticamente). Com isso configurado, as seções Configurar a Anthropic, Obter e usar o token e Delimitar o escopo da sua regra deste guia se aplicam a qualquer implementação SPIFFE.

O SPIFFE atribui a cada workload uma URI de identidade estável no formato spiffe://<trust-domain>/<path>, e o SPIRE emite essa identidade como um JWT-SVID sob demanda por meio da Workload API. Um JWT-SVID é um JWT assinado comum cuja claim sub é o SPIFFE ID do workload e cuja claim aud é fornecida pelo workload no momento da obtenção.

A ponte entre um trust domain (domínio de confiança) do SPIRE e o OIDC padrão é o SPIRE OIDC Discovery Provider, um auxiliar independente que publica /.well-known/openid-configuration e um endpoint JWKS para as chaves de assinatura JWT do trust domain. Com o discovery provider em execução, um JWT-SVID é validado como qualquer outro token OIDC: registre a URL de descoberta como um emissor de federação, escreva uma regra de federação que corresponda ao SPIFFE ID do workload e faça o workload apresentar seu JWT-SVID ao endpoint de troca de tokens da Anthropic.

Os exemplos desta página usam SPIRE e se aplicam a qualquer lugar onde o SPIRE Agent seja executado: pods Kubernetes, máquinas virtuais e hosts bare-metal.

Pré-requisitos

  • Familiaridade com os conceitos de WIF: service accounts (contas de serviço), emissores de federação e regras de federação.
  • Uma implantação SPIFFE com identidades de workload emitidas (os exemplos desta página usam SPIRE Server e Agent) e entradas de registro para os workloads que precisam chamar a Claude API.
  • Um endpoint de descoberta OIDC para o trust domain (no SPIRE, o OIDC Discovery Provider) em execução com um endpoint HTTPS acessível publicamente, ou o JWKS exportado para registro inline.
  • Seu emissor SPIFFE configurado para definir a claim iss nos JWT-SVIDs com o valor que você registrará como issuer_url do emissor de federação. Para o modo discovery, esta é a URL pública do endpoint de descoberta (no SPIRE, a configuração de servidor jwt_issuer).
  • JWT-SVIDs disponíveis para seus workloads. O WIF aceita apenas JWT-SVIDs, não X.509-SVIDs.
  • Permissão para criar service accounts, emissores de federação e regras de federação no Claude Console para sua organização Anthropic.

O valor de audience (audiência) a ser solicitado ao obter um JWT-SVID é sempre https://api.anthropic.com. Use esse valor no jwt_audience do spiffe-helper, na chamada FetchJWTSVID da Workload API e no matcher audience da regra de federação.

Configurar o SPIRE

As instruções desta seção são específicas do SPIRE. Se você usa um emissor SPIFFE diferente, configure seu endpoint de descoberta OIDC e a obtenção de JWT-SVID de acordo com a documentação dele e, em seguida, continue em Configurar a Anthropic.

Se você já executa o SPIRE com o OIDC Discovery Provider, federar com a Anthropic exige três coisas do lado do SPIRE:

  • Um jwt_issuer que corresponda à URL de descoberta
  • Uma entrada de registro para o workload que chamará a Claude API
  • Uma forma de esse workload buscar um JWT-SVID com a audience da Anthropic

As subseções a seguir explicam cada uma. Os trechos de configuração mostram apenas as configurações relevantes para a federação com a Anthropic, não configurações completas de implantação do SPIRE.

Verificar o emissor JWT

A Anthropic valida um JWT-SVID comparando sua claim iss com um emissor de federação registrado e obtendo o JWKS a partir do documento de descoberta desse emissor. Duas configurações do SPIRE devem concordar na mesma URL: o jwt_issuer do SPIRE Server (que se torna a claim iss em todo JWT-SVID emitido) e a lista domains do OIDC Discovery Provider (que determina o host a partir do qual o documento de descoberta e o JWKS são servidos). Essa URL compartilhada é o que você registra na Anthropic.

O trust domain e a URL do emissor são independentes. O trust domain (spiffe://prod.example.com) delimita a claim sub. A URL do emissor (https://oidc-discovery.prod.example.com) é onde a Anthropic obtém as chaves de assinatura. Eles não precisam compartilhar um hostname.

Confirme que jwt_issuer está definido na configuração do SPIRE Server e aponta para a URL pública do discovery provider. O exemplo a seguir também mostra um tempo de vida padrão de JWT-SVID. O padrão interno do SPIRE é de 5 minutos, o que é curto o suficiente para exigir rotação contínua (consulte Executar o spiffe-helper). O endpoint de troca de tokens da Anthropic rejeita qualquer token de identidade cujo tempo de vida exceda o máximo configurado do emissor de federação, que é de 1 hora por padrão (consulte Regras de validação). Essa verificação se aplica a toda implementação SPIFFE, não apenas ao SPIRE, portanto mantenha default_jwt_svid_ttl (ou qualquer substituição por entrada) igual ou abaixo desse máximo.

server.conf
server {
    trust_domain         = "prod.example.com"
    jwt_issuer           = "https://oidc-discovery.prod.example.com"
    default_jwt_svid_ttl = "5m"
    # ...
}

Na configuração do OIDC Discovery Provider, o mesmo hostname deve aparecer em domains, e o provider deve conseguir alcançar o socket de API do SPIRE Server. O provider serve o documento de descoberta e o JWKS via HTTPS. Termine o TLS com seu suporte ACME integrado ou coloque-o atrás de um load balancer que faça isso.

oidc-discovery-provider.conf
domains = ["oidc-discovery.prod.example.com"]

server_api {
    address = "unix:///run/spire/sockets/private/api.sock"
}

acme {
    email        = "platform@example.com"
    tos_accepted = true
}

Registrar o workload

Cada workload que chama a Claude API precisa de uma entrada de registro no SPIRE que mapeie seus seletores de runtime para um SPIFFE ID. Se o workload já estiver registrado, anote seu SPIFFE ID, que você usará no subject_prefix da regra de federação. Caso contrário, registre-o. Para um pod Kubernetes, os seletores normalmente são o namespace e a service account do Kubernetes:

CLI
# Substitua NODE_UID pelo UID do nó:
#   kubectl get node <node-name> -o jsonpath='{.metadata.uid}'
spire-server entry create \
  -spiffeID spiffe://prod.example.com/ns/inference/sa/worker \
  -parentID spiffe://prod.example.com/spire/agent/k8s_psat/prod-cluster/NODE_UID \
  -selector k8s:ns:inference \
  -selector k8s:sa:worker

Workloads fora do Kubernetes usam seletores de nível de host, como unix:uid:1000 (unix:path também está disponível, mas requer discover_workload_path = true na configuração do unix workload attestor do agent). Clusters que executam o spire-controller-manager podem declarar entradas com o recurso personalizado ClusterSPIFFEID em vez de chamar spire-server entry create diretamente.

Executar o spiffe-helper

O spiffe-helper é um utilitário sidecar que se conecta ao socket do SPIRE Agent, obtém um JWT-SVID para uma determinada audience, grava-o em um arquivo e o obtém novamente antes de expirar. O helper é executado em modo daemon por padrão. O exemplo a seguir define daemon_mode = true explicitamente.

helper.conf
agent_address = "/run/spire/sockets/agent.sock"
# The JWT-SVID file is written under cert_dir
cert_dir      = "/var/run/secrets/anthropic.com"
daemon_mode   = true

jwt_svids = [{
    jwt_audience       = "https://api.anthropic.com"
    jwt_svid_file_name = "token"
}]

No Kubernetes, execute o spiffe-helper como um contêiner sidecar que compartilha um volume emptyDir em memória (medium: Memory) com o contêiner da sua aplicação, para que o SVID bearer nunca seja gravado no disco do nó. Monte o socket do SPIRE Agent do host no sidecar, monte o volume compartilhado em /var/run/secrets/anthropic.com em ambos os contêineres e defina ANTHROPIC_IDENTITY_TOKEN_FILE=/var/run/secrets/anthropic.com/token no contêiner da aplicação. Em VMs e bare metal, execute o spiffe-helper como um serviço do sistema ao lado do workload e aponte ambos para um diretório compartilhado.

Configurar a Anthropic

No Claude Console, acesse a página Workload identity (platform.claude.com/settings/workload-identity-federation), clique em Connect workload e selecione Custom OIDC. O assistente orienta você no registro do emissor, na criação de uma service account e na criação de uma regra de federação.

O assistente cria esses recursos para você. Use os seguintes valores, seja inserindo-os no assistente ou enviando-os para a Admin API:

Emissor de federação: Registre a URL pública do OIDC Discovery Provider no modo discovery. A Anthropic obtém /.well-known/openid-configuration dessa URL e segue o jwks_uri retornado para recuperar as chaves de assinatura do trust domain.

{
  "name": "spire-prod",
  "issuer_url": "https://oidc-discovery.prod.example.com",
  "jwks": { "type": "discovery" }
}

Se o discovery provider não for acessível pela internet pública, obtenha o JWKS você mesmo (curl https://oidc-discovery.prod.example.com/keys) e registre o emissor com "jwks": {"type": "inline", "keys": [...]} usando o conteúdo do array keys retornado. No modo inline, o issuer_url é apenas comparado com a claim iss do JWT-SVID. A Anthropic nunca tenta acessá-lo.

Para automatizar as atualizações do JWKS sem expor um endpoint de descoberta público, configure um plugin BundlePublisher do SPIRE Server (aws_s3, gcp_cloudstorage ou k8s_configmap) com format = "jwks" para enviar as chaves de assinatura JWT para um armazenamento externo a cada rotação e, em seguida, atualize as chaves inline do emissor por meio da Admin API.

Regra de federação: Faça a correspondência com o sub do JWT-SVID (o SPIFFE ID) e o aud que você configurou o spiffe-helper para solicitar. SPIFFE IDs são strings URI e subject_prefix os compara como texto opaco, portanto tanto um valor exato quanto uma correspondência de prefixo com * no final funcionam com eles. Para padrões mais complexos, use uma condition CEL.

{
  "name": "spire-inference-worker",
  "issuer_id": "fdis_...",
  "match": {
    "subject_prefix": "spiffe://prod.example.com/ns/inference/sa/worker",
    "audience": "https://api.anthropic.com"
  },
  "target": {
    "type": "service_account",
    "service_account_id": "svac_..."
  },
  "workspace_id": "wrkspc_...",
  "oauth_scope": "workspace:developer",
  "token_lifetime_seconds": 600
}

token_lifetime_seconds é o tempo de vida do token de acesso da Anthropic que a troca retorna, não do JWT-SVID. O SDK renova o token de acesso automaticamente.

Seja tão específico quanto o workload permitir. Afrouxe subject_prefix para spiffe://prod.example.com/ns/inference/* somente se todos os workloads registrados sob esse caminho devem ser mapeados para a mesma service account da Anthropic. Adicione o ID fdrl_... da regra à variável de ambiente ANTHROPIC_FEDERATION_RULE_ID do workload.

Obter e usar o token

O SDK do Claude pode ler o JWT-SVID do arquivo que o spiffe-helper mantém ou, exceto em Java, chamar a SPIFFE Workload API diretamente por meio de um provedor de token. O caminho por arquivo é a integração mais simples e funciona em todas as linguagens do SDK. O caminho por provedor de token elimina o sidecar, mas exige um cliente da SPIFFE Workload API na linguagem da sua aplicação.

Com o spiffe-helper gravando um JWT-SVID novo em /var/run/secrets/anthropic.com/token, defina ANTHROPIC_IDENTITY_TOKEN_FILE com esse caminho, juntamente com ANTHROPIC_FEDERATION_RULE_ID, ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID. O SDK lê o arquivo a cada troca de token, portanto sempre usa o SVID rotacionado mais recentemente, e renova o token de acesso da Anthropic automaticamente antes que ele expire. Consulte Variáveis de ambiente para saber de onde vem cada valor.

import anthropic

# Lê o JWT-SVID que o spiffe-helper grava em
# ANTHROPIC_IDENTITY_TOKEN_FILE, além de ANTHROPIC_FEDERATION_RULE_ID,
# ANTHROPIC_ORGANIZATION_ID, ANTHROPIC_SERVICE_ACCOUNT_ID e ANTHROPIC_WORKSPACE_ID.
client = anthropic.Anthropic()

message = client.messages.create(
    model="claude-opus-5-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello, Claude"}],
)
print(next(block.text for block in message.content if block.type == "text"))

Verificar a configuração

Antes de integrar o SDK, busque um JWT-SVID diretamente do SPIRE Agent e confirme que as claims correspondem ao que sua regra de federação espera. Se você usa uma implementação SPIFFE diferente, busque um JWT-SVID com a CLI ou o cliente da Workload API dela e decodifique o payload da mesma forma.

CLI
spire-agent api fetch jwt \
  -audience https://api.anthropic.com \
  -socketPath /run/spire/sockets/agent.sock \
  -output json \
  | jq -r '.[0].svids[0].svid' \
  | jq -rR 'split(".")[1] | gsub("-";"+") | gsub("_";"/") | @base64d | fromjson'

A flag -output json retorna a resposta do SVID e a resposta do bundle como um array JSON de dois elementos, então jq -r '.[0].svids[0].svid' extrai o token puro. Em versões mais antigas do SPIRE sem -output, o comando imprime um bloco rotulado. Nesse caso, passe a saída padrão por awk '/^[[:space:]]*eyJ/{print $1; exit}' para extrair a linha do token. Verifique se iss é a URL do OIDC Discovery Provider que você registrou, se sub é o SPIFFE ID do workload e se aud contém https://api.anthropic.com. Em seguida, execute o exemplo cURL de Obter e usar o token. Uma troca bem-sucedida retorna um access_token começando com sk-ant-oat01-. Se a troca falhar com a resposta opaca 401 authentication_error (mensagem Authentication failed), verifique a página de histórico de autenticação no Claude Console para ver o motivo da recusa e consulte Solucionar problemas de uma troca com falha. A causa mais comum do lado do SPIRE é uma divergência entre o jwt_issuer do SPIRE Server e a URL registrada como emissor de federação.

Delimitar o escopo da sua regra

As convenções de caminho de SPIFFE ID são definidas pelo operador, portanto o matcher subject_prefix da regra de federação deve refletir o esquema de caminhos que suas entradas de registro usam. Esquemas comuns incluem spiffe://<trust-domain>/ns/<namespace>/sa/<service-account> (o padrão emitido pelo recurso ClusterSPIFFEID no spire-controller-manager) e spiffe://<trust-domain>/host/<hostname>/<service> para workloads em VMs e bare metal.

Restrinja o bloco match da regra ao escopo mais estreito que atenda ao seu caso de uso:

  • Fixar em um único workload: Defina subject_prefix com o SPIFFE ID completo, sem * no final.
  • Sempre definir uma audience: Exija audience na regra e configure o spiffe-helper (ou a chamada da Workload API) com o mesmo valor, para que SVIDs emitidos para outras relying parties sejam rejeitados.
  • Definir o escopo por segmento de caminho: Use spiffe://prod.example.com/ns/inference/* para conceder acesso a todos os workloads registrados em um namespace e crie uma regra e uma service account da Anthropic separadas para cada namespace, em vez de ampliar uma única regra.
  • Registre um emissor para cada trust domain: Cada trust domain do SPIRE tem suas próprias chaves de assinatura e seu próprio OIDC Discovery Provider. Registre cada um como um emissor de federação separado e vincule as regras ao emissor que possui os SPIFFE IDs aos quais elas correspondem.

Próximos passos

Was this page helpful?