diff --git a/docs-mslearn/toolkit/changelog.md b/docs-mslearn/toolkit/changelog.md index c944572de..90b8b3010 100644 --- a/docs-mslearn/toolkit/changelog.md +++ b/docs-mslearn/toolkit/changelog.md @@ -3,7 +3,7 @@ title: FinOps toolkit changelog description: Review the latest features and enhancements in the FinOps toolkit, including updates to FinOps hubs, Power BI reports, and more. author: MSBrett ms.author: brettwil -ms.date: 03/01/2026 +ms.date: 03/02/2026 ms.topic: reference ms.service: finops ms.subservice: finops-toolkit @@ -64,11 +64,12 @@ The following section lists features and enhancements that are currently in deve - **Fixed** - Fixed Init-DataFactory deployment script failing when an Event Grid subscription is already provisioning by checking subscription status before attempting subscribe/unsubscribe and polling separately for completion ([#1996](https://github.com/microsoft/finops-toolkit/issues/1996)). -### [FinOps workbooks](workbooks/finops-workbooks-overview.md) +### [FinOps workbooks](workbooks/finops-workbooks-overview.md) v14 - **Fixed** - Excluded dev/test subscriptions from Azure Hybrid Benefit reports to align with licensing requirements ([#1819](https://github.com/microsoft/finops-toolkit/issues/1819)). - Azure Hybrid Benefit doesn't apply to Dev/Test resources as Windows licenses are already covered by Visual Studio subscriptions. + - Fixed Azure Hybrid Benefit reports to include Windows VMs from all publishers, not just Microsoft-published images ([#1793](https://github.com/microsoft/finops-toolkit/issues/1793)).
diff --git a/src/workbooks/optimization/AHB/AHB.workbook b/src/workbooks/optimization/AHB/AHB.workbook index 4ace37dbf..9b3751fcd 100644 --- a/src/workbooks/optimization/AHB/AHB.workbook +++ b/src/workbooks/optimization/AHB/AHB.workbook @@ -1202,7 +1202,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines' or type =~ 'microsoft.compute/virtualMachineScaleSets'\r\n| where tostring(properties.storageProfile.imageReference.publisher ) == \"MicrosoftWindowsServer\" or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.storageProfile.imageReference.publisher ) == \"microsoftsqlserver\"\r\n| extend OS=properties.storageProfile.imageReference.id \r\n| where isnull(OS)\r\n| where tostring(properties.['licenseType']) !has 'Windows' and tostring(properties.virtualMachineProfile.['licenseType']) != 'Windows_Server'\r\n| extend WindowsId=id, VMIDFull=id, VMName=name, VMLocation=location, VMRG=resourceGroup, OSType=tostring(properties.storageProfile.imageReference.offer), OsVersion = tostring(properties.storageProfile.imageReference.sku), VMSize=tostring (properties.hardwareProfile.vmSize), LicenseType = tostring(properties.['licenseType']), VMSSize=tostring(sku.name), QuickFix=id\r\n ) on subscriptionId \r\n| order by type asc \r\n| project WindowsId,VMName,VMRG,VMSize, VMSSize, VMLocation,OSType, OsVersion,LicenseType, subscriptionId, QuickFix, VMIDFull\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId", + "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines' or type =~ 'microsoft.compute/virtualMachineScaleSets'\r\n| where tostring(properties.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows'\r\n| where tostring(properties.['licenseType']) !has 'Windows' and tostring(properties.virtualMachineProfile.['licenseType']) != 'Windows_Server'\r\n| extend WindowsId=id, VMIDFull=id, VMName=name, VMLocation=location, VMRG=resourceGroup, OSType=tostring(properties.storageProfile.imageReference.offer), OsVersion = tostring(properties.storageProfile.imageReference.sku), VMSize=tostring (properties.hardwareProfile.vmSize), LicenseType = tostring(properties.['licenseType']), VMSSize=tostring(sku.name), QuickFix=id\r\n ) on subscriptionId \r\n| order by type asc \r\n| project WindowsId,VMName,VMRG,VMSize, VMSSize, VMLocation,OSType, OsVersion,LicenseType, subscriptionId, QuickFix, VMIDFull\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId", "size": 0, "title": "AHB Disabled", "noDataMessage": "All of your VMs have AHB enabled.", @@ -1236,7 +1236,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines'\r\n| where tostring(properties.storageProfile.imageReference.publisher ) == \"MicrosoftWindowsServer\" or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.storageProfile.imageReference.publisher ) == \"microsoftsqlserver\"\r\n| extend OS=properties.storageProfile.imageReference.id \r\n| where isnull(OS)\r\n| where tostring(properties.['licenseType']) has \"Windows\"\r\n| extend WindowsId=id, VMName=name, VMLocation=location, VMRG=resourceGroup, OSType=tostring(properties.storageProfile.imageReference.offer), OsVersion = tostring(properties.storageProfile.imageReference.sku), VMSize=tostring (properties.hardwareProfile.vmSize), LicenseType = tostring(properties.['licenseType']), VMSSize=tostring(sku.name)\r\n) on subscriptionId \r\n| order by type asc \r\n| project WindowsId,VMName,VMRG,VMSize, VMSSize, VMLocation,OSType, OsVersion,LicenseType, subscriptionId\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId", + "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines'\r\n| where tostring(properties.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows'\r\n| where tostring(properties.['licenseType']) has \"Windows\"\r\n| extend WindowsId=id, VMName=name, VMLocation=location, VMRG=resourceGroup, OSType=tostring(properties.storageProfile.imageReference.offer), OsVersion = tostring(properties.storageProfile.imageReference.sku), VMSize=tostring (properties.hardwareProfile.vmSize), LicenseType = tostring(properties.['licenseType']), VMSSize=tostring(sku.name)\r\n) on subscriptionId \r\n| order by type asc \r\n| project WindowsId,VMName,VMRG,VMSize, VMSSize, VMLocation,OSType, OsVersion,LicenseType, subscriptionId\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId", "size": 0, "title": "AHB Enabled", "noDataMessage": "None of your VMs have AHB enabled.", @@ -1338,7 +1338,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines'\r\n| where tostring(properties.storageProfile.imageReference.publisher ) == \"MicrosoftWindowsServer\" or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.storageProfile.imageReference.publisher ) == \"microsoftsqlserver\"\r\n| extend OS=properties.storageProfile.imageReference.id \r\n| where isnull(OS)\r\n| extend WindowsId=id\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId\r\n| extend LicenseType = tostring(properties.['licenseType'])\r\n| extend CheckAHBWindows = case(\r\n type == 'microsoft.compute/virtualmachines' or type =~ 'microsoft.compute/virtualMachineScaleSets', iif((properties.['licenseType'])\r\n !has 'Windows' and (properties.virtualMachineProfile.['licenseType']) !has 'Windows' , \"AHB Not Enabled\", \"AHB Enabled\"),\r\n \"Not Windows\"\r\n )\r\n) on subscriptionId \r\n| summarize count() by SubscriptionName, CheckAHBWindows\r\n", + "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines'\r\n| where tostring(properties.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows'\r\n| extend WindowsId=id\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId\r\n| extend LicenseType = tostring(properties.['licenseType'])\r\n| extend CheckAHBWindows = case(\r\n type == 'microsoft.compute/virtualmachines' or type =~ 'microsoft.compute/virtualMachineScaleSets', iif((properties.['licenseType'])\r\n !has 'Windows' and (properties.virtualMachineProfile.['licenseType']) !has 'Windows' , \"AHB Not Enabled\", \"AHB Enabled\"),\r\n \"Not Windows\"\r\n )\r\n) on subscriptionId \r\n| summarize count() by SubscriptionName, CheckAHBWindows\r\n", "size": 0, "title": "Summary of Windows VMs with or without AHB per Subscription", "showRefreshButton": true, @@ -1407,7 +1407,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where tostring(properties.storageProfile.imageReference.publisher ) == \"MicrosoftWindowsServer\" or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.storageProfile.imageReference.publisher ) == \"microsoftsqlserver\"\r\n| where tostring(properties.storageProfile.osDisk.osType) == 'Windows'\r\n| extend OS=properties.storageProfile.imageReference.id \r\n| where isnull(OS)\r\n| extend WindowsId=id\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId\r\n| extend LicenseType = tostring(properties.['licenseType'])\r\n| extend CheckAHBWindows = case(\r\n type == 'microsoft.compute/virtualmachines' or type =~ 'microsoft.compute/virtualMachineScaleSets', iif((properties.['licenseType'])\r\n !has 'Windows' and (properties.virtualMachineProfile.['licenseType']) !has 'Windows' , \"AHB Not Enabled\", \"AHB Enabled\"),\r\n \"Not Windows\"\r\n )\r\n) on subscriptionId \r\n| summarize count() by CheckAHBWindows", + "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where tostring(properties.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows'\r\n| extend WindowsId=id\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId\r\n| extend LicenseType = tostring(properties.['licenseType'])\r\n| extend CheckAHBWindows = case(\r\n type == 'microsoft.compute/virtualmachines' or type =~ 'microsoft.compute/virtualMachineScaleSets', iif((properties.['licenseType'])\r\n !has 'Windows' and (properties.virtualMachineProfile.['licenseType']) !has 'Windows' , \"AHB Not Enabled\", \"AHB Enabled\"),\r\n \"Not Windows\"\r\n )\r\n) on subscriptionId \r\n| summarize count() by CheckAHBWindows", "size": 0, "title": "Summary of Windows VMs with or without AHB", "showRefreshButton": true, diff --git a/src/workbooks/optimization/Compute/AHB.workbook b/src/workbooks/optimization/Compute/AHB.workbook index 04ef3fa94..969e68022 100644 --- a/src/workbooks/optimization/Compute/AHB.workbook +++ b/src/workbooks/optimization/Compute/AHB.workbook @@ -174,7 +174,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines' or type =~ 'microsoft.compute/virtualMachineScaleSets'\r\n| where tostring(properties.storageProfile.imageReference.publisher ) == \"MicrosoftWindowsServer\" or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.storageProfile.imageReference.publisher ) == \"microsoftsqlserver\"\r\n| where tostring(properties.['licenseType']) !has 'Windows' and tostring(properties.virtualMachineProfile.['licenseType']) != 'Windows_Server'\r\n| extend WindowsId=id, VMIDFull=id, VMName=name, VMLocation=location, VMRG=resourceGroup, OSType=tostring(properties.storageProfile.imageReference.offer), OsVersion = tostring(properties.storageProfile.imageReference.sku), VMSize=tostring (properties.hardwareProfile.vmSize), LicenseType = tostring(properties.['licenseType']), VMSSize=tostring(sku.name), QuickFix=id\r\n ) on subscriptionId \r\n| order by type asc \r\n| project WindowsId,VMName,VMRG,VMSize, VMSSize, VMLocation,OSType, OsVersion,LicenseType, subscriptionId, QuickFix, VMIDFull\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId", + "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines' or type =~ 'microsoft.compute/virtualMachineScaleSets'\r\n| where tostring(properties.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows'\r\n| where tostring(properties.['licenseType']) !has 'Windows' and tostring(properties.virtualMachineProfile.['licenseType']) != 'Windows_Server'\r\n| extend WindowsId=id, VMIDFull=id, VMName=name, VMLocation=location, VMRG=resourceGroup, OSType=tostring(properties.storageProfile.imageReference.offer), OsVersion = tostring(properties.storageProfile.imageReference.sku), VMSize=tostring (properties.hardwareProfile.vmSize), LicenseType = tostring(properties.['licenseType']), VMSSize=tostring(sku.name), QuickFix=id\r\n ) on subscriptionId \r\n| order by type asc \r\n| project WindowsId,VMName,VMRG,VMSize, VMSSize, VMLocation,OSType, OsVersion,LicenseType, subscriptionId, QuickFix, VMIDFull\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId", "size": 0, "title": "AHB Disabled", "noDataMessage": "All of your VMs have AHB enabled.", @@ -208,7 +208,7 @@ "type": 3, "content": { "version": "KqlItem/1.0", - "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines'\r\n| where tostring(properties.storageProfile.imageReference.publisher ) == \"MicrosoftWindowsServer\" or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.storageProfile.imageReference.publisher ) == \"microsoftsqlserver\"\r\n| where tostring(properties.['licenseType']) has \"Windows\"\r\n| extend WindowsId=id, VMName=name, VMLocation=location, VMRG=resourceGroup, OSType=tostring(properties.storageProfile.imageReference.offer), OsVersion = tostring(properties.storageProfile.imageReference.sku), VMSize=tostring (properties.hardwareProfile.vmSize), LicenseType = tostring(properties.['licenseType']), VMSSize=tostring(sku.name)\r\n) on subscriptionId \r\n| order by type asc \r\n| project WindowsId,VMName,VMRG,VMSize, VMSSize, VMLocation,OSType, OsVersion,LicenseType, subscriptionId\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId", + "query": "ResourceContainers | where type =~ 'Microsoft.Resources/subscriptions' | where tostring (properties.subscriptionPolicies.quotaId) !has \"MSDNDevTest_2014-09-01\" | extend SubscriptionName=name \r\n| join (\r\nresources \r\n| where resourceGroup in ({ResourceGroup})\r\n| where type =~ 'microsoft.compute/virtualmachines'\r\n| where tostring(properties.storageProfile.osDisk.osType) == 'Windows' or tostring(properties.virtualMachineProfile.storageProfile.osDisk.osType) == 'Windows'\r\n| where tostring(properties.['licenseType']) has \"Windows\"\r\n| extend WindowsId=id, VMName=name, VMLocation=location, VMRG=resourceGroup, OSType=tostring(properties.storageProfile.imageReference.offer), OsVersion = tostring(properties.storageProfile.imageReference.sku), VMSize=tostring (properties.hardwareProfile.vmSize), LicenseType = tostring(properties.['licenseType']), VMSSize=tostring(sku.name)\r\n) on subscriptionId \r\n| order by type asc \r\n| project WindowsId,VMName,VMRG,VMSize, VMSSize, VMLocation,OSType, OsVersion,LicenseType, subscriptionId\r\n| join kind = innerunique(\r\n resources\r\n | extend replaced_tags = replace('{}', 'null', tostring(tags))\r\n | extend replaced_tags = parse_json(replaced_tags)\r\n | mv-expand replaced_tags\r\n | extend tagName = tostring(bag_keys(replaced_tags)[0])\r\n | extend tagValue = tostring(replaced_tags['{TagName}']), WindowsId=id\r\n | where tagName has '{TagName}' and tagValue has '{TagValue}'\r\n | distinct WindowsId\r\n )\r\n on WindowsId", "size": 0, "title": "AHB Enabled", "noDataMessage": "None of your VMs have AHB enabled.",