Automation

Azure Policy : borner une tâche de remédiation avant de réécrire la production

Un runbook de production pour valider la cible, l'identité, les rôles, le canary, les logs et le rollback d'une remédiation Azure Policy avant de l'étendre.

14 août 2026 azureazure-policyremediationmanaged-identityrbacresource-graphactivity-logautomationgovernancerunbookrollbackproduction

Une initiative Azure Policy signale plusieurs centaines de ressources non conformes. La règle semble simple : ajouter les paramètres de diagnostic manquants avec un effet deployIfNotExists, ou corriger une propriété avec modify. Le bouton Create remediation task paraît être la suite logique. En production, il déclenche pourtant une automatisation munie d’une identité managée, capable d’écrire sur toutes les ressources retenues par l’affectation.

Le cas d’usage est une équipe plateforme qui veut appliquer une nouvelle règle de gouvernance à des ressources existantes. L’objectif n’est pas de freiner la conformité, mais de transformer une remédiation globale en changement observable et réversible : figer la définition réellement affectée, produire la liste exacte des cibles, vérifier les droits de l’identité, tester une ressource témoin, puis élargir seulement si l’état attendu et les journaux le prouvent.

Figer le contrat avant la tâche

Une tâche de remédiation n’exécute pas un intitulé ; elle exécute l’effet d’une définition, avec les paramètres d’une affectation, à un périmètre donné. Pour une initiative, le policyDefinitionReferenceId distingue la règle précise à remédier. Capturez ces éléments avant toute exécution, car une définition ou une affectation modifiée entre l’analyse et le lancement change le contrat réel.

text policy-remediation-change-envelope.txt
Changement: chg-20260814-021
Affectation: enforce-platform-baseline-prod
Scope: /subscriptions/00000000-0000-0000-0000-000000000000
Definition reference: deploy-diagnostics-storage
Effect: deployIfNotExists
Parametres: workspace cible, categories, regions autorisees
Mode de decouverte initial: ExistingNonCompliant

Etat attendu
Ajouter les diagnostic settings absents
Ne pas remplacer une configuration deja approuvee
Ne toucher qu'aux ressources Storage du perimetre

Validation
Une ressource canary d'abord
Logs visibles dans le workspace attendu
Aucun role ou parametre elargi pendant l'execution

Rollback
Annuler la tache encore active
Supprimer uniquement les objets crees par la remediation fautive
Restaurer la definition ou l'affectation versionnee si elle a derive

Conservez l’identifiant de définition, sa version dans le dépôt, les paramètres d’affectation, les exemptions, le scope et l’identité. Le statut « non conforme » ne dit pas encore quelle écriture sera produite.

Lire l’effet et les rôles réellement demandés

Les effets deployIfNotExists et modify utilisent l’identité managée associée à l’affectation pour déployer ou modifier les ressources existantes. Les roleDefinitionIds de la définition décrivent les rôles nécessaires, mais ils ne prouvent pas que le périmètre RBAC attribué à l’identité est minimal. Une identité Contributor au niveau subscription mérite une revue, même si la remédiation ne vise qu’un type de ressource.

bash 01-policy-assignment-and-identity.sh
ASSIGNMENT_ID="/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policyAssignments/enforce-platform-baseline-prod"

az policy assignment show --ids "$ASSIGNMENT_ID" --query '{name:name,scope:scope,definition:policyDefinitionId,parameters:parameters,identity:identity,location:location}' --output json

PRINCIPAL_ID="00000000-0000-0000-0000-000000000000"
az role assignment list --assignee "$PRINCIPAL_ID" --all --query '[].{role:roleDefinitionName,scope:scope}' --output table

Pour une définition custom, relisez aussi le template de deployIfNotExists, les opérations de modify, la condition d’existence et les roleDefinitionIds. Si la définition a changé, les permissions de l’identité ne sont pas automatiquement réalignées. Le bon contrôle compare donc trois objets : définition, affectation et rôles effectifs.

Produire la liste exacte des ressources éligibles

La conformité agrégée est insuffisante pour approuver une écriture. Interrogez les états Azure Policy dans Resource Graph afin d’obtenir les identifiants de ressources, régions, types et horodatages. Retirez les exemptions, les environnements hors fenêtre et les ressources dont le propriétaire n’a pas validé le changement.

kusto 02-policy-remediation-targets.kql
let AssignmentId = tolower("/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policyAssignments/enforce-platform-baseline-prod");
let DefinitionReferenceId = "deploy-diagnostics-storage";
policyresources
| where type =~ "microsoft.policyinsights/policystates"
| extend assignmentId = tolower(tostring(properties.policyAssignmentId)),
       definitionReferenceId = tostring(properties.policyDefinitionReferenceId),
       complianceState = tostring(properties.complianceState),
       targetId = tolower(tostring(properties.resourceId)),
       targetType = tostring(properties.resourceType),
       targetLocation = tostring(properties.resourceLocation),
       evaluatedAt = todatetime(properties.timestamp)
| where assignmentId == AssignmentId
| where definitionReferenceId == DefinitionReferenceId
| where complianceState == "NonCompliant"
| project targetId, targetType, targetLocation, evaluatedAt
| order by targetLocation asc, targetId asc

Exportez cette liste dans le dossier du changement et calculez son empreinte. Une nouvelle évaluation peut faire évoluer l’ensemble pendant la fenêtre. Le mode ExistingNonCompliant travaille sur l’état déjà connu ; ReEvaluateCompliance relance la découverte. Ce choix doit être explicite, surtout après une modification récente de la définition.

Tester l’écriture avant la remédiation globale

