Obtenir les changements des ressources

Les ressources évoluent au fil de leur utilisation quotidienne, de leur reconfiguration, voire de leur redéploiement. La plupart des modifications sont normales, mais ce n’est parfois pas le cas. Vous pouvez :

  • Savoir à quel moment des changements ont été détectés sur une propriété Azure Resource Manager.
  • Afficher les détails des modifications de propriété.
  • Interroger les modifications à grande échelle dans vos abonnements, groupes d’administration ou locataires.

Dans cet article, vous apprenez :

  • À quoi ressemble le JSON de la charge utile.
  • Comment interroger les modifications des ressources via Resource Graph en utilisant l’interface CLI, PowerShell ou le portail Azure.
  • Exemples de requêtes et meilleures pratiques pour interroger les modifications des ressources.
  • L’analyse des changements utilise la fonctionnalité Acteur de changement :
    • changedBy: qui est à l’origine d’une modification dans votre ressource, comme un ID d’application ou l’adresse e-mail d’une personne autorisée.
    • clientType : quel client a apporté la modification, comme Portail Azure.
    • operation : quelle opération a été appelée, comme Microsoft.Compute/virtualmachines/write.

Prérequis

Comprendre les propriétés de l’événement de modification

Quand une ressource est créée, mise à jour ou supprimée, une nouvelle ressource de modification (Microsoft.Resources/changes) est créée pour étendre la ressource modifiée et représenter les propriétés changées. Les enregistrements de modifications doivent être disponibles en moins de cinq minutes. L’exemple suivant de charge utile JSON illustre les propriétés de modification des ressources :

{
  "targetResourceId": "/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/myResourceGroup/providers/microsoft.compute/virtualmachines/myVM",
  "targetResourceType": "microsoft.compute/virtualmachines",
  "changeType": "Update",
  "changeAttributes": {
    "previousResourceSnapshotId": "11111111111111111111_22222222-3333-aaaa-bbbb-444444444444_5555555555_6666666666",
    "newResourceSnapshotId": "33333333333333333333_44444444-5555-ffff-gggg-666666666666_7777777777_8888888888",
    "correlationId": "11111111-1111-1111-1111-111111111111",
    "changedByType": "User",
    "changesCount": 2,
    "clientType": "Azure Portal",
    "changedBy": "john@contoso.com",
    "operation": "microsoft.compute/virtualmachines/write",
    "timestamp": "2024-06-12T13:26:17.347+00:00"
  },
  "changes": {
    "properties.provisioningState": {
      "newValue": "Succeeded",
      "previousValue": "Updating",
      "isTruncated": "true"
    },
    "tags.key1": {
      "newValue": "NewTagValue",
      "previousValue": "null",
    }
  }
}

Consultez le guide de référence complet pour les propriétés de modification des ressources.

Exécuter une requête

Tester une requête Resource Graph basée sur un locataire en interrogeant la table resourcechanges. La requête retourne les cinq modifications de ressources Azure les plus récentes, en indiquant l’heure de modification, le type de modification, l’ID de ressource cible, le type de ressource cible et les détails de chaque enregistrement de modification.

# Login first with az login if not using Cloud Shell

# Run Azure Resource Graph query
az graph query -q 'resourcechanges | project properties.changeAttributes.timestamp, properties.changeType, properties.targetResourceId, properties.targetResourceType, properties.changes | limit 5'

Vous pouvez modifier cette requête pour spécifier un nom de colonne plus convivial pour la propriété timestamp.

# Run Azure Resource Graph query with 'extend'
az graph query -q 'resourcechanges | extend changeTime=todatetime(properties.changeAttributes.timestamp) | project changeTime, properties.changeType, properties.targetResourceId, properties.targetResourceType, properties.changes | limit 5'

Pour limiter les résultats de la requête aux modifications les plus récentes, mettez à jour la requête pour appliquer order by à la propriété changeTime définie par l’utilisateur.

# Run Azure Resource Graph query with 'order by'
az graph query -q 'resourcechanges | extend changeTime=todatetime(properties.changeAttributes.timestamp) | project changeTime, properties.changeType, properties.targetResourceId, properties.targetResourceType, properties.changes | order by changeTime desc | limit 5'

Vous pouvez également interroger par groupe d’administration ou par abonnement avec les paramètres -ManagementGroupou -Subscription respectivement.

Remarque

Si la requête ne retourne aucun résultat à partir d’un abonnement auquel vous avez déjà accès, alors l’applet de commande PowerShell Search-AzGraph porte par défaut sur les abonnements du contexte par défaut.

L’Explorateur Resource Graph fournit également une interface simple qui vous permet de convertir les résultats de certaines requêtes sous forme de graphique, que vous pouvez ensuite épingler à un tableau de bord Azure.

Modifications apportées aux ressources de requête

Avec Resource Graph, vous pouvez interroger les tables resourcechanges, resourcecontainerchangesou healthresourcechanges pour filtrer ou trier par n'importe quelle propriété de modification de ressource. Les exemples suivants interrogent la table resourcechanges, mais peuvent également être appliqués à la table resourcecontainerchanges ou healthresourcechanges.

Remarque

