Is there a possible way to get the VM creation date ?
I've tried the following by now
AzureActivity
| where TimeGenerated > ago(90d)
| where ResourceProvider == "Microsoft.Compute" and OperationName == "Create or Update Virtual Machine"
| project Resource ,Datum = format_datetime(EventSubmissionTimestamp, 'MM') ,Caller
| distinct Datum , Resource , Caller
| order by Datum
This kusto query will read the logs from the VM's connected to it. and get all the Create or update virtual machine operations from a vm and its caller ID.
But this is create and update So it gives me double values every time an VM is being updated.
I tried also in PowerShell
$GetVM = Get-AzureRMVM
Foreach ($vms in $GetVM)
{
$vm = get-azurermvm -name $vms.Name -ResourceGroupName $vms.ResourceGroupName
$log = Get-AzureRmLog -ResourceId $vm.Id -StartTime (Get-Date).AddDays(-90) -WarningAction silentlyContinue
Write-Output "- Found VM creation at $($log.EventTimestamp) for VM $($log.Id.split("/")[8]) in Resource Group $($log.ResourceGroupName) found in Azure logs"
}
But Can't seem to find the creation date inside the log files either. Does anyone have a clue if it is possible to find the creation date of a Virtual Machine inside a scripting language , Kusto , Powershell , ...
The easiest way that worked for me to get the Azure VM creation date was to look at the creation date of the OS Disk
Browse to your VM on Azure Portal
On Left Hand side, click on the blade "Disks"
Under OS Disk section, click on your OS Disk.
In the Overview blade of your OS Disk, you can see Time Created field.
Note: All my Azure VMs were created with the OS Disk and were never changed.
Hope it helps. Cheers.
There is no direct way to find out the creation date if it's later than 90 days. But here is a nice workaround solution: https://savilltech.com/2018/02/13/checking-the-creation-time-of-an-azure-iaas-vm/
You can use azure cli
use below command
az vm list
This will list json data with fields and you can filter
date = vm['timeCreated']
//"timeCreated": "2022-06-24T14:13:00.326985+00:00",
The portal does show Created for a cloud service in the Dashboard of a Cloud Service, but that is not shown for a specific VM (which you can see with Azure PowerShell with Get-AzureService <cloud service name> | select DateCreated).
When you do a Quick Create of a VM, that will always create a new cloud service, so the time created would be the same for VM and cloud service. But since you can add multiple VMs to a cloud service, you can't always rely on that.
On the VM's Dashboard in the portal, at the bottom if you look at the VHD column, the VHD name includes the date the disk was created as part of the name, though this is only true for VMs created from an image. If the VM was created from a disk, the name could be anything. You can get that OS disk name in Azure PowerShell with Get-AzureVM <cloud service name> <VM name> | Get-AzureOSDisk | select medialink.
Operation Logs under Management Services in the portal lets you search the last 30 days for operations, so if the VM was created in the last month, you can find evidence of the operation there (for example CreateHostedService and CreateDeployment operations).
For Windows VMs created from an image, the timestamp on WaSetup.log and WaSetup.xml in C:\Windows\panther\ reflect when the VM was provisioned.
Hope it helps.
If you check Deployments in the respective resource group, you will see Last Modified date for each of the deployment in that RG.
I found another way to get it working for me by tweaking your ActivityLog query instead of Powershell. Using the HTTPRequest property seemed to give me what I needed.
AzureActivity
| where TimeGenerated > ago(7d)
| where ResourceProvider contains "Microsoft.Compute" and OperationName == "Create or Update Virtual Machine"
| where HTTPRequest contains "PUT"
| project VMName = Resource, Created_On = format_datetime(EventSubmissionTimestamp,'dd-MM-yyyy-HHtt'), User = Caller
| distinct Created_On, VMName, User
| order by Created_On
In my case, I was trying to get the VMs deleted in the last 7 days. For some reason the time wasn't displaying properly for the query below, hence I had to convert it to my timezone.
AzureActivity
| where TimeGenerated > ago(7d)
| where ResourceProvider == "Microsoft.Compute" and OperationName == "Delete Virtual Machine"
| where HTTPRequest contains "DELETE"
| extend MyTimeZone = EventSubmissionTimestamp + 8h
| project VM_Name = Resource, Deleted_On = format_datetime(MyTimeZone, 'dd-MM-yyyy-HHtt'), User = Caller
| distinct Deleted_On , VM_Name , User
| order by Deleted_On
Related
I am trying to monitor VM status.
I have activated logs, and trying to query the status of the VM.
I can not find the status or health status.
In order to query the status of Azure VMs, make use of below PowerShell commands:
Use the - Status parameter to check whether the VMs are running, deallocated, or stopped using PowerShell like below:
Get-AzVM -Status | Select name, powerstate, provisioningState
If you want to get Status of particular VM then use the below PowerShell command:
Get-AzVM -Name "YourVmName" -ResourceGroup "YourResourceGroupName" -status
If you want to query the status of Azure VMs from Azure Resource Graph Explorer make use of below:
Resources
| project name, location,
PowerState=tostring(properties.extended.instanceView.powerState.code), type
| where type =~ 'Microsoft.Compute/virtualMachines'
| order by name desc
Please note that there is no such state called "Busy", check this MS Doc.
For more information, please find below references:
powershell - Determine Virtual Machine status and activity in Microsoft Azure - Stack Overflow
How to check Azure VM Power state using PowerShell? (tutorialspoint.com)
I'd like to create a dashboard in the Azure Portal that displays the number of active virtual machines per resource group. In this case I'm not interested in any deallocated or stopped VM's.
Since filtering the virtual machines blade doesn't work for the VM's power state, I turned to the Resource Graph. From there the solution gets close, but it doesn't seem possible to filter on power state (yet).
resources
| where type == "microsoft.compute/virtualmachines"
| summarize count() by resourceGroup
| order by resourceGroup asc
Is there a way to combine this data with another data table to be able to filter on power state and get only the running virtual machines? Or maybe a different solution altogether to just display the number of running VM's on a dashboard?
There doesn't seem to be a table that holds the PowerState of the VM in the Resource Graph schema (at least I couldn't find it)
Since you had stated that you would also like to hear about altogether a different approach, I want to suggest the PowerShell route
You can get the PowerState of the VM using the below command
Get-AzVM -Status
This output you may write to a Azure table storage. (this link has details of how to use PowerShell to interact with Azure Storage Accounts [https://learn.microsoft.com/en-us/azure/storage/tables/table-storage-how-to-use-powershell]
You can build a Power BI report on top of this table storage filtering only for PowerState == running and light up your report.
Now to schedule this, you will need to
a) Create an Automation Account. Details on how to create automation account can be found here [https://learn.microsoft.com/en-us/azure/automation/automation-create-standalone-account]
b) Create a PowerShell runbook which get the VM status and inserts rows to table storage
c) Create a schedule and link the runbook to it.
Details on how to schedule can be found here [https://learn.microsoft.com/en-us/azure/automation/shared-resources/schedules]
Thus, using Azure Automation Account and a Runbook (point b) you can setup a schedule and link the runbook with that schedule. Whenever the runbook executes it gets the current powerstatus and uploads it to Azure Table storage as per the schedule which would keep the PowerBI updated.
Hope this helps
hope the example below works for you
resources
| where type == "microsoft.compute/virtualmachines"
| where properties.extended.instanceView.powerState.displayStatus=="VM running"
| summarize count() by resourceGroup
| order by resourceGroup asc
Cheers,
$definition = Get-AzPolicyDefinition | Where-Object {$_.Properties.DisplayName -eq "Allowed virtual machine SKUs"}
New-AzPolicyAssignment -Name 'Test' -DisplayName 'Test' -Scope $ResourceGroup.ResourceID -PolicyDefinition $definition
Running this command will ask for 'listOfAllowedSKUs' for which SKUs i want to allow to be created in the specified resource group. I can find a list of them by going into the azure portal, finding policy and clicking assign policy, then selecting "Allowed virtual machine skus" and then going into parameters and looking at the names.
I can type in those names manually one by one when i get asked for it after running the command, but instead of opening the azure portal every time, i want to be able to list the available SKUs in powershell instead. I can't find anything online about getting a list of available SKUs in the console.
Is is possible to get a list of available SKUs to create?
Hello and welcome to Stack Overflow!
If you want to get the SKUs corresponding to a specific Location, Publisher and Offer, you may use the Get-AzVMImageSku cmdlet to get the VMImage SKUs by providing the Location, PublisherName and Offer as input parameters, and then construct the AllowedSkus object. For example:
$sku = Get-AzVMImageSku -Location "Central US" -PublisherName "Fabrikam" -Offer "LinuxServer"
$AllowedSkus = #{'listOfAllowedSKUs'=($sku.Skus)}
Else, to mimic the list of available SKUs as appearing in the portal, you may use the Get-AzVMSize cmdlet to get the available virtual machine sizes as follows:
$allsizes = Get-AzLocation | Get-AzVmSize | Select-Object -ExpandProperty Name | Sort-Object | Get-Unique
$AllowedSkus = #{'listOfAllowedSKUs'=($allsizes)}
This can finally be passed to the New-AzPolicyAssignment cmdlet using the -PolicyParameterObject option:
New-AzPolicyAssignment -Name '<policy assignment name>' -DisplayName '<display name>' -Scope $ResourceGroup.ResourceID -PolicyDefinition $definition -PolicyParameterObject $AllowedSkus
Other examples here. Hope this helps.
According to my test, if you want to know the available virtual machine SKUs in the subscription, you can use the following PowerShell command
Get-AzComputeResourceSku | where{$_.ResourceType.Equals('virtualMachines')}| fl
Its outputs contain parameter Restrictions. The parameter will tell us which SKU cannot be used.
For example
Giving one type of restriction : Zone Type for size Standard_A0 which means that under a particular subscription, Standard_A0 is not available to be created in West Europe region if placed in Availability Zones
Giving no Restrictions at the end, which means that VM Size : Standard_F8s can be created under this particular subscription in this region : West Europe without any restrcitions ( i.e : it can be created with Availaibility Zone and without Availaibility zone as well )
Giving two types of restrictions : Zone Type and Location Type, which means that VM Size of Standard_DS2_V2_Promo cannot be created in this particular subscription in this region : WestEurope at all.
I want to retrieve the creator of a virtual machine under Azure using azure rm powershell cmdlt or an api whitxh could return this type of information.
I used the "Get-AzureRmVM" command and the "GET https://management.azure.com/subscriptions/subscriptionId/resourceGroups/resourceGroupName/providers/Microsoft.Compute/virtualMachines/vmName?api-version=2018-06-01" api but both of them don't return information about the creator of the VM
You can use the Get-AzLog command to look for the caller value in the Azure Activity logs.
Examples can be found here:
https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-audit#powershell
You can also set up alerts in Azure Monitoring that can send you an email or text message everytime a VM is created.
https://learn.microsoft.com/en-us/azure/azure-monitor/platform/alerts-overview
Example
# Requires the AZ module be installed on your machine. You can get this by running Install-Module 'AZ'
Connect-AzAccount # after calling this a browser window opens, allowing you to log into Azure through the UI under the relevant credentials; on successful login the token for this session is returned to your PowerShell session
# Sets your scope to the subscription you're interested in
Set-AzContext -Subscription 'myAzSubscription'
# Fetches (successful) events in the past 2 weeks
# Filters for those related to VM write events (which includes creating VMs, though sadly we can't just VM creations)
# groups by resource id (i.e. VM).
# Note: The Get-AzLog function can return a maximum of 100,000 events (and this count is based on the filters provided as parameters; filters applied to the results of the cmdlet won't impact this limit), so if things have been particularly busy some of the log may be truncated. If that's a common issue for you, try narrowing the event's time window or restricting queries to specific resource groups.
$events = Get-AzLog -StartTime ((Get-Date).AddDays(-14)) -ResourceProvider 'Microsoft.Compute' -Status 'Succeeded' -MaxRecord 100000 |
Where-Object {$_.Authorization.Action -eq 'Microsoft.Compute/virtualMachines/write'} |
Group-Object -Property #{E={$_.Authorization.Scope}}
# For each VM get the first event with a human caller (i.e. ignore system generated events) and return that caller's name. Filter out events that didn't have a human caller as irrelevant
$events |
Select-Object Name, #{N='InitiatedBy'; E = {
$_.Group |
Sort-Object SubmissionTimestamp |
Select-Object -ExpandProperty 'caller' |
Where-Object{$_ -like '*#*'} |
Select-Object -First 1
} } |
Where-Object InitiatedBy |
Format-Table -AutoSize
This information is not exposed in Azure API (unfortunately). Your only option is to take a look at activity logs of the resource and find the very first write operation to the resource, unfortunately resources do not expose creation time either, so you cannot be sure you will find proper creator, because activity logs only go back 90 days.
I am looking solution to find out Stopped | Deallocated resources Orphan Resources in Azure. I grab the VM data. But if someone spins the VM and VM showing running, How to check owner not used that VM since 30 Days.
az vm list -d --output table
Any automation suggestion will be welcome.
az vm list -d --output table
TESTSXG VM running
I see multiple queries here.
To identify if someone created any resource (say VM) and has forgot to deallocate it.
To check last login in VM if it is older than 30 days.
To check owner not used the VM(s) in the last 30 days.
If we don’t login to VM since a while and if some services (like Jenkins, etc.) are running and untouched.
To audit actions on resources and to determine the operations that were taken on resources, you may use Activity Logs. For more information refer this (https://learn.microsoft.com/en-us/azure/azure-resource-manager/resource-group-audit) link.
For #1, You may execute the below command.
Get-AzureRmVM -Status|select Name, PowerState
For #2 and #3, below is the command which you can run manually in the VM.
Get-WmiObject -Class Win32_NetworkLoginProfile |
Sort-Object -Property LastLogon -Descending |
Select-Object -Property * -First 1 |
Where-Object {$_.LastLogon -match "(\d{14})"} |
Foreach-Object { New-Object PSObject -Property #{ Name=$_.Name;LastLogon=[datetime]::ParseExact($matches[0], "yyyyMMddHHmmss", $null)}}
But I know that we are looking for an automated way to validate all the VM’s under your subscription. So here the requirement is to automatically (i.e., remotely) connect to all the ‘running’ VM’s from Azure portal and then get the required output. If i am not wrong, most probably we can achieve this requirement in multiple ways i.e.,
i. Log Analytics
ii. DSC
iii. Functions
iv. Runbook
v. Logic App
i. Create a Log Analytics OMS workspace and install OMS agent on the VM(s) as instructed here (https://learn.microsoft.com/en-us/azure/azure-monitor/learn/quick-collect-azurevm). Then add Azure Security Center (Security and Audit) solution in OMS so that the security events will be pushed to OMS repository. Then goto Log Analytics -> OMSworkspaceName -> Logs and run the below Kusto query to get the required output.
SecurityEvent
| where EventID == 4624
| sort by TimeGenerated desc
Note that the Event ID 4624 is the ID for the event log of any account logged on to a machine.
ii. Onboard Azure DSC on the VM(s) as instructed here (https://learn.microsoft.com/en-us/azure/automation/automation-dsc-onboarding) and write a DSC configuration script using ‘script’ DSC resource which will run the above mentioned Get-WmiObject…. command remotely on the DSC nodes (i.e., VM’s) and fetch us the required output.
iii. Write a HTTP trigger PowerShell function which will run the above mentioned Get-WmiObject…. command remotely (i.e., may be try a new ps session and invoke command) on the VM’s and fetch us the required output. You may refer this (https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-first-azure-function) link to learn about Functions.
iv. Write a PowerShell runbook which will run the above mentioned Get-WmiObject…. command remotely (i.e., may be try new ps session and invoke command) on the VM’s and fetch us the required output.
v. Currently Azure Logic Apps seems not support to run PowerShell and CLI script. However, we may try to use available Logic Apps Functions connector or any similar connector and internally try to call PowerShell to execute above mentioned Get-WmiObject…. command remotely. Just FYI here (https://feedback.azure.com/forums/287593-logic-apps/suggestions/33913552-run-a-powershell-code-within-a-logic-app-action) is a voice in Azure feedback regarding running PowerShell code within a Logic App, you could vote if you are interested in this option.
For #4, Install OMS agent on the VM’s so that the events details get stored in OMS repository. For example, if no one is logging in to a VM but Jenkins service is running on that VM then in that case you may want to not disturb that VM. So, to validate if Jenkins service is running on a VM or not you may have to run a Kusto query something like this.
Event
| where (EventLog == "System")
| where (RenderedDescription has "jenkins" and RenderedDescription has "stopped")
Hope this helps!!