Introduction
KQL query reference for Azure Arc-enabled servers. These queries help you monitor agent status, track deployments, troubleshoot issues, and maintain your Arc infrastructure.
Failed Extension Installations
Track Azure Arc extension installation failures across your environment.
Detailed Failed Extension Report
This query identifies all servers with failed Azure Arc extension installations, showing server name, user, resource group, extension name, and IP address.
AzureActivity | where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE" and ActivityStatusValue == "Failure" | extend Properties = (parse_json(Properties)) | extend Server = toupper(split(Properties.resource,"/")[0]) | extend ["Extension Name"] = split(Properties.resource,"/")[1] | extend User = Properties.caller | extend ["Resource Group"] = Properties.resourceGroup | extend ["Susbcription ID"] = Properties.SubscriptionId | extend ["IP Address"] = CallerIpAddress | extend ["Activity Status"] = Properties.activityStatusValue | project TimeGenerated, Server, User, ['Resource Group'], ["Extension Name"], ['Susbcription ID'], ['IP Address'], ["Activity Status"] | sort by TimeGenerated
Failed Extensions Summary by Server
This query summarizes failed extension installations by extension name and server name, showing the count and list of failed extensions per server.
AzureActivity
| where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE" and ActivityStatusValue == "Failure"
| extend Properties = parse_json(Properties)
| extend Server = toupper(split(Properties.resource,"/")[0])
| extend ["Extension Name"] = tostring(split(Properties.resource,"/")[1])
| summarize
['Extensions Count'] = dcount(["Extension Name"]),
['List of Extensions'] = make_set(["Extension Name"])
by Server
Extension Activity Monitoring
Monitor all Azure Arc extension installations and modifications, including user activity, IP addresses, and status.
EXTENSIONS/WRITE) include automated Azure operations that create significant noise:
- AZURE UPDATE CENTER S2S SERVICE ROLE PROD - Daily update assessment scans (~90% of all operations)
- AZURE GUEST PATCHING SERVICE ROLE - Automated patching operations (~1%)
Authorization.evidence.role to see only real deployments (human, Azure Policy, or MDE auto-deployment).
Extension Provisioning State Verification
List all Azure Arc extensions to verify they appear in inventory. Note: Just because an extension appears here doesn't mean it's functioning correctly.
resources | where type == "microsoft.hybridcompute/machines/extensions"
Failed Extension Provisioning States
Identify extensions assigned to servers but not working properly. This query shows all extensions where ProvisioningState is not "Succeeded", helping you find extensions that require attention.
resources | where type == "microsoft.hybridcompute/machines"
| project ServerName = tostring(name)
| join kind = inner ( resources
| where type == "microsoft.hybridcompute/machines/extensions"
| extend ServerName = tostring(split(tostring(id),"/",8)[0])
| extend ["Provisioning State"] = properties.provisioningState
| where ["Provisioning State"] != "Succeeded"
| extend Extension = name
)
on ServerName
| project ServerName, Extension,["Provisioning State"]
Get-AzConnectedMachineExtension cmdlet to list machine extensions, then filter for non-acceptable states. This approach works well when you need to verify extension status during troubleshooting or automation workflows.
Real Extension Deployments (Excluding Noise)
Track real extension deployments by filtering out automated Azure Update Manager and Guest Patching operations. Shows who deployed extensions (human users, Azure Policy, or MDE auto-deployment).
AzureActivity
| where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE"
| where ActivityStatusValue == "Success"
| extend Auth = parse_json(Authorization)
| extend AuthEvidence = parse_json(tostring(Auth.evidence))
| extend PrincipalType = tostring(AuthEvidence.principalType)
| extend Role = tostring(AuthEvidence.role)
| where Role !in ("AZURE UPDATE CENTER S2S SERVICE ROLE PROD", "AZURE GUEST PATCHING SERVICE ROLE")
| extend Properties = parse_json(Properties)
| extend Server = toupper(tostring(split(Properties.resource,"/")[0]))
| extend ["Extension Name"] = tostring(split(Properties.resource,"/")[1])
| extend ["Resource Group"] = tostring(Properties.resourceGroup)
| extend Classification = case(
PrincipalType == "User", "Human",
Role == "Security RP Service Role", "Auto MDE",
Role in ("Contributor", "Owner"), "Azure Policy",
"Other")
| project TimeGenerated, Server, ['Extension Name'], Caller, PrincipalType, Role, Classification, ['Resource Group']
| sort by TimeGenerated desc
- Human - User manually deployed extension (PrincipalType = "User")
- Azure Policy - Deployed via Azure Policy (ServicePrincipal + Contributor/Owner role)
- Auto MDE - Microsoft Defender for Endpoint auto-deployment (Security RP Service Role)
All Extension Write Operations (Including Noise)
Track all extension installation and modification activities across Arc-enabled servers, including automated operations. Use this for complete audit trails.
AzureActivity | where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE" | extend Auth = parse_json(Authorization) | extend AuthEvidence = parse_json(tostring(Auth.evidence)) | extend PrincipalType = tostring(AuthEvidence.principalType) | extend Role = tostring(AuthEvidence.role) | extend Properties = parse_json(Properties) | extend Server = toupper(tostring(split(Properties.resource,"/")[0])) | extend ["Extension Name"] = tostring(split(Properties.resource,"/")[1]) | extend ["Resource Group"] = tostring(Properties.resourceGroup) | extend ["IP Address"] = CallerIpAddress | extend ["Activity Status"] = ActivityStatusValue | project TimeGenerated, Server, ['Extension Name'], Caller, PrincipalType, Role, ['Resource Group'], ['IP Address'], ["Activity Status"] | sort by TimeGenerated desc
Extension Operations Classification Breakdown
Get a statistical breakdown of extension operations by classification. This query shows what percentage of operations are real deployments vs automated noise, helping you understand your environment's activity patterns.
AzureActivity
| where TimeGenerated >= ago(30d)
| where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE"
| where ActivityStatusValue == "Success"
| extend Auth = parse_json(Authorization)
| extend AuthEvidence = parse_json(tostring(Auth.evidence))
| extend PrincipalType = tostring(AuthEvidence.principalType)
| extend Role = tostring(AuthEvidence.role)
| extend Classification = case(
PrincipalType == "User", "Human Deployment",
Role == "AZURE UPDATE CENTER S2S SERVICE ROLE PROD", "Update Scanning (NOISE)",
Role == "AZURE GUEST PATCHING SERVICE ROLE", "Patching (NOISE)",
Role == "Security RP Service Role", "Auto MDE Deployment",
Role in ("Contributor", "Owner"), "Azure Policy Deployment",
"Other")
| summarize Count = dcount(CorrelationId) by Classification
| extend Total = toscalar(
AzureActivity
| where TimeGenerated >= ago(30d)
| where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE"
| where ActivityStatusValue == "Success"
| summarize dcount(CorrelationId))
| extend Percentage = round((Count * 100.0) / Total, 1)
| project Classification, Count, Percentage
| order by Count desc
Activity Summary by User/Principal
Identify WHO is performing operations across your Arc environment. This query shows all callers (users and service principals), their roles, and operation counts - essential for security auditing and understanding who has access to your Arc infrastructure.
AzureActivity
| where TimeGenerated >= ago(30d)
| where OperationNameValue in ("MICROSOFT.HYBRIDCOMPUTE/MACHINES/WRITE", "MICROSOFT.HYBRIDCOMPUTE/MACHINES/DELETE", "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE")
| where ActivityStatusValue == "Success"
| extend Auth = parse_json(Authorization)
| extend AuthAction = tostring(Auth.action)
| extend AuthEvidence = parse_json(tostring(Auth.evidence))
| extend PrincipalType = tostring(AuthEvidence.principalType)
| extend Role = tostring(AuthEvidence.role)
// Exclude noise from Update Center and Guest Patching
| where Role !in ("AZURE UPDATE CENTER S2S SERVICE ROLE PROD", "AZURE GUEST PATCHING SERVICE ROLE")
// Exclude tag operations for machine writes
| where not(OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/WRITE" and AuthAction != "Microsoft.HybridCompute/machines/write")
| extend OperationType = case(
OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/WRITE", "MachineWrite",
OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/DELETE", "MachineDelete",
OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE", "ExtensionDeploy",
"Other")
| summarize
MachineWrites = dcountif(CorrelationId, OperationType == "MachineWrite"),
ExtensionDeployments = dcountif(CorrelationId, OperationType == "ExtensionDeploy"),
MachineDeletes = dcountif(CorrelationId, OperationType == "MachineDelete")
by Caller, PrincipalType, Role
| extend TotalOps = MachineWrites + ExtensionDeployments + MachineDeletes
| project Caller, PrincipalType, Role, MachineWrites, ExtensionDeployments, MachineDeletes, TotalOps
| order by TotalOps desc
- Unknown callers with high operation counts
- User principals performing bulk operations (could indicate compromised account)
- Service principals with unexpected roles or permissions
Deleted Server Tracking
Track who deleted Azure Arc-enabled servers from your environment.
Arc Server Deletion Audit
Identify deleted Azure Arc servers, including who deleted them, when, and from which resource group. Critical for security auditing and troubleshooting missing servers.
AzureActivity | where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/DELETE" and ActivityStatusValue == "Success" | extend Properties = (parse_json(Properties)) | extend Server = toupper(split(Properties.resource,"/")[0]) | extend User = Properties.caller | extend ["Resource Group"] = Properties.resourceGroup | project TimeGenerated, Server, User, ['Resource Group'] | sort by TimeGenerated desc
Azure Monitoring Agent (AMA) Removal Detection
Detect when Azure Monitoring Agent extensions are removed from Arc-enabled servers. Critical for maintaining security monitoring coverage.
AMA Extension Removal Audit
Track AMA extension deletions across your Arc infrastructure. Shows who removed the extension, when, and from which server. Essential for Microsoft Sentinel monitoring and compliance.
AzureActivity | where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/DELETE" and ActivityStatusValue == "Success" | extend Properties = (parse_json(Properties)) | extend Server = toupper(split(Properties.resource,"/")[0]) | extend ["Extension Name"] = split(Properties.resource,"/")[1] | extend User = Properties.caller | extend ["Resource Group"] = Properties.resourceGroup | extend ["Susbcription ID"] = Properties.SubscriptionId | extend ["IP Address"] = CallerIpAddress | extend ["Activity Status"] = Properties.activityStatusValue | where ['Extension Name'] == "amawindows" or ['Extension Name'] == "azuremonitorwindowsagent" | project TimeGenerated, Server, User, ['Resource Group'], ["Extension Name"], ['Susbcription ID'], ['IP Address'], ["Activity Status"] | sort by TimeGenerated
amawindows and azuremonitorwindowsagent. Extension naming varies based on your Azure Arc implementation date.
New Server Onboarding Tracking
Identify new Azure Arc-enabled server onboardings to track environment expansion and detect unauthorized server registrations.
MACHINES/WRITE operation includes multiple action types: actual onboardings, tag operations, resource moves, and agent reconnections. You must filter by Authorization.action and Authorization.evidence.role to get TRUE new onboardings only.
New Arc Server Onboardings (TRUE Onboardings Only)
Track new Azure Arc server onboardings with server name, user, resource group, and subscription details. This query filters for the "Azure Connected Machine Onboarding" role which is used exclusively during azcmagent connect operations.
AzureActivity | where OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/WRITE" | where ActivityStatusValue == "Success" | extend AuthAction = tostring(parse_json(Authorization).action) | where AuthAction == "Microsoft.HybridCompute/machines/write" | extend Role = tostring(parse_json(tostring(parse_json(Authorization).evidence)).role) | where Role == "Azure Connected Machine Onboarding" | extend Properties = parse_json(Properties) | extend Server = toupper(tostring(split(Properties.resource,"/")[0])) | extend ["Resource Group"] = tostring(Properties.resourceGroup) | extend ["Subscription ID"] = tostring(SubscriptionId) | project TimeGenerated, Server, Caller, ['Resource Group'], ['Subscription ID'] | sort by TimeGenerated desc
- Azure Connected Machine Onboarding - TRUE new onboarding (azcmagent connect)
- Access NRP Service Role and HCRP - Agent reconnection or property update (not a new machine)
Failed Update Deployments
Track failed Azure Update Manager deployments on Arc-enabled servers to maintain patching compliance and troubleshoot update issues.
Failed Patch Installation Tracking
Identify failed update deployments from Azure Update Manager. Shows which servers failed to install patches, when, and why.
AzureActivity | where OperationNameValue == "MICROSOFT.COMPUTE/VIRTUALMACHINES/INSTALLPATCHES/ACTION" and ActivityStatusValue == "Failed" | extend Properties = (parse_json(Properties)) | extend Server = toupper(split(Properties.resource,"/")[0]) | extend User = Properties.caller | extend ["Resource Group"] = Properties.resourceGroup | extend ["Subscription ID"] = Properties.SubscriptionId | extend ["Activity Status"] = Properties.activityStatusValue | project TimeGenerated, Server, User, ['Resource Group'], ['Subscription ID'], ["Activity Status"] | sort by TimeGenerated desc
Resource Health & Connectivity Tracking
Monitor Azure Arc agent connectivity and track disconnection events to identify connectivity issues and agent failures.
Arc Agent Disconnection Tracking
Track Arc agent disconnection and reconnection events. Shows when servers lost connectivity (ActivityStatusValue = "Active") and when they reconnected (ActivityStatusValue = "Resolved"). Use this to identify connectivity patterns and investigate prolonged disconnections.
AzureActivity | where CategoryValue == "ResourceHealth" | where ResourceProviderValue == "MICROSOFT.HYBRIDCOMPUTE" | extend Properties = (parse_json(Properties)) | extend Server = toupper(split(Properties.resource,"/")[0]) | extend ["Resource Group"] = Properties.resourceGroup | extend ["Health Status"] = ActivityStatusValue | project TimeGenerated, Server, ['Resource Group'], ["Health Status"] | sort by TimeGenerated desc
Activity Timeline Dashboard
Get a daily breakdown of all Azure Arc operations across your environment. This query provides executive-level visibility into onboardings, removals, and extension deployments with proper noise filtering.
Daily Activity Summary
Track daily operational activity with proper classification. Shows new onboardings, machine removals, and real extension deployments (excluding Update Manager noise).
AzureActivity
| where TimeGenerated >= ago(30d)
| where OperationNameValue in ("MICROSOFT.HYBRIDCOMPUTE/MACHINES/WRITE", "MICROSOFT.HYBRIDCOMPUTE/MACHINES/DELETE", "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE")
| where ActivityStatusValue == "Success"
| extend Auth = parse_json(Authorization)
| extend AuthAction = tostring(Auth.action)
| extend AuthEvidence = parse_json(tostring(Auth.evidence))
| extend PrincipalType = tostring(AuthEvidence.principalType)
| extend Role = tostring(AuthEvidence.role)
// Classify operations
| extend IsNewOnboarding = OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/WRITE"
and AuthAction == "Microsoft.HybridCompute/machines/write"
and Role == "Azure Connected Machine Onboarding"
| extend IsRemoval = OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/DELETE"
| extend IsExtension = OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE"
| extend IsHumanDeploy = IsExtension and PrincipalType == "User"
| extend IsPolicyDeploy = IsExtension and Role in ("Contributor", "Owner") and PrincipalType == "ServicePrincipal"
| extend IsMDEDeploy = IsExtension and Role == "Security RP Service Role"
| extend IsUpdateScan = IsExtension and Role == "AZURE UPDATE CENTER S2S SERVICE ROLE PROD"
| extend IsPatching = IsExtension and Role == "AZURE GUEST PATCHING SERVICE ROLE"
// Summarize by day
| summarize
NewOnboardings = dcountif(CorrelationId, IsNewOnboarding),
Removals = dcountif(CorrelationId, IsRemoval),
HumanDeploys = dcountif(CorrelationId, IsHumanDeploy),
PolicyDeploys = dcountif(CorrelationId, IsPolicyDeploy),
MDEDeploys = dcountif(CorrelationId, IsMDEDeploy),
UpdateScans = dcountif(CorrelationId, IsUpdateScan),
PatchingOps = dcountif(CorrelationId, IsPatching)
by bin(TimeGenerated, 1d)
| extend RealExtDeploys = HumanDeploys + PolicyDeploys + MDEDeploys
| extend NoiseOps = UpdateScans + PatchingOps
| project
Date = TimeGenerated,
NewOnboardings,
Removals,
RealExtDeploys,
HumanDeploys,
PolicyDeploys,
MDEDeploys,
NoiseOps
| order by Date desc
- NewOnboardings - TRUE new machines (azcmagent connect)
- Removals - Machines deleted from Arc
- RealExtDeploys - Total real extension deployments
- HumanDeploys - Manual user deployments
- PolicyDeploys - Azure Policy deployments
- MDEDeploys - Microsoft Defender auto-deployments
- NoiseOps - Update scans + patching (informational)
Weekly Activity Summary
For longer-term trend analysis, aggregate by week instead of day.
AzureActivity
| where TimeGenerated >= ago(90d)
| where OperationNameValue in ("MICROSOFT.HYBRIDCOMPUTE/MACHINES/WRITE", "MICROSOFT.HYBRIDCOMPUTE/MACHINES/DELETE", "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE")
| where ActivityStatusValue == "Success"
| extend Auth = parse_json(Authorization)
| extend AuthAction = tostring(Auth.action)
| extend Role = tostring(parse_json(tostring(Auth.evidence)).role)
| extend PrincipalType = tostring(parse_json(tostring(Auth.evidence)).principalType)
| extend IsNewOnboarding = OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/WRITE"
and AuthAction == "Microsoft.HybridCompute/machines/write"
and Role == "Azure Connected Machine Onboarding"
| extend IsRemoval = OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/DELETE"
| extend IsRealExtension = OperationNameValue == "MICROSOFT.HYBRIDCOMPUTE/MACHINES/EXTENSIONS/WRITE"
and Role !in ("AZURE UPDATE CENTER S2S SERVICE ROLE PROD", "AZURE GUEST PATCHING SERVICE ROLE")
| summarize
NewOnboardings = dcountif(CorrelationId, IsNewOnboarding),
Removals = dcountif(CorrelationId, IsRemoval),
ExtensionDeploys = dcountif(CorrelationId, IsRealExtension)
by Week = startofweek(TimeGenerated)
| project Week, NewOnboardings, Removals, ExtensionDeploys
| order by Week desc
Resource Graph Inventory Queries
Use these Resource Graph queries to inventory and track your Azure Arc-enabled servers across subscriptions.
List All Azure Arc Machines
Basic query to list all Azure Arc-enabled servers in your environment.
resources | where type == "microsoft.hybridcompute/machines"
Count Machines by Subscription and Resource Group
Aggregate Azure Arc machines by subscription and resource group to understand distribution across your environment.
resources | where type == "microsoft.hybridcompute/machines" | summarize machineCount = count() by subscriptionId, resourceGroup
Enrich with Subscription Names
Join Azure Arc machine data with subscription information to show subscription names alongside machine counts.
resources
| where type == "microsoft.hybridcompute/machines"
| project serverName = name, subscriptionId, resourceGroup
| join kind=inner (
resourcecontainers
| where type == "microsoft.resources/subscriptions"
| project subscriptionName = name, subscriptionId
) on subscriptionId
| summarize machineCount = count() by subscriptionId, subscriptionName, resourceGroup
Count Machines by Status
Track the operational status distribution of your Azure Arc machines (Connected, Disconnected, Error).
resources | where type == "microsoft.hybridcompute/machines" | extend machineStatus = tostring(properties.status) | summarize machineCount = count() by machineStatus
Agent Version Inventory
List all Arc-enabled servers with their agent versions and connection status. Use this to identify servers running outdated agents.
resources | where type == "microsoft.hybridcompute/machines" | extend ["Server Name"] = toupper(name) | extend ["Agent Version"] = properties.agentVersion | extend ["Connection Status"] = properties.status | project ["Server Name"], ["Agent Version"], ["Connection Status"]