Blog Post

Core Infrastructure and Security Blog
7 MIN READ

Azure Update Management (Log Analytics Agents & Automation Accounts)

wernerrall's avatar
wernerrall
Icon for Microsoft rankMicrosoft
Dec 20, 2021

 

Many of our customers would like to start patching servers as soon as possible using a single Update Management Solution deployed on a single Log Analytics Workspace. To achieve this goal you need to deploy the Azure Monitor Agent (newer version) or the Microsoft Monitoring Agent (current version) on machines that could be domain joined or even on a workgroup. To add even more complexity, the use of PowerShell could be restricted.  

The above requirements can be broken up into 2 scenarios:

 

Scenarios

[Scenario 1] – Virtual Machine on Azure that is already connected to the domain. It might or might not have the agent. It might or might not have the proxy settings filled in.

[Scenario 2] – Virtual Machine on Azure that is not connected to the domain. It might or might not have the agent or proxy settings filled in.

We will now explore 3 Options for deploying the agents and 3 Query Methods to confirm if the installation was actually successful.

 

The 3 Options for deploying the Agent

 

Option 1 – Azure Policy

 

For both Scenario 1 and Scenario 2 this can be used. We would choose the Enable Azure Monitor for VMs Policy Initiative.

 

It can be assigned to any Management Group or Subscription

 

Simply choose your Log Analytics Workspace that is connected to the Automation Account Containing Update Management

 

I normally also create a Remediation Managed Identity

 

Set a default Non-Compliance message

 

And create

 

If we immediately go to the Deploy-VM-Monitoring we can view the compliance

 

By clicking on Non-Compliant Resources I can see the machines

 

But this policy might not have the Failed/Succeeded metric for the actual extension. For that we can use 3 query methods: Azure Resource Graph Explorer, Azure CLI Bash, Azure Cloud Shell PowerShell.

 

Option 2 – PowerShell

 

For Scenario 1 and Scenario 2 Our official method to deploy the Log Analytics Extension with PowerShell in Azure can be seen below.

 

 

$PublicSettings = @{"workspaceId" = "myWorkspaceId"}
$ProtectedSettings = @{"workspaceKey" = "myWorkspaceKey"}
Set-AzVMExtension -ExtensionName "MicrosoftMonitoringAgent" `
   -ResourceGroupName "myResourceGroup" `
    -VMName "myVM" `
    -Publisher "Microsoft.EnterpriseCloud.Monitoring" `
    -ExtensionType "MicrosoftMonitoringAgent" `
    -TypeHandlerVersion 1.0 `
    -Settings $PublicSettings `
    -ProtectedSettings $ProtectedSettings `
    -Location WestUS

 

 

Or if you are using the Azure Monitor Agent

 

 

Set-AzVMExtension -ExtensionName "AMAWindows" `
    -ExtensionType AzureMonitorWindowsAgent `
    -Publisher " Microsoft.Azure.Monitor" `
    -ResourceGroupName "myResourceGroup" `
    -VMName "myVM" `
    -TypeHandlerVersion 1.0 `
    -Location WestUS

 

 

If the Extension already Exists, you mentioned there needs to some proxy settings filled in.

One way to configure Proxy settings quickly on multiple machines would be to use the Custom Script Extension. PowerShell 7 brings the functionality “-Parallel” which will run multiple instances of the same script.

To manually run the Customer Script Extension Proxy Setting on a Server and set the correct Workspace we can use the below script

 

 

#This section adds a new Workspace
$workspaceId = "<WS ID>"
$workspaceKey = "<WS KEy>"

$mma = New-Object -ComObject 'AgentConfigManager.MgmtSvcCfg'
$mma.AddCloudWorkspace($workspaceId, $workspaceKey)

#This section is where the Proxy can be configured
param($ProxyDomainName="https://proxy.contoso.com:30443")
$proxyMethod = $mma | Get-Member -Name 'SetProxyUrl'
if (!$proxyMethod)
{
    Write-Output 'Health Service proxy API not present, will not update settings.'
    return
}
#Clears Proxy settings in MMA
Write-Output "Clearing proxy settings."
$mma.SetProxyUrl('')

#Adds new proxy settings
Write-Output "Setting proxy to $ProxyDomainName"
$mma.SetProxyUrl($ProxyDomainName)
$mma.ReloadConfiguration()

 

 

 

