Le provider Terraform et OpenTofu de fremforge
Le provider fremforge gère les paramètres fremforge de votre organisation depuis OpenTofu ou HashiCorp Terraform : authentification et politique d’accès, liste d’adresses IP autorisées, politique d’analyse et des analyseurs, releases immuables, règles de signature des images et des paquets, proxy de dépendances, accès aux paquets et robots de registre.
Les dépôts, les équipes et les règles de protection de branche sont des objets Forgejo et restent du ressort du provider communautaire svalabs/forgejo, comme décrit dans Configuration as code. Les deux providers fonctionnent côte à côte dans une même configuration.
Installation
Le provider est publié sur frem.sh même, si bien que les deux CLI l’installent sans configuration supplémentaire :
terraform {
required_providers {
fremforge = {
source = "frem.sh/fremforge/fremforge"
version = "~> 0.1"
}
}
}tofu init (ou terraform init) trouve le registre à l’adresse https://frem.sh/.well-known/terraform.json, télécharge l’archive zip correspondant à votre plateforme depuis cli.frem.sh et la contrôle par rapport à SHA256SUMS, dont il vérifie la signature OpenPGP avec la clé de publication de fremforge. Des builds existent pour Linux et macOS (amd64, arm64) et pour Windows (amd64).
La clé de publication :
| Empreinte | AEA6 FE24 2C86 33F0 10C6 D4ED 9099 FD4F C1DC 23C4 |
| ID de clé | 9099FD4FC1DC23C4 |
| Certificat public | https://frem.sh/_app/terraform/signing-key.asc |
La clé privée ne quitte jamais la plateforme fremforge : chaque version est signée par la plateforme, uniquement pour le build de publication du provider.
Configuration
provider "fremforge" {
# endpoint = "https://frem.sh/_app/api/v1" # the default
}Le provider lit son jeton dans FREMFORGE_TOKEN. Utilisez un jeton d’API d’organisation de l’organisation que vous gérez, créé sous Administration de l’organisation → Jetons d’API (frem.sh/<org>/_admin/api-tokens), avec les scopes dont vos ressources ont besoin. Gardez un jeton en lecture seule pour plan et le scope d’écriture pour le job qui exécute apply :
| Ressources | Scope |
|---|---|
| Toutes les ressources de cette page | policy:write |
| Sources de données uniquement | policy:read |
fremforge_push_protection (lecture) | findings:read |
Ressources
Les paramètres d’organisation sont des singletons : chaque organisation les possède toujours et l’API ne permet pas de les supprimer. Tous les arguments sont facultatifs. Seuls les arguments que vous définissez sont écrits ; les autres sont relus dans l’état et laissés tels quels, si bien qu’une modification apportée dans la console à un paramètre que vous ne gérez pas n’est pas une dérive. Importez un singleton à l’aide du slug de son organisation.
| Ressource | Ce qu’elle gère |
|---|---|
fremforge_auth_policy | Politique d’authentification : durée de vie maximale des PAT (0 = aucune limite), scopes des PAT, commits signés, signataires sans clé, SSH activé ou désactivé. |
fremforge_ip_allowlist | La liste d’adresses IP autorisées de l’organisation. L’API refuse une liste appliquée qui ne contient pas l’adresse depuis laquelle la CLI s’exécute ; déployez d’abord une liste avec audit_only = true. |
fremforge_operator_access | Si les opérateurs fremforge peuvent gérer les utilisateurs de l’organisation. |
fremforge_email_domain_policy | Si la liste des domaines e-mail autorisés est appliquée. |
fremforge_ssh_ca | L’autorité de certification SSH. require_cert = true nécessite une clé de CA dans la même configuration. |
fremforge_actions_policy | Actions uniquement sur les branches protégées. |
fremforge_artifact_retention | La durée de conservation des artefacts Actions, en jours. |
fremforge_sla_policy | Les délais de remédiation par niveau de gravité (0 = aucun). |
fremforge_push_protection | Ce que fait un push lorsque l’analyseur de secrets ne peut pas s’exécuter. |
fremforge_immutability | Releases et tags de conteneur immuables. Le plan affiche un avertissement lorsque releases est activé : ce choix est irréversible pour les releases publiées pendant qu’il est actif. |
fremforge_branch_protection_defaults | Les valeurs par défaut que fremforge applique aux nouveaux dépôts (il ne s’agit pas d’une règle Forgejo). |
fremforge_sast_settings, fremforge_dependency_scan_settings, fremforge_image_scan_settings, fremforge_secret_scan_settings, fremforge_license_settings | Les paramètres des analyseurs, une ressource par analyseur. |
fremforge_image_signature_policy | Les signatures d’image considérées comme fiables lors d’un pull, et si un pull non signé est refusé. Déployez avec mode = "shadow". |
fremforge_dependency_proxy | Les paramètres du proxy de dépendances de l’organisation. |
fremforge_package_signature_policy | La règle de signature de la politique de paquets (exigence et signataires de confiance). |
fremforge_package_access_default | Le mode d’accès aux paquets par défaut de l’organisation. |
Chaque singleton est également une source de données du même nom.
Les collections disposent d’une véritable création et d’une véritable suppression :
| Ressource | ID d’import |
|---|---|
fremforge_email_domain | <org>/<pattern> ou <org>/<id> |
fremforge_scan_policy (une par analyseur ; iac_scan à partir de 0.4.0) | <org>/<scanner> |
fremforge_package_access | <org>/<type>/<name> |
fremforge_package_access_team_grant | <org>/<type>/<team>/<name> |
fremforge_package_access_actions_grant | <org>/<type>/<repository>/<name> |
fremforge_package_protection_rule | <org>/<rule id> |
fremforge_registry_robot | <org>/<robot id> |
fremforge_secret_custom_pattern (à partir de 0.3.0 ; repository à partir de 0.7.0) | <org>/<pattern id> |
fremforge_iac_custom_check (à partir de 0.4.0) | <org>/<check id> |
fremforge_ci_secret (à partir de 0.9.0) | <org>/<NAME> / <org>/<repository id>/<NAME> |
Un nom de paquet peut contenir / (un scope npm, un chemin de conteneur) : c’est pourquoi il figure en dernier dans les ID d’import.
Exemple
resource "fremforge_auth_policy" "this" {
org = "acme"
max_pat_lifetime_days = 30
allow_user_pats = false
ssh_disabled = true
}
resource "fremforge_ssh_ca" "this" {
org = "acme"
ca_keys = [file("ssh-ca.pub")]
require_cert = true
}
resource "fremforge_scan_policy" "images" {
org = "acme"
scanner = "image_scan"
mode = "enforce"
block_severity = "high"
}Paramètres supprimés
Deux paramètres ont été supprimés de fremforge le 2026-10-14, car ils étaient enregistrés mais jamais appliqués : principal_policy sur fremforge_ssh_ca et default_template_repo sur fremforge_branch_protection_defaults. Depuis la version 0.1.1 du provider, ces deux attributs sont obsolètes : le provider ne les envoie plus et ne les lit plus, si bien qu’une configuration qui les définit encore continue de fonctionner et produit un plan sans changement, et tofu plan affiche un avertissement d’obsolescence. Retirez-les de votre configuration ; rien ne change lorsque vous le faites. Voir Protection de branche et Autorité de certification SSH.
fremforge_ssh_ca dont le seul argument est principal_policy échoue avec une erreur HTTP 400 (no-fields), et un default_template_repo non vide est refusé avec removed-setting. Mettez à jour avec tofu init -upgrade (ou terraform init -upgrade) ; version = "~> 0.1" récupère la 0.1.1.Secrets CI à portée : la valeur n’entre jamais dans le state
fremforge_ci_secret (à partir du provider 0.9.0) gère un secret CI à portée. La valeur est un argument en écriture seule, value_wo : elle est envoyée à la création du secret et à chaque modification (l’API remplace la valeur et la portée ensemble), et elle n’est jamais relue ni stockée dans le plan ou le state. Les arguments en écriture seule demandent OpenTofu 1.11 ou Terraform 1.11 ou plus récent. Omettez repository_id pour toute l’organisation ; augmentez value_wo_version pour écrire une nouvelle valeur.
variable "deploy_key" {
type = string
sensitive = true
ephemeral = true
}
resource "fremforge_ci_secret" "deploy" {
org = "acme"
name = "DEPLOY_KEY"
repository_id = 42
value_wo = var.deploy_key
value_wo_version = 1
workflows = ["deploy.yaml"]
refs = ["refs/heads/main"]
events = ["push", "workflow_dispatch"]
environment = "production"
}- Rotation : fremforge ne peut pas afficher la valeur, donc une nouvelle
value_woseule n’est pas une modification. Augmentezvalue_wo_versionpour l’écrire. - Dérive : une modification de la portée ou de la description faite hors de votre configuration apparaît dans le plan ; une modification de la valeur, non.
- La création ne reprend jamais un secret existant : si un secret de ce nom et de ce dépôt existe déjà, l’apply échoue et vous invite à l’importer.
- Import :
<org>/<NAME>pour un secret valable pour toute l’organisation,<org>/<repository id>/<NAME>pour un secret lié à un dépôt. Renseignezvalue_wodans la configuration avant le prochain apply. - Scopes du jeton : le jeton du provider doit avoir
ci-secrets:readetci-secrets:write.
Les arguments de portée sont refusés avant toute requête lorsqu’ils pourraient élargir la livraison : une entrée vide, un nom réservé (FORGEJO_, GITHUB_, GITEA_) ou un identifiant de dépôt qui n’est pas un nombre positif.
Les jetons des robots de registre ne vont jamais dans l’état
L’API n’affiche le jeton d’un robot de registre qu’une seule fois, au moment où il est émis. Le provider ne le stocke jamais dans l’état, dans aucun attribut. Il écrit le jeton une seule fois, lorsque l’API l’émet (à la création, et chaque fois que vous modifiez rotation), dans le fichier que vous indiquez dans token_file, avec le mode 0600, et n’écrase jamais un fichier existant :
resource "fremforge_registry_robot" "ci" {
org = "acme"
name = "ci-pull"
access = "read"
token_file = "${path.module}/.robot-ci.token"
rotation = "2026-10" # change to issue a new token; the old one is revoked at once
}Sans token_file, le jeton est perdu. Déplacez le fichier avant d’effectuer une nouvelle rotation.
Dérive, import et destroy
- Dérive :
plan -detailed-exitcodese termine avec le code 2 lorsqu’un paramètre que vous gérez a été modifié en dehors de votre configuration ;applyle rétablit. - Import :
import { to = fremforge_auth_policy.this; id = "acme" }, puistofu plan -generate-config-out=generated.tfécrit la configuration pour vous. - Destroy : pour un singleton, destroy se contente de le retirer de l’état et ne modifie rien dans l’organisation : écrire les valeurs par défaut affaiblirait silencieusement un paramètre de sécurité. Les collections sont supprimées.
fremforge_package_accesssupprime les paramètres du paquet ainsi que toutes les autorisations qui s’y rapportent.
Migrer depuis le module
Le module reste documenté pendant votre migration. Pour chaque paramètre, ajoutez la ressource du provider, importez-la à l’aide du slug de l’organisation, vérifiez que plan n’affiche aucun changement, puis retirez l’argument du module et exécutez tofu state rm sur sa restful_resource.
Comment nous le testons
À chaque modification, chaque ressource et chaque source de données passent par la véritable CLI OpenTofu face à une API fremforge enregistrée : seuls les arguments que vous définissez sont écrits, les modifications non gérées sont ignorées, une dérive gérée apparaît dans le plan, l’import relit le même état, et destroy se comporte comme décrit ci-dessus.
Les paramètres qu’il est sans risque de modifier sur une organisation partagée sont également testés en conditions réelles chaque nuit sur une organisation de test : apply, un plan sans changement, une modification effectuée via l’API, un plan qui la fait apparaître, apply, import dans un état vierge, un plan sans changement, destroy, une relecture, puis la restauration de la valeur d’origine. Il s’agit de la politique d’authentification, de la CA SSH, de la politique de SLA et du filtre de métadonnées du proxy de dépendances ; l’accès aux paquets, les règles de protection et les robots de registre ont été testés en conditions réelles de la même manière avant la publication. La liste d’adresses IP autorisées et les politiques de signature ne sont testées que face à l’API enregistrée, car les modifier sur une organisation partagée perturberait d’autres tests.