Fix: Export-M365SecurityAuditTable function
This commit is contained in:
@@ -31,6 +31,7 @@ The format is based on and uses the types of changes according to [Keep a Change
|
||||
- Phish policy test to return if highest priority policy conforms to the benchmark.
|
||||
- Module assertion to check for minimum version of required modules.
|
||||
- Module assertion to not import the module if it already exists.
|
||||
- Fixed Export-M365SecurityAuditTable to ensure there are only 3 parameter sets: One for specific nested test output, one to export only nested tables, and one to export all tests along with options to export to CSV or Excel.
|
||||
|
||||
## [v0.1.28] - 2025-01-14
|
||||
|
||||
|
@@ -1,235 +1,201 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Exports Microsoft 365 security audit results to CSV or Excel files and supports outputting specific test results as objects.
|
||||
Export Microsoft 365 CIS audit results into CSV/Excel and package with hashes.
|
||||
.DESCRIPTION
|
||||
The Export-M365SecurityAuditTable function exports Microsoft 365 security audit results from an array of CISAuditResult objects or a CSV file.
|
||||
It can export all results to a specified path, output a specific test result as an object, and includes options for exporting results to Excel.
|
||||
Additionally, it computes hashes for the exported files and includes them in the zip archive for verification purposes.
|
||||
Export-M365SecurityAuditTable processes an array of CISAuditResult objects, exporting per-test nested tables
|
||||
and/or a full audit summary (with oversized fields truncated) to CSV or Excel. All output files are
|
||||
hashed (SHA256) and bundled into a ZIP archive whose filename includes a short hash for integrity.
|
||||
.PARAMETER AuditResults
|
||||
An array of CISAuditResult objects containing the audit results. This parameter is mandatory when exporting from audit results.
|
||||
.PARAMETER CsvPath
|
||||
The path to a CSV file containing the audit results. This parameter is mandatory when exporting from a CSV file.
|
||||
.PARAMETER OutputTestNumber
|
||||
The test number to output as an object. Valid values are "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4". This parameter is used to output a specific test result.
|
||||
.PARAMETER ExportNestedTables
|
||||
Switch to export all test results. When specified, all test results are exported to the specified path.
|
||||
An array of PSCustomObject (CISAuditResult) objects containing the audit results to export or query.
|
||||
.PARAMETER ExportPath
|
||||
The path where the CSV or Excel files will be exported. This parameter is mandatory when exporting all tests.
|
||||
.PARAMETER ExportOriginalTests
|
||||
Switch to export the original audit results to a CSV file. When specified, the original test results are exported along with the processed results.
|
||||
Path to the directory where CSV/Excel files and the final ZIP archive will be placed. Required for
|
||||
any file-based export (DefaultExport or OnlyExportNestedTables).
|
||||
.PARAMETER ExportToExcel
|
||||
Switch to export the results to an Excel file. When specified, results are exported in Excel format.
|
||||
Switch to export files in Excel (.xlsx) format instead of CSV. Requires the ImportExcel module.
|
||||
.PARAMETER Prefix
|
||||
A short prefix (0–5 characters, default 'Corp') appended to the summary audit filename and hashes.
|
||||
.PARAMETER OnlyExportNestedTables
|
||||
Switch to export only the per-test nested tables to files, skipping the full audit summary.
|
||||
.PARAMETER OutputTestNumber
|
||||
Specify one test number (valid values: '1.1.1','1.3.1','6.1.2','6.1.3','7.3.4') to return that test’s
|
||||
details in-memory as objects without writing any files.
|
||||
.INPUTS
|
||||
[CISAuditResult[]] - An array of CISAuditResult objects.
|
||||
[string] - A path to a CSV file.
|
||||
System.Object[] (array of CISAuditResult PSCustomObjects)
|
||||
.OUTPUTS
|
||||
[PSCustomObject] - A custom object containing the path to the zip file and its hash.
|
||||
PSCustomObject with property ZipFilePath indicating the final ZIP archive location, or raw test details
|
||||
when using -OutputTestNumber.
|
||||
.EXAMPLE
|
||||
Export-M365SecurityAuditTable -AuditResults $object -OutputTestNumber 6.1.2
|
||||
# Outputs the result of test number 6.1.2 from the provided audit results as an object.
|
||||
# Return details for test 6.1.2
|
||||
Export-M365SecurityAuditTable -AuditResults $audits -OutputTestNumber 6.1.2
|
||||
.EXAMPLE
|
||||
Export-M365SecurityAuditTable -ExportNestedTables -AuditResults $object -ExportPath "C:\temp"
|
||||
# Exports all audit results to the specified path in CSV format.
|
||||
# Full export (nested tables + summary) to CSV
|
||||
Export-M365SecurityAuditTable -AuditResults $audits -ExportPath "C:\temp"
|
||||
.EXAMPLE
|
||||
Export-M365SecurityAuditTable -CsvPath "C:\temp\auditresultstoday1.csv" -OutputTestNumber 6.1.2
|
||||
# Outputs the result of test number 6.1.2 from the CSV file as an object.
|
||||
# Only export nested tables to Excel
|
||||
Export-M365SecurityAuditTable -AuditResults $audits -ExportPath "C:\temp" -OnlyExportNestedTables -ExportToExcel
|
||||
.EXAMPLE
|
||||
Export-M365SecurityAuditTable -ExportNestedTables -CsvPath "C:\temp\auditresultstoday1.csv" -ExportPath "C:\temp"
|
||||
# Exports all audit results from the CSV file to the specified path in CSV format.
|
||||
.EXAMPLE
|
||||
Export-M365SecurityAuditTable -ExportNestedTables -AuditResults $object -ExportPath "C:\temp" -ExportOriginalTests
|
||||
# Exports all audit results along with the original test results to the specified path in CSV format.
|
||||
.EXAMPLE
|
||||
Export-M365SecurityAuditTable -ExportNestedTables -CsvPath "C:\temp\auditresultstoday1.csv" -ExportPath "C:\temp" -ExportOriginalTests
|
||||
# Exports all audit results from the CSV file along with the original test results to the specified path in CSV format.
|
||||
.EXAMPLE
|
||||
Export-M365SecurityAuditTable -ExportNestedTables -AuditResults $object -ExportPath "C:\temp" -ExportToExcel
|
||||
# Exports all audit results to the specified path in Excel format.
|
||||
# Custom prefix for filenames
|
||||
Export-M365SecurityAuditTable -AuditResults $audits -ExportPath "C:\temp" -Prefix Dev
|
||||
.LINK
|
||||
https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Export-M365SecurityAuditTable
|
||||
#>
|
||||
function Export-M365SecurityAuditTable {
|
||||
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
|
||||
[CmdletBinding(
|
||||
DefaultParameterSetName = 'DefaultExport',
|
||||
SupportsShouldProcess,
|
||||
ConfirmImpact = 'High'
|
||||
)]
|
||||
[OutputType([PSCustomObject])]
|
||||
param(
|
||||
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ExportAllResultsFromAuditResults")]
|
||||
[Parameter(Mandatory = $true, Position = 2, ParameterSetName = "OutputObjectFromAuditResultsSingle")]
|
||||
[psobject[]]$AuditResults,
|
||||
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ExportAllResultsFromCsv")]
|
||||
[Parameter(Mandatory = $true, Position = 2, ParameterSetName = "OutputObjectFromCsvSingle")]
|
||||
[ValidateScript({ (Test-Path $_) -and ((Get-Item $_).PSIsContainer -eq $false) })]
|
||||
[string]$CsvPath,
|
||||
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "OutputObjectFromAuditResultsSingle")]
|
||||
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "OutputObjectFromCsvSingle")]
|
||||
[ValidateSet("1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4")]
|
||||
[string]$OutputTestNumber,
|
||||
[Parameter(Mandatory = $false, Position = 0, ParameterSetName = "ExportAllResultsFromAuditResults")]
|
||||
[Parameter(Mandatory = $false, Position = 0, ParameterSetName = "ExportAllResultsFromCsv")]
|
||||
[switch]$ExportNestedTables,
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "ExportAllResultsFromAuditResults")]
|
||||
[Parameter(Mandatory = $true, ParameterSetName = "ExportAllResultsFromCsv")]
|
||||
[string]$ExportPath,
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromAuditResults")]
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromCsv")]
|
||||
[switch]$ExportOriginalTests,
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromAuditResults")]
|
||||
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromCsv")]
|
||||
[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.
|
||||
#───────────────────────────────────────────────────────────────────────────
|
||||
# 1) DefaultExport: full audit export (nested tables + summary) into ZIP
|
||||
# -AuditResults, -ExportPath, [-ExportToExcel], [-Prefix]
|
||||
#───────────────────────────────────────────────────────────────────────────
|
||||
[Parameter(Mandatory, ParameterSetName = 'DefaultExport')]
|
||||
[Parameter(Mandatory, ParameterSetName = 'OnlyExportNestedTables')]
|
||||
[Parameter(Mandatory, ParameterSetName = 'SingleObject')]
|
||||
[psobject[]]
|
||||
$AuditResults,
|
||||
[Parameter(Mandatory, ParameterSetName = 'DefaultExport')]
|
||||
[Parameter(Mandatory, ParameterSetName = 'OnlyExportNestedTables')]
|
||||
[string]
|
||||
$ExportPath,
|
||||
[Parameter(ParameterSetName = 'DefaultExport')]
|
||||
[Parameter(ParameterSetName = 'OnlyExportNestedTables')]
|
||||
[switch]
|
||||
$ExportToExcel,
|
||||
[Parameter(ParameterSetName = 'DefaultExport')]
|
||||
[Parameter(ParameterSetName = 'OnlyExportNestedTables')]
|
||||
[ValidateLength(0,5)]
|
||||
[string]$Prefix = "Corp"
|
||||
[string]
|
||||
$Prefix = 'Corp',
|
||||
#───────────────────────────────────────────────────────────────────────────
|
||||
# 2) OnlyExportNestedTables: nested tables only into ZIP
|
||||
# -AuditResults, -ExportPath, -OnlyExportNestedTables
|
||||
#───────────────────────────────────────────────────────────────────────────
|
||||
[Parameter(Mandatory, ParameterSetName = 'OnlyExportNestedTables')]
|
||||
[switch]
|
||||
$OnlyExportNestedTables,
|
||||
#───────────────────────────────────────────────────────────────────────────
|
||||
# 3) SingleObject: in-memory output of one test’s details
|
||||
# -AuditResults, -OutputTestNumber
|
||||
#───────────────────────────────────────────────────────────────────────────
|
||||
[Parameter(Mandatory, ParameterSetName = 'SingleObject')]
|
||||
[ValidateSet('1.1.1','1.3.1','6.1.2','6.1.3','7.3.4')]
|
||||
[string]
|
||||
$OutputTestNumber
|
||||
)
|
||||
Begin {
|
||||
$createdFiles = @() # Initialize an array to keep track of created files
|
||||
|
||||
# Load v4.0 definitions
|
||||
$Version = '4.0.0'
|
||||
$script:TestDefinitionsObject = Get-TestDefinition -Version $Version
|
||||
# Ensure Excel support if requested
|
||||
if ($ExportToExcel) {
|
||||
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 {
|
||||
$params = @{
|
||||
Rec = $_.Rec
|
||||
Result = [bool]$_.Result
|
||||
Status = $_.Status
|
||||
Details = $_.Details
|
||||
FailureReason = $_.FailureReason
|
||||
}
|
||||
Initialize-CISAuditResult @params
|
||||
}
|
||||
}
|
||||
if ($ExportNestedTables) {
|
||||
$TestNumbers = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
|
||||
Assert-ModuleAvailability -ModuleName ImportExcel -RequiredVersion '7.8.9'
|
||||
}
|
||||
# Tests producing nested tables
|
||||
$nestedTests = '1.1.1','1.3.1','6.1.2','6.1.3','7.3.4'
|
||||
# Initialize collections
|
||||
$results = @()
|
||||
$testsToProcess = if ($OutputTestNumber) { @($OutputTestNumber) } else { $TestNumbers }
|
||||
$createdFiles = [System.Collections.Generic.List[string]]::new()
|
||||
# Determine which tests to process
|
||||
if ($PSCmdlet.ParameterSetName -eq 'SingleObject') {
|
||||
$testsToProcess = @($OutputTestNumber)
|
||||
} else {
|
||||
$testsToProcess = $nestedTests
|
||||
}
|
||||
}
|
||||
Process {
|
||||
foreach ($test in $testsToProcess) {
|
||||
$auditResult = $AuditResults | Where-Object { $_.Rec -eq $test }
|
||||
if (-not $auditResult) {
|
||||
Write-Information "No audit results found for the test number $test."
|
||||
continue
|
||||
}
|
||||
$item = $AuditResults | Where-Object Rec -EQ $test
|
||||
if (-not $item) { continue }
|
||||
switch ($test) {
|
||||
"6.1.2" {
|
||||
$details = $auditResult.Details
|
||||
$newObjectDetails = Get-AuditMailboxDetail -Details $details -Version '6.1.2'
|
||||
$results += [PSCustomObject]@{ TestNumber = $test; Details = $newObjectDetails }
|
||||
}
|
||||
"6.1.3" {
|
||||
$details = $auditResult.Details
|
||||
$newObjectDetails = Get-AuditMailboxDetail -Details $details -Version '6.1.3'
|
||||
$results += [PSCustomObject]@{ TestNumber = $test; Details = $newObjectDetails }
|
||||
}
|
||||
Default {
|
||||
$details = $auditResult.Details
|
||||
$csv = $details | ConvertFrom-Csv -Delimiter '|'
|
||||
$results += [PSCustomObject]@{ TestNumber = $test; Details = $csv }
|
||||
}
|
||||
'6.1.2' { $parsed = Get-AuditMailboxDetail -Details $item.Details -Version '6.1.2' }
|
||||
'6.1.3' { $parsed = Get-AuditMailboxDetail -Details $item.Details -Version '6.1.3' }
|
||||
Default { $parsed = $item.Details | ConvertFrom-Csv -Delimiter '|' }
|
||||
}
|
||||
$results += [PSCustomObject]@{ TestNumber = $test; Details = $parsed }
|
||||
}
|
||||
}
|
||||
End {
|
||||
if ($ExportPath) {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
# 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
|
||||
}
|
||||
}
|
||||
# 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`_$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
|
||||
}
|
||||
# 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
|
||||
}
|
||||
}
|
||||
} # End of ExportPath
|
||||
elseif ($OutputTestNumber) {
|
||||
if ($results[0].Details) {
|
||||
#--- SingleObject: return in-memory details ---
|
||||
if ($PSCmdlet.ParameterSetName -eq 'SingleObject') {
|
||||
if ($results.Count -and $results[0].Details) {
|
||||
return $results[0].Details
|
||||
}
|
||||
else {
|
||||
Write-Information "No results found for test number $($OutputTestNumber)."
|
||||
throw "No results found for test $OutputTestNumber."
|
||||
}
|
||||
#--- File export: DefaultExport or OnlyExportNestedTables ---
|
||||
if (-not $ExportPath) {
|
||||
throw 'ExportPath is required for file export.'
|
||||
}
|
||||
if ($PSCmdlet.ShouldProcess($ExportPath, 'Export and archive audit results')) {
|
||||
# Ensure directory
|
||||
if (-not (Test-Path $ExportPath)) { New-Item -Path $ExportPath -ItemType Directory -Force | Out-Null }
|
||||
$timestamp = (Get-Date).ToString('yyyy.MM.dd_HH.mm.ss')
|
||||
$exportedTests = @()
|
||||
# Always truncate large details before writing files
|
||||
Write-Verbose 'Truncating oversized details...'
|
||||
$truncatedAudit = Get-ExceededLengthResultDetail `
|
||||
-AuditResults $AuditResults `
|
||||
-TestNumbersToCheck $nestedTests `
|
||||
-ExportedTests $exportedTests `
|
||||
-DetailsLengthLimit 30000 `
|
||||
-PreviewLineCount 25
|
||||
#--- Export nested tables ---
|
||||
Write-Verbose "[$($PSCmdlet.ParameterSetName)] exporting nested table CSV/XLSX..."
|
||||
foreach ($entry in $results) {
|
||||
if (-not $entry.Details) { continue }
|
||||
$name = "$timestamp`_$($entry.TestNumber)"
|
||||
$csv = Join-Path $ExportPath "$name.csv"
|
||||
if ($ExportToExcel) {
|
||||
$xlsx = [IO.Path]::ChangeExtension($csv, '.xlsx')
|
||||
$entry.Details | Export-Excel -Path $xlsx -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
|
||||
$createdFiles.Add($xlsx)
|
||||
} else {
|
||||
$entry.Details | Export-Csv -Path $csv -NoTypeInformation
|
||||
$createdFiles.Add($csv)
|
||||
}
|
||||
$exportedTests += $entry.TestNumber
|
||||
}
|
||||
if ($exportedTests.Count) {
|
||||
Write-Information "Exported nested tables: $($exportedTests -join ', ')"
|
||||
} elseif ($OnlyExportNestedTables) {
|
||||
Write-Warning 'No nested data to export.'
|
||||
}
|
||||
#--- Summary export (DefaultExport only) ---
|
||||
if ($PSCmdlet.ParameterSetName -eq 'DefaultExport') {
|
||||
Write-Verbose 'Exporting full summary with truncated details...'
|
||||
$base = "${timestamp}_${Prefix}-M365FoundationsAudit"
|
||||
$out = Join-Path $ExportPath "$base.csv"
|
||||
if ($ExportToExcel) {
|
||||
$xlsx = [IO.Path]::ChangeExtension($out, '.xlsx')
|
||||
$truncatedAudit | select-object * | Export-Excel -Path $xlsx -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
|
||||
$createdFiles.Add($xlsx)
|
||||
} else {
|
||||
Write-Verbose "Exporting to Path: $out"
|
||||
$truncatedAudit | select-object * | Export-Csv -Path $out -NoTypeInformation
|
||||
$createdFiles.Add($out)
|
||||
}
|
||||
Write-Information 'Exported summary of all audit results.'
|
||||
}
|
||||
#--- Hash & ZIP ---
|
||||
Write-Verbose 'Computing file hashes...'
|
||||
$hashFile = Join-Path $ExportPath "$timestamp`_${Prefix}-Hashes.txt"
|
||||
$createdFiles | ForEach-Object {
|
||||
$h = Get-FileHash -Path $_ -Algorithm SHA256
|
||||
"$([IO.Path]::GetFileName($_)): $($h.Hash)"
|
||||
} | Set-Content -Path $hashFile
|
||||
$createdFiles.Add($hashFile)
|
||||
Write-Verbose 'Creating ZIP archive...'
|
||||
$zip = Join-Path $ExportPath "$timestamp`_${Prefix}-M365FoundationsAudit.zip"
|
||||
Compress-Archive -Path $createdFiles -DestinationPath $zip -Force
|
||||
$createdFiles | Remove-Item -Force
|
||||
# Rename to include short hash
|
||||
$zHash = Get-FileHash -Path $zip -Algorithm SHA256
|
||||
$final = Join-Path $ExportPath ("$timestamp`_${Prefix}-M365FoundationsAudit_$($zHash.Hash.Substring(0,8)).zip")
|
||||
Rename-Item -Path $zip -NewName (Split-Path $final -Leaf)
|
||||
return [PSCustomObject]@{ ZipFilePath = $final }
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Error "No valid operation specified. Please provide valid parameters."
|
||||
}
|
||||
# Output the created files at the end
|
||||
#if ($createdFiles.Count -gt 0) {
|
||||
########### $createdFiles
|
||||
#}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user