M365SONE.OneDriveMon.Serial.PA

M365SONE.OneDriveMon.Serial.PA (ProbeActionModuleType)

Designed to leverage a Posh script PA for retrieving properties/metrics.

Element properties:

TypeProbeActionModuleType
IsolationAny
AccessibilityInternal
RunAsM365SL.RunAs.Profile
InputTypeSystem.BaseData
OutputTypeMicrosoft.Windows.SerializedObjectData

Member Modules:

ID Module Type TypeId RunAs 
POSH ProbeAction Microsoft.Windows.PowerShellProbe Default

Overrideable Parameters:

IDParameterTypeSelector
EventIDFilterstring$Config/EventIDFilter$
PoshLibraryPathstring$Config/PoshLibraryPath$
ProbeActionTimeoutSecondsint$Config/ProbeActionTimeoutSeconds$
WriteToEventLogbool$Config/WriteToEventLog$

Source Code:

<ProbeActionModuleType ID="M365SONE.OneDriveMon.Serial.PA" Accessibility="Internal" Batching="false" PassThrough="false" RunAs="M365SL!M365SL.RunAs.Profile">
<Configuration>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="ApiTokenScopeURL" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="ApiTokenURL" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="ApiURL" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="M365_AccountName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="M365_AccountPassword" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="M365_ClientID" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="M365_ClientSecret" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="EventIDFilter" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="PoshLibraryPath" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="ProbeActionTimeoutSeconds" type="xsd:integer"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="TenantName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="TLSVersion" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="WorkflowName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="WriteToEventLog" type="xsd:boolean"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="EventIDFilter" Selector="$Config/EventIDFilter$" ParameterType="string"/>
<OverrideableParameter ID="PoshLibraryPath" Selector="$Config/PoshLibraryPath$" ParameterType="string"/>
<OverrideableParameter ID="ProbeActionTimeoutSeconds" Selector="$Config/ProbeActionTimeoutSeconds$" ParameterType="int"/>
<OverrideableParameter ID="WriteToEventLog" Selector="$Config/WriteToEventLog$" ParameterType="bool"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="POSH" TypeID="Windows!Microsoft.Windows.PowerShellProbe">
<ScriptName>M365SONE.OneDriveMon.ps1</ScriptName>
<ScriptBody><Script>&lt;#
#===============================================================================================================================================================
Created by: Tyson Paul, Taylour Blackwell
Filename: M365SONE.OneDriveMon.ps1
Description: This will upload and download test files to verify OneDrive functionality/access.

Version History:

2020.11.18.22051 - Added API Url params
2020.10.02.1419 - Tested.
2020.09.30.1514 - v1

Requirements: Must have an Azure application registered and have the following:
ClientID &amp; Application Secret

===============================================================================================================================================================
#&gt;

Param(
[string]$ApiTokenScopeURL,
[string]$ApiTokenURL,
[string]$ApiURL,

[string]$M365_AccountName,
[string]$M365_AccountPassword,

# Azure Application auth
[string]$M365_ClientID,
[string]$M365_ClientSecret,

# Comma-separated list of event IDs, script will only write to log for these EventIDs. This is a way to only write specific events. Only valid if $WriteToEventLog parameter is 'true'.
[string]$EventIDFilter,

# Comma-separated list of .ps1 files to load
[string]$PoshLibraryPath,


# This is a clever way to utilize the exact same script for both rule/mon and agent tasks.
[Parameter(Mandatory=$false,
ValueFromPipeline=$false,
ValueFromPipelineByPropertyName=$false,
ValueFromRemainingArguments=$false)]
[ValidateSet('PropertyBag', 'Serialized')]
[string]$ScriptOutputType = 'PropertyBag',

# Azure tenant
[string]$TenantName,

[string]$TLSVersion,

# Typically this is the name of the workflow calling this script. Should be set to the name of the probe/WA if being used by both rules/mons so as not to break cookdown.
# Keep in mind that datasource params need to be identical for cookdown to work.
[string]$WorkflowName,

# type:string. SCOM bool params are different than Posh bool. Will get converted to Posh bool below.
[string]$WriteToEventLog = 'false'
)

# Set defaults for event filters. Apparently setting this in the Params declaration did not work.
If (-NOT $EventIDFilter) {
$EventIDFilter = "9990,9991,9992,9995,9996,9997,9998,9999"
}

$ScriptName = 'M365SONE.OneDriveMon.ps1'
$NameSpace = 'OneDrive'
[bool]$WriteToEventLog = [System.Convert]::ToBoolean($WriteToEventLog)
$Testing = $false

