Déployer sans secret (OIDC)
Fonctionnalité en cours de déploiement. L'interface décrite ici est celle de la prochaine livraison : elle peut encore évoluer, et n'est pas forcément activée sur votre tenant.
GitLab CI et GitHub Actions remettent à chaque job un jeton OIDC de courte durée, qui dit « ce job appartient à ce projet, sur cette branche ». StackNGO l'échange contre une session de tenant. Résultat : aucun secret à stocker, rien à faire tourner.
Vous déclarez quels pipelines vous faites confiance avec un trust OIDC (IAMOIDCTrust),
puis vous lui attachez une policy, exactement comme pour un utilisateur.
Prérequis
- Une session d'administrateur sur le tenant (
sng tenant use acme). - Le projet CI et sa branche de déploiement.
1. Déclarer le trust
# GitLab : pipelines de la branche protégée main du projet acme/infra
sng tenant oidc create gitlab-deploy \
--gitlab-project acme/infra --ref main \
--claim project_id=4242 --claim ref_protected=true
# GitHub : workflows du dépôt acme/infra sur main
sng tenant oidc create github-deploy \
--github-repo acme/infra --ref main \
--claim repository_id=123456789
OIDC trust "gitlab-deploy" created in tenant "acme" (pending: applied in a few minutes)
subject: project_path:acme/infra:ref_type:branch:ref:main
next: sng tenant policy attach POLICY --oidc-trust gitlab-deploy
| Flag | Effet |
|---|---|
--gitlab-project GROUP/PROJECT | Émetteur https://gitlab.com (ou --gitlab-url), sujet project_path:GROUP/PROJECT:ref_type:branch:ref:REF |
--github-repo ORG/REPO | Émetteur https://token.actions.githubusercontent.com, sujet repo:ORG/REPO:ref:refs/heads/REF |
--ref REF | Branche de confiance (main par défaut, * = toutes) |
--claim CLÉ=V1,V2 | Claims supplémentaires exigés ; ET entre clés, OU entre valeurs |
--max-session 15m | Durée des sessions ouvertes par ce trust, de 5m à 1h (défaut 1h) |
--issuer, --audience, --subject | Pour un émetteur quelconque, sans aide |
-f FICHIER | Un manifeste IAMOIDCTrust ou sa spec, en YAML ou JSON (- = entrée standard) |
Un chemin de projet peut être renommé puis réutilisé par quelqu'un d'autre. project_id
(GitLab) et repository_id (GitHub) ne changent jamais : ajoutez-les toujours en --claim.
Le trust est actif quelques minutes plus tard (STATUS passe à applied) :
sng tenant oidc list
NAME ISSUER SUBJECT STATUS
gitlab-deploy https://gitlab.com project_path:acme/infra:ref_type:branch:ref:main applied
sng tenant oidc get gitlab-deploy détaille le trust. Une fois le trust appliqué, la ligne
discovery dit si l'émetteur a répondu : ok, ou failed: <cause> (vérifiez l'URL de
l'émetteur ; la vérification est refaite à chaque échange de jeton). Un émetteur de la
plateforme elle-même est refusé dès la création (issuer "…" is reserved to the platform).
2. Lui donner des droits
Un trust n'accorde rien par lui-même.
sng tenant policy attach readwrite --oidc-trust gitlab-deploy
readwrite suffit pour sng apply. Pour une policy sur mesure (par exemple deploy:* sans
ssm:read), voir Policies. Donnez au pipeline le
strict nécessaire.
3. L'utiliser dans le pipeline
La CLI détecte le jeton du job et ouvre la session toute seule, en mémoire. Il suffit de lui dire sur quel tenant.
| Variable | Rôle |
|---|---|
STNG_TENANT | Tenant visé (obligatoire) |
STNG_OIDC_TOKEN | Jeton OIDC du job (GitLab id_tokens) |
STNG_OIDC_TOKEN_FILE | Idem, dans un fichier |
STNG_OIDC_AUDIENCE | GitHub seulement : audience à demander (défaut : l'URL de l'API) |
STNG_OIDC_TRUST | Nom du trust à utiliser si plusieurs trusts du tenant pourraient correspondre |
Sous GitHub Actions, la CLI utilise directement ACTIONS_ID_TOKEN_REQUEST_URL et
ACTIONS_ID_TOKEN_REQUEST_TOKEN fournis par le runner (avec permissions: id-token: write).
Une session expirée est rouverte en redemandant un jeton au CI ; rien n'est écrit sur disque.
Les pipelines complets sont dans GitLab CI et GitHub Actions.
Runner persistant
Si plusieurs commandes doivent partager une session enregistrée (runner persistant,
scripts hors sng), sng sso login --oidc échange le jeton une fois et enregistre la
session dans le fichier de configuration du runner :
OIDC session saved: tenant acme (token from STNG_OIDC_TOKEN, expires in 900s)
Ce que le trust exige
Pour qu'un job ouvre une session, un trust du tenant visé doit correspondre sur tous les points :
| Champ du trust | Condition |
|---|---|
issuer | Le jeton vient de cet émetteur (GitLab, GitHub ou celui que vous indiquez) |
audiences | Le aud du jeton est dans la liste (par défaut : l'URL de l'API) |
subject | Le sub correspond au motif (* autorisé, au moins 8 caractères littéraux avant le premier *) |
claims | Chaque claim listé a l'une des valeurs attendues |
maxSessionDuration | Borne la session, quelle que soit la durée du jeton |
La session obtenue a pour principal oidc:<tenant>/<trust> : c'est lui que vous voyez dans
sng tenant policy principals et dans les journaux.
Dépannage
| Symptôme | Cause et correction |
|---|---|
no CI OIDC token: set STNG_OIDC_TOKEN … | Le job n'expose pas de jeton : ajoutez id_tokens (GitLab) ou permissions: id-token: write (GitHub) |
OIDC: tenant required: set STNG_TENANT … | STNG_TENANT absent |
invalid identity token | Aucun trust ne correspond, ou plusieurs : comparez iss, aud, sub affichés par la CLI avec sng tenant oidc get, ou fixez STNG_OIDC_TRUST |
jeton OIDC du CI expiré | Le jeton fourni par variable a expiré pendant le job : relancez, ou allongez sa durée côté CI |
forbidden (no policy of this tenant allows it: see sng tenant policy list) | La session est ouverte, mais la policy attachée au trust n'autorise pas cette action |
Supprimer un trust
sng tenant oidc delete gitlab-deploy
Les sessions déjà ouvertes restent valides jusqu'à leur expiration (au plus
maxSessionDuration).