fix: Output suppression
This commit is contained in:
@@ -49,7 +49,7 @@
|
||||
https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Export-M365SecurityAuditTable
|
||||
#>
|
||||
function Export-M365SecurityAuditTable {
|
||||
[CmdletBinding()]
|
||||
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
|
||||
[OutputType([PSCustomObject])]
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ExportAllResultsFromAuditResults")]
|
||||
@@ -74,12 +74,21 @@ function Export-M365SecurityAuditTable {
|
||||
[switch]$ExportOriginalTests,
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromAuditResults")]
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromCsv")]
|
||||
[switch]$ExportToExcel
|
||||
[switch]$ExportToExcel,
|
||||
# Add Prefix to filename after date when outputting to excel or csv.
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromAuditResults")]
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromCsv")]
|
||||
# Validate that the count of letters in the prefix is less than 5.
|
||||
[ValidateLength(0, 5)]
|
||||
[string]$Prefix = "Corp"
|
||||
)
|
||||
Begin {
|
||||
$createdFiles = @() # Initialize an array to keep track of created files
|
||||
|
||||
if ($ExportToExcel) {
|
||||
Assert-ModuleAvailability -ModuleName ImportExcel -RequiredVersion "7.8.9"
|
||||
if ($PSCmdlet.ShouldProcess("ImportExcel v7.8.9", "Assert-ModuleAvailability")) {
|
||||
Assert-ModuleAvailability -ModuleName ImportExcel -RequiredVersion "7.8.9"
|
||||
}
|
||||
}
|
||||
if ($PSCmdlet.ParameterSetName -like "ExportAllResultsFromCsv" -or $PSCmdlet.ParameterSetName -eq "OutputObjectFromCsvSingle") {
|
||||
$AuditResults = Import-Csv -Path $CsvPath | ForEach-Object {
|
||||
@@ -127,94 +136,92 @@ function Export-M365SecurityAuditTable {
|
||||
}
|
||||
End {
|
||||
if ($ExportPath) {
|
||||
$timestamp = (Get-Date).ToString("yyyy.MM.dd_HH.mm.ss")
|
||||
$exportedTests = @()
|
||||
foreach ($result in $results) {
|
||||
$testDef = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $result.TestNumber }
|
||||
if ($testDef) {
|
||||
$fileName = "$ExportPath\$($timestamp)_$($result.TestNumber).$($testDef.TestFileName -replace '\.ps1$').csv"
|
||||
if ($result.Details.Count -eq 0) {
|
||||
Write-Information "No results found for test number $($result.TestNumber)." -InformationAction Continue
|
||||
}
|
||||
else {
|
||||
if (($result.Details -ne "No M365 E3 licenses found.") -and ($result.Details -ne "No M365 E5 licenses found.")) {
|
||||
if ($ExportToExcel) {
|
||||
$xlsxPath = [System.IO.Path]::ChangeExtension($fileName, '.xlsx')
|
||||
$result.Details | Export-Excel -Path $xlsxPath -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
|
||||
$createdFiles += $xlsxPath # Add the created file to the array
|
||||
if ($PSCmdlet.ShouldProcess("Export-M365SecurityAuditTable", "Exporting results to $ExportPath")) {
|
||||
$timestamp = (Get-Date).ToString("yyyy.MM.dd_HH.mm.ss")
|
||||
$exportedTests = @()
|
||||
foreach ($result in $results) {
|
||||
$testDef = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $result.TestNumber }
|
||||
if ($testDef) {
|
||||
$fileName = "$ExportPath\$($timestamp)_$($result.TestNumber).$($testDef.TestFileName -replace '\.ps1$').csv"
|
||||
if ($result.Details.Count -eq 0) {
|
||||
Write-Information "No results found for test number $($result.TestNumber)."
|
||||
}
|
||||
else {
|
||||
if (($result.Details -ne "No M365 E3 licenses found.") -and ($result.Details -ne "No M365 E5 licenses found.")) {
|
||||
if ($ExportToExcel) {
|
||||
$xlsxPath = [System.IO.Path]::ChangeExtension($fileName, '.xlsx')
|
||||
$result.Details | Export-Excel -Path $xlsxPath -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
|
||||
$createdFiles += $xlsxPath # Add the created file to the array
|
||||
}
|
||||
else {
|
||||
$result.Details | Export-Csv -Path $fileName -NoTypeInformation
|
||||
$createdFiles += $fileName # Add the created file to the array
|
||||
}
|
||||
$exportedTests += $result.TestNumber
|
||||
}
|
||||
else {
|
||||
$result.Details | Export-Csv -Path $fileName -NoTypeInformation
|
||||
$createdFiles += $fileName # Add the created file to the array
|
||||
}
|
||||
$exportedTests += $result.TestNumber
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($exportedTests.Count -gt 0) {
|
||||
Write-Information "The following tests were exported: $($exportedTests -join ', ')" -InformationAction Continue
|
||||
}
|
||||
else {
|
||||
if ($exportedTests.Count -gt 0) {
|
||||
Write-Information "The following tests were exported: $($exportedTests -join ', ')"
|
||||
}
|
||||
else {
|
||||
if ($ExportOriginalTests) {
|
||||
Write-Information "Full audit results exported however, none of the following tests had exports: `n1.1.1, 1.3.1, 6.1.2, 6.1.3, 7.3.4"
|
||||
}
|
||||
else {
|
||||
Write-Information "No specified tests were included in the export."
|
||||
}
|
||||
}
|
||||
if ($ExportOriginalTests) {
|
||||
Write-Information "Full audit results exported however, none of the following tests had exports: `n1.1.1, 1.3.1, 6.1.2, 6.1.3, 7.3.4" -InformationAction Continue
|
||||
# Define the test numbers to check
|
||||
$TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
|
||||
# Check for large details and update the AuditResults array
|
||||
$updatedAuditResults = Get-ExceededLengthResultDetail -AuditResults $AuditResults -TestNumbersToCheck $TestNumbersToCheck -ExportedTests $exportedTests -DetailsLengthLimit 30000 -PreviewLineCount 25
|
||||
$originalFileName = "$ExportPath\$timestamp`_$Prefix-M365FoundationsAudit.csv"
|
||||
if ($ExportToExcel) {
|
||||
$xlsxPath = [System.IO.Path]::ChangeExtension($originalFileName, '.xlsx')
|
||||
$updatedAuditResults | Export-Excel -Path $xlsxPath -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
|
||||
$createdFiles += $xlsxPath # Add the created file to the array
|
||||
}
|
||||
else {
|
||||
$updatedAuditResults | Export-Csv -Path $originalFileName -NoTypeInformation
|
||||
$createdFiles += $originalFileName # Add the created file to the array
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Information "No specified tests were included in the export." -InformationAction Continue
|
||||
# Hash each file and add it to a dictionary
|
||||
# Hash each file and save the hashes to a text file
|
||||
$hashFilePath = "$ExportPath\$timestamp`_Hashes.txt"
|
||||
$fileHashes = @()
|
||||
foreach ($file in $createdFiles) {
|
||||
$hash = Get-FileHash -Path $file -Algorithm SHA256
|
||||
$fileHashes += "$($file): $($hash.Hash)"
|
||||
}
|
||||
}
|
||||
if ($ExportOriginalTests) {
|
||||
# Define the test numbers to check
|
||||
$TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
|
||||
# Check for large details and update the AuditResults array
|
||||
$updatedAuditResults = Get-ExceededLengthResultDetail -AuditResults $AuditResults -TestNumbersToCheck $TestNumbersToCheck -ExportedTests $exportedTests -DetailsLengthLimit 30000 -PreviewLineCount 25
|
||||
$originalFileName = "$ExportPath\$timestamp`_M365FoundationsAudit.csv"
|
||||
if ($ExportToExcel) {
|
||||
$xlsxPath = [System.IO.Path]::ChangeExtension($originalFileName, '.xlsx')
|
||||
$updatedAuditResults | Export-Excel -Path $xlsxPath -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
|
||||
$createdFiles += $xlsxPath # Add the created file to the array
|
||||
$fileHashes | Set-Content -Path $hashFilePath
|
||||
$createdFiles += $hashFilePath # Add the hash file to the array
|
||||
# Create a zip file and add all the created files
|
||||
$zipFilePath = "$ExportPath\$timestamp`_$Prefix-M365FoundationsAudit.zip"
|
||||
Compress-Archive -Path $createdFiles -DestinationPath $zipFilePath
|
||||
# Remove the original files after they have been added to the zip
|
||||
foreach ($file in $createdFiles) {
|
||||
Remove-Item -Path $file -Force
|
||||
}
|
||||
else {
|
||||
$updatedAuditResults | Export-Csv -Path $originalFileName -NoTypeInformation
|
||||
$createdFiles += $originalFileName # Add the created file to the array
|
||||
# Compute the hash for the zip file and rename it
|
||||
$zipHash = Get-FileHash -Path $zipFilePath -Algorithm SHA256
|
||||
$newZipFilePath = "$ExportPath\$timestamp`_$Prefix-M365FoundationsAudit_$($zipHash.Hash.Substring(0, 8)).zip"
|
||||
Rename-Item -Path $zipFilePath -NewName $newZipFilePath
|
||||
# Output the zip file path with hash
|
||||
return [PSCustomObject]@{
|
||||
ZipFilePath = $newZipFilePath
|
||||
}
|
||||
}
|
||||
# Hash each file and add it to a dictionary
|
||||
# Hash each file and save the hashes to a text file
|
||||
$hashFilePath = "$ExportPath\$timestamp`_Hashes.txt"
|
||||
$fileHashes = @()
|
||||
foreach ($file in $createdFiles) {
|
||||
$hash = Get-FileHash -Path $file -Algorithm SHA256
|
||||
$fileHashes += "$($file): $($hash.Hash)"
|
||||
}
|
||||
$fileHashes | Set-Content -Path $hashFilePath
|
||||
$createdFiles += $hashFilePath # Add the hash file to the array
|
||||
|
||||
# Create a zip file and add all the created files
|
||||
$zipFilePath = "$ExportPath\$timestamp`_M365FoundationsAudit.zip"
|
||||
Compress-Archive -Path $createdFiles -DestinationPath $zipFilePath
|
||||
|
||||
# Remove the original files after they have been added to the zip
|
||||
foreach ($file in $createdFiles) {
|
||||
Remove-Item -Path $file -Force
|
||||
}
|
||||
|
||||
# Compute the hash for the zip file and rename it
|
||||
$zipHash = Get-FileHash -Path $zipFilePath -Algorithm SHA256
|
||||
$newZipFilePath = "$ExportPath\$timestamp`_M365FoundationsAudit_$($zipHash.Hash.Substring(0, 8)).zip"
|
||||
Rename-Item -Path $zipFilePath -NewName $newZipFilePath
|
||||
|
||||
# Output the zip file path with hash
|
||||
[PSCustomObject]@{
|
||||
ZipFilePath = $newZipFilePath
|
||||
}
|
||||
} # End of ExportPath
|
||||
elseif ($OutputTestNumber) {
|
||||
if ($results[0].Details) {
|
||||
return $results[0].Details
|
||||
}
|
||||
else {
|
||||
Write-Information "No results found for test number $($OutputTestNumber)." -InformationAction Continue
|
||||
Write-Information "No results found for test number $($OutputTestNumber)."
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -139,7 +139,8 @@
|
||||
https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit
|
||||
#>
|
||||
function Invoke-M365SecurityAudit {
|
||||
[CmdletBinding(SupportsShouldProcess = $true, DefaultParameterSetName = 'Default')]
|
||||
# Add confirm to high
|
||||
[CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "High" , DefaultParameterSetName = 'Default')]
|
||||
[OutputType([CISAuditResult[]])]
|
||||
param (
|
||||
[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.")]
|
||||
@@ -206,7 +207,7 @@ function Invoke-M365SecurityAudit {
|
||||
)
|
||||
Begin {
|
||||
if ($script:MaximumFunctionCount -lt 8192) {
|
||||
Write-Verbose "Setting the `$script:MaximumFunctionCount to 8192 for the test run." -Verbose
|
||||
Write-Verbose "Setting the `$script:MaximumFunctionCount to 8192 for the test run."
|
||||
$script:MaximumFunctionCount = 8192
|
||||
}
|
||||
# Ensure required modules are installed
|
||||
@@ -214,8 +215,8 @@ function Invoke-M365SecurityAudit {
|
||||
# Format the required modules list
|
||||
$requiredModulesFormatted = Format-RequiredModuleList -RequiredModules $requiredModules
|
||||
# Check and install required modules if necessary
|
||||
if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Check for required modules: $requiredModulesFormatted", "Check")) {
|
||||
Write-Host "Checking for and installing required modules..." -ForegroundColor DarkMagenta
|
||||
if (!($NoModuleCheck) -and $PSCmdlet.ShouldProcess("Modules: $requiredModulesFormatted", "Assert-ModuleAvailability")) {
|
||||
Write-Information "Checking for and installing required modules..."
|
||||
foreach ($module in $requiredModules) {
|
||||
Assert-ModuleAvailability -ModuleName $module.ModuleName -RequiredVersion $module.RequiredVersion -SubModules $module.SubModules
|
||||
}
|
||||
@@ -265,46 +266,59 @@ function Invoke-M365SecurityAudit {
|
||||
try {
|
||||
$actualUniqueConnections = Get-UniqueConnection -Connections $requiredConnections
|
||||
if (!($DoNotConnect) -and $PSCmdlet.ShouldProcess("Establish connections to Microsoft 365 services: $($actualUniqueConnections -join ', ')", "Connect")) {
|
||||
Write-Host "Establishing connections to Microsoft 365 services: $($actualUniqueConnections -join ', ')" -ForegroundColor DarkMagenta
|
||||
Write-Information "Establishing connections to Microsoft 365 services: $($actualUniqueConnections -join ', ')"
|
||||
Connect-M365Suite -TenantAdminUrl $TenantAdminUrl -RequiredConnections $requiredConnections -SkipConfirmation:$DoNotConfirmConnections
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-Host "Connection execution aborted: $_" -ForegroundColor Red
|
||||
break
|
||||
Throw "Connection execution aborted: $_"
|
||||
}
|
||||
try {
|
||||
Write-Host "A total of $($totalTests) tests were selected to run..." -ForegroundColor DarkMagenta
|
||||
# Import the test functions
|
||||
$testFiles | ForEach-Object {
|
||||
$currentTestIndex++
|
||||
Write-Progress -Activity "Loading Test Scripts" -Status "Loading $($currentTestIndex) of $($totalTests): $($_.Name)" -PercentComplete (($currentTestIndex / $totalTests) * 100)
|
||||
Try {
|
||||
# Dot source the test function
|
||||
. $_.FullName
|
||||
if ($PSCmdlet.ShouldProcess("Measure and display audit results for $($totalTests) tests", "Measure")) {
|
||||
Write-Information "A total of $($totalTests) tests were selected to run..."
|
||||
# Import the test functions
|
||||
$testFiles | ForEach-Object {
|
||||
$currentTestIndex++
|
||||
Write-Progress -Activity "Loading Test Scripts" -Status "Loading $($currentTestIndex) of $($totalTests): $($_.Name)" -PercentComplete (($currentTestIndex / $totalTests) * 100)
|
||||
Try {
|
||||
# Dot source the test function
|
||||
. $_.FullName
|
||||
}
|
||||
Catch {
|
||||
# Log the error and add the test to the failed tests collection
|
||||
Write-Verbose "Failed to load test function $($_.Name): $_"
|
||||
$script:FailedTests.Add([PSCustomObject]@{ Test = $_.Name; Error = $_ })
|
||||
}
|
||||
}
|
||||
Catch {
|
||||
# Log the error and add the test to the failed tests collection
|
||||
Write-Verbose "Failed to load test function $($_.Name): $_" -Verbose
|
||||
$script:FailedTests.Add([PSCustomObject]@{ Test = $_.Name; Error = $_ })
|
||||
}
|
||||
}
|
||||
$currentTestIndex = 0
|
||||
# Execute each test function from the prepared list
|
||||
foreach ($testFunction in $testFiles) {
|
||||
$currentTestIndex++
|
||||
Write-Progress -Activity "Executing Tests" -Status "Executing $($currentTestIndex) of $($totalTests): $($testFunction.Name)" -PercentComplete (($currentTestIndex / $totalTests) * 100)
|
||||
$functionName = $testFunction.BaseName
|
||||
if ($PSCmdlet.ShouldProcess($functionName, "Execute test")) {
|
||||
$currentTestIndex = 0
|
||||
# Execute each test function from the prepared list
|
||||
foreach ($testFunction in $testFiles) {
|
||||
$currentTestIndex++
|
||||
Write-Progress -Activity "Executing Tests" -Status "Executing $($currentTestIndex) of $($totalTests): $($testFunction.Name)" -PercentComplete (($currentTestIndex / $totalTests) * 100)
|
||||
$functionName = $testFunction.BaseName
|
||||
Write-Information "Executing test function: $functionName"
|
||||
$auditResult = Invoke-TestFunction -FunctionFile $testFunction -DomainName $DomainName -ApprovedCloudStorageProviders $ApprovedCloudStorageProviders -ApprovedFederatedDomains $ApprovedFederatedDomains
|
||||
# Add the result to the collection
|
||||
[void]$allAuditResults.Add($auditResult)
|
||||
}
|
||||
# Call the private function to calculate and display results
|
||||
Measure-AuditResult -AllAuditResults $allAuditResults -FailedTests $script:FailedTests
|
||||
# Return all collected audit results
|
||||
# Define the test numbers to check
|
||||
$TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
|
||||
# Check for large details in the audit results
|
||||
$exceedingTests = Get-ExceededLengthResultDetail -AuditResults $allAuditResults -TestNumbersToCheck $TestNumbersToCheck -ReturnExceedingTestsOnly -DetailsLengthLimit 30000
|
||||
if ($exceedingTests.Count -gt 0) {
|
||||
Write-Information "The following tests exceeded the details length limit: $($exceedingTests -join ', ')"
|
||||
Write-Information "( Assuming the results were instantiated. Ex: `$object = invoke-M365SecurityAudit )`nUse the following command and adjust as necessary to view the full details of the test results:"
|
||||
Write-Information "Export-M365SecurityAuditTable -ExportAllTests -AuditResults `$object -ExportPath `"C:\temp`" -ExportOriginalTests"
|
||||
}
|
||||
return $allAuditResults.ToArray() | Sort-Object -Property Rec
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# Log the error and add the test to the failed tests collection
|
||||
Write-Verbose "Invoke-M365SecurityAudit: Failed to load test function $($_.Name): $_" -Verbose
|
||||
throw "Failed to execute test function $($testFunction.Name): $_"
|
||||
$script:FailedTests.Add([PSCustomObject]@{ Test = $_.Name; Error = $_ })
|
||||
}
|
||||
finally {
|
||||
@@ -315,20 +329,6 @@ function Invoke-M365SecurityAudit {
|
||||
}
|
||||
}
|
||||
End {
|
||||
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
|
||||
# Define the test numbers to check
|
||||
$TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
|
||||
# Check for large details in the audit results
|
||||
$exceedingTests = Get-ExceededLengthResultDetail -AuditResults $allAuditResults -TestNumbersToCheck $TestNumbersToCheck -ReturnExceedingTestsOnly -DetailsLengthLimit 30000
|
||||
if ($exceedingTests.Count -gt 0) {
|
||||
Write-Information "The following tests exceeded the details length limit: $($exceedingTests -join ', ')" -InformationAction Continue
|
||||
Write-Host "(Assuming the results were instantiated. Ex: `$object = invoke-M365SecurityAudit) Use the following command and adjust as neccesary to view the full details of the test results:" -ForegroundColor DarkCyan
|
||||
Write-Host "Export-M365SecurityAuditTable -ExportAllTests -AuditResults `$object -ExportPath `"C:\temp`" -ExportOriginalTests" -ForegroundColor Green
|
||||
}
|
||||
return $allAuditResults.ToArray() | Sort-Object -Property Rec
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user