Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marckean/d155622b73f224e8366b03c818d9d9ce to your computer and use it in GitHub Desktop.
Save marckean/d155622b73f224e8366b03c818d9d9ce to your computer and use it in GitHub Desktop.
# --------------------------------------------------------------------------------------------------------------
#  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