M365SSPO.SharePointMon.Serial.PA

M365SSPO.SharePointMon.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$
WorkflowNamestring$Config/WorkflowName$
WriteToEventLogbool$Config/WriteToEventLog$

Source Code:

<ProbeActionModuleType ID="M365SSPO.SharePointMon.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="SiteDisplayName" type="xsd:string"/>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" minOccurs="1" name="SiteID" type="xsd:string"/>
<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="WorkflowName" Selector="$Config/WorkflowName$" ParameterType="string"/>
<OverrideableParameter ID="WriteToEventLog" Selector="$Config/WriteToEventLog$" ParameterType="bool"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<ProbeAction ID="POSH" TypeID="Windows!Microsoft.Windows.PowerShellProbe">
<ScriptName>M365SSPO.SharePointMon.ps1</ScriptName>
<ScriptBody><Script>&lt;#
#===============================================================================================================================================================
Created by: Tyson Paul, Taylour Blackwell
Filename: M365SSPO.SharePointMon.ps1
Description: This will upload and download test files to verify SharePoint functionality/access.

Version History:
2020.11.19.0058 - Added API Url params
2020.10.15.1751 - v1.

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

===============================================================================================================================================================
#&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',

[string]$SiteDisplayName,

[string]$SiteID,

# 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 = 'M365SSPO.SharePointMon.ps1'
$NameSpace = 'SharePoint'
[bool]$WriteToEventLog = [System.Convert]::ToBoolean($WriteToEventLog)
$Testing = $false

######################### FUNCTIONS ############################
################################################################
Function Load-Library {
Param (
[string]$PoshLibraryPath
)
$ErrorActionPreference = 'STOP'
If ($PoshLibraryPath ){
ForEach ($Path in $PoshLibraryPath.Split(',') ){
Try {
If (($Path.Length) -AND ($Path -notmatch '^-1$')) {
. $Path
}
} Catch {
Write-Host "Line [$($MyInvocation.ScriptLineNumber )]: Error loading PoshLibrary at path:[$($Path)]. This is likely to cause many other dependent functions to fail. `n`nError data: $($_)`n`n"
}
}
}
$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()
}

$TestFolder = "C:\Test\M365SMP_Dev\$($NameSpace)\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',"FAILURE") #default, unless any one of the tests fails
$bag.AddValue('DisplayName',"&lt;no data&gt;")
$bag.AddValue('Name',"&lt;no data&gt;")
$bag.AddValue('ID',"&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
LogIt -EventID 9992 -Type $info -Msg "Decode password..." -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$M365_AccountPassword_DECRYPTED = Decode-UserData -Data $M365_AccountPassword
} Catch {
$Message = " Unable to decode password. Error: $($Error[0] | Out-String -Stream)"
LogIt -EventID 9995 -Type $warn -Msg $Message -Proceed $true -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
}

# Decode Client Secret
LogIt -EventID 9992 -Type $info -Msg "Decode ClientSecret..." -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$M365_ClientSecret_DECRYPTED = Decode-UserData -Data $M365_ClientSecret
} Catch {
$Message = " Unable to decode ClientSecret. Error: $($Error[0] | Out-String -Stream)"
LogIt -EventID 9995 -Type $warn -Msg $Message -Proceed $true -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
}

# Get Access Token
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 retrieve Access Token. Error: $($Error[0] | Out-String -Stream)"
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
Output $bag -Tag 'TokenFailure'
Exit
}


#------------------#------------------#------------------#------------------
# Retrieve object(s)
LogIt -EventID 9992 -Type $info -Msg "Retrieve object(s)" -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$URL = "$($ApiURL)/v1.0/sites?search='$SiteDisplayName'"
[array]$thisObject = Invoke-RestMethod -Headers @{Authorization = "Bearer $($TokenResponse.access_token)"} -Uri $URL -Method Get -ContentType 'application/json' -ErrorAction Stop
[array]$Object = $thisObject.Value | Where-Object { ($_.Id -eq $SiteID) }

If (-NOT $Object) {throw}

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

$bag.ID = "$($Object.ID)"
$bag.Name = "$($Object.Name)"
$bag.DisplayName = "$($Object.DisplayName)"
$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: [$($URL)]. Error: $($Error[0] | Out-String -Stream)"
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $true -LINE $(_LINE_); $Error.Clear()
$bag.Message += " $Message"
Output $bag -Tag 'GetObjectFailure'
Exit
}

# Proceed to file transfer test
$TestID = (Get-Date -format MMddyyyyhhmmss) + "-" + "$($ThisScriptInstanceGUID)"
$TestFileName = 'TestDoc-' + "$($env:computername).$($env:USERDNSDOMAIN)" + '-' + $TestID + '.tmp'

# UPLOAD
$UploadFileApiURL = "$($ApiURL)/v1.0/sites/$($Object.ID)/drive/items/root:/$($TestFileName):/content"
$Message = "Attempt to upload file [$($TestFileName)] to $($NameSpace) URL: [$($UploadFileApiURL)] ..."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$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
$bag.Result = 'SUCCESS'
$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). Error: $($Error[0] | Out-String -Stream)"
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
$bag.Message = $Message
$bag.Result = 'FAILURE'
}

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

# DOWNLOAD FILE
$DownloadLocation = (Join-Path $TempFolder $TestFileName)
$Message = "Attempt to download file from WebURL: [$($PutUploadFile.webUrl)] to local path: [$($DownloadLocation)] ..."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$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)]."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
}
Catch {
$Message = " Failed attempt to download file from WebURL: [$($PutUploadFile.webUrl)]. Error: $($Error[0] | Out-String -Stream)"
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
$bag.Result = 'FAILURE'
}

$bag.Message += " $Message"

# DELETE FILE
$FileURL = "$($ApiURL)/v1.0/Sites/$($Object.Id)/drive/items/$($PutUploadFile.Id)"
$Message = "Attempt to delete file at: [$($FileURL)]..."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
Try {
$DeleteFileResult = Invoke-RestMethod -Headers @{Authorization = "Bearer $($Tokenresponse.access_token)"} -Uri $FileURL -Method Delete -ContentType 'application/json' -ErrorAction Stop
$Message = " Successful attempt to delete file at: [$($FileURL)]."
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
}
Catch {
$Message += " Failed attempt to delete file at: [$($FileURL)]. Error: $($Error[0] | Out-String -Stream)"
LogIt -EventID 9992 -Type $info -Msg $Message -Proceed $WriteToEventLog -LINE $(_LINE_); $Error.Clear()
$bag.Result = 'FAILURE'
}

$bag.Message += " $Message"
}
#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 = " Notice: Failed attempt to delete local temp file: [$($DownloadLocation)]. Error: $($Error[0] | Out-String -Stream)"
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.M365SSPO.M365Library.ps1.Resource']/Path$,$Config/PoshLibraryPath$</Value>
</Parameter>
<Parameter>
<Name>ScriptOutputType</Name>
<Value>Serialized</Value>
</Parameter>
<Parameter>
<Name>SiteDisplayName</Name>
<Value>$Config/SiteDisplayName$</Value>
</Parameter>
<Parameter>
<Name>SiteID</Name>
<Value>$Config/SiteID$</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>M365SSPO.SharePointMon.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>