3 Commits

Author SHA1 Message Date
Doug Rios
7309925e89 Merge pull request #136 from CriticalSolutionsNetwork/135-add-parameter-validation-to-new-parameters
135 add parameter validation to new parameters
2024-06-30 12:55:10 -05:00
DrIOS
5637855c8b docs: Update CHANGELOG 2024-06-30 12:53:21 -05:00
DrIOS
ac98307ed1 fix: parameter validation for new parameters in Invoke-M365SecurityAudit function 2024-06-30 12:53:07 -05:00
2 changed files with 8 additions and 29 deletions

View File

@@ -4,6 +4,12 @@ The format is based on and uses the types of changes according to [Keep a Change
## [Unreleased] ## [Unreleased]
### Fixed
- Fixed parameter validation for new parameters in `Invoke-M365SecurityAudit` function.
## [0.1.19] - 2024-06-30
### Added ### Added
- Added `ApprovedCloudStorageProviders` parameter to `Invoke-M365SecurityAudit` to allow for testing of approved cloud storage providers for 8.1.1. - Added `ApprovedCloudStorageProviders` parameter to `Invoke-M365SecurityAudit` to allow for testing of approved cloud storage providers for 8.1.1.

View File

@@ -132,30 +132,23 @@ function Invoke-M365SecurityAudit {
[Parameter(Mandatory = $false, HelpMessage = "The SharePoint tenant admin URL, which should end with '-admin.sharepoint.com'. If not specified none of the Sharepoint Online tests will run.")] [Parameter(Mandatory = $false, HelpMessage = "The SharePoint tenant admin URL, which should end with '-admin.sharepoint.com'. If not specified none of the Sharepoint Online tests will run.")]
[ValidatePattern('^https://[a-zA-Z0-9-]+-admin\.sharepoint\.com$')] [ValidatePattern('^https://[a-zA-Z0-9-]+-admin\.sharepoint\.com$')]
[string]$TenantAdminUrl, [string]$TenantAdminUrl,
[Parameter(Mandatory = $false, HelpMessage = "Specify this to test only the default domain for password expiration and DKIM Config for tests '1.3.1' and 2.1.9. The domain name of your organization, e.g., 'example.com'.")] [Parameter(Mandatory = $false, HelpMessage = "Specify this to test only the default domain for password expiration and DKIM Config for tests '1.3.1' and 2.1.9. The domain name of your organization, e.g., 'example.com'.")]
[ValidatePattern('^[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$')] [ValidatePattern('^[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$')]
[string]$DomainName, [string]$DomainName,
# E-Level with optional ProfileLevel selection # E-Level with optional ProfileLevel selection
[Parameter(Mandatory = $true, ParameterSetName = 'ELevelFilter', HelpMessage = "Specifies the E-Level (E3 or E5) for the audit.")] [Parameter(Mandatory = $true, ParameterSetName = 'ELevelFilter', HelpMessage = "Specifies the E-Level (E3 or E5) for the audit.")]
[ValidateSet('E3', 'E5')] [ValidateSet('E3', 'E5')]
[string]$ELevel, [string]$ELevel,
[Parameter(Mandatory = $true, ParameterSetName = 'ELevelFilter', HelpMessage = "Specifies the profile level (L1 or L2) for the audit.")] [Parameter(Mandatory = $true, ParameterSetName = 'ELevelFilter', HelpMessage = "Specifies the profile level (L1 or L2) for the audit.")]
[ValidateSet('L1', 'L2')] [ValidateSet('L1', 'L2')]
[string]$ProfileLevel, [string]$ProfileLevel,
# IG Filters, one at a time # IG Filters, one at a time
[Parameter(Mandatory = $true, ParameterSetName = 'IG1Filter', HelpMessage = "Includes tests where IG1 is true.")] [Parameter(Mandatory = $true, ParameterSetName = 'IG1Filter', HelpMessage = "Includes tests where IG1 is true.")]
[switch]$IncludeIG1, [switch]$IncludeIG1,
[Parameter(Mandatory = $true, ParameterSetName = 'IG2Filter', HelpMessage = "Includes tests where IG2 is true.")] [Parameter(Mandatory = $true, ParameterSetName = 'IG2Filter', HelpMessage = "Includes tests where IG2 is true.")]
[switch]$IncludeIG2, [switch]$IncludeIG2,
[Parameter(Mandatory = $true, ParameterSetName = 'IG3Filter', HelpMessage = "Includes tests where IG3 is true.")] [Parameter(Mandatory = $true, ParameterSetName = 'IG3Filter', HelpMessage = "Includes tests where IG3 is true.")]
[switch]$IncludeIG3, [switch]$IncludeIG3,
# Inclusion of specific recommendation numbers # Inclusion of specific recommendation numbers
[Parameter(Mandatory = $true, ParameterSetName = 'RecFilter', HelpMessage = "Specifies specific recommendations to include in the audit. Accepts an array of recommendation numbers.")] [Parameter(Mandatory = $true, ParameterSetName = 'RecFilter', HelpMessage = "Specifies specific recommendations to include in the audit. Accepts an array of recommendation numbers.")]
[ValidateSet( [ValidateSet(
@@ -168,7 +161,6 @@ function Invoke-M365SecurityAudit {
'8.5.7', '8.6.1' '8.5.7', '8.6.1'
)] )]
[string[]]$IncludeRecommendation, [string[]]$IncludeRecommendation,
# Exclusion of specific recommendation numbers # Exclusion of specific recommendation numbers
[Parameter(Mandatory = $true, ParameterSetName = 'SkipRecFilter', HelpMessage = "Specifies specific recommendations to exclude from the audit. Accepts an array of recommendation numbers.")] [Parameter(Mandatory = $true, ParameterSetName = 'SkipRecFilter', HelpMessage = "Specifies specific recommendations to exclude from the audit. Accepts an array of recommendation numbers.")]
[ValidateSet( [ValidateSet(
@@ -181,26 +173,21 @@ function Invoke-M365SecurityAudit {
'8.5.7', '8.6.1' '8.5.7', '8.6.1'
)] )]
[string[]]$SkipRecommendation, [string[]]$SkipRecommendation,
# Common parameters for all parameter sets # Common parameters for all parameter sets
[Parameter(Mandatory = $false, HelpMessage = "Specifies the approved cloud storage providers for the audit. Accepts an array of cloud storage provider names.")] [Parameter(Mandatory = $false, HelpMessage = "Specifies the approved cloud storage providers for the audit. Accepts an array of cloud storage provider names.")]
[ValidateSet( [ValidateSet(
'GoogleDrive', 'ShareFile', 'Box', 'DropBox', 'Egnyte' 'GoogleDrive', 'ShareFile', 'Box', 'DropBox', 'Egnyte'
)] )]
[string[]]$ApprovedCloudStorageProviders = @(), [string[]]$ApprovedCloudStorageProviders = @(),
[Parameter(Mandatory = $false, HelpMessage = "Specifies the approved federated domains for the audit test 8.2.1. Accepts an array of allowed domain names.")] [Parameter(Mandatory = $false, HelpMessage = "Specifies the approved federated domains for the audit test 8.2.1. Accepts an array of allowed domain names.")]
[ValidatePattern('^[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$')]
[string[]]$ApprovedFederatedDomains, [string[]]$ApprovedFederatedDomains,
[Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not establish a connection to Microsoft 365 services.")] [Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not establish a connection to Microsoft 365 services.")]
[switch]$DoNotConnect, [switch]$DoNotConnect,
[Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not disconnect from Microsoft 365 services after execution.")] [Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not disconnect from Microsoft 365 services after execution.")]
[switch]$DoNotDisconnect, [switch]$DoNotDisconnect,
[Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not check for the presence of required modules.")] [Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not check for the presence of required modules.")]
[switch]$NoModuleCheck, [switch]$NoModuleCheck,
[Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them.")] [Parameter(Mandatory = $false, HelpMessage = "Specifies that the cmdlet will not prompt for confirmation before proceeding with established connections and will disconnect from all of them.")]
[switch]$DoNotConfirmConnections [switch]$DoNotConfirmConnections
) )
@@ -210,10 +197,8 @@ function Invoke-M365SecurityAudit {
} }
# Ensure required modules are installed # Ensure required modules are installed
$requiredModules = Get-RequiredModule -AuditFunction $requiredModules = Get-RequiredModule -AuditFunction
# Format the required modules list # Format the required modules list
$requiredModulesFormatted = Format-RequiredModuleList -RequiredModules $requiredModules $requiredModulesFormatted = Format-RequiredModuleList -RequiredModules $requiredModules
# Check and install required modules if necessary # Check and install required modules if necessary
if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Check for required modules: $requiredModulesFormatted", "Check")) { if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Check for required modules: $requiredModulesFormatted", "Check")) {
Write-Host "Checking for and installing required modules..." -ForegroundColor DarkMagenta Write-Host "Checking for and installing required modules..." -ForegroundColor DarkMagenta
@@ -221,13 +206,11 @@ function Invoke-M365SecurityAudit {
Assert-ModuleAvailability -ModuleName $module.ModuleName -RequiredVersion $module.RequiredVersion -SubModules $module.SubModules Assert-ModuleAvailability -ModuleName $module.ModuleName -RequiredVersion $module.RequiredVersion -SubModules $module.SubModules
} }
} }
# Load test definitions from CSV # Load test definitions from CSV
$testDefinitionsPath = Join-Path -Path $PSScriptRoot -ChildPath "helper\TestDefinitions.csv" $testDefinitionsPath = Join-Path -Path $PSScriptRoot -ChildPath "helper\TestDefinitions.csv"
$testDefinitions = Import-Csv -Path $testDefinitionsPath $testDefinitions = Import-Csv -Path $testDefinitionsPath
# Load the Test Definitions into the script scope for use in other functions # Load the Test Definitions into the script scope for use in other functions
$script:TestDefinitionsObject = $testDefinitions $script:TestDefinitionsObject = $testDefinitions
# Apply filters based on parameter sets # Apply filters based on parameter sets
$params = @{ $params = @{
TestDefinitions = $testDefinitions TestDefinitions = $testDefinitions
@@ -256,17 +239,14 @@ function Invoke-M365SecurityAudit {
# Initialize a collection to hold failed test details # Initialize a collection to hold failed test details
$script:FailedTests = [System.Collections.ArrayList]::new() $script:FailedTests = [System.Collections.ArrayList]::new()
} # End Begin } # End Begin
Process { Process {
$allAuditResults = [System.Collections.ArrayList]::new() # Initialize a collection to hold all results $allAuditResults = [System.Collections.ArrayList]::new() # Initialize a collection to hold all results
# Dynamically dot-source the test scripts # Dynamically dot-source the test scripts
$testsFolderPath = Join-Path -Path $PSScriptRoot -ChildPath "tests" $testsFolderPath = Join-Path -Path $PSScriptRoot -ChildPath "tests"
$testFiles = Get-ChildItem -Path $testsFolderPath -Filter "Test-*.ps1" | $testFiles = Get-ChildItem -Path $testsFolderPath -Filter "Test-*.ps1" |
Where-Object { $testsToLoad -contains $_.BaseName } Where-Object { $testsToLoad -contains $_.BaseName }
$totalTests = $testFiles.Count $totalTests = $testFiles.Count
$currentTestIndex = 0 $currentTestIndex = 0
# Establishing connections if required # Establishing connections if required
try { try {
$actualUniqueConnections = Get-UniqueConnection -Connections $requiredConnections $actualUniqueConnections = Get-UniqueConnection -Connections $requiredConnections
@@ -279,8 +259,6 @@ function Invoke-M365SecurityAudit {
Write-Host "Connection execution aborted: $_" -ForegroundColor Red Write-Host "Connection execution aborted: $_" -ForegroundColor Red
break break
} }
try { try {
Write-Host "A total of $($totalTests) tests were selected to run..." -ForegroundColor DarkMagenta Write-Host "A total of $($totalTests) tests were selected to run..." -ForegroundColor DarkMagenta
# Import the test functions # Import the test functions
@@ -297,7 +275,6 @@ function Invoke-M365SecurityAudit {
$script:FailedTests.Add([PSCustomObject]@{ Test = $_.Name; Error = $_ }) $script:FailedTests.Add([PSCustomObject]@{ Test = $_.Name; Error = $_ })
} }
} }
$currentTestIndex = 0 $currentTestIndex = 0
# Execute each test function from the prepared list # Execute each test function from the prepared list
foreach ($testFunction in $testFiles) { foreach ($testFunction in $testFiles) {
@@ -330,7 +307,6 @@ function Invoke-M365SecurityAudit {
# Return all collected audit results # Return all collected audit results
# Define the test numbers to check # Define the test numbers to check
$TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4" $TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
# Check for large details in the audit results # Check for large details in the audit results
$exceedingTests = Get-ExceededLengthResultDetail -AuditResults $allAuditResults -TestNumbersToCheck $TestNumbersToCheck -ReturnExceedingTestsOnly -DetailsLengthLimit 30000 $exceedingTests = Get-ExceededLengthResultDetail -AuditResults $allAuditResults -TestNumbersToCheck $TestNumbersToCheck -ReturnExceedingTestsOnly -DetailsLengthLimit 30000
if ($exceedingTests.Count -gt 0) { if ($exceedingTests.Count -gt 0) {
@@ -341,7 +317,4 @@ function Invoke-M365SecurityAudit {
return $allAuditResults.ToArray() | Sort-Object -Property Rec return $allAuditResults.ToArray() | Sort-Object -Property Rec
} }
} }
} }