Pour une définition deployIfNotExists, validez le template ARM séparément avec what-if sur un environnement représentatif. Pour modify, relisez chaque opération et son alias : l’effet peut ajouter une valeur, la remplacer ou ne pas s’appliquer selon le mode de l’alias. Dans les deux cas, commencez la remédiation sur une ressource canary, pas sur une limite numérique arbitraire au niveau subscription.

bash 03-policy-remediation-canary.sh
ASSIGNMENT_ID="/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policyAssignments/enforce-platform-baseline-prod"
CANARY_ID="/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-policy-canary/providers/Microsoft.Storage/storageAccounts/stpolicycanary01"
TASK="remediate-diagnostics-canary-20260814"

az policy remediation create --resource "$CANARY_ID" --name "$TASK" --policy-assignment "$ASSIGNMENT_ID" --definition-reference-id deploy-diagnostics-storage --resource-discovery-mode ExistingNonCompliant

az policy remediation show --resource "$CANARY_ID" --name "$TASK" --output json

Le canary doit partager le même type, la même région, les mêmes verrous et les mêmes contraintes réseau que les futures cibles. Une ressource vide créée uniquement pour passer le test ne valide ni les conflits de configuration existante ni les droits réels.

Corréler la tâche, les déploiements et l’Activity Log

Un statut global Succeeded indique que la tâche a terminé, pas que le service produit le résultat métier attendu. Récupérez le correlationId, le résumé des déploiements et les opérations de l’identité managée. Pour un diagnostic setting, vérifiez ensuite que les catégories attendues arrivent dans le bon workspace ; pour modify, relisez la propriété sur la ressource.

kusto 04-policy-remediation-activity.kql
let Start = datetime(2026-08-14T07:30:00Z);
let End = datetime(2026-08-14T08:00:00Z);
let RemediationIdentity = "00000000-0000-0000-0000-000000000000";
AzureActivity
| where TimeGenerated between (Start .. End)
| where Caller == RemediationIdentity
| project TimeGenerated,
        OperationNameValue,
        ActivityStatusValue,
        ResourceId,
        ResourceGroup,
        CorrelationId,
        Properties
| order by TimeGenerated asc

Conservez les échecs autant que les succès. Un défaut de rôle, un verrou, une région non prise en charge ou un conflit de nom peut créer un résultat partiel. Par défaut, une tâche peut continuer malgré des déploiements en échec ; la stratégie de lot et le seuil d’échec doivent donc être décidés avant l’élargissement.

Élargir par lots contrôlés

Après validation du canary, utilisez un scope enfant ou un groupe de ressources cohérent, une concurrence basse et un nombre de ressources borné. PowerShell expose ResourceCount, ParallelDeploymentCount, FailureThreshold et ResourceDiscoveryMode, ce qui permet de rendre la vitesse et le point d’arrêt visibles dans la demande de changement.

powershell 05-policy-remediation-bounded-batch.ps1
$params = @{
Name = "remediate-diagnostics-weu-batch01"
PolicyAssignmentId = "/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Authorization/policyAssignments/enforce-platform-baseline-prod"
PolicyDefinitionReferenceId = "deploy-diagnostics-storage"
Scope = "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-data-prod-weu"
ResourceDiscoveryMode = "ExistingNonCompliant"
ResourceCount = 20
ParallelDeploymentCount = 2
FailureThreshold = 0.10
}

Start-AzPolicyRemediation @params

Un lot n’est validé que si son inventaire avant/après correspond, si chaque écriture est attribuable, et si les signaux du service restent sains. N’augmentez pas simultanément scope, concurrence et nombre de ressources : vous perdriez la variable qui explique un échec.

Décider poursuite, annulation ou compensation

Annuler une tâche arrête les nouvelles opérations, mais n’efface pas les changements déjà appliqués. Le rollback dépend donc de l’effet. Une propriété modifiée doit retrouver sa valeur précédente connue. Un objet déployé doit être supprimé seulement si son origine, son absence d’usage et son propriétaire sont prouvés. Réaffecter la politique en audit évite de nouvelles corrections automatiques pendant l’analyse, mais ne restaure pas l’état.

text policy-remediation-decision.txt
Poursuivre
Canary conforme et effet metier valide
Cibles identiques a l'inventaire approuve
Identite et roles bornes
Aucun echec non explique

Suspendre l'elargissement
Resultat partiel ou latence de preuve
Nouvelles cibles depuis la derniere evaluation
Proprietes existantes remplacees de facon inattendue

Annuler la tache
Mauvaise definition referencee
Scope ou identite trop large
Ecritures hors inventaire
Taux d'echec au-dessus du seuil accepte

Compenser
Reprendre la valeur avant pour modify
Supprimer uniquement le deploiement cree et sans consommateur
Valider a nouveau conformite et service
Conserver correlationId, ressources touchees et decision

La remédiation est terminée lorsque l’état technique, le signal métier et l’inventaire convergent. Un pourcentage de conformité plus élevé ne suffit pas si la collecte de logs est vide, si une configuration approuvée a été remplacée ou si l’identité conserve des droits inutiles.

Conclusion

Une tâche Azure Policy est une opération de production pilotée par identité. Avant de remédier à grande échelle, il faut figer définition et affectation, inventorier les ressources éligibles, vérifier les rôles, valider le template ou les opérations modify, puis passer par un canary et des lots observables.

La décision finale devient alors exploitable : poursuivre quand l’effet est prouvé, arrêter quand l’inventaire dérive, ou compenser précisément les écritures déjà appliquées. La conformité reste automatisée, mais elle cesse d’être une réécriture opaque de la production.