If we wanted to Automate this for multiple machines, we could do something like mentioned in below article.

How to run scripts against multiple Azure VMs by using Run Command - Thomas Maurer

 

Option 3 – Desired State Configuration

 

Desired State Configuration is another great way of ensuring the MMA is present on machines and configured correctly. This also makes execution easier because you can use a specified approved account or Hybrid runbook worker to execute the DSC in case of strict security rules where only certain accounts can run PowerShell scripts.

Steps

  1. Download the MMA Agent

 

  1. Extract the contents because we want the MSI

 

  1. Open Notepad and save the below as “Get-MSIFileInformation.ps1” in your Downloads folder.

 

param(
[parameter(Mandatory=$true)]
[IO.FileInfo]$Path,
[parameter(Mandatory=$true)]
[ValidateSet("ProductCode","ProductVersion","ProductName")]
[string]$Property
)
try {
    $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
    $MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase","InvokeMethod",$Null,$WindowsInstaller,@($Path.FullName,0))
    $Query = "SELECT Value FROM Property WHERE Property = '$($Property)'"
    $View = $MSIDatabase.GetType().InvokeMember("OpenView","InvokeMethod",$null,$MSIDatabase,($Query))
    $View.GetType().InvokeMember("Execute", "InvokeMethod", $null, $View, $null)
    $Record = $View.GetType().InvokeMember("Fetch","InvokeMethod",$null,$View,$null)
    $Value = $Record.GetType().InvokeMember("StringData","GetProperty",$null,$Record,1)
    return $Value
}
catch {
    Write-Output $_.Exception.Message
}

 

 

  1. Open PowerShell and cd to Downloads, and run the Newly saved MSI Script

.\Get-MSIFileInformation.ps1 -Path C:\Users\<youruser>\Downloads\MMASetup-A
MD64\MOMAgent.msi -Property ProductCode

 

 

  1. Create Automation Variables for

OPSINSIGHTS_WS_ID  (This is your Workspace you need the server to connect to),

OPSINSIGHTS_WS_KEY (This is the key for the workspace),

