Testing/Unit/PowerShell/Orchestrator/Invoke-CyberCached.Tests.ps1
|
$OrchestratorPath = '../../../../Modules/Orchestrator.psm1' Import-Module (Join-Path -Path $PSScriptRoot -ChildPath $OrchestratorPath) -Function 'Invoke-CyberAssessmentCached' -Force InModuleScope Orchestrator { Describe -Tag 'Orchestrator' -Name 'Invoke-CyberAssessmentCached' { BeforeAll { Mock -ModuleName Orchestrator Remove-Resources {} Mock -ModuleName Orchestrator Import-Resources {} function Invoke-Connection {} Mock -ModuleName Orchestrator Invoke-Connection { @() } function Get-TenantDetail {} Mock -ModuleName Orchestrator Get-TenantDetail { '{"DisplayName": "displayName"}' } function Invoke-ProviderList {} Mock -ModuleName Orchestrator Invoke-ProviderList {} function Invoke-RunRego {} Mock -ModuleName Orchestrator Invoke-RunRego {} function Invoke-ReportCreation {} Mock -ModuleName Orchestrator Invoke-ReportCreation {} function Merge-JsonOutput {throw 'this will be mocked'} Mock -ModuleName Orchestrator Merge-JsonOutput {} function Disconnect-CyberAssessmentTenant {} Mock -ModuleName Orchestrator Disconnect-CyberAssessmentTenant function ConvertTo-ResultsCsv {throw 'this will be mocked'} Mock -ModuleName Orchestrator ConvertTo-ResultsCsv {} function Set-Utf8NoBom {} Mock -ModuleName Orchestrator Set-Utf8NoBom Mock -CommandName Write-Debug {} Mock -CommandName New-Item {} Mock -CommandName Get-Content { "" } Mock -CommandName Get-Member { $true } Mock -CommandName New-Guid { "00000000-0000-0000-0000-000000000000" } Mock -CommandName Get-ChildItem { [pscustomobject]@{"FullName"="CyberResults.json"; "CreationTime"=[DateTime]"2024-01-01"} } Mock -CommandName Remove-Item {} Mock -CommandName ConvertFrom-Json { [PSCustomObject]@{"report_uuid"="00000000-0000-0000-0000-000000000000"} } } Context 'When checking the conformance of commercial tenants' { BeforeAll { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'SplatParams')] $SplatParams = @{ M365Environment = 'commercial' } } It 'Given -ProductNames aad should not throw' { $SplatParams += @{ ProductNames = @("aad") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames defender should not throw' { $SplatParams += @{ ProductNames = @("defender") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames exo should not throw' { $SplatParams += @{ ProductNames = @("exo") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames powerplatform should not throw' { $SplatParams += @{ ProductNames = @("powerplatform") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames teams should not throw' { $SplatParams += @{ ProductNames = @("teams") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames * should not throw' { $SplatParams += @{ ProductNames = @("*") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } } Context 'When omitting the export of the commercial tenant provider json' { BeforeAll { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', 'SplatParams')] $SplatParams = @{ M365Environment = 'commercial' ExportProvider = $false } } It 'Given -ProductNames aad should not throw' { $SplatParams += @{ ProductNames = @("aad") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames defender should not throw' { $SplatParams += @{ ProductNames = @("defender") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames exo should not throw' { $SplatParams += @{ ProductNames = @("exo") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames powerplatform should not throw' { $SplatParams += @{ ProductNames = @("powerplatform") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames teams should not throw' { $SplatParams += @{ ProductNames = @("teams") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -ProductNames * should not throw' { $SplatParams += @{ ProductNames = @("*") } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given an existing UUID should not generate a new one' { # Get-Member was mocked above to return True so as far as the # provider can tell, the existing output already has a UUID {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw Should -Invoke -CommandName New-Guid -Exactly -Times 0 } It 'Given output without a UUID should generate a new one' { Mock -CommandName ConvertFrom-Json { [PSCustomObject]@{} } Mock -CommandName Get-Member { $false } # Now Get-Member will return False so as far as the provider # can tell, the existing output does not have a UUID {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw Should -Invoke -CommandName New-Guid -Exactly -Times 1 } } Context 'When checking module version' { It 'Given -Version should not throw' { {Invoke-CyberAssessmentCached -Version} | Should -Not -Throw } } Context 'When modifying the CSV output files names' { It 'Given -OutCsvFileName should not throw' { $SplatParams += @{ OutCsvFileName = "a" } {Invoke-CyberAssessmentCached -Version} | Should -Not -Throw } It 'Given -OutActionPlanFileName should not throw' { $SplatParams += @{ OutActionPlanFileName = "a" } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given both -OutCsvFileName and -OutActionPlanFileName should not throw' { $SplatParams += @{ OutCsvFileName = "a" OutActionPlanFileName = "b" } {Invoke-CyberAssessmentCached @SplatParams} | Should -Not -Throw } It 'Given -OutCsvFileName and -OutActionPlanFileName equal should throw' { $SplatParams += @{ OutCsvFileName = "a" OutActionPlanFileName = "a" } {Invoke-CyberAssessmentCached @SplatParams} | Should -Throw } } Context "When there are multiple CyberResults*.json files" { # It's possible (but not expected) that there are multiple files matching # "CyberResults*.json". In this case, CyberAssessment should choose the file # created most recently. It 'Should select the most recently created' { Mock -CommandName Get-ChildItem { @( [pscustomobject]@{"FullName"="CyberResultsOld.json"; "CreationTime"=[DateTime]"2023-01-01"}, [pscustomobject]@{"FullName"="CyberResultsNew.json"; "CreationTime"=[DateTime]"2024-01-01"}, [pscustomobject]@{"FullName"="CyberResultsOldest.json"; "CreationTime"=[DateTime]"2022-01-01"} ) } Mock -CommandName Get-Content { if ($Path -ne "CyberResultsNew.json") { # Should be the new one, throw if not throw } } {Invoke-CyberAssessmentCached @SplatParams} | Should -Throw } } } } AfterAll { Remove-Module Orchestrator -ErrorAction SilentlyContinue } |