Utiliser les registres fremforge depuis GitHub Actions et OpenShift
Votre code source et votre CI peuvent rester sur GitHub, et vos clusters sur OpenShift, tandis que les paquets résident dans votre organisation fremforge. Les deux accèdent au registre via un robot de registre : un identifiant qui appartient à l’organisation, et non à une personne.
Un robot de registre :
- lit, ou lit et publie, les paquets d’une seule organisation, pour tous les types de paquets ;
- peut publier mais pas supprimer : la suppression d’une version de paquet, d’un fichier, d’un tag
de conteneur ou d’une image est refusée avec
403et consignée dans le journal d’audit sousregistry_robot.delete_refused. La suppression reste l’affaire d’un administrateur de l’organisation, dans l’interface web ou avec ses propres identifiants ; - ne peut pas lire le code, ouvrir l’interface web ni accéder à une autre organisation ;
- n’occupe aucun utilisateur payant ;
- a une durée de validité de 365 jours au maximum, après quoi il cesse de fonctionner, ainsi que tous ses jetons ;
- est listé, avec la personne qui l’a créé, sous Administration de l’organisation → Sécurité → Accès → Robots de registre, et chaque création, renouvellement, suppression et suppression de paquet refusée figure dans le journal d’audit de l’organisation.
Dans la CI propre à fremforge, vous n’en avez pas besoin : une tâche Forgejo Actions dispose déjà d’un jeton pour les paquets de sa propre organisation. Voir Publier depuis Forgejo Actions.
Créer un robot
Dans la console : Administration de l’organisation → Sécurité → Accès → Robots de registre → Créer un robot. Choisissez Lire les paquets pour un secret de pull et Lire et publier les paquets (sans suppression) pour une tâche CI qui publie.
La page affiche alors une seule fois le nom d’utilisateur et le jeton du robot. Copiez les deux ; le jeton ne sera plus affiché. S’il est perdu, Renouveler le jeton en émet un nouveau et révoque immédiatement l’ancien.
Ou avec l’API, en utilisant un jeton d’API doté du scope policy:write :
curl -sS -X POST "https://frem.sh/_app/api/v1/orgs/<org>/registry-robots" \
-H "Authorization: Bearer $FREMFORGE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "github-publish", "access": "write", "expires_in_days": 90}'La réponse contient username et token. access vaut read ou write, et
expires_in_days est compris entre 1 et 365 (90 par défaut). Renouvelez avec
POST /orgs/<org>/registry-robots/<id>/rotate, éventuellement avec {"expires_in_days": n} pour
fixer une nouvelle date d’expiration, et supprimez avec DELETE /orgs/<org>/registry-robots/<id>.
Le nom d’utilisateur a la forme <org prefix>-fremforge-bot-reg-<8 hex characters>. Le préfixe est
le nom de votre organisation, raccourci si nécessaire pour que le nom d’utilisateur tienne en
40 caractères : un robot d’acme-infrastructure-team porte un nom du type
acme-infrastr-fremforge-bot-reg-1a2b3c4d. Copiez le nom d’utilisateur affiché par la page ou par
l’API plutôt que de le reconstruire à partir du nom de l’organisation. Chaque client ci-dessous
l’utilise comme nom d’utilisateur, et le jeton comme mot de passe.
GitHub Actions
Enregistrez le robot dans le dépôt ou l’organisation GitHub : le nom d’utilisateur comme variable
FREMFORGE_REGISTRY_USER et le jeton comme secret FREMFORGE_REGISTRY_TOKEN. Définissez ORG sur
votre organisation fremforge.
Images de conteneurs
- name: Push to fremforge
env:
FREMFORGE_USER: ${{ vars.FREMFORGE_REGISTRY_USER }}
FREMFORGE_TOKEN: ${{ secrets.FREMFORGE_REGISTRY_TOKEN }}
ORG: <org>
run: |
echo "$FREMFORGE_TOKEN" | docker login frem.sh -u "$FREMFORGE_USER" --password-stdin
docker build -t "frem.sh/$ORG/app:$GITHUB_SHA" .
docker push "frem.sh/$ORG/app:$GITHUB_SHA"Récupérez de la même manière, avec docker pull frem.sh/<org>/app:<tag>. Un tag poussé ne peut
pas être écrasé lorsque les versions immuables sont activées
pour l’organisation.
npm
npm n’envoie un jeton qu’à une URL de registre qui correspond exactement ; indiquez-lui donc le registre du scope et le jeton pour cette URL :
- name: Publish to fremforge
env:
FREMFORGE_TOKEN: ${{ secrets.FREMFORGE_REGISTRY_TOKEN }}
ORG: <org>
run: |
printf '@<scope>:registry=https://frem.sh/api/packages/%s/npm/\n//frem.sh/api/packages/%s/npm/:_authToken=%s\n' \
"$ORG" "$ORG" "$FREMFORGE_TOKEN" > .npmrc
npm publishLe même .npmrc permet d’installer les paquets @<scope>/… avec npm install.
PyPI
- name: Publish to fremforge
env:
FREMFORGE_USER: ${{ vars.FREMFORGE_REGISTRY_USER }}
FREMFORGE_TOKEN: ${{ secrets.FREMFORGE_REGISTRY_TOKEN }}
ORG: <org>
run: |
python -m pip install twine
twine upload --repository-url "https://frem.sh/api/packages/$ORG/pypi" \
-u "$FREMFORGE_USER" -p "$FREMFORGE_TOKEN" dist/*Installez avec les identifiants du robot dans l’URL de l’index :
pip install --index-url "https://$FREMFORGE_USER:$FREMFORGE_TOKEN@frem.sh/api/packages/$ORG/pypi/simple/" <package>Maven
Ajoutez un serveur portant l’id que votre pom.xml utilise pour le dépôt fremforge, en lisant le
robot depuis l’environnement :
<settings>
<servers>
<server>
<id>fremforge</id>
<username>${env.FREMFORGE_USER}</username>
<password>${env.FREMFORGE_TOKEN}</password>
</server>
</servers>
</settings>- name: Publish to fremforge
env:
FREMFORGE_USER: ${{ vars.FREMFORGE_REGISTRY_USER }}
FREMFORGE_TOKEN: ${{ secrets.FREMFORGE_REGISTRY_TOKEN }}
run: mvn --batch-mode -s .ci/settings.xml deployavec le dépôt déclaré dans pom.xml comme dans Maven :
https://frem.sh/api/packages/<org>/maven.
Sans secret stocké : le jeton OIDC de GitHub
Un robot peut aussi accepter le jeton OIDC de GitHub Actions à la place d’un jeton de registre
stocké. Indiquez au robot l’id numérique de votre organisation GitHub (ou de votre utilisateur)
et, éventuellement, un dépôt, sous GitHub Actions sur le robot, ou avec
github_repository_owner_id et github_repository dans l’API. Une tâche de ce propriétaire
demande alors son jeton OIDC avec l’audience https://frem.sh/<org>
(permissions: id-token: write) et l’échange sur POST https://frem.sh/_app/api/v1/registry/oidc-token
(org, robot, id_token) contre le nom d’utilisateur du robot et un jeton valable 1 heure.
L’échange est décrit dans la référence de l’API sous Registry robots ;
chaque jeton qu’il émet figure dans le journal d’audit avec le dépôt, la ref et l’id d’exécution.
SBOM
Les SBOM sont envoyés à l’API fremforge, et non au registre, avec un jeton d’API doté du scope
sboms:write. Voir
Téléverser des SBOM depuis GitHub Actions.
OpenShift et Kubernetes
Récupérez les images depuis fremforge avec un robot en lecture seule utilisé comme secret de pull d’images :
kubectl create secret docker-registry frem-sh \
--docker-server=frem.sh \
--docker-username=<robot username> \
--docker-password=<robot token> \
--namespace=<namespace>et référencez-le depuis la charge de travail :
spec:
imagePullSecrets:
- name: frem-sh
containers:
- name: app
image: frem.sh/<org>/app:1.4.2OpenShift lit le même secret kubernetes.io/dockerconfigjson. Renouvelez le robot avant son
expiration et remplacez le secret par un nouveau créé à partir du nouveau jeton.
Hôtes à autoriser dans un pare-feu sortant
| Hôte | Port | Utilisation |
|---|---|---|
frem.sh | 443 | Toutes les requêtes au registre : connexions, index, téléversements, ainsi que manifestes et couches des images de conteneurs |
obs.eu-de.otc.t-systems.com | 443 | Téléchargements des fichiers de paquets autres que les images de conteneurs : tarballs npm, wheels, JAR, etc. |
Le téléchargement d’un fichier de paquet autre qu’une image de conteneur répond 303 avec un lien
signé de courte durée vers le fichier dans le stockage objet sur obs.eu-de.otc.t-systems.com,
que le client suit. Ce nom est un CNAME de obs.lz01.eu-de.otc.t-systems.com ; un pare-feu qui
vérifie chaque nom de la chaîne a donc besoin des deux. Les couches des images de conteneurs sont
servies par frem.sh lui-même.
frem.sh est servi via un CDN, ses adresses changent donc : autorisez-le par nom, et non par
adresse IP.
Proxy de dépendances
Un robot disposant d’un accès en lecture récupère aussi les paquets via le proxy de dépendances de votre organisation (Docker Hub, npm, PyPI et les autres registres publics), avec le même jeton. Voir Authentification.