Private/InvestigationConnectionHelpers.ps1
|
function Import-NSPInvestigationDependency { # Installed modules only. The fallback discovers the WindowsPowerShell installation in PS7. param([Parameter(Mandatory)][string]$Name, [version]$MinimumVersion = '0.0') $loaded = @(Get-Module -Name $Name | Where-Object Version -ge $MinimumVersion) if ($loaded.Count) { return } $available = @(Get-Module -ListAvailable -Name $Name | Where-Object Version -ge $MinimumVersion) if (-not $available.Count -and $env:ProgramFiles) { $base = Join-Path $env:ProgramFiles ('WindowsPowerShell/Modules/' + $Name) if (Test-Path -LiteralPath $base) { $available = @(Get-ChildItem -LiteralPath $base -Filter ($Name + '.psd1') -Recurse -File | ForEach-Object { Get-Module -ListAvailable -Name $_.FullName } | Where-Object Version -ge $MinimumVersion) } } $chosen = $available | Sort-Object Version -Descending | Select-Object -First 1 if (-not $chosen) { throw "$Name $MinimumVersion or later is not installed. No installation was attempted." } Import-Module $chosen.Path -Global -ErrorAction Stop } function Get-NSPInvestigationExchangeConnection { param([Parameter(Mandatory)][guid]$TenantId, [string]$ConnectionId) if (-not (Get-Command Get-ConnectionInformation -ErrorAction SilentlyContinue)) { throw 'No Exchange REST connection information is available.' } $all = @(Get-ConnectionInformation -ErrorAction Stop) $candidates = @($all | Where-Object { $_.State -eq 'Connected' -and -not $_.IsEopSession -and [string]$_.TenantID -eq $TenantId.ToString() -and (-not $ConnectionId -or [string]$_.ConnectionId -eq $ConnectionId) }) if ($candidates.Count -ne 1) { throw 'Exchange connection selection is missing or ambiguous for TenantId. Supply a unique ConnectionId.' } $selected = $candidates[0] if (-not $selected.ConnectionId -or -not $selected.ModuleName) { throw 'Exchange connection lacks its command-module identity.' } if ($selected.TokenStatus -and $selected.TokenStatus -ne 'Active') { throw 'Selected Exchange token is not active.' } if (@($all | Where-Object { $_.State -eq 'Connected' -and [string]$_.ModulePrefix -eq [string]$selected.ModulePrefix }).Count -ne 1) { throw 'Exchange command prefix is shared by multiple connections. Use a unique prefix in a separate connection.' } $selected } function Get-NSPInvestigationExchangeCommand { param([Parameter(Mandatory)]$Connection, [Parameter(Mandatory)][string]$CommandName) $parts = $CommandName -split '-', 2 $name = $parts[0] + '-' + [string]$Connection.ModulePrefix + $parts[1] $identity = [string]$Connection.ModuleName $leaf = [IO.Path]::GetFileNameWithoutExtension($identity.TrimEnd([char[]]'\/')) $modules = @(Get-Module | Where-Object { $_.Name -eq $identity -or $_.Name -eq $leaf -or $_.ModuleBase -eq $identity -or $_.Path -eq $identity }) if ($modules.Count -ne 1) { throw 'Selected Exchange command module is missing or ambiguous.' } $command = $modules[0].ExportedCommands[$name] if (-not $command) { throw "Selected Exchange connection does not export $name. No fallback to another session is permitted." } $command } |