Automation
Azure Automation : prouver la version publiée avant d'exécuter un runbook
Un runbook de production pour relier commit source, job de synchronisation, brouillon, version publiée, test sans effet et rollback avant d'autoriser une exécution Azure Automation.
Un runbook Azure Automation vient d’être corrigé dans Git, relu puis fusionné. Le prochain job doit modifier une allowlist de production. Pourtant, personne ne peut prouver que la version publiée dans l’Automation Account correspond au commit approuvé. La synchronisation a peut-être échoué, le code est peut-être resté en brouillon, ou une correction directe dans le portail a créé une dérive invisible depuis le dépôt.
Le cas fil rouge est un runbook PowerShell nommé reconcile-firewall-allowlist. Il calcule un diff, puis applique uniquement les entrées autorisées. L’objectif n’est pas de refaire la revue de code : il faut relier un commit immuable à l’artefact Azure, exécuter un test sans effet, publier une seule version et décider entre exécution, nouvelle synchronisation, blocage ou rollback.
Figer le contrat de release
Commencez par nommer la version attendue avant de lancer une synchronisation. Le nom de branche seul ne suffit pas : il bouge. Conservez le commit, le chemin exact du script, son hash, l’Automation Account cible, le nom du runbook, le runtime et le comportement attendu de la synchronisation.
runbook: reconcile-firewall-allowlist
automation_account: aa-platform-prod
resource_group: rg-automation-prod
source_control: platform-runbooks
branch: main
source_path: /Runbooks/reconcile-firewall-allowlist.ps1
approved_commit: 7c91e1f
approved_sha256: <sha256-of-reviewed-script>
runtime: PowerShell-5.1
sync_should_publish: false
execution_mode: Plan
target_scope: /subscriptions/.../resourceGroups/rg-network-prod
success:
- sync job completes for the approved commit
- draft hash equals the reviewed script hash
- no-effect test returns the expected bounded diff
- published hash is captured after promotion
rollback: import and publish the last approved artifact Azure Automation conserve un brouillon et une version publiée. Le volet de test valide le brouillon ; les exécutions normales utilisent la version publiée. Une synchronisation réussie ne prouve donc pas, à elle seule, quelle version sera exécutée.
Qualifier la frontière de synchronisation
L’intégration source control est un flux à sens unique du dépôt vers Azure Automation. Vérifiez la branche, le dossier synchronisé, l’état de l’auto-sync et l’option de publication automatique. Un fichier placé hors du dossier configuré, une branche de production différente ou un webhook expiré peut laisser Azure sur une ancienne version sans que le merge Git soit en cause.
Cette intégration ne doit pas être supposée universelle. La synchronisation source control native prend en charge les runbooks PowerShell 5.1. Pour un runtime PowerShell plus récent, utilisez un pipeline explicite d’import et de publication, puis appliquez le même contrat de hash, de test et de rollback.
Ne profitez pas de l’incident pour recréer la connexion source control, renouveler ses credentials et publier le runbook en une seule opération. Séparez la réparation du canal de synchronisation de la promotion du code.
Lire le job et ses streams avant de relancer
Un statut Completed doit être relié au bon source control, au bon commit et aux bons fichiers. Listez les jobs récents, ouvrez le job candidat et conservez ses streams. Un nouveau sync lancé sans lire le précédent peut masquer l’erreur initiale.
RG="rg-automation-prod"
ACCOUNT="aa-platform-prod"
SOURCE="platform-runbooks"
az automation source-control sync-job list --resource-group "$RG" --automation-account-name "$ACCOUNT" --source-control-name "$SOURCE" --output table
JOB_ID="<sync-job-id>"
az automation source-control sync-job show --resource-group "$RG" --automation-account-name "$ACCOUNT" --source-control-name "$SOURCE" --job-id "$JOB_ID" --output json
az automation source-control sync-job stream list --resource-group "$RG" --automation-account-name "$ACCOUNT" --source-control-name "$SOURCE" --sync-job-id "$JOB_ID" --output json Cherchez une erreur d’authentification, un chemin ignoré, un type de runbook non supporté, un import partiel ou une publication absente. Si le job ne porte pas le commit attendu, ne comparez pas encore le comportement applicatif : le mauvais artefact a été promu dans la chaîne.
Comparer dépôt, brouillon et version publiée
Exportez séparément les deux slots. Calculez leur hash sans modifier les fichiers, puis comparez-les au script issu du commit approuvé. Les trois états peuvent être différents : dépôt correct, brouillon correct, version publiée ancienne.
$ResourceGroup = "rg-automation-prod"
$Account = "aa-platform-prod"
$Runbook = "reconcile-firewall-allowlist"
$Output = Join-Path $PWD "runbook-evidence"
New-Item -ItemType Directory -Path $Output -Force | Out-Null
Export-AzAutomationRunbook `
-ResourceGroupName $ResourceGroup `
-AutomationAccountName $Account `
-Name $Runbook `
-Slot Draft `
-OutputFolder (Join-Path $Output "draft") `
-Force
Export-AzAutomationRunbook `
-ResourceGroupName $ResourceGroup `
-AutomationAccountName $Account `
-Name $Runbook `
-Slot Published `
-OutputFolder (Join-Path $Output "published") `
-Force
Get-ChildItem $Output -Recurse -File |
Get-FileHash -Algorithm SHA256 |
Select-Object Path, Hash Un diff de commentaires ou d’encodage peut changer le hash sans changer le comportement. Dans ce cas, gardez le hash comme alerte de dérive et complétez-le par un diff lisible. En revanche, ne normalisez pas silencieusement le code avant comparaison : cela peut masquer une différence exécutable.
Ajoutez aussi au runbook un identifiant de release non secret, émis au début de chaque job. Il relie les streams d’exécution à la version attendue sans dépendre du souvenir d’un opérateur.
$Release = "git:7c91e1f"
Write-Output "release=$Release runbook=reconcile-firewall-allowlist mode=$Mode"
if ($Mode -eq "Plan") {
Write-Output "No production write is allowed in Plan mode"
} Tester le brouillon sans effet de bord
Le test doit utiliser les mêmes entrées et la même identité logique que la production, mais un mode qui interdit toute écriture. Pour reconcile-firewall-allowlist, le runbook lit la configuration effective, calcule les ajouts et suppressions, puis s’arrête avant l’appel de modification.
Le résultat attendu n’est pas seulement Completed. Le test doit exposer le release marker, le scope cible, le nombre d’objets lus, le diff calculé et la preuve qu’aucune écriture n’a été tentée. Vérifiez en parallèle l’Activity Log sur le scope cible : un test dit sans effet n’est validé que si le plan de contrôle ne montre aucune mutation correspondante.
Si le runbook ne possède pas de mode Plan, ne l’inventez pas pendant l’incident. Utilisez une cible canari isolée ou bloquez la publication jusqu’à ce que le contrat d’exécution soit corrigé.
Publier puis valider un canari borné
Quand le brouillon correspond au commit approuvé et que le test sans effet est propre, publiez explicitement ce runbook. Réexportez ensuite le slot Published et recalculez son hash. La publication terminée dans le portail ou l’API ne remplace pas cette preuve.
Publish-AzAutomationRunbook `
-ResourceGroupName "rg-automation-prod" `
-AutomationAccountName "aa-platform-prod" `
-Name "reconcile-firewall-allowlist"
Export-AzAutomationRunbook `
-ResourceGroupName "rg-automation-prod" `
-AutomationAccountName "aa-platform-prod" `
-Name "reconcile-firewall-allowlist" `
-Slot Published `
-OutputFolder "$PWD/published-after" `
-Force
Get-FileHash "$PWD/published-after/reconcile-firewall-allowlist.ps1" `
-Algorithm SHA256 Lancez d’abord une exécution publiée en Plan, puis une action canari sur une seule entrée réversible. Corrélez job ID, release marker, identité, cible, diff appliqué et Activity Log. N’ouvrez le scope complet que si la version et l’effet sont tous deux prouvés.
Décider exécution, resynchronisation ou rollback
Exécuter
commit approuvé, brouillon et publié sont reliés
test Plan et canari publié sont propres
release marker et Activity Log concordent
Resynchroniser
job absent, échoué ou rattaché au mauvais commit
connexion, branche et dossier sont confirmés avant relance
aucun job de production ne peut partir pendant la réparation
Publier
brouillon égal au commit approuvé
version publiée encore ancienne
test du brouillon sans effet validé
Rollbacker
version publiée incorrecte ou canari en régression
réimporter l'artefact précédent connu, puis le publier
rejouer Plan et canari avant de réactiver schedules ou webhooks
Bloquer
hash ou commit impossible à relier
test avec effets non maîtrisés
runtime non supporté par le mécanisme de synchronisation Le rollback porte sur un artefact connu, pas sur la branche main du moment. Importez la dernière version approuvée, publiez-la, réexportez-la et vérifiez son release marker. Suspendez temporairement schedules et webhooks si une exécution automatique peut partir entre import et validation.
Conclusion
Dans Azure Automation, « le code est mergé » et « ce code sera exécuté » sont deux affirmations différentes. La chaîne exploitable relie commit, job de synchronisation, brouillon, test sans effet, version publiée, canari et trace d’exécution.
La décision devient alors vérifiable : exécuter la version prouvée, resynchroniser le bon commit, publier un brouillon validé, restaurer l’artefact précédent ou bloquer la production tant que l’identité de la version reste ambiguë.