Dans nos articles précédents, nous avons abordé les bases de l'Infrastructure as Code avec Terraform et Jamf Pro, puis nous avons examiné les fournisseurs Terraform dédiés pour Jamf Protect et la Plateforme Jamf. Si vous ne les avez pas encore lus, nous vous recommandons de commencer par là — ils couvrent les fondamentaux de Terraform, la structure des projets, la gestion de l'état et la façon de définir les ressources Jamf en code à partir de zéro.
Cette fois-ci, nous traitons une question que nous posons souvent : « Tout cela semble formidable, mais j'ai déjà des centaines de stratégies, de profils, de scripts et de groupes dans mon environnement Jamf. Est-ce que je dois vraiment tout réécrire à la main ? »
La réponse courte est non. Nous avons créé un outil appelé jamformer pour aider exactement cela — mais avant de nous plonger dedans, il est important d'être honnête sur ce qu'il est et ce qu'il n'est pas.
Qu'est-ce que jamformer ?
jamformer est un outil d'activation et d'accélération pour les équipes adoptant Jamf avec Terraform. Il se connecte à votre instance Jamf existante, découvre tout ce qu'il peut trouver et génère un projet Terraform comme point de départ — un scaffold réaliste à partir duquel vous pouvez apprendre et affiner. Considérez-le comme un pont entre où vous êtes aujourd'hui (un environnement Jamf entièrement configuré géré via la console) et où vous voulez être (ce même environnement géré en tant que code) — mais le pont n'est pas un tapis roulant. Vous devez toujours le traverser.
Il n'est délibérément pas :
- Un générateur de code de production. Le HCL qu'il produit est un premier brouillon. Avant de gérer une infrastructure réelle avec celui-ci, attendez-vous à examiner chaque fichier, à refactoriser dans votre propre structure de modules, à appliquer des conventions de nommage, à renforcer la gestion des secrets et à gérer les quirks de dérive des fournisseurs.
- Un substitut pour apprendre Terraform ou les fournisseurs Jamf. Il aplatit la courbe d'apprentissage ; il ne l'élimine pas.
- Un bouton de migration en un clic. Les environnements Jamf importants ou inhabituels auront toujours besoin d'un jugement humain.
Ce pour quoi il est bon :
- Voir ce qui se trouve réellement dans votre instance Jamf, exprimé dans le propre modèle de ressources des fournisseurs Terraform — attributs, références croisées, quirks de cycle de vie et tout.
- Amorcer des preuves de concept, des démonstrations, des ateliers, des formations internes et des séances de planification de migration.
- Donner aux ingénieurs un scaffold réaliste à refactoriser en IaC plutôt que de fixer un éditeur vierge.
C'est aussi en lecture seule. jamformer ne modifie, crée ni supprime rien dans votre instance Jamf. La seule chose qu'il écrit est un ensemble de fichiers Terraform sur votre machine locale.
Gardez ce cadrage à l'esprit pour le reste de cet article. Lorsque nous parcourons le flux de travail et affichons des exemples de sortie, vous regardez une matière première qu'un ingénieur humain doit affiner — pas l'article fini.
Pourquoi ne pas simplement utiliser terraform import ?
Vous pouvez absolument le faire, et si vous avez lu l'article sur Protect, vous avez déjà vu comment terraform import et terraform query avec des blocs list peuvent mettre des ressources existantes sous gestion.
Mais si vous gérez un environnement Jamf via la console depuis un certain temps, vous saurez qu'il y a beaucoup de choses dedans. Importer manuellement tout signifie inventorier chaque type de ressource, écrire des centaines de blocs d'importation avec les ID Jamf corrects, comprendre quelle stratégie référence quel script et quel groupe et quelle catégorie, extraire les scripts intégrés et les charges utiles de profils de configuration dans des fichiers autonomes et gérer les quirks des fournisseurs autour des valeurs par défaut.
C'est beaucoup de travail. Nous voulions rendre cela plus facile.
Qu'est-ce qu'il supporte ?
jamformer fonctionne avec quatre fournisseurs Terraform dans la famille de produits Jamf :
| Fournisseur | Comment il découvre |
|---|---|
| Jamf Pro (par défaut) | API Jamf Pro |
| Jamf Protect | terraform query |
| Jamf Platform | terraform query |
| Jamf Security Cloud (JSC) | Sources de données Terraform |
Pour Jamf Pro seul, cela couvre les stratégies, les scripts, les profils de configuration, les groupes intelligents, les groupes statiques, les préparations informatiques, les profils de périphériques mobiles, les attributs d'extension, les packages, les catégories, les bâtiments, les départements et bien plus — plus les paramètres comme l'enregistrement des clients, le point de distribution cloud et la configuration du libre-service. La liste faisant autorité et toujours à jour est jamformer -list-resources (optionnellement filtrée avec -provider).
Que se passe-t-il quand vous l'exécutez ?
Lorsque vous pointez jamformer vers votre instance Jamf, il passe par plusieurs étapes. Nous allons parcourir ce que chacun fait afin que vous sachiez à quoi vous attendre.
D'abord, il découvre vos ressources. Pour Jamf Pro, il s'authentifie à votre instance (OAuth2 ou authentification de base) et interroge l'API pour chaque type de ressource supportée. Il parcourt votre environnement dans l'ordre des dépendances — d'abord les sites et les catégories, puis les scripts et les packages, puis les stratégies et les profils — afin de pouvoir mapper les relations entre les ressources. Pour Jamf Protect et Jamf Platform, il utilise terraform query avec des blocs list (la même approche que nous avons couverte dans l'article sur Protect) pour découvrir les ressources directement via le fournisseur.
Ensuite, il génère les blocs d'importation. Pour chaque ressource découverte, jamformer écrit un bloc Terraform import avec une étiquette dérivée du nom de la ressource. Les espaces deviennent des traits de soulignement, les caractères spéciaux sont supprimés, et si deux ressources se retrouvent avec la même étiquette, un suffixe numérique est ajouté pour les garder uniques. Il génère aussi provider.tf, variables.tf et terraform.tfvars configurés pour le bon fournisseur.
Voici à quoi pourraient ressembler ces blocs d'importation :
import {
to = jamfpro_policy.software_update_enforce
id = "142"
}
import {
to = jamfpro_script.install_rosetta
id = "87"
}
import {
to = jamfpro_category.productivity
id = "5"
}
Puis il demande à Terraform de générer le HCL. jamformer exécute terraform plan -generate-config-out (ou terraform query -generate-config-out pour Protect et Platform), ce qui permet au fournisseur de produire le HCL pour chaque ressource importée. Étant donné que le fournisseur lui-même fait le travail lourd ici, la configuration générée correspond toujours à ce que le fournisseur attend.
Si certaines ressources échouent à importer — c'est possible, parfois un fournisseur ne peut pas relire une ressource particulière correctement — jamformer supprime automatiquement le bloc d'importation défaillant et réessaie. Vous verrez un message indiquant quelles ressources ont été ignorées afin que vous puissiez les gérer ultérieurement.
Enfin, il nettoie la sortie. La sortie brute de Terraform est un seul grand fichier avec des valeurs littérales partout. jamformer le transforme en quelque chose que vous voudriez réellement utiliser :
- jamformer réécrit les ID Jamf littéraux en références Terraform. Une stratégie qui référence l'ID de catégorie
5devientjamfpro_category.productivity.id, afin que Terraform comprenne les relations entre vos ressources — tout comme vous l'écririez à la main. - Les scripts intégrés vont vers des fichiers individuels sous
support_files/scripts/, les charges utiles de profils de configuration verssupport_files/macos_configuration_profiles/, les scripts d'attributs d'extension verssupport_files/extension_attributes/, et les configurations d'applications de périphériques mobiles verssupport_files/app_configurations/. jamformer met à jour le HCL avec des référencesfile()afin que vos scripts et profils soient des fichiers appropriés que vous pouvez comparer, examiner et modifier indépendamment. Les jetons d'inscription de périphériques et d'achat en volume utilisent des variables de cheminfile(var.xxx)— vous placez vos fichiers de jetons (téléchargés depuis Apple Business Manager) au chemin que vous spécifiez dans la variable. - jamformer résout les ressources d'icônes en URL CDN (les icônes ne sont pas téléchargées localement) et ajoute un bloc
lifecycle { ignore_changes }pour prévenir les cycles inutiles de destruction/création lors de la première application. - Les attributs facultatifs qui reviennent comme
nullsont supprimés, les valeurs connues pour causer des problèmes (commecategory_id = -1pour les ressources non catégorisées) sont supprimées, et le grand fichier unique est divisé en fichiers par type de ressource —policies.tf,scripts.tf,categories.tfet ainsi de suite. - Une passe de validation exécute
terraform validatepour détecter les attributs conditionnellement invalides — par exemple, les attributs qui ne sont valides que pour un type CDN spécifique — et les supprime automatiquement afin que vous n'ayez pas à chasser les erreurs de schéma à la main.
Après le post-traitement, jamformer analyse la sortie pour les secrets. Les environnements Jamf contiennent souvent des identifiants intégrés dans les profils de configuration, les scripts et les attributs de ressources — des choses comme les mots de passe de liaison LDAP, les identifiants SMTP, les secrets Wi-Fi partagés et les jetons API. jamformer utilise gitleaks avec des règles spécifiques à Jamf pour les trouver avant que vous n'ayez accidentellement les valider dans Git.
Lorsque jamformer trouve des secrets, il affiche un rapport groupé par ressource et attribut. En mode interactif, vous pouvez choisir de corriger automatiquement tous les résultats, de les parcourir individuellement ou d'ignorer complètement la correction. La correction déplace les secrets dans des variables Terraform sensibles — pour les fichiers .tf, la valeur du secret est remplacée par une référence var. ; pour les fichiers de support comme les scripts et les profils, le fichier est converti en modèle .tpl en utilisant templatefile(). Vous pouvez ignorer cette étape avec -skip-secret-scan si vous préférez gérer les secrets vous-même.
Mise en route
Si vous avez suivi l'article d'introduction, vous devriez déjà avoir Terraform et un éditeur de texte configurés. Les étapes ici sont simples.
1. Installer jamformer
Homebrew :
brew install Jamf-Concepts/tap/jamformer
Des binaires pré-construits et un installateur .pkg sont disponibles à partir de la page des versions.
Vous n'avez pas besoin d'installer Terraform séparément — jamformer le télécharge automatiquement dans un répertoire temporaire, il ne sera donc en conflit avec aucune installation Terraform existante sur votre machine.
2. Exécutez-le contre votre instance
Le moyen le plus facile de commencer est d'exécuter jamformer sans arguments :
jamformer
Il vous guidera à travers tout de manière interactive — quel fournisseur vous voulez utiliser, l'URL de votre instance et vos identifiants. Vous saisissez les mots de passe et les secrets des clients en tant qu'entrée masquée afin qu'ils n'apparaissent pas dans l'historique de votre terminal.
Les URL raccourcies fonctionnent aussi ici — vous pouvez simplement taper yourinstance et jamformer l'élargira à yourinstance.jamfcloud.com. Pour Protect, your-tenant s'élargit à your-tenant.protect.jamfcloud.com.
Une fois que vous êtes à l'aise avec l'outil ou que vous voulez le scripter, vous pouvez définir les identifiants via des variables d'environnement :
# Jamf Pro avec OAuth2
export JAMF_CLIENT_ID='your-client-id'
export JAMF_CLIENT_SECRET='your-client-secret'
jamformer -url https://yourinstance.jamfcloud.com
# Jamf Protect
export JAMF_CLIENT_ID='your-client-id'
export JAMF_CLIENT_SECRET='your-client-secret'
jamformer -provider jamfprotect -url https://your-tenant.protect.jamfcloud.com
jamformer ne lit les identifiants que parmi les variables d'environnement ou les invites interactives — jamais les drapeaux CLI — pour éviter de fuir les secrets dans l'historique du shell et les listes de processus. Vous pouvez passer l'URL comme drapeau (-url) ou via JAMF_URL.
jamformer n'écrit pas les identifiants dans terraform.tfvars et génère un .gitignore qui exclut les fichiers tfvars, les fichiers d'état et le répertoire .terraform/.
3. L'importation de tout à la fois est facultative
Si votre environnement est volumineux et que vous préférez commencer petit, vous pouvez cibler des types de ressources spécifiques :
# Commencer avec juste les stratégies, les scripts et les catégories
./jamformer -include-resources "policies scripts categories"
# Tout sauf les packages et les icônes
./jamformer -exclude-resources "packages icons"
# Voir tous les noms de filtres disponibles
./jamformer -list-resources
Lorsqu'un type de dépendance n'est pas inclus (par exemple vous importez des stratégies mais pas des catégories), les références à ces types restent en tant qu'ID littéraux plutôt que des expressions Terraform. Vous pouvez toujours exécuter à nouveau avec plus de types ultérieurement à mesure que vous vous sentez à l'aise.
Alors, à quoi ressemble vraiment la sortie ?
Après la fin de jamformer, vous aurez un répertoire qui ressemble à ceci :
generated/
.gitignore
provider.tf
variables.tf
terraform.tfvars
policies.tf
policies_import.tf
scripts.tf
scripts_import.tf
categories.tf
categories_import.tf
...
support_files/
scripts/
install_rosetta.sh
set_wallpaper.sh
extension_attributes/
battery_health.sh
macos_configuration_profiles/
wifi_corporate.mobileconfig
filevault_enforce.mobileconfig
device_enrollment_tokens/ (vide - placez vos fichiers .p7m ici)
volume_purchasing_tokens/ (vide - placez vos fichiers .vpptoken ici)
app_configurations/
managed_browser.xml
Chaque type de ressource obtient son propre fichier .tf et un fichier _import.tf correspondant. Le répertoire support_files/ contient des scripts, des profils et des configurations d'applications extraites référencés via des expressions file(). jamformer crée des répertoires de jetons (device_enrollment_tokens/ et volume_purchasing_tokens/) comme lieu recommandé pour vos fichiers de jetons Apple Business Manager — ceux-ci utilisent des variables de chemin file(var.xxx) car l'API ne retourne pas de données de jeton.
Mode compact
Par défaut, jamformer génère un bloc de ressources par objet — une disposition plate et explicite facile à lire et à examiner. Mais si votre environnement a des douzaines de ressources similaires (catégories, bâtiments, départements), la sortie peut sembler répétitive.
Le drapeau -compact consolide les types de ressources éligibles en motifs for_each + locals, produisant une sortie plus proche de ce que vous écriveriez à la main :
jamformer -compact
Sans le mode compact, vous obtiendriez des blocs individuels :
resource "jamfpro_category" "productivity" {
name = "Productivity"
}
resource "jamfpro_category" "security" {
name = "Security"
}
Avec le mode compact activé, celles-ci deviennent :
locals {
categories = {
productivity = { name = "Productivity" }
security = { name = "Security" }
}
}
resource "jamfpro_category" "all" {
for_each = local.categories
name = each.value.name
}
jamformer réécrit automatiquement les références entre ressources pour utiliser le nouvel adressage — jamfpro_category.all["productivity"].id au lieu de jamfpro_category.productivity.id — afin que tout reste connecté. Il met à jour les blocs d'importation de la même manière.
jamformer détermine l'admissibilité de manière dynamique au moment de l'exécution. Un type de ressource est admissible lorsque le fichier contient deux blocs de ressources ou plus qui partagent tous le même ensemble d'attributs et aucun n'a de blocs imbriqués (autres que lifecycle). Les attributs identiques dans toutes les instances deviennent des valeurs littérales sur le bloc de ressources ; seules les valeurs qui varient vont dans la carte locals. Cela fonctionne sur les quatre fournisseurs.
Si vous voulez un contrôle plus fin, vous pouvez cibler des types spécifiques :
# Compacter uniquement les catégories et les bâtiments
jamformer -compact -compact-include "categories buildings"
# Compacter tout ce qui est admissible sauf les stratégies
jamformer -compact -compact-exclude "policies"
Support multi-environnement
⚠️ Expérimental et très avancé. Cette fonctionnalité cible les personnes qui maîtrisent déjà les modules Terraform, les flux de travail de branches longues et le modèle de ressources du fournisseur Jamf. La sortie est plus au niveau du scaffold que le mode environnement unique, pas moins — attendez-vous à éditer le module généré, les racines par environnement et l'extraction de variables avant que tout cela ne soit utilisable. Traitez-le comme une fonctionnalité de recherche/activation, pas un flux de travail de production pris en charge. Si vous êtes nouveau à Terraform ou que vous travaillez encore sur votre premier projet d'instance unique, commencez par là et revenez à cela plus tard.
Si vous gérez plusieurs environnements Jamf Pro — préparation et production, ou développement et prod — vous avez probablement réfléchi à la façon de les maintenir synchronisés. jamformer peut générer un projet Terraform structuré autour d'un module partagé avec des répertoires racines par environnement, conçu pour un flux de travail de branches Git où chaque branche longue représente un environnement.
export JAMF_URL_STAGING=https://staging.jamfcloud.com
export JAMF_CLIENT_ID_STAGING=xxx
export JAMF_CLIENT_SECRET_STAGING=xxx
export JAMF_URL_PROD=https://prod.jamfcloud.com
export JAMF_CLIENT_ID_PROD=xxx
export JAMF_CLIENT_SECRET_PROD=xxx
jamformer -multi-env "staging prod"
jamformer exécute la découverte par rapport à chaque environnement indépendamment, fait correspondre les ressources par nom et produit une sortie qui ressemble à ceci :
generated/
modules/jamf/ # définitions de ressources partagées
policies.tf # ressources présentes dans tous les environnements
scripts.tf
categories.tf
policies_staging_only.tf # ressources uniquement dans la mise en stage
variables.tf # variables d'entrée du module
providers.tf
support_files/ # fichiers identiques dans les environnements
scripts/
macos_configuration_profiles/
environments/
staging/
main.tf # config fournisseur + appel de module
backend.tf # placeholder pour votre backend d'état
variables.tf
terraform.tfvars # valeurs spécifiques à l'environnement
imports.tf # blocs d'importation avec préfixe module.jamf.
support_files/ # fichiers qui diffèrent de l'autre environnement
prod/
main.tf
backend.tf
variables.tf
terraform.tfvars
imports.tf
support_files/
Le module partagé dans modules/jamf/ contient des définitions de ressources communes à tous les environnements. Lorsque les valeurs d'attribut diffèrent entre les environnements — une stratégie avec un category_id ou un profil différent avec une description différente — jamformer extrait ces valeurs aux variables de module et les définit par environnement dans terraform.tfvars. Les références entre ressources restent des expressions Terraform appropriées (par exemple, jamfpro_category.productivity.id), afin que les relations entre les ressources restent intactes.
Cela fonctionne mieux lorsque vous gardez intentionnellement vos environnements synchronisés — les mêmes stratégies, scripts, profils et groupes déployés dans les instances. Plus ils correspondent, plus la sortie est propre. Cela dit, jamformer gère les différences courantes du monde réel :
- Même ressource, paramètres différents (par exemple, une stratégie avec une catégorie ou une fréquence différente en staging par rapport à prod) — les attributs différents deviennent des variables de module, avec les valeurs de chaque environnement dans son propre
terraform.tfvars. jamformer trie les variables alphabétiquement et les regroupe par type de ressource pour la lisibilité. - Les ressources qui existent dans certains environnements mais pas dans d'autres (par exemple, une stratégie de test uniquement en staging) — jamformer les sépare en fichiers clairement étiquetés comme
policies_staging_only.tfau sein du module. Sur la branche d'un autre environnement, vous supprimez simplement ces fichiers. - Les fichiers de support qui diffèrent (par exemple, un script avec un contenu légèrement différent dans les instances) — les fichiers identiques dans tous les environnements vivent dans le répertoire
support_files/du module partagé. Lorsque les fichiers diffèrent, jamformer les place dans le répertoiresupport_files/de chaque environnement et les transmet au module en tant que variables.
Chaque répertoire d'environnement a son propre placeholder backend.tf, son propre état et ses propres blocs d'importation avec le préfixe module.jamf.. Cela signifie que vous pouvez exécuter terraform plan et terraform apply indépendamment par environnement, en parallèle si nécessaire, sans aucun risque que l'état d'un environnement interfère avec un autre.
jamformer utilise le premier environnement répertorié comme source de vérité pour les définitions de ressources partagées ; utilisez -source-env pour remplacer cela. Il fait correspondre les ressources par nom, donc une stratégie appelée « Software Update - Enforce » en staging correspondra à une stratégie portant le même nom en prod indépendamment de leurs ID Jamf.
Le flux de travail envisagé consiste à valider la sortie dans un référentiel, à créer une branche longue par environnement, à configurer le backend.tf de chaque branche avec le backend d'état approprié et à configurer CI pour exécuter terraform apply dans le répertoire environments/<env>/ correspondant lorsque le code arrive sur cette branche. Les changements passent des branches de fonctionnalités au premier environnement, puis se promeuvent à travers les branches via des demandes d'extraction.
Plus vos environnements divergent, plus la sortie contiendra de variables et de fichiers spécifiques à l'environnement. Si vos instances sont substantiellement différentes, vous pourriez mieux vous porter en exécutant jamformer séparément pour chacune et en maintenant des projets Terraform indépendants.
Travailler avec la sortie générée
Nous l'avons dit en haut et nous le redisons ici, car c'est la partie la plus importante : la configuration générée n'est pas une Terraform prête pour la production. jamformer est un outil d'activation et d'accélération. Il vous donne un point de départ réaliste sur le chemin vers la gestion de votre environnement Jamf en tant que code — pas un raccourci qui vous y amène immédiatement. Prévoyez de consacrer du temps réel à l'examen, à l'affinage et à la compréhension de ce qu'il a produit avant que quoi que ce soit ne modifie l'infrastructure réelle.
La sortie est intentionnellement plate — un bloc de ressources par objet, un fichier par type, pas de modules. En pratique, vous voudrez probablement la refactoriser dans une structure de projet modulaire, tirer parti des fonctionnalités HCL comme for_each et locals pour réduire la répétition, transformer des choses comme les URL d'instance et les paramètres communs en variables pour votre environnement et organiser les ressources d'une manière qui a du sens pour votre équipe. jamformer vous donne la matière brute pour faire cela ; comment vous la façonnez dépend de vous. Ce travail de façonnage est où la plupart de l'apprentissage réel de Terraform se produit — et c'est toute la raison pour laquelle jamformer existe sous sa forme actuelle.
Cela dit, voici le flux de travail que nous recommandons.
Les mêmes commandes que vous avez apprises dans l'introduction s'appliquent ici :
cd generated
terraform plan # Examinez le plan d'importation, vérifiez les erreurs du fournisseur
Attendez-vous à des diffs dans votre premier plan. Il est normal de voir des différences entre ce que Terraform génère et ce qui existe réellement dans votre instance Jamf. Certains attributs peuvent afficher des valeurs qui ne correspondent pas à ce que vous voyez dans la console, certains champs optionnels peuvent avoir des valeurs par défaut que le fournisseur remplit qui diffèrent de la configuration en direct, et certaines ressources peuvent avoir des erreurs de validation en raison de champs en écriture seule que le fournisseur ne peut pas relire. Ce sont des quirks au niveau du fournisseur, pas des bugs dans jamformer, et ils auront besoin d'attention manuelle.
Parcourez la sortie du plan, corrigez les erreurs et ajustez les attributs jusqu'à ce que vous soyez satisfait de ce que Terraform rapporte. Ce processus d'examen est où vous apprendrez le plus sur la façon dont le fournisseur représente vos ressources — et c'est une étape importante avant de remettre le contrôle à Terraform.
Une fois que le plan semble propre :
terraform apply # Importez les ressources dans l'état (vous serez invité à confirmer)
L'exécution de terraform apply ici importe vos ressources existantes dans l'état Terraform. Cela ne change rien dans Jamf — elle indique seulement à Terraform « ces ressources existent déjà et voici à quoi elles ressemblent. »
Une fois que vous avez appliqué avec succès, les blocs d'importation ont terminé leur travail. Vous pouvez les supprimer :
rm *_import.tf
Puis exécutez terraform plan à nouveau. Idéalement, vous ne voyez pas de modifications. Si des différences apparaissent, ce sont des cas où les valeurs par défaut du fournisseur ne correspondent pas tout à fait à ce qui se trouve réellement dans Jamf — ajustez le HCL généré jusqu'à ce que vous obteniez un plan propre.
À ce stade, vous avez un projet Terraform qui représente votre environnement Jamf. Validez-le dans Git et vous êtes prêt à commencer le vrai travail : affiner la configuration, l'organiser pour correspondre au flux de travail de votre équipe et progressivement vers la réalisation des changements via des demandes d'extraction, l'examen du code et terraform apply plutôt que la console.
Choses à garder à l'esprit
Par défaut, jamformer télécharge les packages depuis le point de distribution cloud. Pour les grands environnements avec beaucoup de packages, cela peut prendre un certain temps. Utilisez -skip-package-downloads pour ignorer cette étape et gérer les packages séparément.
L'analyse des secrets s'exécute automatiquement après la génération.