Auditing the VMware UEM Configuration Share

I want to start this blog post by saying that the content of this post is based upon great solutions and work by others. A special thanks and appreciation goes out to Boe Prox for providing his PowerShell function New-FileSystemWatcher and to Mike Bijl for providing the configuration steps and his PowerShell script for looking up file/folder changes and user name and machine name lookup.

Introduction

VMware User Environment Manager (UEM) does not have auditing build in. However, VMware UEM is all file/folder based, and therefore a solution that audits files and folders should normally be sufficient. In this blog post I want to describe a solution which is easy to implement and which can easily be adjusted to your own needs. The solution is built using

  • A Group Policy Object (GPO)
  • A PowerShell script
  • A scheduled task

One important thing to mention: This solution only works using a Windows file server (share) that hosts the VMware UEM configuration.

Auditing GPO

A GPO that audits the file system and file share is required for being able to look up the user name that made the change and for looking up the system name from which the change happened.

Use the following steps for creating the Auditing GPO.

In this example my domain controller (INFRA01) is also the server hosting the VMware UEM Configuration Share.

Configure the following Subcategories and enable the Audit Events for Success

  • Audit Detailed File Share
  • Audit File Share
  • Audit File System

Audit VMware UEM Configuration Share PowerShell Script

The Audit VMware UEM Configuration Share PowerShell Script is the actual brain in this solution. It uses the FileSystemWatcher class for setting up a listener that watches predefined folders and/or files. The following script is an example of how I implemented it in my LAB environment and it does the following (high level).

  • Creates an event log for VMware UEM Configuration Share auditing (VMware UEM)
  • “Listens” for changes in the specified local path (C:\Shares\UEM_Config –> \INFRA01.lab.local\UEM_Config)
  • Creates events for changes in the specified local path in the specified event log (VMware UEM)

This is the actual content of my script.

$EventLogName = "VMware UEM"
$EventSource = "VMware UEM Configuration"
$UEMConfigPath = "C:\Shares\UEM_Config"

$logFileExists = Get-EventLog -list | Where-Object {$_.logdisplayname -eq $EventLogName} 
if (! $logFileExists) {
    New-EventLog -LogName $EventLogName -Source $EventSource
}

#
# Credits go to Boe Prox for this part --> https://mcpmag.com/articles/2015/09/24/changes-to-a-folder-using-powershell.aspx
#

Function Start-FileSystemWatcher  {

  [cmdletbinding()]
  Param (
  [parameter()]
  [string]$Path,
  [parameter()]
  [ValidateSet('Changed','Created','Deleted','Renamed')]
  [string[]]$EventName,
  [parameter()]
  [string]$Filter,
  [parameter()]
  [System.IO.NotifyFilters]$NotifyFilter,
  [parameter()]
  [switch]$Recurse,
  [parameter()]
  [scriptblock]$Action
  )

  #region Build  FileSystemWatcher

  $FileSystemWatcher  = New-Object  System.IO.FileSystemWatcher
  If (-NOT $PSBoundParameters.ContainsKey('Path')){
  $Path  = $PWD
  }

  $FileSystemWatcher.Path = $Path
  If ($PSBoundParameters.ContainsKey('Filter')) {
  $FileSystemWatcher.Filter = $Filter
  }
  If ($PSBoundParameters.ContainsKey('NotifyFilter')) {
  $FileSystemWatcher.NotifyFilter =  $NotifyFilter
  }
  If ($PSBoundParameters.ContainsKey('Recurse')) {
  $FileSystemWatcher.IncludeSubdirectories =  $True
  }
  If (-NOT $PSBoundParameters.ContainsKey('EventName')){
  $EventName  = 'Changed','Created','Deleted','Renamed'
  }
  If (-NOT $PSBoundParameters.ContainsKey('Action')){
  $Action  = {
  Switch  ($Event.SourceEventArgs.ChangeType) {
  'Renamed'  {
  $Object  = "{0} was  {1} to {2} at {3}" -f $Event.SourceArgs[-1].OldFullPath,
  $Event.SourceEventArgs.ChangeType,
  $Event.SourceArgs[-1].FullPath,
  $Event.TimeGenerated
  }
  Default  {
  $Object  = "{0} was  {1} at {2}" -f $Event.SourceEventArgs.FullPath,
  $Event.SourceEventArgs.ChangeType,
  $Event.TimeGenerated
  }
  }
  $WriteHostParams  = @{
  ForegroundColor = 'Green'
  BackgroundColor = 'Black'
  Object =  $Object
  }
  Write-Host  @WriteHostParams
  }
  }

#endregion  Build FileSystemWatcher
    #region  Initiate Jobs for FileSystemWatcher
  $ObjectEventParams  = @{
  InputObject =  $FileSystemWatcher
  Action =  $Action
  }
  ForEach  ($Item in  $EventName) {
  $ObjectEventParams.EventName = $Item
  $ObjectEventParams.SourceIdentifier =  "File.$($Item)"
  Write-Verbose  "Starting watcher for Event: $($Item)"
  $Null  = Register-ObjectEvent  @ObjectEventParams
  }
  #endregion  Initiate Jobs for FileSystemWatcher
}

Start-FileSystemWatcher -Path $UEMConfigPath -Recurse -Action {

    #
    # Credits go to Mike Bijl for this part --> https://www.linkedin.com/in/mikebijl/
    #

    $name = $Event.SourceEventArgs.Name
    $changeType = $Event.SourceEventArgs.ChangeType
    $timeStamp = $Event.TimeGenerated
    $after = $timeStamp.addSeconds(-2) 
    $before = $timeStamp.addSeconds(+2)
    start-sleep -Seconds 2
    $evententries = @(Get-WinEvent -FilterHashtable @{logname="Security"; starttime=$after;endtime=$before; ID = 5145 } -MaxEvents 10 )
    foreach($evententry in $evententries) {
        $user = ""
        $null = $($evententry.Message) -match '.*Account\sName:\s*(?.*)\x0D'
        $user = $($matches['content'])
        $null = $($evententry.Message) -match '.*Source\sAddress:\s*(?.*)\x0D'
        $machine = $($matches['content']) + " `($([system.net.dns]::gethostentry("$($matches['content'])").HostName)`)"
        If ($user -ne "") {break}
    }

    $Object  = "{0} was {1} at {2} by {3} on {4}" -f $Event.SourceEventArgs.FullPath,
    ($Event.SourceEventArgs.ChangeType | Out-String).ToUpper(),
    $Event.TimeGenerated,
    $user.ToUpper(),
    $machine.ToUpper()
    $WriteHostParams  = @{
        ForegroundColor = 'Green'
        BackgroundColor =  'Black'
        Object =  $Object
    }

    Write-Host @WriteHostParams
    Write-EventLog -LogName "VMware UEM" -Source "VMware UEM Configuration" -EntryType "Information" -EventId "1001" -Message $Object
}

You can download the script and change it to your own needs.

Scheduled Task Configuration

Follow the next steps for creating the scheduled task that runs the PowerShell script.

Select Delay task for 1 minute

Select Repeat task every 1 hour for a duration of Indefinitely

Select Enabled

For Program/script enter C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe

For Add arguments (optional) enter -noexit -executionpolicy bypass -file “D:\Audit VMware UEM Configuration Share.ps1”

Change the path to the script when needed.

End Results

When I now create/edit/delete configurations in the VMware UEM Management Console it will be picked up by the PowerShell script that’s running (scheduled task) and it will create events in the event log, specifying the file/folder, action (Create/Delete/Change), date/time, user name and source computer name.

Share