######################### FUNCTIONS ############################
################################################################
Function Load-Library {
Param (
[string]$PoshLibraryPath
)
$ErrorActionPreference = 'STOP'
If (-NOT $NameSpace.Length) {
$NameSpace = $ScriptName
}
$EventSource = "M365 Supplemental"
$EventLogName = "Application"
$objEvent = New-Object System.Diagnostics.EventLog
$objEvent.Source = $EventSource
$objEvent.Log = $EventLogName
$EventID_Normal = 9992
$EventID_Anomaly = 9996
[Int]$info=4 #System.Diagnostics.EventInstance
[Int]$critical=1
[Int]$warn=2

If ($PoshLibraryPath ){
Start-Sleep -Seconds 5 #Allow time for Library to be deployed
ForEach ($Path in $PoshLibraryPath.Split(',') ){
Try {
If (($Path.Length) -AND ($Path -notmatch '^-1$')) {
. $Path
If ([bool]$WriteToEventLog -eq $true) {
$msg = "Line [$($MyInvocation.ScriptLineNumber)], $($MyInvocation.PSCommandPath): Success loading library file: [$($Path)]"
$logData = "$($Msg)^$($Msg)^$($ScriptName)^$($TenantName)^$($NameSpace)"
[array]$arrMessage = @($logData.Split('^'))
$objEventID = New-Object System.Diagnostics.EventInstance($EventID_Normal,1,$info)
$objEvent.WriteEvent($objEventID, @($arrMessage))
}
}
} Catch {
[bool]$LibExists =$false
Try {
# It's possible the libfile exists (as it should) but cannot be loaded for some reason.
[bool]$LibExists = [bool](Test-Path -Path $Path -PathType Leaf)
} Catch {
#File does not exist. LibExists = $false already by default
}
$msg = "Line [$($MyInvocation.ScriptLineNumber )]: Error loading PoshLibrary at path:[$($Path)]. Library file exists? [$($LibExists)]. This is likely to cause many other dependent functions to fail. `n`nError data: $($_)`n`n"
$logData = "$($Msg)^$($Msg)^$($ScriptName)^$($TenantName)^$($NameSpace)"
[array]$arrMessage = @($logData.Split('^'))
$objEventID = New-Object System.Diagnostics.EventInstance($EventID_Anomaly,1,$warn)
$objEvent.WriteEvent($objEventID, @($arrMessage))
}
}
}
$ErrorActionPreference = 'CONTINUE'
}
################################################################

############## TESTING ##############
&lt;# #Run this as needed when testing

Function Testing {
$Testing = $true
Get-Item Alias:\_LINE_ -ErrorAction Ignore | Remove-Item -ErrorAction Ignore
$testParamsFile = (Join-path $TestFolder ("PARAMS_$($ScriptName)"))
#Write-Host "$(Test-Path $testParamsFile):$($testParamsFile)" -F Yellow -B Green
. $testParamsFile
. Load-Library -PoshLibraryPath $PoshLibraryPath

# Encode user data/passwords in current test user context
$M365_ClientSecret = Encode-UserData $M365_ClientSecret_PLAINTEXT
$M365_AccountPassword = Encode-UserData $M365_AccountPassword_PLAINTEXT
$error.Clear()
}

$ThisScriptFullName = $MyInvocation.MyCommand.Path
$TestFolder = Join-Path (Split-Path $ThisScriptFullName -Parent) "TestSetup"
If (Test-Path -Path $TestFolder) {
. Testing
}

#&gt;
############## TESTING ##############


. Load-Library -PoshLibraryPath $PoshLibraryPath
LogIt -EventID 9990 -Type $info -Msg "Begin script..." -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()

$TempFolder = Get-TempFolderPath

# Set up BasicBag with defaults
$bag = New-Object -TypeName BasicBag
$bag.AddValue('Category',"FileTest")
$bag.AddValue('Message',"")
$bag.AddValue('Result',"UNKNOWN") #default, unless the tests succeed
$bag.AddValue('DriveName',"&lt;no data&gt;")
$bag.AddValue('DriveID',"&lt;no data&gt;")

$bag.AddValue('FileUploadDurationMS', [double]0.00)
$bag.AddValue('FileDownloadDurationMS',[double]0.00)
$bag.AddValue('TotalDurationMS',[double]0.00)

$bag.AddValue('ThisScriptInstanceGUID',"$ThisScriptInstanceGUID")
$bag.AddValue('Whoami',"$whoami")
$bag.AddValue('M365_ClientID',"$M365_ClientID")
$bag.AddValue('M365_AccountName',"$M365_AccountName")
$bag.AddValue('TenantName',"$TenantName")


