Last active
January 20, 2021 10:56
-
-
Save marckean/d155622b73f224e8366b03c818d9d9ce to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -------------------------------------------------------------------------------------------------------------- | |
# | |
# Title : Azure - Azure VM enable guest level monitoring | |
# Written by : Marc Kean | |
# Date : December, 2017 | |
# | |
# -------------------------------------------------------------------------------------------------------------- | |
# | |
# Script to turn on guest OS level monitoring across all VMs in a subscription. This will work its way through all | |
# ARM based Azure VMs one by one. VMs need to be turned on, otherwise they can't be enabled. Run again over and over | |
# to fill in the missed VMs | |
# | |
# GitHub: https://gist.github.com/marckean/d155622b73f224e8366b03c818d9d9ce | |
# | |
# Written with Azure PowerShell Module v5.0.1 | |
# https://github.com/Azure/azure-powershell/releases/tag/v5.0.1-November2017 | |
# | |
# -------------------------------------------------------------------------------------------------------------- | |
<# | |
Will cycle through all Azure VMs and turn on guest-level monitoring for Azure VMs | |
Azure VMs need to be turned on first | |
#> | |
# Retrieve Azure Module properties | |
"" | |
"Validating installed PowerShell Version and Azure PowerShell Module version..." | |
$ReqVersions = Get-Module Azure -list | Select-Object Version, PowerShellVersion | |
# Current PowerShell version must be higher then the one required by the Azure Module | |
if($PSVersionTable.PSVersion.Major -lt $ReqVersions.PowerShellVersion.Major) | |
{ | |
$PSVerReq = $ReqVersions.PowerShellVersion | |
$PSVerInst = $PSVersionTable.PSVersion | |
"Validation failed..." | |
"Installed PowerShell version: $PSVerInst" | |
"Powershell version $PSVerReq required. Please update the version of Powershell on this system" | |
"Exiting Script" | |
Break | |
} | |
# Current script was tested with Azure module 5.0.1 | |
if($ReqVersions.Version.Major -lt 5) | |
{ | |
$AZModuleInst = $ReqVersions.Version | |
"Validation failed..." | |
"Installed Azure PS Module: $AZModuleInst. This script was tested with version 5.0.1" | |
"Please download and install/update the Azure Powershell module using the Microsoft Web Platform Installer..." | |
"Download link: https://github.com/Azure/azure-powershell/releases/tag/v5.0.1-November2017" | |
"Exiting Script" | |
Break | |
} | |
########################################################################################## | |
################## Optional AAD SP Info for un-attended sign-in ################## | |
########################################################################################## | |
# SP = Service Principal | |
$SP_Password = '' # or Certificate Thumbprint, a blank password will prompt for prompt for sign-in | |
$AADAppId = '19b4a2ce-73fb-4de8-xxxx-1f229998c07' | |
$TenantID = 'a8c74611-6a11-45d0-xxxx-689029996e87' # Directory ID | |
########################################################################################## | |
################################# Logon to Azure ################################## | |
########################################################################################## | |
switch -Wildcard ($SP_Password) | |
{ | |
?* { | |
$secpasswd = ConvertTo-SecureString $SP_Password -AsPlainText -Force | |
$Cred = New-Object System.Management.Automation.PSCredential ($AADAppId, $secpasswd) | |
Login-AzureRmAccount -Credential $cred -ServicePrincipal -TenantId $TenantId | |
} | |
default { | |
Login-AzureRmAccount | |
} | |
} | |
#region Logon to Azure & choose Azure subscription | |
$Subscription = (Get-AzureRmSubscription | Out-GridView -Title "Choose a Source & Target Subscription ..." -PassThru) | |
Select-AzureRmSubscription -Subscription $Subscription | |
$SubscriptionId = $Subscription.Id | |
#endregion | |
########################################################################################## | |
################################### Functions ##################################### | |
########################################################################################## | |
# Using logged in credentials | |
Function RestAPI-AuthToken ($TenantId) { | |
# Load ADAL Azure AD Authentication Library Assemblies | |
$adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.dll" | |
$adalforms = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll" | |
$null = [System.Reflection.Assembly]::LoadFrom($adal) | |
$null = [System.Reflection.Assembly]::LoadFrom($adalforms) | |
$adTenant = $Subscription.TenantId | |
# Client ID for Azure PowerShell | |
$clientId = "1950a258-227b-4e31-a9cf-717495945fc2" | |
# Set redirect URI for Azure PowerShell | |
$redirectUri = "urn:ietf:wg:oauth:2.0:oob" | |
# Set Resource URI to Azure Service Management API | @marckean | |
$resourceAppIdURIARM = "https://management.core.windows.net/" | |
# Authenticate and Acquire Token | |
# Set Authority to Azure AD Tenant | |
$authority = "https://login.windows.net/$TenantId" | |
# Create Authentication Context tied to Azure AD Tenant | |
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority | |
# Acquire token | |
$global:Token = $authContext.AcquireToken($resourceAppIdURIARM, $clientId, $redirectUri, "Auto") | |
} | |
# Using AAD Application Service Principal | |
Function RestAPI-SPN-AuthToken ($TenantId) { | |
$Username = $Cred.Username | |
$Password = $Cred.Password | |
# Set Resource URI to Azure Service Management API | |
$resourceAppIdURI = 'https://management.core.windows.net/' | |
# Set Authority to Azure AD Tenant | |
$authority = "https://login.windows.net/$TenantId" | |
# Build up the credentials | |
$ClientCred = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]::new($UserName, $Password) | |
# Acquire token | |
$authContext = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new($authority) | |
$global:Token = $authContext.AcquireTokenAsync($resourceAppIdURI,$ClientCred) | |
} | |
Function SPNRequestHeader { | |
# Create Authorization Header | |
$authHeader = $global:Token.Result.CreateAuthorizationHeader() | |
# Set HTTP request headers to include Authorization header | @marckean | |
$requestHeader = @{ | |
"x-ms-version" = "2014-10-01"; #'2014-10-01' | |
"Authorization" = $authHeader | |
} | |
return $RequestHeader | |
} | |
Function RequestHeader { | |
# Create Authorization Header | |
# Set HTTP request headers to include Authorization header | @marckean | |
$requestHeader = @{ | |
"Content-Type" = "application/json"; #'2014-10-01' | |
"Authorization" = "Bearer $($global:Token.AccessToken)" | |
} | |
return $RequestHeader | |
} | |
########################################################################################## | |
################################ Rest API Token ################################## | |
########################################################################################## | |
switch -Wildcard ($SP_Password) | |
{ | |
?* { | |
RestAPI-SPN-AuthToken $Subscription.TenantId # To Logon to Rest and get an an auth key | |
$RequestHeader = SPNRequestHeader | |
} | |
default { | |
RestAPI-AuthToken $Subscription.TenantId | |
$RequestHeader = RequestHeader | |
} | |
} | |
########################################################################################## | |
#################### Get Virtual Machines in the subscription ###################### | |
########################################################################################## | |
#region Select Azure Source Virtual Machine | @marckean | |
$VirtualMachines = Get-AzureRmVM | |
#endregion | |
########################################################################################## | |
######## Turn on guest-level monitoring for VMs that don't have it enabled ########## | |
########################################################################################## | |
# Use PowerShell to enable Azure Diagnostics in a virtual machine running Windows | |
# https://docs.microsoft.com/en-us/azure/virtual-machines/windows/ps-extensions-diagnostics | |
foreach($VirtualMachine in $VirtualMachines){ | |
$ResourceGroupName = $($VirtualMachine.ResourceGroupName) | |
$VirtualMachinename = $($VirtualMachine.name) | |
$VMResourceID = $($VirtualMachine.ID) | |
$APIURL = 'https://management.azure.com' | |
$myAPIPath = ` | |
"/subscriptions/$SubscriptionId/resourcegroups/$ResourceGroupName/providers/Microsoft.Compute/virtualMachines/$VirtualMachinename" | |
write-host -nonewline "`n`tCurrent VM is: " -ForegroundColor Yellow; ` | |
write-host -nonewline $($VirtualMachine.name)`n -ForegroundColor Green | |
# InstanceView | |
$apicall = "$myAPIPath/InstanceView?api-version=2017-03-30" | |
$Uri = "{0}{1}" -f $APIURL, $apicall | |
$VMInstanceView = Invoke-RestMethod -Method Get -Headers $RequestHeader -Uri $uri | |
# Get running state of the VM | |
$VMStatus = ($VMInstanceView.statuses | where {$_.code -Like '*power*'}).displayStatus | |
# Check if Microsoft.Azure.Diagnostics.IaaSDiagnostics is installed | |
$IaaSDiagnostics = 'False' | |
$VMInstanceView.vmAgent.extensionHandlers.type | | |
% {if($_ -match 'Microsoft.Azure.Diagnostics.IaaSDiagnostics'){$IaaSDiagnostics = 'True'}} | |
<# | |
Check if the VM is running and the VM agent is healthy before continuing | |
#> | |
if($IaaSDiagnostics -eq 'False' ` | |
-and $VMInstanceView.vmAgent.vmAgentVersion -ne 'Unknown' ` | |
-and $VMStatus -match 'running') | |
{ | |
$DiagStgAccountName = ($VMInstanceView.bootDiagnostics.consoleScreenshotBlobUri -split '//' -split '/' | | |
select -Index 1) -split '\.' | select -Index 0 | |
### If no existing diagnostics storage account, create one | |
if(!$DiagStgAccountName){ | |
$DiagStgAccountName = "{0}{1}"-f "diagstg", (Get-Random -Minimum 111111 -Maximum 999999) | |
# Create the storage account | |
New-AzureRmStorageAccount -Name $DiagStgAccountName -ResourceGroupName $ResourceGroupName ` | |
-Location $VirtualMachine.Location -SkuName Standard_LRS | |
} | |
$DiagnosticsConfigurationPath = "$env:TEMP\DiagnosticsConfiguration{0}.xml" -f (Get-Random -Minimum 1111 -Maximum 9999) | |
$DiagnosticsConfiguration = @" | |
<?xml version="1.0" encoding="utf-8"?> | |
<PublicConfig xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration"> | |
<WadCfg> | |
<DiagnosticMonitorConfiguration overallQuotaInMB="4096"> | |
<DiagnosticInfrastructureLogs scheduledTransferLogLevelFilter="Error"/> | |
<PerformanceCounters scheduledTransferPeriod="PT1M"> | |
<PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% Processor Time" sampleRate="PT15S" unit="Percent"> | |
<annotation displayName="CPU utilization" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% Privileged Time" sampleRate="PT15S" unit="Percent"> | |
<annotation displayName="CPU privileged time" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Processor(_Total)\% User Time" sampleRate="PT15S" unit="Percent"> | |
<annotation displayName="CPU user time" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Processor Information(_Total)\Processor Frequency" sampleRate="PT15S" unit="Count"> | |
<annotation displayName="CPU frequency" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\System\Processes" sampleRate="PT15S" unit="Count"> | |
<annotation displayName="Processes" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Process(_Total)\Thread Count" sampleRate="PT15S" unit="Count"> | |
<annotation displayName="Threads" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Process(_Total)\Handle Count" sampleRate="PT15S" unit="Count"> | |
<annotation displayName="Handles" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Memory\% Committed Bytes In Use" sampleRate="PT15S" unit="Percent"> | |
<annotation displayName="Memory usage" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Memory\Available Bytes" sampleRate="PT15S" unit="Bytes"> | |
<annotation displayName="Memory available" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Memory\Committed Bytes" sampleRate="PT15S" unit="Bytes"> | |
<annotation displayName="Memory committed" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Memory\Commit Limit" sampleRate="PT15S" unit="Bytes"> | |
<annotation displayName="Memory commit limit" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Memory\Pool Paged Bytes" sampleRate="PT15S" unit="Bytes"> | |
<annotation displayName="Memory paged pool" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\Memory\Pool Nonpaged Bytes" sampleRate="PT15S" unit="Bytes"> | |
<annotation displayName="Memory non-paged pool" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\% Disk Time" sampleRate="PT15S" unit="Percent"> | |
<annotation displayName="Disk active time" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\% Disk Read Time" sampleRate="PT15S" unit="Percent"> | |
<annotation displayName="Disk active read time" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\% Disk Write Time" sampleRate="PT15S" unit="Percent"> | |
<annotation displayName="Disk active write time" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Disk Transfers/sec" sampleRate="PT15S" unit="CountPerSecond"> | |
<annotation displayName="Disk operations" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Disk Reads/sec" sampleRate="PT15S" unit="CountPerSecond"> | |
<annotation displayName="Disk read operations" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Disk Writes/sec" sampleRate="PT15S" unit="CountPerSecond"> | |
<annotation displayName="Disk write operations" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Disk Bytes/sec" sampleRate="PT15S" unit="BytesPerSecond"> | |
<annotation displayName="Disk speed" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Disk Read Bytes/sec" sampleRate="PT15S" unit="BytesPerSecond"> | |
<annotation displayName="Disk read speed" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Disk Write Bytes/sec" sampleRate="PT15S" unit="BytesPerSecond"> | |
<annotation displayName="Disk write speed" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Avg. Disk Queue Length" sampleRate="PT15S" unit="Count"> | |
<annotation displayName="Disk average queue length" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Avg. Disk Read Queue Length" sampleRate="PT15S" unit="Count"> | |
<annotation displayName="Disk average read queue length" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\PhysicalDisk(_Total)\Avg. Disk Write Queue Length" sampleRate="PT15S" unit="Count"> | |
<annotation displayName="Disk average write queue length" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\LogicalDisk(_Total)\% Free Space" sampleRate="PT15S" unit="Percent"> | |
<annotation displayName="Disk free space (percentage)" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
<PerformanceCounterConfiguration counterSpecifier="\LogicalDisk(_Total)\Free Megabytes" sampleRate="PT15S" unit="Count"> | |
<annotation displayName="Disk free space (MB)" locale="en-us"/> | |
</PerformanceCounterConfiguration> | |
</PerformanceCounters> | |
<Metrics resourceId="$VMResourceID" > | |
<MetricAggregation scheduledTransferPeriod="PT1H"/> | |
<MetricAggregation scheduledTransferPeriod="PT1M"/> | |
</Metrics> | |
<WindowsEventLog scheduledTransferPeriod="PT1M"> | |
<DataSource name="Application!*[System[(Level = 1 or Level = 2)]]"/> | |
<DataSource name="Security!*[System[(Level = 1 or Level = 2)]"/> | |
<DataSource name="System!*[System[(Level = 1 or Level = 2)]]"/> | |
</WindowsEventLog> | |
</DiagnosticMonitorConfiguration> | |
</WadCfg> | |
<StorageAccount>$DiagStgAccountName</StorageAccount> | |
</PublicConfig> | |
"@ | |
Set-Content -Value $DiagnosticsConfiguration -Path $DiagnosticsConfigurationPath -Force | |
# Turn on guest-level monitoring | |
Set-AzureRmVMDiagnosticsExtension -ResourceGroupName $ResourceGroupName -VMName $VirtualMachinename ` | |
-DiagnosticsConfigurationPath $DiagnosticsConfigurationPath | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment