Modules/Providers/ProviderHelpers/CommandTracker.psm1
|
Import-Module -Name $PSScriptRoot/../ExportEXOProvider.psm1 -Function Get-CyberSpfRecord, Get-CyberDkimRecord, Get-CyberDmarcRecord Import-Module -Name $PSScriptRoot/../ExportAADProvider.psm1 -Function Get-PrivilegedRole, Get-PrivilegedUser Import-Module -Name $PSScriptRoot/AADRiskyPermissionsHelper.psm1 -Function Get-ApplicationsWithRiskyPermissions, Get-ServicePrincipalsWithRiskyPermissions, Format-RiskyApplications, Format-RiskyThirdPartyServicePrincipals Import-Module -Name $PSScriptRoot/../../Utility/Utility.psm1 -Function Invoke-GraphDirectly, ConvertFrom-GraphHashtable class CommandTracker { [string[]]$SuccessfulCommands = @() [string[]]$UnSuccessfulCommands = @() [System.Object[]] TryCommand([string]$Command, [hashtable]$CommandArgs, [bool]$SuppressWarning = $false) { <# .Description Wraps the given Command inside a try/catch, run with the provided arguments, and tracks successes/failures. Unless otherwise specified, ErrorAction defaults to "Stop" .Functionality Internal #> if (-Not $CommandArgs.ContainsKey("ErrorAction")) { $CommandArgs.ErrorAction = "Stop" } $isGraphDirect = $false $Result = @() # Pre-process command arguments if ($CommandArgs.ContainsKey("GraphDirect")) { # Check if GraphDirect is set to true, if so set $isGraphDirect to true and remove the key. This will make a Graph API call using Invoke-GraphDirectly $isGraphDirect = $CommandArgs['GraphDirect'] -eq $true $CommandArgs.Remove("GraphDirect") # Remove GraphDirect as it is not needed for the command, its just a flag to indicate we want to use the Graph API directly if (-not $isGraphDirect) { # For standard PowerShell commands, remove M365Environment if present $CommandArgs.Remove("M365Environment") } } try { if ($isGraphDirect) { # This will pull the Graph API vice the PowerShell module Write-Verbose "Running $($Command) API Call" $ModCommand = Invoke-GraphDirectly -Commandlet $Command @CommandArgs $Result = $ModCommand # Check if $Result.value exists, if it does, return it if not return just $Result if ($Result.value) { $Result = $Result.value } } else { Write-Verbose "Running $($Command) with arguments: $($CommandArgs)" $Result = & $Command @CommandArgs } $this.SuccessfulCommands += $Command } catch { if (-not $SuppressWarning) { Write-Warning "Error running $($Command): $($_.Exception.Message)`n$($_.ScriptStackTrace)" } $this.UnSuccessfulCommands += $Command $Result = @() } return $Result } [System.Object[]] TryCommand([string]$Command, [hashtable]$CommandArgs) { <# .Description Wraps the given Command inside a try/catch, run with the provided arguments, and tracks successes/failures. SuppressWarning defaults to false. .Functionality Internal #> return $this.TryCommand($Command, $CommandArgs, $false) } [System.Object[]] TryCommand([string]$Command) { <# .Description Wraps the given Command inside a try/catch and tracks successes/ failures. No command arguments are specified beyond ErrorAction=Stop .Functionality Internal #> return $this.TryCommand($Command, @{}, $false) } [void] AddSuccessfulCommand([string]$Command) { $this.SuccessfulCommands += $Command } [void] AddUnSuccessfulCommand([string]$Command) { $this.UnSuccessfulCommands += $Command } [string[]] GetUnSuccessfulCommands() { return $this.UnSuccessfulCommands } [string[]] GetSuccessfulCommands() { return $this.SuccessfulCommands } } function Get-CommandTracker { [CommandTracker]::New() } |