LogIt -EventID 9992 -Type $info -msg "Setting TLS for session, Version: [$($TLSVersion)]." -Proceed $WriteToEventLog -Line $(_LINE_); $Error.Clear();
#Set Default TLS
. Set-TLS -TLSVersion $TLSVersion

# Decode Account Password
$Message = "Decode password for [$($NameSpace)]."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$M365_AccountPassword_DECRYPTED = Decode-UserData -Data $M365_AccountPassword
} Catch {
$Message += "Unable to $($Message). See error data."
LogIt -EventID 9995 -Type $warn -Msg $Message -Proceed $true -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
}

# Decode Client Secret
$Message = "Decode client secret for [$($NameSpace)]."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$M365_ClientSecret_DECRYPTED = Decode-UserData -Data $M365_ClientSecret
} Catch {
$Message += "Unable to $($Message). See error data."
LogIt -EventID 9995 -Type $warn -Msg $Message -Proceed $true -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
}

# Get Access Token
$Message = "Get Access Token for [$($NameSpace)]."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$TokenResponse = Get-AccessToken -Delegated -User $M365_AccountName -Pass $M365_AccountPassword_DECRYPTED -ClientID $M365_ClientID -ClientSecret $M365_ClientSecret_DECRYPTED -TenantName $TenantName -ApiTokenUrl $ApiTokenURL -ApiTokenScopeURL $ApiTokenScopeURL
} Catch {
$Message = "Unable to $($Message). See error data. Exiting."
LogIt -EventID 9997 -Type $warn -Msg $Message -Proceed $true -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
# Monitor type supports Critical CD for token failure.
Output $bag -Tag 'TokenFailure'
Exit
}

# Retrieve object(s)
LogIt -EventID 9992 -Type $info -Msg "Retrieve object(s)" -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$DriveContentsApiURL = "$($ApiURL)/v1.0/me/drive/root/"
$DriveContents = Invoke-RestMethod -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $DriveContentsApiURL -Method Get -ContentType 'application/json'

If (-NOT $DriveContents) {throw}

$Msg =@"
Retrieved object Name(s):
$($DriveContents.Name | Out-String)
"@

$bag.DriveID = "$($DriveContents.ID)"
$bag.DriveName = "$($DriveContents.Name)"
$bag.Result = 'SUCCESS'
LogIt -EventID 9992 -Type $info -Msg $Msg -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
} Catch {
$Message = " Unable to get object(s) at Graph URL: [$($DriveContentsApiURL)]. See error data. Verify that the correct permissions have been granted to the App Registration and that Admin Consent has been granted to all permissions, regardless of if consent is 'required'."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $true -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
$bag.Result = 'FAILURE'
Output $bag -Tag 'GetObjectFailure'
Exit
}

# Proceed to file test
###--- Generate Test ID and File Name Upload File ---###
$TestID = (Get-Date -format MMddyyyyhhmmss) + "-" + "$($ThisScriptInstanceGUID)"
$TestFileName = 'TestDoc-' + "$($env:computername).$($env:USERDNSDOMAIN)" + '-' + $TestID + '.tmp'

# UPLOAD
$Message = "Attempt to upload file [$($TestFileName)] to $($NameSpace)..."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$UploadFileApiURL = "$($ApiURL)/v1.0/me/drive/items/root:/$($TestFileName):/content"
$TestMessage = "$($TestFileName) Hello, this is a test file created to verify the ability to upload and download files to $($NameSpace)."
$StopWatch = [System.Diagnostics.Stopwatch]::StartNew()
$PutUploadFile = Invoke-RestMethod -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $UploadFileApiURL -Body $TestMessage -Method Put -ContentType 'text/plain' -ErrorAction Stop
$StopWatch.Stop()
$bag.FileUploadDurationMS = Format-Number $StopWatch.Elapsed.TotalMilliseconds
$bag.TotalDurationMS = $bag.FileUploadDurationMS
$Message = "Successful attempt to upload file [$($TestFileName)] to $($NameSpace)."
$bag.Message = $Message
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
} Catch {
$Message = " Unable to upload file [$($TestFileName)] to $($NameSpace). See error data."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
$bag.Message = $Message
$bag.Result = 'FAILURE'
Output $bag -Tag 'UploadFileFailure'
Exit
}


