From e6da6d9d4786420bb889ef4d17345f56484fc5cb Mon Sep 17 00:00:00 2001 From: DrIOS <58635327+DrIOSX@users.noreply.github.com> Date: Sat, 8 Jun 2024 20:42:38 -0500 Subject: [PATCH] fix: whatif --- CHANGELOG.md | 6 +++ helpers/Build-Help.ps1 | 2 +- source/Private/Get-UniqueConnection.ps1 | 28 +++++++++++ source/Public/Invoke-M365SecurityAudit.ps1 | 50 ++++++++++++------- .../Private/Get-UniqueConnection.tests.ps1 | 27 ++++++++++ 5 files changed, 94 insertions(+), 19 deletions(-) create mode 100644 source/Private/Get-UniqueConnection.ps1 create mode 100644 tests/Unit/Private/Get-UniqueConnection.tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 924569f..4efc630 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ The format is based on and uses the types of changes according to [Keep a Change ## [Unreleased] +### Fixed + +- Whatif support for `Invoke-M365SecurityAudit`. + +## [0.1.7] - 2024-06-08 + ### Added - Added pipeline support to `Sync-CISExcelAndCsvData` function for `[CISAuditResult[]]` input. diff --git a/helpers/Build-Help.ps1 b/helpers/Build-Help.ps1 index 3cda1d0..4b00ef4 100644 --- a/helpers/Build-Help.ps1 +++ b/helpers/Build-Help.ps1 @@ -4,7 +4,7 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1 <# - $ver = "v0.1.6" + $ver = "v0.1.7" git checkout main git pull origin main git tag -a $ver -m "Release version $ver refactor Update" diff --git a/source/Private/Get-UniqueConnection.ps1 b/source/Private/Get-UniqueConnection.ps1 new file mode 100644 index 0000000..a05f282 --- /dev/null +++ b/source/Private/Get-UniqueConnection.ps1 @@ -0,0 +1,28 @@ +function Get-UniqueConnection { + [CmdletBinding()] + [OutputType([string[]])] + param ( + [Parameter(Mandatory = $true)] + [string[]]$Connections + ) + + $uniqueConnections = @() + + if ($Connections -contains "AzureAD" -or $Connections -contains "AzureAD | EXO" -or $Connections -contains "AzureAD | EXO | Microsoft Graph") { + $uniqueConnections += "AzureAD" + } + if ($Connections -contains "Microsoft Graph" -or $Connections -contains "AzureAD | EXO | Microsoft Graph") { + $uniqueConnections += "Microsoft Graph" + } + if ($Connections -contains "EXO" -or $Connections -contains "AzureAD | EXO" -or $Connections -contains "Microsoft Teams | EXO" -or $Connections -contains "AzureAD | EXO | Microsoft Graph") { + $uniqueConnections += "EXO" + } + if ($Connections -contains "SPO") { + $uniqueConnections += "SPO" + } + if ($Connections -contains "Microsoft Teams" -or $Connections -contains "Microsoft Teams | EXO") { + $uniqueConnections += "Microsoft Teams" + } + + return $uniqueConnections | Sort-Object -Unique +} diff --git a/source/Public/Invoke-M365SecurityAudit.ps1 b/source/Public/Invoke-M365SecurityAudit.ps1 index abdaa72..e3db882 100644 --- a/source/Public/Invoke-M365SecurityAudit.ps1 +++ b/source/Public/Invoke-M365SecurityAudit.ps1 @@ -150,12 +150,12 @@ function Invoke-M365SecurityAudit { [Parameter(Mandatory = $true, ParameterSetName = 'RecFilter')] [ValidateSet( '1.1.1', '1.1.3', '1.2.1', '1.2.2', '1.3.1', '1.3.3', '1.3.6', '2.1.1', '2.1.2', ` - '2.1.3', '2.1.4', '2.1.5', '2.1.6', '2.1.7', '2.1.9', '3.1.1', '5.1.2.3', ` - '5.1.8.1', '6.1.1', '6.1.2', '6.1.3', '6.2.1', '6.2.2', '6.2.3', '6.3.1', ` - '6.5.1', '6.5.2', '6.5.3', '7.2.1', '7.2.10', '7.2.2', '7.2.3', '7.2.4', ` - '7.2.5', '7.2.6', '7.2.7', '7.2.9', '7.3.1', '7.3.2', '7.3.4', '8.1.1', ` - '8.1.2', '8.2.1', '8.5.1', '8.5.2', '8.5.3', '8.5.4', '8.5.5', '8.5.6', ` - '8.5.7', '8.6.1' + '2.1.3', '2.1.4', '2.1.5', '2.1.6', '2.1.7', '2.1.9', '3.1.1', '5.1.2.3', ` + '5.1.8.1', '6.1.1', '6.1.2', '6.1.3', '6.2.1', '6.2.2', '6.2.3', '6.3.1', ` + '6.5.1', '6.5.2', '6.5.3', '7.2.1', '7.2.10', '7.2.2', '7.2.3', '7.2.4', ` + '7.2.5', '7.2.6', '7.2.7', '7.2.9', '7.3.1', '7.3.2', '7.3.4', '8.1.1', ` + '8.1.2', '8.2.1', '8.5.1', '8.5.2', '8.5.3', '8.5.4', '8.5.5', '8.5.6', ` + '8.5.7', '8.6.1' )] [string[]]$IncludeRecommendation, @@ -163,12 +163,12 @@ function Invoke-M365SecurityAudit { [Parameter(Mandatory = $true, ParameterSetName = 'SkipRecFilter')] [ValidateSet( '1.1.1', '1.1.3', '1.2.1', '1.2.2', '1.3.1', '1.3.3', '1.3.6', '2.1.1', '2.1.2', ` - '2.1.3', '2.1.4', '2.1.5', '2.1.6', '2.1.7', '2.1.9', '3.1.1', '5.1.2.3', ` - '5.1.8.1', '6.1.1', '6.1.2', '6.1.3', '6.2.1', '6.2.2', '6.2.3', '6.3.1', ` - '6.5.1', '6.5.2', '6.5.3', '7.2.1', '7.2.10', '7.2.2', '7.2.3', '7.2.4', ` - '7.2.5', '7.2.6', '7.2.7', '7.2.9', '7.3.1', '7.3.2', '7.3.4', '8.1.1', ` - '8.1.2', '8.2.1', '8.5.1', '8.5.2', '8.5.3', '8.5.4', '8.5.5', '8.5.6', ` - '8.5.7', '8.6.1' + '2.1.3', '2.1.4', '2.1.5', '2.1.6', '2.1.7', '2.1.9', '3.1.1', '5.1.2.3', ` + '5.1.8.1', '6.1.1', '6.1.2', '6.1.3', '6.2.1', '6.2.2', '6.2.3', '6.3.1', ` + '6.5.1', '6.5.2', '6.5.3', '7.2.1', '7.2.10', '7.2.2', '7.2.3', '7.2.4', ` + '7.2.5', '7.2.6', '7.2.7', '7.2.9', '7.3.1', '7.3.2', '7.3.4', '8.1.1', ` + '8.1.2', '8.2.1', '8.5.1', '8.5.2', '8.5.3', '8.5.4', '8.5.5', '8.5.6', ` + '8.5.7', '8.6.1' )] [string[]]$SkipRecommendation, @@ -183,8 +183,19 @@ function Invoke-M365SecurityAudit { $script:MaximumFunctionCount = 8192 } # Ensure required modules are installed - if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Check for required modules", "Check")) { - $requiredModules = Get-RequiredModule -AuditFunction + $requiredModules = Get-RequiredModule -AuditFunction + $requiredModulesFormatted = "" + foreach ($module in $requiredModules) { + if ($module.SubModuleName) { + $requiredModulesFormatted += "$($module.ModuleName) - SubModule: $($module.SubModuleName), " + } + else { + $requiredModulesFormatted += "$($module.ModuleName), " + } + } + $requiredModulesFormatted = $requiredModulesFormatted.TrimEnd(", ") + + if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Check for required modules: $requiredModulesFormatted", "Check")) { foreach ($module in $requiredModules) { Assert-ModuleAvailability -ModuleName $module.ModuleName -RequiredVersion $module.RequiredVersion -SubModuleName $module.SubModuleName } @@ -207,7 +218,7 @@ function Invoke-M365SecurityAudit { $testDefinitions = Get-TestDefinitionsObject @params # Extract unique connections needed $requiredConnections = $testDefinitions.Connection | Sort-Object -Unique - if ($requiredConnections -contains 'SPO'){ + if ($requiredConnections -contains 'SPO') { if (-not $TenantAdminUrl) { $requiredConnections = $requiredConnections | Where-Object { $_ -ne 'SPO' } $testDefinitions = $testDefinitions | Where-Object { $_.Connection -ne 'SPO' } @@ -235,10 +246,13 @@ function Invoke-M365SecurityAudit { $currentTestIndex = 0 # Establishing connections if required - if (!($DoNotConnect) -and $PSCmdlet.ShouldProcess("Establish connections to Microsoft 365 services", "Connect")) { + $actualUniqueConnections = Get-UniqueConnection -Connections $requiredConnections + if (!($DoNotConnect) -and $PSCmdlet.ShouldProcess("Establish connections to Microsoft 365 services: $($actualUniqueConnections -join ', ')", "Connect")) { Connect-M365Suite -TenantAdminUrl $TenantAdminUrl -RequiredConnections $requiredConnections } + + # Import the test functions $testFiles | ForEach-Object { $currentTestIndex++ @@ -269,11 +283,11 @@ function Invoke-M365SecurityAudit { } End { - if (!($DoNotDisconnect) -and $PSCmdlet.ShouldProcess("Disconnect from Microsoft 365 services", "Disconnect")) { + if (!($DoNotDisconnect) -and $PSCmdlet.ShouldProcess("Disconnect from Microsoft 365 services: $($actualUniqueConnections -join ', ')", "Disconnect")) { # Clean up sessions Disconnect-M365Suite -RequiredConnections $requiredConnections } - if ($PSCmdlet.ShouldProcess("Measure and display audit results", "Measure")) { + if ($PSCmdlet.ShouldProcess("Measure and display audit results for $($totalTests) tests", "Measure")) { # Call the private function to calculate and display results Measure-AuditResult -AllAuditResults $allAuditResults -FailedTests $script:FailedTests # Return all collected audit results diff --git a/tests/Unit/Private/Get-UniqueConnection.tests.ps1 b/tests/Unit/Private/Get-UniqueConnection.tests.ps1 new file mode 100644 index 0000000..4a2aa69 --- /dev/null +++ b/tests/Unit/Private/Get-UniqueConnection.tests.ps1 @@ -0,0 +1,27 @@ +$ProjectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$ProjectName = ((Get-ChildItem -Path $ProjectPath\*\*.psd1).Where{ + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try { Test-ModuleManifest $_.FullName -ErrorAction Stop } catch { $false } ) + }).BaseName + + +Import-Module $ProjectName + +InModuleScope $ProjectName { + Describe Get-PrivateFunction { + Context 'Default' { + BeforeEach { + $return = Get-PrivateFunction -PrivateData 'string' + } + + It 'Returns a single object' { + ($return | Measure-Object).Count | Should -Be 1 + } + + It 'Returns a string based on the parameter PrivateData' { + $return | Should -Be 'string' + } + } + } +} +