KQL to identify which vm has CustomScript extension - azure

I want how many and what VMs have "CustomScript"extension enabled along with the “properties” of that extensions and I have tried this query but didn't extract the custom-extension
Resources
| where type == 'microsoft.compute/virtualmachines'
| extend
JoinID = toupper(id),
OSName = tostring(properties.osProfile.computerName),
OSType = tostring(properties.storageProfile.osDisk.osType),
VMSize = tostring(properties.hardwareProfile.vmSize)
| join kind=leftouter(
Resources
| where type == 'microsoft.compute/virtualmachines/extensions'
| extend
VMId = toupper(substring(id, 0, indexof(id, '/extensions'))),
ExtensionName =~ 'custom-script'
) on $left.JoinID == $right.VMId
| top 5 by name asc

For the custom script extensions, for Windows and Linux, they have slightly different names. This query will return a list of VM with custom script extension and the properties for the VM and the extension.
resources
| where type == 'microsoft.compute/virtualmachines'
| extend
JoinID = toupper(id),
OSName = tostring(properties.osProfile.computerName),
OSType = tostring(properties.storageProfile.osDisk.osType),
VMSize = tostring(properties.hardwareProfile.vmSize)
| join kind=leftouter(
resources
| where type == 'microsoft.compute/virtualmachines/extensions'
| where name in ("CustomScriptExtension", "CustomScriptForLinux")
| extend VMId = toupper(substring(id,0,indexof(id,"/",0,-1,9)))
)
on $left.JoinID == $right.VMId

Related

How to dynamically get all nested properties from JSON Array object (example VM data disks) in Azure resource graph

I am trying to get all data disks attached to a Azure VM from Azure Resource Graph Query. I am able to get specific data disk by specifying the index( for example properties.storageProfile.dataDisks[0].name for first disk) but but how do I get this dynamically when more than 1 data disks are attached.
Row per disk
resources
| where ['type'] == 'microsoft.compute/virtualmachines'
| mv-expand with_itemindex = i properties.storageProfile.dataDisks
| extend DataDiskName = properties_storageProfile_dataDisks.name
,DataDiskSizeGB = properties_storageProfile_dataDisks.diskSizeGB
,DataDiskSizeType = properties_storageProfile_dataDisks.managedDisk.storageAccountType
Column per disk
resources
| where ['type'] == 'microsoft.compute/virtualmachines'
| mv-expand with_itemindex=i dataDisk = properties.storageProfile.dataDisks
| extend dataDisk = pack_array(dataDisk.name, dataDisk.diskSizeGB, dataDisk.managedDisk.storageAccountType)
| summarize dataDisk0 = anyif(dataDisk, i == 0)
,dataDisk1 = anyif(dataDisk, i == 1)
,dataDisk2 = anyif(dataDisk, i == 2)
,dataDisk3 = anyif(dataDisk, i == 3)
,dataDisk4 = anyif(dataDisk, i == 4)
by id

how to get Azure VM last reboot using azure resource graph

I'm using azure resource graph to create dashboard and need the VM last reboot or Power-Off date.
Need your helps please.
Thank you
I tried to reproduce the same in my environment:
Graph query:
Resources
| where type == 'microsoft.compute/virtualmachines'
| summarize count() by PowerState = tostring(properties.extended.instanceView.powerState.code)
Checked the powerstate :
Tried below query :
resources
| where type has 'microsoft.compute/virtualmachines/extensions'
| where name has 'MicrosoftMonitoringAgent' or name has 'AzureMonitorWindowsAgent'
| extend AzureVM = extract('virtualMachines/(.*)/extensions',1,id), ArcVM = extract('machines/(.*)/extensions',1,id)
|summarize count() by name=tolower(AzureVM), ArcVM=tolower(ArcVM), subscriptionId, resourceGroup, AgentType=name
| extend hasBoth = iff(count_ > 0, 'Yes', 'No')
| join
(
resources
| where type =~ 'Microsoft.Compute/virtualMachines'
| project name, properties.extended.instanceView.powerState.displayStatus,
properties.extended.instanceView.powerState.code,
created_ = properties.timeCreated
| order by name desc
) on name
where i got created time of azure vm running and deallocation time.
If you want the alert when the vm stpped you can check this : azureportal - Azure alert to notify when a vm is stopped - Stack Overflow
Reference: resource-graph-samples | Microsoft Learn

