Cloud
Azure Deployment Stacks : valider unmanage et deny settings avant une mise à jour
Un runbook de production pour contrôler les ressources gérées, le comportement d’unmanage, les deny settings, les identités d’exception, la validation et le rollback avant de mettre à jour une Azure Deployment Stack.
Une mise à jour d’Azure Deployment Stack peut déployer exactement le template attendu et produire malgré tout un mauvais résultat opérationnel. Le risque apparaît quand une ressource sort du template, quand le comportement d’unmanage ne correspond pas à l’intention, ou quand un deny setting empêche ensuite une équipe d’exploitation, une identité de pipeline ou un outil de restauration d’agir.
Le cas d’usage est une stack platform-prod qui gère le socle d’une application : réseau, identité, coffre de secrets, observabilité et quelques ressources partagées. Une pull request retire une ressource devenue « inutile » et durcit les deny settings. Avant la promotion, l’équipe doit décider si elle peut mettre à jour la stack, si elle doit détacher certaines ressources, corriger le template, limiter le deny, ou bloquer le changement tant que le retour arrière n’est pas prouvé.
Figer le contrat de la stack
Commencez par écrire le périmètre attendu. Une stack n’est pas seulement un template Bicep avec un nom. Elle porte aussi une frontière de propriété, un comportement pour les ressources qui sortent de cette frontière et des règles de protection qui peuvent survivre au déploiement.
stack:
name: platform-prod
scope: resource-group
resource_group: rg-platform-prod
template_ref: platform/main.bicep@8f42c31
pipeline_identity: mi-platform-deployer-prod
lifecycle_intent:
removed_managed_resources: detach_until_owner_confirms
shared_resources: never_delete_from_this_stack
application_resources: delete_only_with_data_owner_approval
protection_intent:
mode: denyDelete
apply_to_child_scopes: false
excluded_principals:
- mi-platform-deployer-prod
- breakglass-platform-operations
promotion_blockers:
- managed_resource_inventory_missing
- unmanage_action_not_reviewed
- excluded_principal_not_tested
- restore_or_recreate_path_missing
- post_change_probe_missing Ce contrat évite deux ambiguïtés : considérer qu’une ressource absente du nouveau template doit forcément disparaître, et croire qu’un deny setting est un simple détail RBAC. Ces deux décisions touchent directement l’exploitabilité.
Capturer l’état effectif avant le diff
Le dépôt décrit l’intention. Azure décrit la réalité. Capturez la stack avant le changement, son état de provisioning, ses paramètres de protection et la liste des ressources qu’elle gère. Gardez cet export avec la preuve de déploiement.
az stack group show --resource-group rg-platform-prod --name platform-prod --output json > platform-prod.before.json
az stack group show --resource-group rg-platform-prod --name platform-prod --query "{state:provisioningState,actionOnUnmanage:actionOnUnmanage,denySettings:denySettings,resources:resources}" --output json Relisez la sortie au lieu de vous fier au dernier pipeline vert. Une ressource peut avoir été déplacée, recréée sous un autre identifiant ou modifiée hors IaC. Une stack en état inattendu ne doit pas servir de base à une mise à jour destructive.
Construire l’inventaire des ressources gérées
Le diff utile ne se limite pas aux lignes Bicep. Il compare quatre ensembles : ressources gérées aujourd’hui, ressources déclarées demain, ressources partagées, et ressources qui portent un état ou des données difficiles à reconstruire.
Pour chaque ressource geree
Resource ID actuel
Declaration presente dans le nouveau template
Owner technique et owner des donnees
Ressource partagee avec une autre application
Dependances entrantes et sortantes
Donnees ou configuration non recreees par IaC
Action attendue si elle sort de la stack
Preuve de restauration ou de recreation
Classer la ressource
KEEP reste dans le template et dans la stack
DETACH sort de la stack mais reste dans Azure
DELETE suppression explicite, approuvee et recreable
BLOCK ownership, dependances ou retour arriere inconnus Une ressource partagée ne doit pas être supprimée parce qu’elle a été rangée dans le mauvais module historique. À l’inverse, tout détacher par défaut masque les ressources devenues orphelines. La classification doit être explicite et reliée à un owner.
Séparer le diff du comportement d’unmanage
Quand une ressource n’est plus gérée par la nouvelle définition, le comportement d’unmanage décide ce qu’il advient de cette ressource. Le point de contrôle est donc la combinaison entre le diff et l’action de cycle de vie, pas chacun séparément.
removed_from_template:
log_analytics_workspace:
stateful: true
shared: true
decision: detach
reason: workspace consumed by other workloads
follow_up: move ownership to observability stack
obsolete_dashboard:
stateful: false
shared: false
decision: delete
reason: replacement validated and no inbound dependency
rollback: redeploy previous dashboard module
key_vault:
stateful: true
shared: unknown
decision: block
reason: secret consumers and recovery path not proven Ne choisissez pas une action globale parce qu’elle convient à la majorité des ressources. Si le lot mélange ressources jetables et ressources avec données, séparez le changement ou réorganisez l’ownership avant la mise à jour.
Qualifier les deny settings comme un chemin d’exploitation
Un deny setting utile protège la stack contre des suppressions ou modifications hors du chemin contrôlé. Un deny mal borné bloque aussi les opérations légitimes : correction d’incident, rotation, restauration, pipeline de sécurité ou suppression approuvée.
Questions obligatoires
Quel mode de deny est demande et pour quelle menace ?
Le deny s'applique-t-il aux scopes enfants ?
Quelles identites doivent encore deployer, restaurer ou supprimer ?
Les excluded principals sont-ils des object IDs stables et attendus ?
Une identite d'urgence existe-t-elle avec journalisation et procedure ?
Azure Policy, locks et deny assignments existants se superposent-ils ?
Bloquer la promotion
Principal exclu non identifiable
Exclusion trop large au niveau groupe ou abonnement
Pipeline nominal incapable de mettre a jour la stack
Equipe de restauration sans chemin teste
Scope enfant protege sans inventaire de ses owners Le test important n’est pas « un administrateur peut-il contourner le contrôle ? ». Il est « l’identité prévue peut-elle exécuter l’opération prévue, et toutes les autres sont-elles refusées comme attendu ? ».
Tester le scénario, pas seulement le template
Reproduisez la mise à jour sur un scope non production représentatif. Le test doit inclure une ressource retirée, une ressource conservée, une tentative interdite et une opération autorisée par une identité exclue. Comparez ensuite les ressources effectives, pas seulement le statut du déploiement.
test_cases:
- name: managed_resource_stays_managed
expected: resource_present_and_owned_by_stack
- name: detached_resource_survives_update
expected: resource_present_without_stack_ownership
- name: approved_delete_removes_only_target
expected: target_absent_and_neighbors_unchanged
- name: unauthorized_delete_is_denied
expected: deny_evidence_recorded
- name: pipeline_identity_can_update
expected: update_succeeds_with_expected_identity
- name: rollback_path_recreates_configuration
expected: application_probe_returns_to_baseline
evidence:
- before_and_after_resource_ids
- deployment_operation_logs
- identity_object_ids
- deny_result
- application_and_observability_probes Un succès de déploiement ne prouve pas que le cycle de vie est correct. Le test doit montrer qu’une ressource détachée existe encore, qu’une suppression reste bornée et que le deny protège sans neutraliser l’exploitation.
Poser une gate de promotion
La pipeline doit refuser la mise à jour si elle ne peut pas expliquer les ressources retirées ou les effets du deny. Une approbation humaine reste utile, mais elle doit porter sur un artefact relisible.
Autoriser la mise a jour
Etat effectif de la stack capture
Inventaire actuel compare au nouveau template
Chaque ressource retiree classee DETACH ou DELETE
Ressources BLOCK sorties du lot de changement
Action on unmanage coherente avec chaque ressource
Deny settings testes avec identite nominale et identite refusee
Validation applicative et observabilite pretes
Export before et chemin de rollback disponibles
Refuser la mise a jour
Ressource stateful retiree sans owner
Action globale destructive sur un lot mixte
Excluded principal ajoute sans justification
Scope enfant touche sans inventaire
Rollback limite au redeploiement du template precedent Le dernier point est essentiel : redéployer l’ancien template peut recréer une ressource, mais ne restaure pas automatiquement ses données, ses secrets, son historique ou ses dépendances.
Valider après mise à jour et décider le rollback
Après la promotion, recapturez la stack et vérifiez les Resource IDs attendus. Testez les chemins applicatifs, les alertes, l’accès des identités et le comportement du deny. Une différence non expliquée doit arrêter les changements suivants.
Maintenir la mise a jour
Toutes les ressources KEEP restent gerees
Toutes les ressources DETACH existent et ont un nouvel owner
Seules les ressources DELETE approuvees ont disparu
Deny settings refusent et autorisent les identites attendues
Probes applicatives et signaux d'observabilite sont au nominal
Corriger sans rollback global
Metadata, owner ou exclusion d'identite incomplet
Ressource detachee saine mais non reprise dans une nouvelle stack
Protection trop large sans suppression de ressource
Rollbacker ou restaurer
Ressource non approuvee supprimee
Pipeline ou procedure d'urgence bloquee par le deny
Regression applicative correlee au changement
Ressource stateful recreee sans ses donnees
Avant rollback
Geler les ecritures concurrentes
Conserver les exports before et after
Choisir restauration de donnees, redeploiement ou detach cible
Revalider l'application apres chaque etape Conclusion
Une Azure Deployment Stack rend l’ownership IaC plus explicite, mais elle ne décide pas à la place de l’équipe ce qui est jetable, partagé ou restaurable. La mise à jour sûre relie le diff du template, l’inventaire effectif, le comportement d’unmanage, les deny settings et les identités d’exploitation.
La décision finale doit être nette : promouvoir si chaque sortie de périmètre et chaque refus d’accès sont prouvés, détacher si l’ownership change sans suppression, séparer le lot si les cycles de vie diffèrent, ou rollbacker avec un plan de restauration quand l’état réel ne correspond plus au contrat.