Émetteurs OIDC
Cette section explique comment configurer github-sts pour valider les jetons OIDC des
fournisseurs d’identité. Le vérificateur exige que chaque jeton :
- Possède une revendication
issprésente dansoidc.allowed_issuers. - Porte un
kiddans l’en-tête JWT correspondant à une clé du JWKS de l’émetteur. - Résolve un
jwks_uri(via la découverte OIDC) dont l’hôte correspond soit à l’hôte de l’émetteur, soit est accepté viaoidc.trusted_jwks_hosts. - Porte une revendication
audcorrespondant au champaudience:de la politique (obligatoire dans chaque politique) et, si défini, àoidc.required_audienceau niveau du serveur.
Piège de l’audience. La plupart des bibliothèques OIDC définissent
audpar défaut à une valeur utile uniquement pour l’émetteur (par exemple, GitHub Actions utilise l’URL du dépôt du workflow par défaut). Ce défaut n’est pas sûr pour un STS: chaque workflow de l’organisation pourrait alors échanger ses jetons ici. Transmettez toujours une audience explicite qui identifie ce déploiement STS, par exemplecore.getIDToken('https://sts.example.com')pouractions/github-script, et définissez la même valeur dans le champaudience:de la politique.
Configuration par fournisseur
Comment découvrir les valeurs pour n’importe quel émetteur
Deux commandes, sans autre outil que curl et jq :
ISSUER="<the issuer URL>"
# 1. Print the discovery doc (sanity check).
curl -fsS "${ISSUER}/.well-known/openid-configuration" | jq .
# 2. Extract just the jwks_uri host.
curl -fsS "${ISSUER}/.well-known/openid-configuration" \
| jq -r '.jwks_uri | sub("^https?://"; "") | sub("/.*$"; "")'Si l’hôte affiché ne correspond pas à l’hôte de l’émetteur, cet émetteur nécessite une
entrée oidc.trusted_jwks_hosts.
Exemple combiné : les deux fournisseurs
oidc:
allowed_issuers:
- https://token.actions.githubusercontent.com
- https://login.microsoftonline.com/00000000-0000-0000-0000-000000000000/v2.0Valider votre configuration de bout en bout
# 1. Mint a token from your CI provider.
# 2. Decode the token header to confirm 'kid' is set.
echo "$TOKEN" | cut -d. -f1 | base64 -d 2>/dev/null | jq .
# 3. Confirm 'iss' matches an entry in allowed_issuers.
echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq .issModes d’échec à prévoir :
| Symptôme dans les journaux | Cause | Correction |
|---|---|---|
issuer "X" not in allowed list | iss absent de allowed_issuers | Ajoutez l’URL de l’émetteur exactement comme elle apparaît dans le jeton. |
token header missing kid | Le jeton n’a pas de kid | L’émetteur est mal configuré ; ce service rejette les jetons sans kid. |
key "X" not found in JWKS | L’émetteur a renouvelé ses clés | Le cache JWKS a un TTL de 1 h: attendez ou redémarrez les pods. |
jwks_uri host "X" is not the issuer host and not in the trusted JWKS host override | Le JWKS de l’émetteur est sur un autre hôte | Ajoutez l’hôte à trusted_jwks_hosts. |
audience mismatch (server required_audience) | L’aud du jeton ne contient pas oidc.required_audience | Transmettez la bonne audience au workflow (core.getIDToken('<value>')). |
audience check failed (par politique) | L’aud du jeton ne correspond pas au champ audience: de la politique | Définissez audience: dans .sts.yaml pour correspondre au workflow. |
Maintenance : détection de la dérive des hôtes JWKS
Les fournisseurs cloud changent occasionnellement d’hôtes JWKS. Exécutez cette vérification périodiquement et alertez sur tout écart: ne mettez pas à jour automatiquement.
#!/usr/bin/env bash
# scripts/check-jwks-drift.sh
set -euo pipefail
VALUES="${1:-values.yaml}"
for iss in $(yq '.oidc.allowed_issuers[]' "$VALUES"); do
iss_host=$(echo "$iss" | sed -E 's#^https?://([^/]+).*#\1#')
observed=$(curl -fsS "${iss}/.well-known/openid-configuration" \
| jq -r '.jwks_uri | sub("^https?://"; "") | sub("/.*$"; "")') || {
echo "FAIL: discovery for $iss did not respond"
continue
}
if [ "$observed" = "$iss_host" ]; then
continue
fi
pinned=$(yq ".oidc.trusted_jwks_hosts[\"$iss\"][]" "$VALUES" 2>/dev/null || true)
if ! grep -qx "$observed" <<< "$pinned"; then
echo "DRIFT: $iss now publishes JWKS at $observed (not in trusted_jwks_hosts)"
fi
doneIntégrez-le à un job CI hebdomadaire ; traitez toute ligne DRIFT comme un élément de revue de sécurité.