Azure Graph query to get VM Agent status for all VMs

I'm trying to get a query to check the VM Agent status in Azure. Currently I'm using RestAPI, but I need one call to the API for each machine, and I want to do it with Azure Graph to list all the VMs with the Azure Agent status in a single request.
This is the query in Azure Graph
Resources
| where type in~ ("microsoft.compute/virtualmachines","microsoft.classiccompute/virtualmachines")
But under properties the STATUS of the agent is not available. Any ideas?
I tried listing the extensions but it is also not helping, with this query:
Resources
| where type == 'microsoft.compute/virtualmachines'
| extend
JoinID = toupper(id),
OSName = tostring(properties.osProfile.computerName),
OSType = tostring(properties.storageProfile.osDisk.osType),
VMSize = tostring(properties.hardwareProfile.vmSize)
| join kind=leftouter(
Resources
| where type == 'microsoft.compute/virtualmachines/extensions'
| extend
VMId = toupper(substring(id, 0, indexof(id, '/extensions'))),
ExtensionName = name
) on $left.JoinID == $right.VMId
| summarize Extensions = make_list(ExtensionName) by id, OSName, OSType, VMSize
| order by tolower(OSName) asc
I can only see the extensions but I need the Azure Agent STATUS.
After trying many approaches, Agent Status cannot be retrieved directly from the VM properties but ProvisioningState as well as powerstate can be retrieved.
This ProvisionVMAgent property is there for marketplace images that have the agent installed on creation as mentioned here.
To identify the exact health check of the VM, we can use the "ProvisioningState" attribute rather than the "Agent status".
I've done these changes to your code:
Resources
| where type == 'microsoft.compute/virtualmachines'
| extend
JoinID = toupper(id),
OSName = tostring(properties.osProfile.computerName),
OSType = tostring(properties.storageProfile.osDisk.osType),
VMSize = tostring(properties.hardwareProfile.vmSize),
powerState = tostring(properties.extended.instanceView.powerState.displayStatus),
ProvisioningState = tostring(properties.provisioningState)
| join kind=leftouter(
Resources
| where type == 'microsoft.compute/virtualmachines/extensions'
| extend
VMId = toupper(substring(id, 0, indexof(id, '/extensions'))),
ExtensionName = name
) on $left.JoinID == $right.VMId
| summarize Extensions = make_list(ExtensionName) by id, OSName, OSType, VMSize, powerState, ProvisioningState
| order by tolower(OSName) asc
Output:
Note: All statuses of VM's can be received by calling PowerShell command Get-AzVM -status
Reference: AzureVMAgent, Finding VM Agent-Powershell
given by #rakhesh sasidharan

Find logs of POD in AKS using Log Analytics Query