# If successful file upload/write, proceed to perform additional tests
#region IFSuccessfulUpload
If ($PutUploadFile) {

# DOWNLOAD FILE
$Message = "Attempt to download file from WebURL: [$($PutUploadFile.webUrl)]..."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
###--- Download test file to watcher node---###
Try {
$DownloadLocation = (Join-Path $TempFolder $TestFileName)
$StopWatch = [System.Diagnostics.Stopwatch]::StartNew()
Invoke-webrequest -Uri $($PutUploadFile.'@microsoft.graph.downloadUrl') -OutFile $DownloadLocation -ErrorAction Stop
$StopWatch.Stop()
$bag.FileDownloadDurationMS = Format-Number $StopWatch.Elapsed.TotalMilliseconds
$bag.TotalDurationMS += $bag.FileDownloadDurationMS
$Message = " Successful attempt to download file from WebURL: [$($PutUploadFile.webUrl)]."
$bag.Message += " $Message"
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
}
Catch {
$Message = " Failed attempt to download file from WebURL: [$($PutUploadFile.webUrl)]. See error data."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
$bag.Result = 'FAILURE'
Output $bag -Tag 'DownloadFileFailure'
Exit
}

# DELETE FILE
$Message = "Attempt to delete file from WebURL: [$($PutUploadFile.webUrl)]..."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$FileURL = "$($ApiURL)/v1.0/me/drive/items/$($PutUploadFile.id)"
$DeleteFileResult = Invoke-RestMethod -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $FileURL -Method Delete -ContentType 'application/json' -ErrorAction Stop
$Message = " Successful attempt to delete file from Graph URL: [$($FileURL)]."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
}
Catch {
$Message += " Failed attempt to delete file from Graph URL: [$($FileURL)]. See error data."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
$bag.Result = 'FAILURE'
Output $bag -Tag 'DeleteTempfileOnlineFailure'
Exit
}
}
#endregion IFSuccessfulUpload

# CLEANUP TMP FILE
$Message = "Attempt to delete local temp file: [$($DownloadLocation)]..."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
Get-Item -Path $DownloadLocation | Remove-Item -Force -ErrorAction Stop
$Message = "Successful attempt to delete local temp file: [$($DownloadLocation)]..."
} Catch {
$Message = " Failed attempt to delete local temp file: [$($DownloadLocation)]. See error data."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
}

$bag.Message += " $Message"

Output $bag
LogIt -EventID 9991 -Type $info -Msg "Script End. Finished in [$($ScriptTimer.Elapsed.TotalSeconds)] seconds. `n" -LINE $(_LINE_)
</Script></ScriptBody>
<Parameters>
<Parameter>
<Name>ApiTokenScopeURL</Name>
<Value>$Config/ApiTokenScopeURL$</Value>
</Parameter>
<Parameter>
<Name>ApiTokenURL</Name>
<Value>$Config/ApiTokenURL$</Value>
</Parameter>
<Parameter>
<Name>ApiURL</Name>
<Value>$Config/ApiURL$</Value>
</Parameter>
<Parameter>
<Name>M365_AccountName</Name>
<Value>$Config/M365_AccountName$</Value>
</Parameter>
<Parameter>
<Name>M365_AccountPassword</Name>
<Value>$Config/M365_AccountPassword$</Value>
</Parameter>
<Parameter>
<Name>M365_ClientID</Name>
<Value>$Config/M365_ClientID$</Value>
</Parameter>
<Parameter>
<Name>M365_ClientSecret</Name>
<Value>$Config/M365_ClientSecret$</Value>
</Parameter>
<Parameter>
<Name>EventIDFilter</Name>
<Value>$Config/EventIDFilter$</Value>
</Parameter>
<Parameter>
<Name>PoshLibraryPath</Name>
<Value>$FileResource[Name='Res.M365SONE.M365Library.ps1.Resource']/Path$,$Config/PoshLibraryPath$</Value>
</Parameter>
<Parameter>
<Name>ScriptOutputType</Name>
<Value>Serialized</Value>
</Parameter>
<Parameter>
<Name>TenantName</Name>
<Value>$Config/TenantName$</Value>
</Parameter>
<Parameter>
<Name>TLSVersion</Name>
<Value>$Config/TLSVersion$</Value>
</Parameter>
<Parameter>
<Name>WorkflowName</Name>
<Value>M365SONE.OneDriveMon.Serial.PA_($Config/WorkflowName$)</Value>
</Parameter>
<Parameter>
<Name>WriteToEventLog</Name>
<Value>$Config/WriteToEventLog$</Value>
</Parameter>
</Parameters>
<TimeoutSeconds>$Config/ProbeActionTimeoutSeconds$</TimeoutSeconds>
</ProbeAction>
</MemberModules>
<Composition>
<Node ID="POSH"/>
</Composition>
</Composite>
</ModuleImplementation>
<!--<OutputType>System!System.PropertyBagData</OutputType>-->
<OutputType>Windows!Microsoft.Windows.SerializedObjectData</OutputType>
<InputType>System!System.BaseData</InputType>
</ProbeActionModuleType>