diff --git a/helpers/Build-Help.ps1 b/helpers/Build-Help.ps1 index bebbbf8..fe923fc 100644 --- a/helpers/Build-Help.ps1 +++ b/helpers/Build-Help.ps1 @@ -4,7 +4,7 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1 <# - $ver = "v0.1.9" + $ver = "v0.1.10" git checkout main git pull origin main git tag -a $ver -m "Release version $ver refactor Update" diff --git a/source/Private/Connect-M365Suite.ps1 b/source/Private/Connect-M365Suite.ps1 index 1d57549..04fe394 100644 --- a/source/Private/Connect-M365Suite.ps1 +++ b/source/Private/Connect-M365Suite.ps1 @@ -18,7 +18,7 @@ function Connect-M365Suite { Write-Host "Successfully connected to Azure Active Directory." -ForegroundColor Green } - if ($RequiredConnections -contains "Microsoft Graph" -or $RequiredConnections -contains "AzureAD | EXO | Microsoft Graph") { + if ($RequiredConnections -contains "Microsoft Graph" -or $RequiredConnections -contains "EXO | Microsoft Graph") { Write-Host "Connecting to Microsoft Graph with scopes: Directory.Read.All, Domain.Read.All, Policy.Read.All, Organization.Read.All" -ForegroundColor Cyan try { Connect-MgGraph -Scopes "Directory.Read.All", "Domain.Read.All", "Policy.Read.All", "Organization.Read.All" -NoWelcome | Out-Null @@ -31,7 +31,7 @@ function Connect-M365Suite { } } - if ($RequiredConnections -contains "EXO" -or $RequiredConnections -contains "AzureAD | EXO" -or $RequiredConnections -contains "Microsoft Teams | EXO" -or $RequiredConnections -contains "AzureAD | EXO | Microsoft Graph") { + if ($RequiredConnections -contains "EXO" -or $RequiredConnections -contains "AzureAD | EXO" -or $RequiredConnections -contains "Microsoft Teams | EXO" -or $RequiredConnections -contains "EXO | Microsoft Graph") { Write-Host "Connecting to Exchange Online..." -ForegroundColor Cyan Connect-ExchangeOnline | Out-Null Write-Host "Successfully connected to Exchange Online." -ForegroundColor Green diff --git a/source/helper/TestDefinitions.csv b/source/helper/TestDefinitions.csv index 63434ec..d3f4e8c 100644 --- a/source/helper/TestDefinitions.csv +++ b/source/helper/TestDefinitions.csv @@ -18,8 +18,8 @@ 17,Test-RestrictTenantCreation.ps1,5.1.2.3,Ensure 'Restrict non-admin users from creating tenants' is set to 'Yes',E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Graph 18,Test-PasswordHashSync.ps1,5.1.8.1,Ensure password hash sync is enabled for hybrid deployments,E3,L1,6.7,Centralize Access Control,FALSE,TRUE,TRUE,TRUE,Microsoft Graph 19,Test-AuditDisabledFalse.ps1,6.1.1,Ensure 'AuditDisabled' organizationally is set to 'False',E3,L1,8.2,Collect Audit Logs,TRUE,TRUE,TRUE,TRUE,Microsoft Graph -20,Test-MailboxAuditingE3.ps1,6.1.2,Ensure mailbox auditing for Office E3 users is Enabled,E3,L1,8.2,Collect audit logs.,TRUE,TRUE,TRUE,TRUE,AzureAD | EXO | Microsoft Graph -21,Test-MailboxAuditingE5.ps1,6.1.3,Ensure mailbox auditing for Office E5 users is Enabled,E5,L1,8.2,Collect audit logs.,TRUE,TRUE,TRUE,TRUE,AzureAD | EXO | Microsoft Graph +20,Test-MailboxAuditingE3.ps1,6.1.2,Ensure mailbox auditing for Office E3 users is Enabled,E3,L1,8.2,Collect audit logs.,TRUE,TRUE,TRUE,TRUE,EXO | Microsoft Graph +21,Test-MailboxAuditingE5.ps1,6.1.3,Ensure mailbox auditing for Office E5 users is Enabled,E5,L1,8.2,Collect audit logs.,TRUE,TRUE,TRUE,TRUE,EXO | Microsoft Graph 22,Test-BlockMailForwarding.ps1,6.2.1,Ensure all forms of mail forwarding are blocked and/or disabled,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,EXO 23,Test-NoWhitelistDomains.ps1,6.2.2,Ensure mail transport rules do not whitelist specific domains,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,EXO 24,Test-IdentifyExternalEmail.ps1,6.2.3,Ensure email from external senders is identified,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,EXO diff --git a/source/tests/Test-MailboxAuditingE3.ps1 b/source/tests/Test-MailboxAuditingE3.ps1 index 010b049..59ead24 100644 --- a/source/tests/Test-MailboxAuditingE3.ps1 +++ b/source/tests/Test-MailboxAuditingE3.ps1 @@ -29,30 +29,33 @@ function Test-MailboxAuditingE3 { # Dot source the class script if necessary #. .\source\Classes\CISAuditResult.ps1 - $e3SkuPartNumbers = @("ENTERPRISEPACK", "OFFICESUBSCRIPTION") + $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") $allFailures = @() - $allUsers = Get-AzureADUser -All $true + #$allUsers = Get-AzureADUser -All $true + $founde3Sku = Get-MgSubscribedSku -All | Where-Object {$_.SkuPartNumber -eq $e3SkuPartNumber} $processedUsers = @{} # Dictionary to track processed users $recnum = "6.1.2" } + process { - try { - foreach ($user in $allUsers) { - if ($processedUsers.ContainsKey($user.UserPrincipalName)) { - Write-Verbose "Skipping already processed user: $($user.UserPrincipalName)" - continue - } + if ($null -ne $founde3Sku) { + $allUsers = Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($founde3Sku.SkuId) )" -All + try { + foreach ($user in $allUsers) { + if ($processedUsers.ContainsKey($user.UserPrincipalName)) { + Write-Verbose "Skipping already processed user: $($user.UserPrincipalName)" + 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." + #$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." - if ($hasOfficeE3) { $userUPN = $user.UserPrincipalName $mailbox = Get-EXOMailbox -Identity $userUPN -PropertySets Audit @@ -84,39 +87,49 @@ function Test-MailboxAuditingE3 { # Mark the user as processed $processedUsers[$user.UserPrincipalName] = $true } - } - # Prepare failure reasons and details based on compliance - $failureReasons = if ($allFailures.Count -eq 0) { "N/A" } else { "Audit issues detected." } - $details = if ($allFailures.Count -eq 0) { - "All Office E3 users have correct mailbox audit settings." - } - else { - "UserPrincipalName|AuditEnabled|AdminActionsMissing|DelegateActionsMissing|OwnerActionsMissing`n" + ($allFailures -join "`n") - } + # Prepare failure reasons and details based on compliance + $failureReasons = if ($allFailures.Count -eq 0) { "N/A" } else { "Audit issues detected." } + $details = if ($allFailures.Count -eq 0) { + "All Office E3 users have correct mailbox audit settings." + } + else { + "UserPrincipalName|AuditEnabled|AdminActionsMissing|DelegateActionsMissing|OwnerActionsMissing`n" + ($allFailures -join "`n") + } - # Populate the audit result + # Populate the audit result + $params = @{ + Rec = $recnum + Result = $allFailures.Count -eq 0 + Status = if ($allFailures.Count -eq 0) { "Pass" } else { "Fail" } + Details = $details + FailureReason = $failureReasons + } + $auditResult = Initialize-CISAuditResult @params + } + catch { + Write-Error "An error occurred during the test: $_" + + # Retrieve the description from the test definitions + $testDefinition = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $recnum } + $description = if ($testDefinition) { $testDefinition.RecDescription } else { "Description not found" } + + $script:FailedTests.Add([PSCustomObject]@{ Rec = $recnum; Description = $description; Error = $_ }) + + # Call Initialize-CISAuditResult with error parameters + $auditResult = Initialize-CISAuditResult -Rec $recnum -Failure + } + } + else { $params = @{ Rec = $recnum - Result = $allFailures.Count -eq 0 - Status = if ($allFailures.Count -eq 0) { "Pass" } else { "Fail" } - Details = $details - FailureReason = $failureReasons + Result = $false + Status = "Fail" + Details = "No M365 E3 licenses found." + FailureReason = "The audit is for M365 E3 licenses, but no such licenses were found." } $auditResult = Initialize-CISAuditResult @params } - catch { - Write-Error "An error occurred during the test: $_" - - # Retrieve the description from the test definitions - $testDefinition = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $recnum } - $description = if ($testDefinition) { $testDefinition.RecDescription } else { "Description not found" } - - $script:FailedTests.Add([PSCustomObject]@{ Rec = $recnum; Description = $description; Error = $_ }) - - # Call Initialize-CISAuditResult with error parameters - $auditResult = Initialize-CISAuditResult -Rec $recnum -Failure - } } end { diff --git a/source/tests/Test-MailboxAuditingE5.ps1 b/source/tests/Test-MailboxAuditingE5.ps1 index f5c3891..62ec0cb 100644 --- a/source/tests/Test-MailboxAuditingE5.ps1 +++ b/source/tests/Test-MailboxAuditingE5.ps1 @@ -27,30 +27,32 @@ function Test-MailboxAuditingE5 { # - Condition C: AuditDelegate actions do not include all of the following: ApplyRecord, Create, HardDelete, MailItemsAccessed, MoveToDeletedItems, SendAs, SendOnBehalf, SoftDelete, Update, UpdateFolderPermissions, UpdateInboxRules. # - Condition D: AuditOwner actions do not include all of the following: ApplyRecord, HardDelete, MailItemsAccessed, MoveToDeletedItems, Send, SoftDelete, Update, UpdateCalendarDelegation, UpdateFolderPermissions, UpdateInboxRules. - $e5SkuPartNumbers = @("SPE_E5", "ENTERPRISEPREMIUM", "OFFICEE5") + $e5SkuPartNumber = "SPE_E5" $AdminActions = @("ApplyRecord", "Copy", "Create", "FolderBind", "HardDelete", "MailItemsAccessed", "Move", "MoveToDeletedItems", "SendAs", "SendOnBehalf", "Send", "SoftDelete", "Update", "UpdateCalendarDelegation", "UpdateFolderPermissions", "UpdateInboxRules") $DelegateActions = @("ApplyRecord", "Create", "FolderBind", "HardDelete", "MailItemsAccessed", "Move", "MoveToDeletedItems", "SendAs", "SendOnBehalf", "SoftDelete", "Update", "UpdateFolderPermissions", "UpdateInboxRules") $OwnerActions = @("ApplyRecord", "Create", "HardDelete", "MailboxLogin", "Move", "MailItemsAccessed", "MoveToDeletedItems", "Send", "SoftDelete", "Update", "UpdateCalendarDelegation", "UpdateFolderPermissions", "UpdateInboxRules") $allFailures = @() - $allUsers = Get-AzureADUser -All $true + #$allUsers = Get-AzureADUser -All $true + $founde5Sku = Get-MgSubscribedSku -All | Where-Object { $_.SkuPartNumber -eq $e5SkuPartNumber } $processedUsers = @{} # Dictionary to track processed users $recnum = "6.1.3" } process { - try { - foreach ($user in $allUsers) { - if ($processedUsers.ContainsKey($user.UserPrincipalName)) { - Write-Verbose "Skipping already processed user: $($user.UserPrincipalName)" - continue - } + if ($null -ne $founde5Sku) { + $allUsers = Get-MgUser -Filter "assignedLicenses/any(x:x/skuId eq $($founde5Sku.SkuId) )" -All + try { + foreach ($user in $allUsers) { + if ($processedUsers.ContainsKey($user.UserPrincipalName)) { + Write-Verbose "Skipping already processed user: $($user.UserPrincipalName)" + continue + } - $licenseDetails = Get-MgUserLicenseDetail -UserId $user.UserPrincipalName - $hasOfficeE5 = ($licenseDetails | Where-Object { $_.SkuPartNumber -in $e5SkuPartNumbers }).Count -gt 0 - Write-Verbose "Evaluating user $($user.UserPrincipalName) for Office E5 license." + #$licenseDetails = Get-MgUserLicenseDetail -UserId $user.UserPrincipalName + #$hasOfficeE5 = ($licenseDetails | Where-Object { $_.SkuPartNumber -in $e5SkuPartNumbers }).Count -gt 0 + #Write-Verbose "Evaluating user $($user.UserPrincipalName) for Office E5 license." - if ($hasOfficeE5) { $userUPN = $user.UserPrincipalName $mailbox = Get-EXOMailbox -Identity $userUPN -PropertySets Audit @@ -81,39 +83,49 @@ function Test-MailboxAuditingE5 { # Mark the user as processed $processedUsers[$user.UserPrincipalName] = $true } - } - # Prepare failure reasons and details based on compliance - $failureReasons = if ($allFailures.Count -eq 0) { "N/A" } else { "Audit issues detected." } - $details = if ($allFailures.Count -eq 0) { - "All Office E5 users have correct mailbox audit settings." # Condition A for pass - } - else { - "UserPrincipalName|AuditEnabled|AdminActionsMissing|DelegateActionsMissing|OwnerActionsMissing`n" + ($allFailures -join "`n") # Condition A for fail - } + # Prepare failure reasons and details based on compliance + $failureReasons = if ($allFailures.Count -eq 0) { "N/A" } else { "Audit issues detected." } + $details = if ($allFailures.Count -eq 0) { + "All Office E5 users have correct mailbox audit settings." # Condition A for pass + } + else { + "UserPrincipalName|AuditEnabled|AdminActionsMissing|DelegateActionsMissing|OwnerActionsMissing`n" + ($allFailures -join "`n") # Condition A for fail + } - # Populate the audit result + # Populate the audit result + $params = @{ + Rec = $recnum + Result = $allFailures.Count -eq 0 + Status = if ($allFailures.Count -eq 0) { "Pass" } else { "Fail" } + Details = $details + FailureReason = $failureReasons + } + $auditResult = Initialize-CISAuditResult @params + } + catch { + Write-Error "An error occurred during the test: $_" + + # Retrieve the description from the test definitions + $testDefinition = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $recnum } + $description = if ($testDefinition) { $testDefinition.RecDescription } else { "Description not found" } + + $script:FailedTests.Add([PSCustomObject]@{ Rec = $recnum; Description = $description; Error = $_ }) + + # Call Initialize-CISAuditResult with error parameters + $auditResult = Initialize-CISAuditResult -Rec $recnum -Failure + } + } + else { $params = @{ Rec = $recnum - Result = $allFailures.Count -eq 0 - Status = if ($allFailures.Count -eq 0) { "Pass" } else { "Fail" } - Details = $details - FailureReason = $failureReasons + Result = $false + Status = "Fail" + Details = "No M365 E5 licenses found." + FailureReason = "The audit is for M365 E5 licenses, but no such licenses were found." } $auditResult = Initialize-CISAuditResult @params } - catch { - Write-Error "An error occurred during the test: $_" - - # Retrieve the description from the test definitions - $testDefinition = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $recnum } - $description = if ($testDefinition) { $testDefinition.RecDescription } else { "Description not found" } - - $script:FailedTests.Add([PSCustomObject]@{ Rec = $recnum; Description = $description; Error = $_ }) - - # Call Initialize-CISAuditResult with error parameters - $auditResult = Initialize-CISAuditResult -Rec $recnum -Failure - } } end {