OPINSIGHTS_PROXY_URL (This is the proxy URL in format  https://proxy.contoso.com:30443)

 

 

  1. Import the Module into the Automation Account

 

 

  1. Save the below script as MMAgent.ps1 and Modify the ProductID that was found in Step 4. Also update the ProductID as found in Step 4.

 

Configuration MMAgent
{
    $OIPackageLocalPath = "C:\Deploy\MMASetup-AMD64.exe"
    $OPSINSIGHTS_WS_ID = Get-AutomationVariable -Name "OPSINSIGHTS_WS_ID"
    $OPSINSIGHTS_WS_KEY = Get-AutomationVariable -Name "OPSINSIGHTS_WS_KEY"
    $OPINSIGHTS_PROXY_URL = Get-AutomationVariable -Name " OPINSIGHTS_PROXY_URL"

    Import-DscResource -ModuleName xPSDesiredStateConfiguration
    Import-DscResource -ModuleName PSDesiredStateConfiguration

    Node OMSnode {
        Service OIService
        {
            Name = "HealthService"
            State = "Running"
            DependsOn = "[Package]OI"
        }
        xRemoteFile OIPackage {
            Uri = "https://go.microsoft.com/fwlink/?LinkId=828603"
            DestinationPath = $OIPackageLocalPath
        }
        Package OI {
            Ensure = "Present"
            Path  = $OIPackageLocalPath
            Name = "Microsoft Monitoring Agent"
            ProductId = "88EE688B-31C6-4B90-90DF-FBB345223F94"
            Arguments = '/C:"setup.exe /qn NOAPM=1 ADD_OPINSIGHTS_WORKSPACE=1 OPINSIGHTS_WORKSPACE_ID=' + $OPSINSIGHTS_WS_ID + ' OPINSIGHTS_WORKSPACE_KEY=' + $OPSINSIGHTS_WS_KEY + ' OPINSIGHTS_PROXY_URL=' + $OPINSIGHTS_PROXY_URL + ' AcceptEndUserLicenseAgreement=1"'
            DependsOn = "[xRemoteFile]OIPackage"
        }
    }
}

 

 

  1. Import the MMAgent.ps1 script into the Automation Account State Configuration under Configurations. After the import click on MMAgent and click Compile.

 

 

 

  1. Assign a computer or node and within a few minutes the Agent will get pushed to the machine.

 

 

 

 

The 3 Methods to Query Agent Installation

 

1.      Azure Resource Graph Explorer [Query All Servers]*

 

 

// LogAnalyticsandHealthyAgentv5
// All Running, All Health and All Monitoring Extensions
// Click the "Run query" command above to execute the query and see results.
// Linux and Windows Agents
// Click the "Run query" command above to execute the query and see results.
// This query will show machines that are currently running.
// This query will show the extensions that relates to MicrosoftMonitoringAgent','AzureMonitorWindowsAgent'and 'OMSAgentForLinux'

resources
| where type == 'microsoft.compute/virtualmachines'
| where properties.extended.instanceView.powerState.displayStatus=="VM running" and properties.osProfile.windowsConfiguration.provisionVMAgent=="true" or properties.extended.instanceView.powerState.displayStatus=="VM running" and properties.osProfile.linuxConfiguration.provisionVMAgent=="true"
| extend
    JoinID = toupper(id),
    OSName = tostring(name),
    OSType = tostring(properties.storageProfile.osDisk.osType),
    RSG = tostring(resourceGroup),
    SUB = tostring(subscriptionId),
    LOC = tostring(location)
| join kind=leftouter(
resources
| where type == 'microsoft.compute/virtualmachines/extensions' and name == 'MicrosoftMonitoringAgent' or name == 'AzureMonitorWindowsAgent' or name == 'OMSAgentForLinux'
// | where properties.provisioningState == 'Succeeded'
|extend 
  VMId = toupper(substring(id, 0, indexof(id, '/extensions'))),
  props = tostring(properties.settings),
  prvstatus = tostring(properties)
)on $left.JoinID == $right.VMId
| summarize Extensions = make_list(props) by id, OSName, OSType, RSG, SUB, LOC, prvstatus

 

 

Example of execution. This will show me all machines that are running and their provisionState of the Extension that related to Log Analytics.

 

The subscription where the policies have not applied yet.

 

Another subscription to showcase the Provisioning Status

 

*Although Resource Graph is the easiest way to get information about all machines at once it takes longer to update than the Bash or PowerShell. This means if you are querying your machines and you see one has failed and you repair the failure Resource Graph will take time to update. Therefore if you want realtime information please refer to Azure CLI or Cloud Shell, the limitation being only looking at one server.

 

2.      Azure CLI Bash [Deep Dive 1 Server Real Time]

If I find that I need to deep dive into one specific server to see if the Extension Provisioning succeeded or failed I can use Cloud Shell Bash in the Azure Portal.

The command is:

 

 

az vm extension show -g <resource group> --vm-name <vmname> --name MicrosoftMonitoringAgent

 

 

 

3.      Azure Cloud Shell PowerShell [Deep Dive 1 Server]

The Bash is great at showing a one pager but if I wanted to dive into even more detail about why an extension failed I can use Cloud Shell PowerShell

The command is:

 

 

Get-AzVM -ResourceGroupName <resource group> -Name <server> -Status

 

 

I can look at the Extensions Portion and I will have the error code and message

 

And the ExtensionHandlers will give me some more information

 

These are only methods to assist you in querying your VM Extensions. We need them to be healthy to connect to the Automation Account.

 

Thank you for reading and I hope this has been beneficial to you in your patching journey.

 

Some more helpful Links

 

PowerShell/Get-MSIFileInformation.ps1 at master · NickolajA/PowerShell (github.com)

Install Log Analytics agent on Windows computers - Azure Monitor | Microsoft Docs

Install the Azure Monitor agent - Azure Monitor | Microsoft Docs

Log Analytics virtual machine extension for Windows - Azure Virtual Machines | Microsoft Docs

https://docs.microsoft.com/en-us/azure/security-center/faq-data-collection-agents#what-are-the-recommended-steps-when-opting-out-of-automatic-provisioning

https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/oms-windows

https://docs.microsoft.com/en-us/azure/virtual-machines/extensions/oms-linux

https://docs.microsoft.com/en-us/azure/azure-monitor/vm/quick-collect-linux-computer#obtain-workspace-id-and-key

 

 

Disclaimer
The sample scripts are not supported under any Microsoft standard support program or service. The sample scripts are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.

 

Updated Dec 21, 2021
Version 2.0
No CommentsBe the first to comment