次の方法で共有


リソースの変更の取得

リソースは、日々の使用や再構成を通じて、また再デプロイによっても変わります。 多くの変更は目的を持って行われますが、そうでないものもあります。 次のことを実行できます。

  • Azure Resource Manager プロパティでいつ変更が検出されたかを見つける。
  • プロパティ変更の詳細を表示します。
  • サブスクリプション、管理グループ、またはテナントでの大規模な変更を照会します。

この記事では、次の内容について解説します:

  • ペイロード JSON の外観。
  • CLI、PowerShell、または Azure portal を使い、Resource Graph でリソースの変更のクエリを実行する方法。
  • リソースの変更のクエリを実行するためのクエリの例とベスト プラクティス。
  • 変更分析では、変更アクター機能を使用します。
    • changedBy: アプリ ID や承認されたユーザーのメール アドレスなどのリソースの変更を開始したユーザー。
    • clientType: Azure portal など、変更を行ったクライアント。
    • operation: Microsoft.Compute/virtualmachines/write など、呼び出された操作

前提条件

変更イベントのプロパティの概要

リソースが作成、更新、または削除されると、変更されたリソースを拡張し、変更されたプロパティを表す新しい変更リソース (Microsoft.Resources/changes) が作成されます。 変更レコードは、5 分以内に利用できるようになります。 次の JSON ペイロードの例は、リソースの変更プロパティを示しています。

{
  "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",
    }
  }
}

リソースの変更プロパティについては、詳細なリファレンス ガイドを参照してください。

クエリの実行

resourcechanges テーブルに対してテナントベースの Resource Graph クエリを実行してみましょう。 このクエリは、Azure リソースの変更のうち最新の 5 つを、変更の時刻、変更の種類、ターゲット リソース ID、ターゲット リソースの種類、各変更レコードの変更の詳細と共に返します。

# 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'

このクエリを更新して、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'

クエリ結果を最新の変更に限定するには、ユーザー定義の changeTime プロパティを基準に並べ替える (order by) ようにクエリを更新します。

# 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'

また、管理グループまたはサブスクリプションごとにクエリを実行するには、それぞれ -ManagementGroup または -Subscription のパラメーターを使います。

Note

既にアクセスできているサブスクリプションからクエリの結果が返されなかった場合、Search-AzGraph PowerShell コマンドレットでは既定コンテキストのサブスクリプションが既定で使用されます。

また、Resource Graph エクスプローラーには、整然としたインターフェイスが備わっていて、いくつかのクエリの結果をグラフに変換して Azure ダッシュボードにピン留めすることもできます。

リソースの変更のクエリを実行する

Resource Graph を使うと、resourcechangesresourcecontainerchanges、または healthresourcechanges テーブルのクエリを実行して、リソースの変更プロパティのいずれかで絞り込んだり並べ替えたりすることができます。 次の例では resourcechanges テーブルのクエリを実行していますが、resourcecontainerchanges または healthresourcechanges テーブルにも適用できます。

Note

healthresourcechanges データの詳細については、Project Flash のドキュメントを参照してください。

リソースの変更のクエリを実行して分析する前に、次のベスト プラクティスを確認してください。

  • 特定の時間枠の間の変更イベントのクエリを実行し、変更の詳細を評価する。
    • このクエリが最も役立つのは、インシデントの管理時に、関連している "可能性がある" 変更を把握する場合です。
  • 構成管理データベース (CMDB) を最新の状態に保ちます。
    • すべてのリソースとその完全なプロパティ セットをスケジュールされた頻度で更新するのではなく、その変更のみを受け取ります。
  • リソースがコンプライアンス状態を変更したときに他のどのプロパティが変更されたかを把握します。
    • これらの追加プロパティを評価することにより、Azure Policy 定義による管理が必要な可能性がある他のプロパティの分析情報を得ることができます。
  • クエリ コマンドの順序が重要です。 次の例では、limit コマンドの前に order by が必要です。
    • order by コマンドを実行すると、クエリ結果を変更時間順に並べ替えることができます。
    • 次に、最新の 5 つの結果を確実に取得できるように、limit コマンドを実行して、並べ替えられた結果を制限します。
  • Unknown とはどういう意味ですか? 
    • 認識されないクライアントで変更が行われると、Unknown が表示されます。 クライアントは、元の変更要求に関連付けられたユーザー エージェントとクライアント アプリケーション ID に基づいて認識されます。
  • System とはどういう意味ですか?
    • 直接のユーザー アクションと関連付けられなかったバックグラウンド変更が発生したときに、changedBy 値として System が表示されます。

過去 24 時間のすべての変更

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

特定のリソース グループで削除されたリソース

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

特定のプロパティ値の変更

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

誰によってどのクライアントで行われたかを示し、数別に並べ替えられた、過去 7 日間の変更

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 

仮想マシンのサイズの変更

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

変更の種類とサブスクリプション名別の変更の数

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  

特定のタグを指定して作成されたリソースの最新のリソースの変更

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

次のステップ