Identité des runs
Plutôt que de conserver des clés de longue durée comme secrets, un run peut prouver à quelle organisation il appartient. Cadence.CI est un émetteur OpenID Connect : chaque run reçoit des jetons d’identité de courte durée, qu’AWS, Google Cloud, Azure, Vault et OpenBao acceptent une fois une relation de confiance établie, comme ils acceptent les jetons des jobs GitHub Actions et GitLab CI.
Obtenir un jeton
Sur un worker Cadence.CI, le localisateur api-id:<audience> donne le jeton d’identité du run pour une audience, en Secret<string> : api-id:sts.amazonaws.com pour AWS, api-id:vault pour un rôle Vault lié à l’audience vault. Passez-le à l’élément qui l’échange contre un accès, comme n’importe quel secret.
Un jeton est valable 10 minutes ; le moteur en demande un nouveau une fois qu’il a expiré. Comme api:, api-id: ne fonctionne que sur les workers Cadence.CI, et le jeton n’est jamais affiché.
Émetteur
| Émetteur | https://api.melodium.tech |
| Découverte | https://api.melodium.tech/.well-known/openid-configuration |
| Clés | https://api.melodium.tech/.well-known/jwks.json |
| Signature | RS256 |
| Durée de vie | 10 minutes |
Claims
| Claim | Valeur |
|---|---|
iss | https://api.melodium.tech |
aud | l’audience demandée |
sub | organization:<organization-id>, suivi de :public pour les runs publics et les runs qu’ils lancent |
organization_id | l’organisation du run |
run_id | le run |
group_id | son groupe d’exécution |
parent_id | le run qui l’a lancé, s’il y en a un |
tags | les tags du run |
public | si le run, ou un run qui l’a lancé, est public |
melodium_version | la version de Mélodium du moteur |
iat, nbf, exp | sa date d’émission, le début de sa validité, son expiration |
jti | son identifiant unique |
Le sujet est le même pour tous les runs privés d’une organisation, pour que les fournisseurs qui le comparent exactement, comme AWS et Azure, fassent confiance à l’organisation dans son ensemble. Les conditions sur les tags ou les runs passent par les autres claims, là où le fournisseur peut les tester, comme Google Cloud, Vault et OpenBao. Les runs publics, et les runs qu’ils lancent, ont un sujet à part : une relation de confiance établie pour organization:<organization-id> ne les accepte jamais. Gardez-le ainsi pour tout ce qui est sensible, car les runs publics exécutent du code que n’importe qui peut proposer.
L’identifiant de votre organisation figure sur la page Organisation du tableau de bord.
AWS
- Dans IAM, sous Identity providers, ajoutez un fournisseur OpenID Connect avec l’URL
https://api.melodium.techet l’audiencests.amazonaws.com. - Créez un rôle pour ce fournisseur, avec une politique de confiance limitée à votre organisation :
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<account-id>:oidc-provider/api.melodium.tech"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"api.melodium.tech:aud": "sts.amazonaws.com",
"api.melodium.tech:sub": "organization:<organization-id>"
}
}
}
]
}- Dans le programme, donnez
api-id:sts.amazonaws.comà ce qui endosse le rôle avecAssumeRoleWithWebIdentity, avec l’ARN du rôle.
Google Cloud
- Créez un pool d’identités de charge de travail, et un fournisseur qui fait confiance aux runs de votre organisation :
gcloud iam workload-identity-pools create cadence-ci --location=global
gcloud iam workload-identity-pools providers create-oidc cadence-ci \
--location=global \
--workload-identity-pool=cadence-ci \
--issuer-uri="https://api.melodium.tech" \
--allowed-audiences="gcp" \
--attribute-mapping="google.subject=assertion.sub,attribute.organization_id=assertion.organization_id" \
--attribute-condition="assertion.organization_id == '<organization-id>' && !assertion.public"- Accordez les rôles dont les runs ont besoin à l’ensemble de principaux de l’organisation,
principalSet://iam.googleapis.com/projects/<project-number>/locations/global/workloadIdentityPools/cadence-ci/attribute.organization_id/<organization-id>, ou laissez-le emprunter l’identité d’un compte de service avecroles/iam.workloadIdentityUser. - Dans le programme, demandez le jeton pour l’audience autorisée :
api-id:gcp.
Azure
- Sur une identité managée attribuée par l’utilisateur, ou sur une inscription d’application, ajoutez une information d’identification fédérée pour l’organisation :
az identity federated-credential create \
--name cadence-ci \
--identity-name <identity> \
--resource-group <resource-group> \
--issuer "https://api.melodium.tech" \
--subject "organization:<organization-id>" \
--audiences "api://AzureADTokenExchange"- Donnez à l’identité les rôles dont les runs ont besoin.
- Dans le programme, demandez le jeton pour l’audience qu’attend Azure :
api-id:api://AzureADTokenExchange.
Vault et OpenBao
- Activez la méthode d’authentification
jwt, en faisant confiance à Cadence.CI, et un rôle pour les runs de votre organisation (avec OpenBao, utilisezbaoau lieu devault) :
vault auth enable jwt
vault write auth/jwt/config \
oidc_discovery_url="https://api.melodium.tech" \
bound_issuer="https://api.melodium.tech"
vault write auth/jwt/role/cadence-ci - <<EOF
{
"role_type": "jwt",
"user_claim": "sub",
"bound_audiences": ["vault"],
"bound_subject": "organization:<organization-id>",
"token_policies": ["ci"],
"token_ttl": "10m"
}
EOF- Dans le programme, le modèle
vault::Vaultse connecte avec le jeton d’identité, et les secrets localisésvault:<chemin>#<champ>sont lus avec les politiques du rôle :
use sql::SqlPool
use std/ops/option::|wrap
use vault::Vault
treatment database(const password: Secret<string> = "vault:kv/data/app/db#password")
model vault: Vault(address="https://vault.example.com:8200", auth="jwt", role="cadence-ci", jwt="api-id:vault")
model pool: SqlPool(url="postgresql://app@db.example.com/app", password=|wrap<Secret<string>>(password))
{
}bound_claims restreint encore le rôle, sur les autres claims, comme run_id ou tags.
Pour aller plus loin
- Secrets : enregistrer des secrets sur Cadence.CI.
- Clés.
- Package Vault dans la référence Mélodium.