From 7b3762191786d558426eb4de3ed917750c8385ef Mon Sep 17 00:00:00 2001 From: DrIOS <58635327+DrIOSX@users.noreply.github.com> Date: Sat, 15 Jun 2024 16:12:24 -0500 Subject: [PATCH] add new function for exporting nested tables --- .gitignore | 3 +- helpers/Build-Help.ps1 | 72 +------------------ .../Public/Export-M365SecurityAuditTable.ps1 | 30 +++++--- .../Test-AdministrativeAccountCompliance.ps1 | 2 +- source/tests/Test-MailboxAuditingE3.ps1 | 59 ++++++++------- 5 files changed, 56 insertions(+), 110 deletions(-) diff --git a/.gitignore b/.gitignore index d18e461..e8a7ae6 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,5 @@ output/ markdownissues.txt node_modules package-lock.json -Aligned.xlsx \ No newline at end of file +Aligned.xlsx +test-gh.ps1 \ No newline at end of file diff --git a/helpers/Build-Help.ps1 b/helpers/Build-Help.ps1 index fe923fc..3a5d89a 100644 --- a/helpers/Build-Help.ps1 +++ b/helpers/Build-Help.ps1 @@ -4,7 +4,7 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1 <# - $ver = "v0.1.10" + $ver = "v0.1.11" git checkout main git pull origin main git tag -a $ver -m "Release version $ver refactor Update" @@ -13,73 +13,3 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1 git push origin $ver # git tag -d $ver #> - -# Refresh authentication to ensure the correct scopes -gh auth refresh -s project,read:project,write:project,repo - -# Create the project -gh project create --owner CriticalSolutionsNetwork --title "Test Validation Project" - -$repoOwner = "CriticalSolutionsNetwork" -$repoName = "M365FoundationsCISReport" -$directoryPath = ".\source\tests" -$projectName = "Test Validation Project" - -# Function to create GitHub issues -function Create-GitHubIssue { - param ( - [string]$title, - [string]$body, - [string]$project - ) - - # Create the issue and add it to the specified project - $issue = gh issue create --repo "$repoOwner/$repoName" --title "$title" --body "$body" --project "$project" - return $issue -} - -# Load test definitions from CSV -$testDefinitionsPath = ".\source\helper\TestDefinitions.csv" -$testDefinitions = Import-Csv -Path $testDefinitionsPath - -# Iterate over each .ps1 file in the directory -Get-ChildItem -Path $directoryPath -Filter "*.ps1" | ForEach-Object { - $fileName = $_.Name - $testDefinition = $testDefinitions | Where-Object { $_.TestFileName -eq $fileName } - - if ($testDefinition) { - $rec = $testDefinition.Rec - $elevel = $testDefinition.ELevel - $profileLevel = $testDefinition.ProfileLevel - $ig1 = $testDefinition.IG1 - $ig2 = $testDefinition.IG2 - $ig3 = $testDefinition.IG3 - $connection = $testDefinition.Connection - - $issueTitle = "Rec: $rec - Validate $fileName, ELevel: $elevel, ProfileLevel: $profileLevel, IG1: $ig1, IG2: $ig2, IG3: $ig3, Connection: $connection" - $issueBody = @" -# Validation for $fileName - -## Tasks -- [ ] Validate test for a pass - - Description of passing criteria: -- [ ] Validate test for a fail - - Description of failing criteria: -- [ ] Add notes and observations - - Placeholder for additional notes: -"@ - - # Create the issue using GitHub CLI - try { - Create-GitHubIssue -title "$issueTitle" -body "$issueBody" -project "$projectName" - Write-Output "Created issue for $fileName" - } catch { - Write-Error "Failed to create issue for $fileName : $_" - } - - # Introduce a delay of 2 seconds - Start-Sleep -Seconds 2 - } else { - Write-Warning "No matching test definition found for $fileName" - } -} diff --git a/source/Public/Export-M365SecurityAuditTable.ps1 b/source/Public/Export-M365SecurityAuditTable.ps1 index 057672d..5291343 100644 --- a/source/Public/Export-M365SecurityAuditTable.ps1 +++ b/source/Public/Export-M365SecurityAuditTable.ps1 @@ -12,12 +12,12 @@ function Export-M365SecurityAuditTable { [Parameter(Mandatory = $false, Position = 1, ParameterSetName = "FromAuditResultsSingle")] [Parameter(Mandatory = $false, Position = 1, ParameterSetName = "FromCsvSingle")] - [ValidateSet("6.1.2","6.1.3","7.3.4")] + [ValidateSet("1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4")] [string]$TestNumber, [Parameter(Mandatory = $false, Position = 1, ParameterSetName = "FromAuditResultsMultiple")] [Parameter(Mandatory = $false, Position = 1, ParameterSetName = "FromCsvMultiple")] - [ValidateSet("6.1.2","6.1.3","7.3.4")] + [ValidateSet("1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4")] [string[]]$TestNumbers, [Parameter(Mandatory = $true, Position = 2, ParameterSetName = "FromAuditResultsMultiple")] @@ -50,9 +50,8 @@ function Export-M365SecurityAuditTable { } } - #$script:TestDefinitionsObject = Import-Csv -Path .\source\helper\TestDefinitions.csv if (-not $TestNumbers -and -not $TestNumber) { - $TestNumbers = "6.1.2","6.1.3","7.3.4" + $TestNumbers = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4" if (-not $ExportPath) { Write-Error "ExportPath is required when exporting all test results." return @@ -71,6 +70,19 @@ function Export-M365SecurityAuditTable { } switch ($test) { + "6.1.2" { + $details = $auditResult.Details + $csv = $details | ConvertFrom-Csv -Delimiter '|' + + foreach ($row in $csv) { + $row.AdminActionsMissing = (Get-Action -AbbreviatedActions $row.AdminActionsMissing.Split(',') -ReverseActionType Admin | Where-Object { $_ -notin @("MailItemsAccessed", "Send") }) -join ',' + $row.DelegateActionsMissing = (Get-Action -AbbreviatedActions $row.DelegateActionsMissing.Split(',') -ReverseActionType Delegate | Where-Object { $_ -notin @("MailItemsAccessed") }) -join ',' + $row.OwnerActionsMissing = (Get-Action -AbbreviatedActions $row.OwnerActionsMissing.Split(',') -ReverseActionType Owner | Where-Object { $_ -notin @("MailItemsAccessed", "Send") }) -join ',' + } + + $newObjectDetails = $csv + $results += [PSCustomObject]@{ TestNumber = $test; Details = $newObjectDetails } + } "6.1.3" { $details = $auditResult.Details $csv = $details | ConvertFrom-Csv -Delimiter '|' @@ -84,9 +96,6 @@ function Export-M365SecurityAuditTable { $newObjectDetails = $csv $results += [PSCustomObject]@{ TestNumber = $test; Details = $newObjectDetails } } - "7.3.4" { - # Placeholder for specific logic for 7.3.4 if needed - } Default { $details = $auditResult.Details $csv = $details | ConvertFrom-Csv -Delimiter '|' @@ -101,10 +110,11 @@ function Export-M365SecurityAuditTable { $testDef = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $result.TestNumber } if ($testDef) { $fileName = "$ExportPath\$($timestamp)_$($result.TestNumber).$($testDef.TestFileName -replace '\.ps1$').csv" - $result.Details | Out-File -FilePath $fileName + $result.Details | Export-Csv -Path $fileName -NoTypeInformation -Delimiter '|' } } - } else { + } + else { return $results.Details } -} \ No newline at end of file +} diff --git a/source/tests/Test-AdministrativeAccountCompliance.ps1 b/source/tests/Test-AdministrativeAccountCompliance.ps1 index 2a1b0a8..35dbe6f 100644 --- a/source/tests/Test-AdministrativeAccountCompliance.ps1 +++ b/source/tests/Test-AdministrativeAccountCompliance.ps1 @@ -101,7 +101,7 @@ function Test-AdministrativeAccountCompliance { $result = $nonCompliantUsers.Count -eq 0 $status = if ($result) { 'Pass' } else { 'Fail' } - $details = if ($nonCompliantUsers) { "Non-compliant accounts: `nUsername | Roles | Cloud-Only Status | Entra ID License Status | Other Applications Assigned Status`n$failureReasons" } else { "N/A" } + $details = if ($nonCompliantUsers) { "Username | Roles | Cloud-Only Status | Entra ID License Status | Other Applications Assigned Status`n$failureReasons" } else { "N/A" } Write-Verbose "Assessment completed. Result: $status" diff --git a/source/tests/Test-MailboxAuditingE3.ps1 b/source/tests/Test-MailboxAuditingE3.ps1 index d7c699a..40dd9c1 100644 --- a/source/tests/Test-MailboxAuditingE3.ps1 +++ b/source/tests/Test-MailboxAuditingE3.ps1 @@ -29,21 +29,22 @@ function Test-MailboxAuditingE3 { # Dot source the class script if necessary #. .\source\Classes\CISAuditResult.ps1 - $e3SkuPartNumber = "SPE_E3" - $AdminActions = @("ApplyRecord", "Copy", "Create", "FolderBind", "HardDelete", "Move", "MoveToDeletedItems", "SendAs", "SendOnBehalf", "SoftDelete", "Update", "UpdateCalendarDelegation", "UpdateFolderPermissions", "UpdateInboxRules") - $DelegateActions = @("ApplyRecord", "Create", "FolderBind", "HardDelete", "Move", "MoveToDeletedItems", "SendAs", "SendOnBehalf", "SoftDelete", "Update", "UpdateFolderPermissions", "UpdateInboxRules") - $OwnerActions = @("ApplyRecord", "Create", "HardDelete", "MailboxLogin", "Move", "MoveToDeletedItems", "SoftDelete", "Update", "UpdateCalendarDelegation", "UpdateFolderPermissions", "UpdateInboxRules") + $e3SkuPartNumber = "SPE_E5" + + $actionDictionaries = Get-Action -Dictionaries + # E3 specific actions + $AdminActions = $actionDictionaries.AdminActions.Keys | Where-Object { $_ -notin @("MailItemsAccessed", "Send") } + $DelegateActions = $actionDictionaries.DelegateActions.Keys | Where-Object { $_ -notin @("MailItemsAccessed") } + $OwnerActions = $actionDictionaries.OwnerActions.Keys | Where-Object { $_ -notin @("MailItemsAccessed", "Send") } $allFailures = @() - #$allUsers = Get-AzureADUser -All $true - $founde3Sku = Get-MgSubscribedSku -All | Where-Object {$_.SkuPartNumber -eq $e3SkuPartNumber} + $founde3Sku = Get-MgSubscribedSku -All | Where-Object { $_.SkuPartNumber -eq $e3SkuPartNumber } $processedUsers = @{} # Dictionary to track processed users $recnum = "6.1.2" } - process { - if (($founde3Sku.count)-ne 0) { + if ($founde3Sku.Count -ne 0) { $allUsers = Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($founde3Sku.SkuId) )" -All $mailboxes = Get-EXOMailbox -PropertySets Audit try { @@ -53,36 +54,36 @@ function Test-MailboxAuditingE3 { continue } - #$licenseDetails = Get-MgUserLicenseDetail -UserId $user.UserPrincipalName - #$hasOfficeE3 = ($licenseDetails | Where-Object { $_.SkuPartNumber -in $e3SkuPartNumbers }).Count -gt 0 - #Write-Verbose "Evaluating user $($user.UserPrincipalName) for Office E3 license." - $userUPN = $user.UserPrincipalName $mailbox = $mailboxes | Where-Object { $_.UserPrincipalName -eq $user.UserPrincipalName } - $missingActions = @() + $missingAdminActions = @() + $missingDelegateActions = @() + $missingOwnerActions = @() + if ($mailbox.AuditEnabled) { foreach ($action in $AdminActions) { - # Condition B: Checking if the `AuditAdmin` actions include required actions - if ($mailbox.AuditAdmin -notcontains $action) { $missingActions += "Admin action '$action' missing" } + if ($mailbox.AuditAdmin -notcontains $action) { + $missingAdminActions += (Get-Action -Actions $action -ActionType "Admin") + } } foreach ($action in $DelegateActions) { - # Condition C: Checking if the `AuditDelegate` actions include required actions - if ($mailbox.AuditDelegate -notcontains $action) { $missingActions += "Delegate action '$action' missing" } + if ($mailbox.AuditDelegate -notcontains $action) { + $missingDelegateActions += (Get-Action -Actions $action -ActionType "Delegate") + } } foreach ($action in $OwnerActions) { - # Condition D: Checking if the `AuditOwner` actions include required actions - if ($mailbox.AuditOwner -notcontains $action) { $missingActions += "Owner action '$action' missing" } + if ($mailbox.AuditOwner -notcontains $action) { + $missingOwnerActions += (Get-Action -Actions $action -ActionType "Owner") + } } - if ($missingActions.Count -gt 0) { - $formattedActions = Format-MissingAction -missingActions $missingActions - $allFailures += "$userUPN|True|$($formattedActions.Admin)|$($formattedActions.Delegate)|$($formattedActions.Owner)" + if ($missingAdminActions.Count -gt 0 -or $missingDelegateActions.Count -gt 0 -or $missingOwnerActions.Count -gt 0) { + $allFailures += "$userUPN|True|$($missingAdminActions -join ',')|$($missingDelegateActions -join ',')|$($missingOwnerActions -join ',')" } } else { - # Condition A: Checking if mailbox audit logging is enabled - $allFailures += "$userUPN|False|||" + $allFailures += "$userUPN|False|||" # Condition A for fail } # Mark the user as processed @@ -90,7 +91,12 @@ function Test-MailboxAuditingE3 { } # Prepare failure reasons and details based on compliance - $failureReasons = if ($allFailures.Count -eq 0) { "N/A" } else { "Audit issues detected." } + if ($allFailures.Count -eq 0) { + $failureReasons = "N/A" + } + else { + $failureReasons = "Audit issues detected." + } $details = if ($allFailures.Count -eq 0) { "All Office E3 users have correct mailbox audit settings." } @@ -134,14 +140,13 @@ function Test-MailboxAuditingE3 { } end { - #$verbosePreference = 'Continue' $detailsLength = $details.Length Write-Verbose "Character count of the details: $detailsLength" if ($detailsLength -gt 32767) { Write-Verbose "Warning: The character count exceeds the limit for Excel cells." } - #$verbosePreference = 'SilentlyContinue' + return $auditResult } }