Pular para o conteúdo principal

OIDC Issuer — CipherVault como IdP

A partir da v4.6, o CipherVault não é apenas consumer de OIDC (GitHub Actions, GitLab, etc.) — também atua como OIDC Identity Provider, expondo discovery e JWKS pra que clouds (AWS, GCP, Azure) federe workloads contra ele.

Paridade real com Pulumi ESC.

Discovery

curl https://cv.acme.com.br/.well-known/openid-configuration
{
"issuer": "https://cv.acme.com.br",
"jwks_uri": "https://cv.acme.com.br/.well-known/jwks.json",
"token_endpoint": "https://cv.acme.com.br/oidc/token",
"response_types_supported": ["id_token"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["ES256"]
}

JWKS

EC P-256 ES256 keys públicas pra verificação de assinatura:

curl https://cv.acme.com.br/.well-known/jwks.json
{
"keys": [
{ "kid": "cv-2026-05", "kty": "EC", "crv": "P-256", "x": "...", "y": "...", "use": "sig", "alg": "ES256" }
]
}

Token mint

App autenticado no CV troca seu bearer por JWT assinado:

curl -X POST https://cv.acme.com.br/oidc/token \
-H "Authorization: Bearer $CV_TOKEN" \
-d '{
"audience": "sts.amazonaws.com",
"subject": "app1:production"
}'
# → { "token": "eyJ...", "expires_at": "...", "kid": "cv-2026-05" }

Claims emitidos:

ClaimConteúdo
issURL do CV (https://cv.acme.com.br)
audAudience requisitado (sts.amazonaws.com, etc.)
subSubject identifier (tenant:app, configurável)
iat, exp, nbfStandard
cv_tenant_id, cv_app_idCustom claims para policy matching

Rotação de chaves

POST /oidc/rotate gera novo keypair, mantém o anterior como inactive até TTL de tokens emitidos expirar (default 24h):

curl -X POST https://cv.acme.com.br/oidc/rotate \
-H "Authorization: Bearer $CV_ADMIN_TOKEN"
# → { "new_kid": "cv-2026-06", "previous_kid": "cv-2026-05", "rotated_at": "..." }

JWKS pública continua expondo ambas até cleanup automático.

Caso de uso: AWS AssumeRoleWithWebIdentity

App no Kubernetes (ou EC2, ou Lambda) federa AWS sem static keys:

1. AWS-side — cria OIDC provider:

aws iam create-open-id-connect-provider \
--url https://cv.acme.com.br \
--client-id-list sts.amazonaws.com \
--thumbprint-list <(curl -s https://cv.acme.com.br/.well-known/openid-configuration | jq -r .jwks_uri | xargs -I {} curl -s {} | jq -r ...)

2. AWS-side — cria role com trust policy:

{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "Federated": "arn:aws:iam::123456789:oidc-provider/cv.acme.com.br" },
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"cv.acme.com.br:aud": "sts.amazonaws.com",
"cv.acme.com.br:sub": "tenant42:checkout-svc"
}
}
}]
}

3. App-side — troca por AWS creds:

JWT=$(curl -s -X POST https://cv.acme.com.br/oidc/token \
-H "Authorization: Bearer $CV_TOKEN" \
-d '{"audience":"sts.amazonaws.com","subject":"tenant42:checkout-svc"}' | jq -r .token)

aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::123:role/checkout-svc-fed \
--role-session-name checkout1 \
--web-identity-token "$JWT"
# → { Credentials: { AccessKeyId, SecretAccessKey, SessionToken, Expiration } }

Zero static keys em qualquer ponto da chain.

UI

Settings → OIDC tab (v4.7) mostra:

  • Discovery preview (mock fetch + render)
  • JWKS keys table com kid, created_at, status, expires_at
  • Rotate button com confirm dialog
  • AWS IAM setup walkthrough copiável (gera CLI commands com tenant_id pré-preenchido)

Comparação vs static AWS keys

Static keys (legacy)OIDC federation
SetupIAM user + access keyOIDC provider + role
StorageCV armazena keyCV nada (mint on-demand)
RotationManualAutomática (JWT TTL 1h)
AuditApp→AWS opacoOIDC token em audit CV
Compromise blastPermanente até rotateExpira em 1h

Use sempre OIDC federation quando possível.

Limitações atuais

  • Apenas EC P-256 ES256 — RSA não suportado (overhead JWKS desnecessário)
  • Sem PKCE ainda (auth code flow não implementado — token endpoint usa CV bearer)
  • Sem Dynamic Client Registration — relying parties (AWS/GCP/Azure) configurados estaticamente

Referências