There is a AKS running that is connected to Log Analytics in Azure.
I'm trying to view logs of named PODs using the following query snippet:
let KubePodLogs = (clustername:string, podnameprefix:string) {
let ContainerIdList = KubePodInventory
| where ClusterName =~ clustername
| where Name startswith strcat(podnameprefix, "-")
| where strlen(ContainerID)>0
| distinct ContainerID;
ContainerLog
| where ContainerID in (ContainerIdList)
| join (KubePodInventory | project ContainerID, Name, PodLabel, Namespace, Computer) on ContainerID
| project TimeGenerated, Node=Computer, Namespace, PodName=Name1, PodLabel, ContainerID, LogEntry
};
KubePodLogs('aks-my-cluster', 'my-service') | order by TimeGenerated desc
The above query does return rows of the matching PODs but not all that are actually available.
Trying to get results of the partial queries by inspecting POD details:
KubePodInventory
| where ClusterName =~ 'aks-my-cluster'
| where Name startswith 'my-service-'
| where strlen(ContainerID)>0
| distinct ContainerID;
gives me a container-id. Now feeding this container-id into another query shows more
results then the combined query from above. Why ?
ContainerLog
| where ContainerID == "aec001...fc31"
| order by TimeGenerated desc
| project TimeGenerated, ContainerID, LogEntry
One thing I noticed is that the later simple query result contain log results that have a LogEntry field parsed from JSON formatted output of the POD. In the results I can expand LogEntryto more fields corresponding to the original JSON data of that POD log output.
I.e. it seems like the combined query ( with a join ) skips those JSON LogEntry ContainerLog entries, but why ?
As far as I can see the combined query doesn't filter in any way on the LogEntry field.
A changed query seems to produce the results I would expect:
I exchanged the join with a lookup and used more columns to distinct the KubePodInventory results.
let KubePodLogs = (clustername:string, podnameprefix:string) {
let ContainerIdList = KubePodInventory
| where ClusterName =~ clustername
| where Name startswith strcat(podnameprefix, "-")
| where strlen(ContainerID)>0
| distinct ContainerID, PodLabel, Namespace, PodIp, Name;
ContainerLog
| where ContainerID in (ContainerIdList)
| lookup kind=leftouter (ContainerIdList) on ContainerID
| project-away Image, ImageTag, Repository, Name, TimeOfCommand
| project-rename PodName=Name1
};
KubePodLogs('aks-my-cluster', 'my-service') | order by TimeGenerated desc

Azure Resource Graph Explorer - Query Azure VM descriptions, OS, sku - I need to join to columns (OS and sku in one)

I have a issue. I want to know how can I join two columns in one.
I want to join the "OS" and "sku" columns in one with the name "OS"
This is my KQL:
Kusto Query on Azure Resource Graph
Resources
| where type == "microsoft.compute/virtualmachines"
| extend OS = properties.storageProfile.imageReference.offer
| extend sku = properties.storageProfile.imageReference.sku
| project OS, sku, name, nic = (properties.networkProfile.networkInterfaces)
| mvexpand nic
| project OS, sku, name, nic_id = tostring(nic.id)
| join (
    Resources 
    | where type == "microsoft.network/networkinterfaces" 
    | project nic_id = tostring(id), properties) on nic_id
    | mvexpand ipconfig = (properties.ipConfigurations)
    | extend subnet_resource_id = split(tostring(ipconfig.properties.subnet.id), '/'), ipAddress = ipconfig.properties.privateIPAddress
    | order by name desc
| project vmName=(name), OS, sku, vnetName=subnet_resource_id[8], subnetName=subnet_resource_id[10], ipAddress
This is my result:
I need like this:
Can anyone help me, thanks so much.
I've tried to use the "union" operator, but I can't make it work.
I have used these reference link:
Azure Docs Link 1
Azure Docs Link 2
Azure Docs Link 3
If you want to combine two strings - you can use strcat() function:
Resources
| where type == "microsoft.compute/virtualmachines"
| extend OS = properties.storageProfile.imageReference.offer
| extend sku = properties.storageProfile.imageReference.sku
| project OS, sku, name, nic = (properties.networkProfile.networkInterfaces)
| mvexpand nic
| project OS, sku, name, nic_id = tostring(nic.id)
| join (
Resources
| where type == "microsoft.network/networkinterfaces"
| project nic_id = tostring(id), properties) on nic_id
| mvexpand ipconfig = (properties.ipConfigurations)
| extend subnet_resource_id = split(tostring(ipconfig.properties.subnet.id), '/'), ipAddress = ipconfig.properties.privateIPAddress
| order by name desc
| project vmName=(name), OS = strcat(OS, ' ', sku), vnetName=subnet_resource_id[8], subnetName=subnet_resource_id[10], ipAddress

Resources