Exercice 08 : Gouvernance avec Azure Policy
🎯 Objectifs
À la fin de cet exercice, vous serez capable de :
- ✅ Créer et assigner une Azure Policy pour imposer des tags obligatoires
- ✅ Utiliser l'effet
Denypour bloquer des ressources non conformes - ✅ Utiliser l'effet
Auditpour signaler sans bloquer - ✅ Vérifier la conformité des ressources existantes dans le portail
Durée estimée : 40 minutes
Difficulté : ⭐⭐⭐⭐☆ (Avancé)
Prérequis : Permissions Owner ou Contributor + Policy Contributor sur l'abonnement
📖 Contexte
Dans une grande organisation, des dizaines d'équipes créent des ressources dans Azure. Sans gouvernance, on se retrouve avec des ressources non taguées (impossible de faire une facturation par projet), des VM sans chiffrement, des storage accounts publics... Azure Policy est le mécanisme de garde-fous : vous définissez des règles, Azure les applique automatiquement.
📋 Énoncé
Implémentez une Policy qui impose le tag Environnement sur toutes les ressources, et une Policy qui empêche la création de ressources hors de la région autorisée.
🧭 Déroulement de l'exercice
Tâche 1 : Créer une Policy personnalisée (tag obligatoire)
az group create --name rg-policy-exercice --location francecentral
# Définir la Policy (require-env-tag)
cat > policy-require-env-tag.json << 'EOF'
{
"displayName": "Exiger le tag Environnement",
"description": "Toutes les ressources doivent avoir le tag 'Environnement' avec une valeur valide",
"policyType": "Custom",
"mode": "Indexed",
"parameters": {
"valeursAutorisees": {
"type": "Array",
"metadata": {
"displayName": "Valeurs autorisées pour le tag Environnement",
"description": "Liste des valeurs acceptées"
},
"defaultValue": ["dev", "staging", "prod"]
}
},
"policyRule": {
"if": {
"allOf": [
{
"field": "tags['Environnement']",
"notIn": "[parameters('valeursAutorisees')]"
}
]
},
"then": {
"effect": "Deny"
}
}
}
EOF
# Créer la définition de Policy
az policy definition create \
--name "require-env-tag" \
--display-name "Exiger le tag Environnement" \
--description "Bloque les ressources sans tag Environnement valide" \
--rules policy-require-env-tag.json \
--mode IndexedTâche 2 : Assigner la Policy au groupe de ressources
RG_ID=$(az group show --name rg-policy-exercice --query id -o tsv)
# Assigner la Policy au RG
az policy assignment create \
--name "enforce-env-tag" \
--display-name "Imposer le tag Environnement sur rg-policy-exercice" \
--policy "require-env-tag" \
--scope $RG_ID \
--params '{"valeursAutorisees": {"value": ["dev", "staging", "prod"]}}'
# Vérifier l'assignment
az policy assignment list \
--scope $RG_ID \
--query '[].{Nom:displayName,Portée:scope}' \
--output tableTâche 3 : Tester la Policy
# Test 1 : Créer une ressource SANS le tag → doit être refusée
az storage account create \
--name "testpolicynok$(date +%H%M%S)" \
--resource-group rg-policy-exercice \
--sku Standard_LRS
# → RequestDisallowedByPolicy - tag 'Environnement' manquant
# Test 2 : Créer une ressource avec un tag invalide → refusée
az storage account create \
--name "testpolicynok$(date +%H%M%S)" \
--resource-group rg-policy-exercice \
--sku Standard_LRS \
--tags Environnement=recette
# → RequestDisallowedByPolicy - valeur 'recette' non autorisée
# Test 3 : Créer une ressource avec un tag valide → autorisée
az storage account create \
--name "testpolicyok$(date +%H%M%S)" \
--resource-group rg-policy-exercice \
--sku Standard_LRS \
--tags Environnement=dev
# → Création réussie !Tâche 4 : Policy d'audit des locations autorisées
# Assigner une Policy built-in Azure : "Allowed locations"
# ID de la définition built-in
ALLOWED_LOCATIONS_ID="/providers/Microsoft.Authorization/policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4f"
az policy assignment create \
--name "allowed-locations-audit" \
--display-name "Audit: Régions autorisées" \
--policy $ALLOWED_LOCATIONS_ID \
--scope $RG_ID \
--params '{"listOfAllowedLocations": {"value": ["francecentral", "westeurope"]}}' \
--enforcement-mode DoNotEnforce # Audit seulement, ne bloque pas
# Voir la conformité
az policy state summarize --resource-group rg-policy-exerciceTâche 5 : Initiative (regroupement de Policies)
Une initiative regroupe plusieurs Policies en un standard cohérent.
cat > initiative-baseline-securite.json << 'EOF'
{
"policyDefinitions": [
{
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/0961003e-5a0a-4549-abde-af6a37f2724d",
"policyDefinitionReferenceId": "chiffrement-vm",
"parameters": {}
},
{
"policyDefinitionId": "/providers/Microsoft.Authorization/policyDefinitions/7433c107-6db4-4ad1-b57a-a76dce0154a1",
"policyDefinitionReferenceId": "https-storage",
"parameters": {}
}
]
}
EOF
az policy set-definition create \
--name "baseline-securite-devops" \
--display-name "Baseline Sécurité DevOps" \
--description "Regroupement de policies de sécurité minimales" \
--definitions initiative-baseline-securite.json
# Voir toutes les initiatives disponibles (built-in + custom)
az policy set-definition list \
--query '[?policyType==`Custom`].{Nom:displayName}' \
--output tableTâche 6 : Nettoyer
az policy assignment delete --name "enforce-env-tag" --scope $RG_ID
az policy assignment delete --name "allowed-locations-audit" --scope $RG_ID
az policy definition delete --name "require-env-tag"
az group delete --name rg-policy-exercice --yes --no-wait✅ Vérification du résultat
- La création d'un storage account sans tag est refusée avec
RequestDisallowedByPolicy - La création avec
--tags Environnement=devréussit - La Policy d'audit des locations est assignée en mode
DoNotEnforce - L'initiative
baseline-securite-devopsest créée
💡 À retenir
Effets Azure Policy (du moins au plus restrictif) :
| Effet | Comportement |
|---|---|
| Disabled | Policy ignorée |
| Audit | Log dans Activity log, pas de blocage |
| AuditIfNotExists | Audit si une ressource liée est absente |
| Modify | Ajoute automatiquement des tags/propriétés |
| Deny | Bloque la création/modification non conforme |
| DeployIfNotExists | Déploie automatiquement une ressource liée |
Portée d'application : Management Group > Subscription > Resource Group > Resource
✨ Solution Complète
# Assigner une policy built-in en mode audit
az policy assignment create \
--name "mon-audit" \
--policy "<policy-definition-id>" \
--scope "/subscriptions/$(az account show --query id -o tsv)" \
--enforcement-mode DoNotEnforce
# Voir l'état de conformité
az policy state summarize --subscription $(az account show --query id -o tsv)