Segredos do Vault
O Firstlume não guarda os segredos: quem lê o Vault é o executor, dentro do pod do run, e os valores não passam pelo servidor nem pelo banco. Para isso, o Firstlume emite para cada fase um JWT (ES256, válido por 15 minutos) que diz qual stack está rodando, e o executor o troca por um token do Vault. O token é revogado ao fim da fase.
1. No Firstlume
Defina a conexão da organização com PUT /api/v1/orgs/{org}/vault:
{"address": "https://vault.example.com:8200"}
Os campos opcionais são ca_cert, namespace, auth_path (padrão jwt) e audience (padrão vault).
Defina o papel, herdado como as outras configurações, numa pasta ou no stack:
{"vault_role": "infra-dev"}
FIRSTLUME_PUBLIC_URL (no Helm, controlPlane.publicURL; o padrão é o host do ingress) é o iss dos JWTs.
2. No Vault
Ligue o método jwt confiando no Firstlume, com a descoberta ou com a chave pública:
vault auth enable jwt
vault write auth/jwt/config bound_issuer=https://firstlume.example.com \
oidc_discovery_url=https://firstlume.example.com # ou [email protected]
vault policy write infra-dev - <<'EOF'
path "secret/data/infra/dev/*" { capabilities = ["read"] }
EOF
vault write auth/jwt/role/infra-dev role_type=jwt user_claim=sub bound_audiences=vault \
bound_claims_type=glob bound_claims='{"stack_path": "infra/dev/*"}' \
token_policies=infra-dev token_ttl=15m
A chave pública fica em GET /api/v1/orgs/{org}/vault/public-key (PEM) e em /.well-known/jwks.json.
3. No repositório
Use {vault: secret/infra/dev/${name}, field: ip} em qualquer valor da declaração. O caminho é o mesmo do vault kv get (KV v1 e v2 são detectados), e outros engines também funcionam.
Claims do JWT
| Claim | Valor |
|---|---|
sub |
stack:<id> |
org |
a organização |
stack_id, stack_name |
o stack |
stack_path |
pastas e nome, como infra/dev/machines |
folder_ids |
os ids das pastas |
run_id, run_type |
o run |
phase |
plan, apply ou drift |
Com bound_claims, um stack de dev não lê segredos de prod, e um papel com phase = apply não serve para o plan. Prefira folder_ids a stack_path se renomear pastas puder mudar o acesso.
Como os valores são tratados
- Tudo o que vem do Vault é sensível: mascarado no log, e os arquivos saem com
0600. - Plan e apply: o apply relê o Vault e confere com o plan (por um hash com chave, sem guardar valores). Se um segredo mudou entre os dois, o apply falha com
the secret in <caminho>#<campo> changed since the plan: plan again. - Erros dizem o item da declaração, o caminho e o campo, nunca o valor: sem conexão, sem papel, login recusado, permissão negada, segredo ou campo ausente, Vault fora do ar.
Testar sem rodar nada
POST /api/v1/orgs/{org}/stacks/{id}/vault/check faz o login como o stack e diz, por caminho, se o papel pode ler, sem ler nenhum valor:
{"paths": ["secret/infra/dev/n01"]}