Auditing in PSU?

For almost all stuff in PSU, who can see who executed what, and in git you can see who created/deleted/edited anything.

Would it be possible to present that in any way? I feel like that could be interesting for enterprises.

What I basically would like to end up with is the ability query PSU to display a table of who did what.

Since its beyond my imagination, I didn’t wanna go ahead and make an official issue of it just yet.

I’ve actually spent the last couple days building out a logging method using the PSFramework module in my environment. Whether it’s suitable for more than just us, I’m not sure. I’m dropping my internal documentation into this post in case it helps anyone.

At this point, I’m just adding Write-PSFMessage to important endpoints and dashboards, and viewing the logs either with CMTrace or the Pages I’ve created.


The PSFramework module is being used to facilitate easy logging across PowerShell Universal.

This module provides flexibility and power. This will attempt to describe the way it has been configured and how to extend its use in the future.


PSFramework Module

The PSFramework module has been installed through PowerShell Gallery in the ‘Modules’ pane in the PSU web UI - for the moment, this module is synced to this repo.

There are many options for configuring this module, including GPO and registry, but the simplest seemed to be configuring the logging providers with a script each time Universal starts. This should ensure portability between dev and prod environments and allow migration to a new instance if required.

Logging Providers

We are using the Logfile provider .
Each logging provider that is configured can be set to save log files to a unique path, specify a log file format, among other options. Each configuration of a logging provider is called an Instance.

This is important, as it allows the option of sending a log message, specifying a function name and having that log message only be sent to the provider configured to log that function, as specified in the ‘IncludeFunctions’ option.

The logging providers are configured using the ‘Set-LoggingOptions’ script - The Integrated environment has been configured to run this script on startup.

An example of the configuration performed:
$API_AD_Actions_logs_paramSetPSFLoggingProvider = @{ Name = 'logfile' InstanceName = 'API_AD_Actions_logs' FilePath = 'C:\UniversalAzureRepo\Logs\API_AD_Actions_logs-%Date%.log' IncludeFunctions = 'API_osd-Get-DesiredADComputerOU', 'API_osd-Get-PossibleADComputerOUs', 'API_osd-Get-SchoolName', 'API_osd-Get-ADComputer', 'API_osd-Remove-ADComputer' FileType = 'cmtrace' Enabled = $true LogRotatePath = 'C:\UniversalAzureRepo\Logs\API_AD_Actions_logs-*.log' # MutexName = 'API_AD_Actions_logs' }

Functions, Instances and Log Destination

Function Name Instance Name Log File
API_osd-Get-DesiredADComputerOU API_AD_Actions_logs API_AD_Actions_logs-%Date%.log
API_osd-Get-PossibleADComputerOUs API_AD_Actions_logs API_AD_Actions_logs-%Date%.log
API_osd-Get-ADComputer API_AD_Actions_logs API_AD_Actions_logs-%Date%.log
API_osd-Remove-ADComputer API_AD_Actions_logs API_AD_Actions_logs-%Date%.log
API_osd-tracking API_OSD_Misc_logs API_OSD_Misc_logs-%Date%.log
API_osd-New-TSBackgroundRemoteViewerShortcut API_OSD_Misc_logs API_OSD_Misc_logs-%Date%.log
API_osd-Remove-TSBackgroundRemoteViewerShortcut API_OSD_Misc_logs API_OSD_Misc_logs-%Date%.log
dashboard_Xibo-UserAdmin dashboard_logs dashboard_logs-%Date%.log
dashboard_Xibo-DisplayAdmin dashboard_logs dashboard_logs-%Date%.log

Writing Logs

As specified in the logging provider configuration, log files are written in a CMTrace format to a file specified under the C:\UniversalAuzureRepo\Logs\ folder

These logs are set to auto-clean using the default options of 30 days, but can be configured per-provider if necessary.

Normal output

In normal circumstances when we just want to record activities, a simple ‘Write-PSFMessage’ that specifies the level ‘Host’ and function name is appropriate. Note in the example below that the FunctionName parameter is using a $LogName variable - this example is from an API endpoint and specifies the API call used.

Write-PSFMessage -Level Host -FunctionName $LogName -Message "Request to delete account $Name from $Domain" -Target $RemoteIPAddress

Warning output

In events where we expect potential failure, a try/catch block should be used. The following example is in the catch block - Note the level is ‘Warning’ and the ‘ErrorRecord’ parameter includes the pipeline output of the error that triggered the catch block using $PSItem (or $_)

Write-PSFMessage -Level Warning -FunctionName $LogName -Message "Unable to delete account $Name from $Domain" -Target $RemoteIPAddress -ErrorRecord $PSItem

Viewing Logs

Log files

Log files can be viewed with CMTrace directly in the C:\UniversalAzureRepo\Logs folder on the production or dev server.


Log entries that are in memory can be retrieved via Get-PSFMessage. This has been added to a script that acts as a data source for the Log Viewer pages. At the moment, this script is only configured to pull logs from to Instances of log providers, the ‘API_AD_Actions_logs’ instance and the ‘API_OSD_Misc_logs’ instance.

The logs viewable by this script and the Pages it populates are only in memory until the Universal service gets restarted.