docs: Comment conditions on each test

This commit is contained in:
DrIOS
2024-06-11 13:03:59 -05:00
parent f85101d0de
commit e6b6e064bf
13 changed files with 298 additions and 82 deletions

View File

@@ -4,7 +4,7 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1
<#
$ver = "v0.1.8"
$ver = "v0.1.9"
git checkout main
git pull origin main
git tag -a $ver -m "Release version $ver refactor Update"

View File

@@ -2,29 +2,44 @@ function Test-BlockSharedMailboxSignIn {
[CmdletBinding()]
[OutputType([CISAuditResult])]
param (
# Aligned
# Parameters can be added if needed
)
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "1.2.2"
# Conditions for 1.2.2 (L1) Ensure sign-in to shared mailboxes is blocked
#
# Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: No shared mailboxes have the "Sign-in blocked" option disabled in the properties pane on the Microsoft 365 admin center.
# - Condition B: Using PowerShell, the `AccountEnabled` property for all shared mailboxes is set to `False`.
#
# Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
# - Condition A: One or more shared mailboxes have the "Sign-in blocked" option enabled in the properties pane on the Microsoft 365 admin center.
# - Condition B: Using PowerShell, the `AccountEnabled` property for one or more shared mailboxes is set to `True`.
}
process {
try {
# 1.2.2 (L1) Ensure sign-in to shared mailboxes is blocked
# Retrieve shared mailbox details
# Step: Retrieve shared mailbox details
$MBX = Get-EXOMailbox -RecipientTypeDetails SharedMailbox
# Step: Retrieve details of shared mailboxes from Azure AD (Condition B: Pass/Fail)
$sharedMailboxDetails = $MBX | ForEach-Object { Get-AzureADUser -ObjectId $_.ExternalDirectoryObjectId }
# Step: Identify enabled mailboxes (Condition B: Pass/Fail)
$enabledMailboxes = $sharedMailboxDetails | Where-Object { $_.AccountEnabled } | ForEach-Object { $_.DisplayName }
$allBlocked = $enabledMailboxes.Count -eq 0
# Prepare failure reasons and details based on compliance
# Step: Determine failure reasons based on enabled mailboxes (Condition A & B: Fail)
$failureReasons = if (-not $allBlocked) {
"Some mailboxes have sign-in enabled: $($enabledMailboxes -join ', ')"
}
@@ -32,6 +47,7 @@ function Test-BlockSharedMailboxSignIn {
"N/A"
}
# Step: Prepare details for the audit result (Condition A & B: Pass/Fail)
$details = if ($allBlocked) {
"All shared mailboxes have sign-in blocked."
}
@@ -39,10 +55,10 @@ function Test-BlockSharedMailboxSignIn {
"Enabled Mailboxes: $($enabledMailboxes -join ', ')"
}
# Create and populate the CISAuditResult object
# Step: Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
Result = $allBlocked
Result = $allBlocked # Pass: Condition A, Condition B
Status = if ($allBlocked) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons

View File

@@ -7,6 +7,24 @@ function Test-CommonAttachmentFilter {
)
begin {
<#
Conditions for 2.1.2 (L1) Ensure the Common Attachment Types Filter is enabled
Validate test for a pass:
- Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
- Specific conditions to check:
- Condition A: The Common Attachment Types Filter is enabled in the Microsoft 365 Security & Compliance Center.
- Condition B: Using Exchange Online PowerShell, verify that the `EnableFileFilter` property of the default malware filter policy is set to `True`.
- Condition C: Ensure that the setting is enabled in the highest priority policy listed if custom policies exist.
Validate test for a fail:
- Confirm that the failure conditions in the automated test are consistent with the manual audit results.
- Specific conditions to check:
- Condition A: The Common Attachment Types Filter is not enabled in the Microsoft 365 Security & Compliance Center.
- Condition B: Using Exchange Online PowerShell, verify that the `EnableFileFilter` property of the default malware filter policy is set to `False`.
- Condition C: Ensure that the setting is not enabled in the highest priority policy listed if custom policies exist.
#>
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
@@ -16,6 +34,8 @@ function Test-CommonAttachmentFilter {
process {
try {
# 2.1.2 (L1) Ensure the Common Attachment Types Filter is enabled
# Condition A: The Common Attachment Types Filter is enabled in the Microsoft 365 Security & Compliance Center.
# Condition B: Using Exchange Online PowerShell, verify that the `EnableFileFilter` property of the default malware filter policy is set to `True`.
# Retrieve the attachment filter policy
$attachmentFilter = Get-MalwareFilterPolicy -Identity Default | Select-Object EnableFileFilter
@@ -23,6 +43,8 @@ function Test-CommonAttachmentFilter {
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $result) {
# Condition A: The Common Attachment Types Filter is not enabled in the Microsoft 365 Security & Compliance Center.
# Condition B: Using Exchange Online PowerShell, verify that the `EnableFileFilter` property of the default malware filter policy is set to `False`.
"Common Attachment Types Filter is disabled"
}
else {

View File

@@ -9,43 +9,58 @@ function Test-CustomerLockbox {
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "1.3.6"
# Conditions for 1.3.6 (L2) Ensure the customer lockbox feature is enabled (Automated)
#
# Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: In the Microsoft 365 admin center, the box labeled "Customer Lockbox Requests" is checked.
# - Condition B: Using the SecureScore portal, the Customer Lockbox feature is enabled.
# - Condition C: Using PowerShell, the Customer Lockbox feature is set to `True`.
#
# Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
# - Condition A: In the Microsoft 365 admin center, the box labeled "Customer Lockbox Requests" is not checked.
# - Condition B: Using the SecureScore portal, the Customer Lockbox feature is not enabled.
# - Condition C: Using PowerShell, the Customer Lockbox feature is not set to `True`.
}
process {
try {
# 1.3.6 (L2) Ensure the customer lockbox feature is enabled
# Step: Retrieve the organization configuration (Condition C: Pass/Fail)
$orgConfig = Get-OrganizationConfig | Select-Object CustomerLockBoxEnabled
$customerLockboxEnabled = $orgConfig.CustomerLockBoxEnabled
# Retrieve the organization configuration
$orgConfig = Get-OrganizationConfig | Select-Object CustomerLockBoxEnabled
$customerLockboxEnabled = $orgConfig.CustomerLockBoxEnabled
# Step: Prepare failure reasons and details based on compliance (Condition A, B, & C: Fail)
$failureReasons = if (-not $customerLockboxEnabled) {
"Customer lockbox feature is not enabled."
}
else {
"N/A"
}
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $customerLockboxEnabled) {
"Customer lockbox feature is not enabled."
}
else {
"N/A"
}
# Step: Prepare details for the audit result (Condition A, B, & C: Pass/Fail)
$details = if ($customerLockboxEnabled) {
"Customer Lockbox Enabled: True"
}
else {
"Customer Lockbox Enabled: False"
}
$details = if ($customerLockboxEnabled) {
"Customer Lockbox Enabled: True"
}
else {
"Customer Lockbox Enabled: False"
}
# Create and populate the CISAuditResult object #
$params = @{
Rec = $recnum
Result = $customerLockboxEnabled
Status = if ($customerLockboxEnabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
# Step: Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
Result = $customerLockboxEnabled
Status = if ($customerLockboxEnabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
}
catch {
Write-Error "An error occurred during the test: $_"

View File

@@ -12,17 +12,28 @@ function Test-ExternalSharingCalendars {
# Initialization code, if needed
$recnum = "1.3.3"
# Conditions for 1.3.3 (L2) Ensure 'External sharing' of calendars is not available (Automated)
#
# Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: In the Microsoft 365 admin center, external calendar sharing is disabled.
# - Condition B: Using the Exchange Online PowerShell Module, the `OrganizationConfig` property `ExternalSharingEnabled` is set to `False`.
#
# Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
# - Condition A: In the Microsoft 365 admin center, external calendar sharing is enabled.
# - Condition B: Using the Exchange Online PowerShell Module, the `OrganizationConfig` property `ExternalSharingEnabled` is set to `True`.
}
process {
try {
# 1.3.3 (L2) Ensure 'External sharing' of calendars is not available (Automated)
# Retrieve sharing policies related to calendar sharing
# Step: Retrieve sharing policies related to calendar sharing
$sharingPolicies = Get-SharingPolicy | Where-Object { $_.Domains -like '*CalendarSharing*' }
# Check if calendar sharing is disabled in all applicable policies
# Step (Condition A & B: Pass/Fail): Check if calendar sharing is disabled in all applicable policies
$isExternalSharingDisabled = $true
$sharingPolicyDetails = @()
foreach ($policy in $sharingPolicies) {
@@ -32,7 +43,7 @@ function Test-ExternalSharingCalendars {
}
}
# Prepare failure reasons and details based on compliance
# Step: Prepare failure reasons and details based on compliance (Condition A & B: Fail)
$failureReasons = if (-not $isExternalSharingDisabled) {
"Calendar sharing with external users is enabled in one or more policies."
}
@@ -40,6 +51,7 @@ function Test-ExternalSharingCalendars {
"N/A"
}
# Step: Prepare details for the audit result (Condition A & B: Pass/Fail)
$details = if ($isExternalSharingDisabled) {
"Calendar sharing with external users is disabled."
}
@@ -47,7 +59,7 @@ function Test-ExternalSharingCalendars {
"Enabled Sharing Policies: $($sharingPolicyDetails -join ', ')"
}
# Create and populate the CISAuditResult object
# Step: Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
Result = $isExternalSharingDisabled

View File

@@ -2,13 +2,27 @@ function Test-GlobalAdminsCount {
[CmdletBinding()]
[OutputType([CISAuditResult])]
param (
# Aligned
# Define your parameters here if needed
)
begin {
# Dot source the class script if necessary
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Conditions for 1.1.3 (L1) Ensure that between two and four global admins are designated
#
# Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: The number of global admins is at least 2.
# - Condition B: The number of global admins is at most 4.
# - Condition C: The list of global admin usernames is accurately retrieved and displayed.
#
# Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
# - Condition A: The number of global admins is less than 2.
# - Condition B: The number of global admins is more than 4.
# - Condition C: Any discrepancies or errors in retrieving the list of global admin usernames.
# Initialization code, if needed
$recnum = "1.1.3"
@@ -16,17 +30,21 @@ function Test-GlobalAdminsCount {
process {
try {
# 1.1.3 (L1) Ensure that between two and four global admins are designated
# Retrieve global admin role and members
# Step: Retrieve global admin role
$globalAdminRole = Get-MgDirectoryRole -Filter "RoleTemplateId eq '62e90394-69f5-4237-9190-012177145e10'"
# Step: Retrieve global admin members
$globalAdmins = Get-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id
# Step: Count the number of global admins
$globalAdminCount = $globalAdmins.Count
# Step: Retrieve and format the usernames of global admins
$globalAdminUsernames = ($globalAdmins | ForEach-Object {
"$($_.AdditionalProperties["displayName"]) ($($_.AdditionalProperties["userPrincipalName"]))"
}) -join ', '
# Prepare failure reasons and details based on compliance
# Step: Determine failure reasons based on global admin count
$failureReasons = if ($globalAdminCount -lt 2) {
"Less than 2 global admins: $globalAdminUsernames"
}
@@ -37,9 +55,10 @@ function Test-GlobalAdminsCount {
"N/A"
}
# Step: Prepare details for the audit result
$details = "Count: $globalAdminCount; Users: $globalAdminUsernames"
# Create and populate the CISAuditResult object
# Step: Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
Result = $globalAdminCount -ge 2 -and $globalAdminCount -le 4

View File

@@ -2,25 +2,37 @@ function Test-ManagedApprovedPublicGroups {
[CmdletBinding()]
[OutputType([CISAuditResult])]
param (
# Aligned
# Parameters can be added if needed
)
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "1.2.1"
# Conditions for 1.2.1 (L2) Ensure that only organizationally managed/approved public groups exist (Automated)
#
# Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: No groups have the status 'Public' in the privacy column on the Active teams and groups page.
# - Condition B: Using Microsoft Graph PowerShell, all groups return a status other than 'Public' when checked.
#
# Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
# - Condition A: One or more groups have the status 'Public' in the privacy column on the Active teams and groups page.
# - Condition B: Using Microsoft Graph PowerShell, one or more groups return a status of 'Public' when checked.
}
process {
try {
# 1.2.1 (L2) Ensure that only organizationally managed/approved public groups exist (Automated)
# Retrieve all public groups
# Step: Retrieve all groups with visibility set to 'Public'
$allGroups = Get-MgGroup -All | Where-Object { $_.Visibility -eq "Public" } | Select-Object DisplayName, Visibility
# Prepare failure reasons and details based on compliance
# Step: Determine failure reasons based on the presence of public groups
$failureReasons = if ($null -ne $allGroups -and $allGroups.Count -gt 0) {
"There are public groups present that are not organizationally managed/approved."
}
@@ -28,6 +40,7 @@ function Test-ManagedApprovedPublicGroups {
"N/A"
}
# Step: Prepare details for the audit result
$details = if ($null -eq $allGroups -or $allGroups.Count -eq 0) {
"No public groups found."
}
@@ -36,7 +49,7 @@ function Test-ManagedApprovedPublicGroups {
"Public groups found: $($groupDetails -join ', ')"
}
# Create and populate the CISAuditResult object
# Step: Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
Result = $null -eq $allGroups -or $allGroups.Count -eq 0
@@ -61,7 +74,7 @@ function Test-ManagedApprovedPublicGroups {
}
end {
# Return auditResults
# Return the audit result
return $auditResult
}
}

View File

@@ -7,6 +7,22 @@ function Test-NotifyMalwareInternal {
)
begin {
<#
# Conditions for 2.1.3 (L1) Ensure notifications for internal users sending malware is Enabled
#
# Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: Notifications for internal users sending malware are enabled in the Microsoft 365 Security & Compliance Center.
# - Condition B: Using PowerShell, the `NotifyInternal` property in the anti-malware policy is set to `True` and includes at least one valid email address for notifications.
#
# Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
# - Condition A: Notifications for internal users sending malware are not enabled in the Microsoft 365 Security & Compliance Center.
# - Condition B: Using PowerShell, the `NotifyInternal` property in the anti-malware policy is set to `False` or does not include any valid email addresses for notifications.
#>
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
@@ -19,8 +35,9 @@ function Test-NotifyMalwareInternal {
# Retrieve all 'Custom' malware filter policies and check notification settings
$malwareNotifications = Get-MalwareFilterPolicy | Where-Object { $_.RecommendedPolicyType -eq 'Custom' }
$policiesToReport = @()
# Condition B: Using PowerShell, the `NotifyInternal` property in the anti-malware policy is set to `True` and includes at least one valid email address for notifications.
$policiesToReport = @()
foreach ($policy in $malwareNotifications) {
if ($policy.EnableInternalSenderAdminNotifications -ne $true) {
$policiesToReport += "$($policy.Identity): Notifications Disabled"
@@ -35,6 +52,7 @@ function Test-NotifyMalwareInternal {
"N/A"
}
else {
# Condition A: Notifications for internal users sending malware are not enabled in the Microsoft 365 Security & Compliance Center.
"Some custom policies do not have notifications for internal users sending malware enabled."
}

View File

@@ -7,6 +7,7 @@ function Test-PasswordNeverExpirePolicy {
)
begin {
# .TODO add supported services to output details. ({Email, OfficeCommunicationsOnline, Intune})
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
@@ -17,11 +18,25 @@ function Test-PasswordNeverExpirePolicy {
# Add headers for the details
$detailsList += "Domain|Validity Period|IsDefault"
# Conditions for 1.3.1 (L1) Ensure the 'Password expiration policy' is set to 'Set passwords to never expire (recommended)'
#
# Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: Password expiration policy is set to "Set passwords to never expire" in the Microsoft 365 admin center.
# - Condition B: Using Microsoft Graph PowerShell, the `PasswordPolicies` property for all users is set to `DisablePasswordExpiration`.
#
# Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
# - Condition A: Password expiration policy is not set to "Set passwords to never expire" in the Microsoft 365 admin center.
# - Condition B: Using Microsoft Graph PowerShell, the `PasswordPolicies` property for one or more users is not set to `DisablePasswordExpiration`.
}
process {
try {
# Retrieve all domains or a specific domain
# Step: Retrieve all domains or a specific domain
$domains = if ($DomainName) {
Get-MgDomain -DomainId $DomainName
} else {
@@ -31,14 +46,14 @@ function Test-PasswordNeverExpirePolicy {
foreach ($domain in $domains) {
$domainName = $domain.Id
$isDefault = $domain.IsDefault
# Retrieve password expiration policy
# Step (Condition A): Retrieve password expiration policy
$passwordPolicy = $domain.PasswordValidityPeriodInDays
# Determine if the policy is compliant
# Step (Condition A & B): Determine if the policy is compliant
$isCompliant = $passwordPolicy -eq 0
$overallResult = $overallResult -and $isCompliant
# Prepare failure reasons and details based on compliance
# Step (Condition A & B): Prepare failure reasons and details based on compliance
$failureReasons = if ($isCompliant) {
"N/A"
} else {
@@ -56,7 +71,7 @@ function Test-PasswordNeverExpirePolicy {
$finalFailureReason = $failureReasonsList -join "`n"
$finalDetails = $detailsList -join "`n"
# Create and populate the CISAuditResult object
# Step: Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
Result = $overallResult

View File

@@ -9,8 +9,29 @@ function Test-SafeAttachmentsPolicy {
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "2.1.4"
<#
Conditions for 2.1.4 (L2) Ensure Safe Attachments policy is enabled
Validate test for a pass:
- Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
- Specific conditions to check:
- Condition A: The Safe Attachments policy is enabled in the Microsoft 365 Defender portal.
- Condition B: The policy covers all recipients within the organization.
- Condition C: The policy action is set to "Dynamic Delivery" or "Quarantine".
- Condition D: The policy is not disabled.
Validate test for a fail:
- Confirm that the failure conditions in the automated test are consistent with the manual audit results.
- Specific conditions to check:
- Condition A: The Safe Attachments policy is not enabled in the Microsoft 365 Defender portal.
- Condition B: The policy does not cover all recipients within the organization.
- Condition C: The policy action is not set to "Dynamic Delivery" or "Quarantine".
- Condition D: The policy is disabled.
#>
}
process {
@@ -20,8 +41,12 @@ function Test-SafeAttachmentsPolicy {
# Retrieve all Safe Attachment policies where Enable is set to True
$safeAttachmentPolicies = Get-SafeAttachmentPolicy | Where-Object { $_.Enable -eq $true }
# Determine result and details based on the presence of enabled policies
# Condition A: Check if any Safe Attachments policy is enabled
$result = $null -ne $safeAttachmentPolicies -and $safeAttachmentPolicies.Count -gt 0
# Condition B, C, D: Additional checks can be added here if more detailed policy attributes are required
# Determine details and failure reasons based on the presence of enabled policies
$details = if ($result) {
"Enabled Safe Attachments Policies: $($safeAttachmentPolicies.Name -join ', ')"
}
@@ -66,4 +91,3 @@ function Test-SafeAttachmentsPolicy {
}
}
# Additional helper functions (if any)

View File

@@ -9,6 +9,23 @@ function Test-SafeAttachmentsTeams {
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Conditions for 2.1.5 (L2) Ensure Safe Attachments for SharePoint, OneDrive, and Microsoft Teams is Enabled
#
# Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: Safe Attachments for SharePoint is enabled.
# - Condition B: Safe Attachments for OneDrive is enabled.
# - Condition C: Safe Attachments for Microsoft Teams is enabled.
#
# Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
# - Condition A: Safe Attachments for SharePoint is not enabled.
# - Condition B: Safe Attachments for OneDrive is not enabled.
# - Condition C: Safe Attachments for Microsoft Teams is not enabled.
# Initialization code, if needed
$recnum = "2.1.5"
}
@@ -27,6 +44,10 @@ function Test-SafeAttachmentsTeams {
$_.AllowSafeDocsOpen -eq $false
}
# Condition A: Check Safe Attachments for SharePoint
# Condition B: Check Safe Attachments for OneDrive
# Condition C: Check Safe Attachments for Microsoft Teams
# Determine the result based on the ATP policy settings
$result = $null -ne $atpPolicyResult
$details = if ($result) {
@@ -72,5 +93,3 @@ function Test-SafeAttachmentsTeams {
return $auditResult
}
}
# Additional helper functions (if any)

View File

@@ -11,6 +11,32 @@ function Test-SafeLinksOfficeApps {
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "2.1.1"
<#
Conditions for 2.1.1 (L2) Ensure Safe Links for Office Applications is Enabled
Validate test for a pass:
- Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
- Specific conditions to check:
- Condition A: In the Microsoft 365 security center, Safe Links policy for Office applications is enabled and the following protection settings are set:
- Office 365 Apps: On
- Teams: On
- Email: On
- Click protection settings: On
- Do not track when users click safe links: Off
- Condition B: Using the Exchange Online PowerShell Module, Safe Links policies are retrieved, and the relevant policy shows Safe Links for Office applications is enabled.
Validate test for a fail:
- Confirm that the failure conditions in the automated test are consistent with the manual audit results.
- Specific conditions to check:
- Condition A: In the Microsoft 365 security center, Safe Links policy for Office applications is not enabled or one or more of the required protection settings are not set correctly.
- Office 365 Apps: Off
- Teams: Off
- Email: Off
- Click protection settings: Off
- Do not track when users click safe links: On
- Condition B: Using the Exchange Online PowerShell Module, Safe Links policies are retrieved, and the relevant policy shows Safe Links for Office applications is not enabled.
#>
}
process {
@@ -28,16 +54,13 @@ function Test-SafeLinksOfficeApps {
$policyDetails = Get-SafeLinksPolicy -Identity $policy.Name
# Check each required property and record failures
# Condition A: Checking policy settings
$failures = @()
if ($policyDetails.EnableSafeLinksForEmail -ne $true) { $failures += "EnableSafeLinksForEmail: False" }
if ($policyDetails.EnableSafeLinksForTeams -ne $true) { $failures += "EnableSafeLinksForTeams: False" }
if ($policyDetails.EnableSafeLinksForOffice -ne $true) { $failures += "EnableSafeLinksForOffice: False" }
if ($policyDetails.TrackClicks -ne $true) { $failures += "TrackClicks: False" }
if ($policyDetails.AllowClickThrough -ne $false) { $failures += "AllowClickThrough: True" }
if ($policyDetails.ScanUrls -ne $true) { $failures += "ScanUrls: False" }
if ($policyDetails.EnableForInternalSenders -ne $true) { $failures += "EnableForInternalSenders: False" }
if ($policyDetails.DeliverMessageAfterScan -ne $true) { $failures += "DeliverMessageAfterScan: False" }
if ($policyDetails.DisableUrlRewrite -ne $false) { $failures += "DisableUrlRewrite: True" }
if ($policyDetails.EnableSafeLinksForEmail -ne $true) { $failures += "EnableSafeLinksForEmail: False" } # Email: On
if ($policyDetails.EnableSafeLinksForTeams -ne $true) { $failures += "EnableSafeLinksForTeams: False" } # Teams: On
if ($policyDetails.EnableSafeLinksForOffice -ne $true) { $failures += "EnableSafeLinksForOffice: False" } # Office 365 Apps: On
if ($policyDetails.TrackClicks -ne $true) { $failures += "TrackClicks: False" } # Click protection settings: On
if ($policyDetails.AllowClickThrough -ne $false) { $failures += "AllowClickThrough: True" } # Do not track when users click safe links: Off
# Only add details for policies that have misconfigurations
if ($failures.Count -gt 0) {
@@ -46,6 +69,7 @@ function Test-SafeLinksOfficeApps {
}
# Prepare the final result
# Condition B: Ensuring no misconfigurations
$result = $misconfiguredDetails.Count -eq 0
$details = if ($result) { "All Safe Links policies are correctly configured." } else { $misconfiguredDetails -join ' | ' }
$failureReasons = if ($result) { "N/A" } else { "The following Safe Links policies settings do not meet the recommended configuration: $($misconfiguredDetails -join ' | ')" }

View File

@@ -11,23 +11,41 @@ function Test-SpamPolicyAdminNotify {
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResult = [CISAuditResult]::new()
$recnum = "2.1.6"
<#
Conditions for 2.1.6 (L1) Ensure Exchange Online Spam Policies are set to notify administrators
Validate recommendation details:
- Confirm that the recommendation details are accurate and complete as per the CIS benchmark.
Validate test for a pass:
- Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
- Specific conditions to check:
- Condition A: In the Microsoft 365 Security & Compliance Center, the Exchange Online Spam Policies are set to notify administrators when a sender in the organization has been blocked for sending spam emails.
- Condition B: Using PowerShell, the `NotifyOutboundSpam` and `NotifyOutboundSpamContact` properties are correctly set in all relevant spam filter policies.
Validate test for a fail:
- Confirm that the failure conditions in the automated test are consistent with the manual audit results.
- Specific conditions to check:
- Condition A: In the Microsoft 365 Security & Compliance Center, the Exchange Online Spam Policies are not set to notify administrators when a sender in the organization has been blocked for sending spam emails.
- Condition B: Using PowerShell, the `NotifyOutboundSpam` and `NotifyOutboundSpamContact` properties are not correctly set in all relevant spam filter policies.
#>
}
process {
try {
# 2.1.6 Ensure Exchange Online Spam Policies are set to notify administrators
# Get the default hosted outbound spam filter policy
# Retrieve the default hosted outbound spam filter policy
$hostedOutboundSpamFilterPolicy = Get-HostedOutboundSpamFilterPolicy | Where-Object { $_.IsDefault -eq $true }
# Check if both settings are enabled
# Check if both settings are enabled (Condition A and Condition B for pass)
$bccSuspiciousOutboundMailEnabled = $hostedOutboundSpamFilterPolicy.BccSuspiciousOutboundMail
$notifyOutboundSpamEnabled = $hostedOutboundSpamFilterPolicy.NotifyOutboundSpam
$areSettingsEnabled = $bccSuspiciousOutboundMailEnabled -and $notifyOutboundSpamEnabled
# Prepare failure details if any setting is not enabled
# Prepare failure details if any setting is not enabled (Condition A and Condition B for fail)
$failureDetails = @()
if (-not $bccSuspiciousOutboundMailEnabled) {
$failureDetails += "BccSuspiciousOutboundMail is not enabled."
@@ -65,3 +83,4 @@ function Test-SpamPolicyAdminNotify {
return $auditResult
}
}