En savoir plus sur les données healthresourcechanges dans la documentation Project Flash.

Exemples

Avant d’interroger et d’analyser les modifications apportées à vos ressources, passez en revue les meilleures pratiques suivantes.

  • Interrogez les événements de modification dans une fenêtre de temps spécifique et évaluez les détails des modifications.
    • Cette requête fonctionne mieux pendant la gestion des incidents pour comprendre des modifications potentiellement liées.
  • Gardez à jour une base de données de gestion de la configuration (CMDB).
    • Au lieu d’actualiser toutes les ressources et leurs ensembles de propriétés complètes à une fréquence planifiée, vous recevez seulement leurs modifications.
  • Découvrez quelles autres propriétés ont été modifiées quand une ressource change d’état de conformité.
    • L’évaluation de ces propriétés supplémentaires peut fournir des insights sur les autres propriétés susceptibles de nécessiter une gestion via une définition Azure Policy.
  • L’ordre des commandes de requête est important. Dans les exemples suivants, order by doit précéder la commande limit.
    • La commande order by trie les résultats de la requête par heure de modification.
    • La commande limit limite ensuite les résultats ordonnés pour vous assurer d’obtenir les cinq résultats les plus récents.
  • Que signifie Inconnu ? 
    • Inconnu est affiché quand la modification s’est produite sur un client non reconnu. Les clients sont reconnus en fonction de l’agent utilisateur et de l’ID d’application cliente associés à la demande de modification d’origine.
  • Que signifie Système ?
    • Système est affiché sous la forme d’une valeur changedBy quand une modification en arrière-plan s’est produite sans avoir été corrélée avec une action directe de l’utilisateur.

Toutes les modifications apportées au cours des dernières 24 heures

resourcechanges
| extend changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceId = tostring(properties.targetResourceId),
changeType = tostring(properties.changeType), correlationId = properties.changeAttributes.correlationId, 
changedProperties = properties.changes, changeCount = properties.changeAttributes.changesCount
| where changeTime > ago(1d)
| order by changeTime desc
| project changeTime, targetResourceId, changeType, correlationId, changeCount, changedProperties

Ressources supprimées dans un groupe de ressources spécifique

resourcechanges
| where resourceGroup == "myResourceGroup"
| extend changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceId = tostring(properties.targetResourceId),
  changeType = tostring(properties.changeType), correlationId = properties.changeAttributes.correlationId
| where changeType == "Delete"
| order by changeTime desc
| project changeTime, resourceGroup, targetResourceId, changeType, correlationId

Modifications apportées à une valeur de propriété spécifique

resourcechanges
| extend provisioningStateChange = properties.changes["properties.provisioningState"], changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceId = tostring(properties.targetResourceId), changeType = tostring(properties.changeType)
| where isnotempty(provisioningStateChange)and provisioningStateChange.newValue == "Succeeded"
| order by changeTime desc
| project changeTime, targetResourceId, changeType, provisioningStateChange.previousValue, provisioningStateChange.newValue

Modifications au cours des sept derniers jours, par qui et par quel client, classées par total

resourcechanges 
| extend changeTime = todatetime(properties.changeAttributes.timestamp), 
  targetResourceId = tostring(properties.targetResourceId), 
  changeType = tostring(properties.changeType), changedBy = tostring(properties.changeAttributes.changedBy), 
  changedByType = properties.changeAttributes.changedByType, 
  clientType = tostring(properties.changeAttributes.clientType) 
| where changeTime > ago(7d) 
| project changeType, changedBy, changedByType, clientType 
| summarize count() by changedBy, changeType, clientType 
| order by count_ desc 

Modifications apportées à la taille de la machine virtuelle

resourcechanges
| extend vmSize = properties.changes["properties.hardwareProfile.vmSize"], changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceId = tostring(properties.targetResourceId), changeType = tostring(properties.changeType) 
| where isnotempty(vmSize) 
| order by changeTime desc 
| project changeTime, targetResourceId, changeType, properties.changes, previousSize = vmSize.previousValue, newSize = vmSize.newValue

Nombre de modifications par type de modification et nom d’abonnement

resourcechanges  
| extend changeType = tostring(properties.changeType), changeTime = todatetime(properties.changeAttributes.timestamp), targetResourceType=tostring(properties.targetResourceType)  
| summarize count() by changeType, subscriptionId 
| join (resourcecontainers | where type=='microsoft.resources/subscriptions' | project SubscriptionName=name, subscriptionId) on subscriptionId 
| project-away subscriptionId, subscriptionId1
| order by count_ desc  

Dernières modifications de ressources pour les ressources créées avec une certaine balise

resourcechanges 
|extend targetResourceId = tostring(properties.targetResourceId), changeType = tostring(properties.changeType), createTime = todatetime(properties.changeAttributes.timestamp) 
| where createTime > ago(7d) and changeType == "Create" or changeType == "Update" or changeType == "Delete"
| project  targetResourceId, changeType, createTime 
| join ( resources | extend targetResourceId=id) on targetResourceId
| where tags ['Environment'] =~ 'prod' 
| order by createTime desc 
| project createTime, id, resourceGroup, type

Étapes suivantes