Partager via


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 a initié 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. Le operation champ dans les données de modification des ressources représente les autorisations de contrôle d’accès en fonction du rôle Azure utilisées pour initier la modification.

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. Certains détails de modification peuvent apparaître avant d’autres. 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.

Le operation champ dans les données de modification des ressources représente les autorisations de contrôle d’accès en fonction du rôle Azure utilisées pour initier la modification. Ce champ ne décrit pas toujours l’opération réelle effectuée, mais plutôt l’autorisation (action d’autorisation) utilisée. Par exemple, Microsoft.Compute/virtualmachines/write correspond à l’autorisation de l’opération PUT/providers/Microsoft.Compute/virtualmachines.

Pour comprendre le type de modification capturé dans la ressource (c’est-à-dire créer, supprimer, mettre à jour), nous vous recommandons d’utiliser le changeType champ plutôt que le operation champ, qui représente plutôt les autorisations de contrôle d’accès en fonction du rôle Azure utilisées pour initier la modification.

Si le type de client est connu, le clientType champ affiche le nom du client, tel que « Portail Azure ». Si le client est fourni, mais pas connu, le champ affiche l’ID de l’application cliente.

Remarque

Les instantanés ne sont actuellement pas pris en charge pour les ressources supprimées. Pour les enregistrements avec changeType: Supprimer, la changesCount valeur est affichée sous la forme 0, car la ressource elle-même est supprimée et il n’y a pas de propriétés restantes. Pour les enregistrements avec changeType: Créer, la changesCount valeur est également affichée sous la forme 0, car chaque propriété de ressource est modifiée lors de la création de la ressource et la journalisation de chaque modification de propriété entraîne trop de bruit.

Lorsque de nouvelles propriétés sont introduites, elles ne sont pas affichées en tant que modifications. Par exemple, cela peut se produire lorsqu’une nouvelle version d’API introduit de nouvelles propriétés. De même, si de nouvelles clés sont ajoutées aux balises sans aucune valeur, ces modifications ne s’affichent pas.

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