Merge pull request #5 from CriticalSolutionsNetwork/test-arraylist

Refactor and Align Tests with selected template
This commit is contained in:
Doug Rios
2024-05-28 20:12:30 -05:00
committed by GitHub
64 changed files with 1638 additions and 1265 deletions

1
.gitignore vendored
View File

@@ -15,3 +15,4 @@ output/
markdownissues.txt markdownissues.txt
node_modules node_modules
package-lock.json package-lock.json
Aligned.xlsx

View File

@@ -6,6 +6,32 @@ The format is based on and uses the types of changes according to [Keep a Change
### Added ### Added
- Array list to store the results of the audit.
- Arraylist tests and helper template.
- New testing function.
- Missing properties to CSV.
### Changed
- Refactored object initialization to source `RecDescription`, `CISControl`, and `CISDescription` properties from the CSV.
- Added `Automated` and `Connection` properties to the output object.
- All test functions aligned with the test-template.
- Initialize-CISAuditResult refactored to use global test definitions.
### Fixed
- Corrected test-template.
- Details added to pass.
### Docs
- Updated comments and documentation for new functions.
## [0.1.2] - 2024-04-29
### Added
- Automated and organized CSV testing and added test 1.1.1. - Automated and organized CSV testing and added test 1.1.1.
- Functions to merge tests into an Excel benchmark. - Functions to merge tests into an Excel benchmark.
- Public function for merging tests. - Public function for merging tests.
@@ -24,6 +50,7 @@ The format is based on and uses the types of changes according to [Keep a Change
- Updated comments for new functions. - Updated comments for new functions.
- Updated help documentation. - Updated help documentation.
- Updated online link in public function.
## [0.1.1] - 2024-04-02 ## [0.1.1] - 2024-04-02

BIN
README.md

Binary file not shown.

Binary file not shown.

View File

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

View File

@@ -0,0 +1,97 @@
function Test-Template {
[CmdletBinding()]
param (
# Parameters can be added if needed
)
begin {
# Initialization code, if needed
# Load necessary scripts, define variables, etc.
}
process {
# Fetch relevant data
# Example: $data = Get-SomeData
# Process the data to evaluate compliance
# Example: $compliantItems = $data | Where-Object { $_.Property -eq 'ExpectedValue' }
# Example: $nonCompliantItems = $data | Where-Object { $_.Property -ne 'ExpectedValue' }
# Prepare failure reasons for non-compliant items
$failureReasons = $nonCompliantItems | ForEach-Object {
# Example: "Item: $($_.Name) - Reason: Missing expected value"
}
$failureReasons = $failureReasons -join "`n"
# Prepare details for non-compliant items
$nonCompliantDetails = $nonCompliantItems | ForEach-Object {
# Example: "$($_.Name) - Value: $($_.Property)"
}
$nonCompliantDetails = $nonCompliantDetails -join "`n"
# Prepare details based on compliance
$details = if ($nonCompliantItems) {
"Non-Compliant Items: $($nonCompliantItems.Count)`nDetails:`n$nonCompliantDetails"
} else {
"Compliant Items: $($compliantItems.Count)"
}
# Create and populate the CISAuditResult object
$auditResult = [CISAuditResult]::new()
$auditResult.Status = if ($nonCompliantItems) { 'Fail' } else { 'Pass' }
$auditResult.ELevel = 'E3' # Modify as needed
$auditResult.ProfileLevel = 'L1' # Modify as needed
$auditResult.Rec = '1.1.1' # Modify as needed
$auditResult.RecDescription = "Description of the recommendation" # Modify as needed
$auditResult.CISControlVer = 'v8' # Modify as needed
$auditResult.CISControl = "5.4" # Modify as needed
$auditResult.CISDescription = "Description of the CIS control" # Modify as needed
$auditResult.IG1 = $true # Modify as needed
$auditResult.IG2 = $true # Modify as needed
$auditResult.IG3 = $true # Modify as needed
$auditResult.Result = $nonCompliantItems.Count -eq 0
$auditResult.Details = $details
$auditResult.FailureReason = if ($nonCompliantItems) {
"Non-compliant items:`n$failureReasons"
} else {
"N/A"
}
# Example output object for a pass result
# Status : Pass
# ELevel : E3
# ProfileLevel : L2
# Rec : 8.1.1
# RecDescription : Ensure external file sharing in Teams is enabled for only approved cloud storage services
# CISControlVer : v8
# CISControl : 3.3
# CISDescription : Configure Data Access Control Lists
# IG1 : True
# IG2 : True
# IG3 : True
# Result : True
# Details : Compliant Items: 5
# FailureReason : N/A
# Example output object for a fail result
# Status : Fail
# ELevel : E3
# ProfileLevel : L2
# Rec : 8.1.1
# RecDescription : Ensure external file sharing in Teams is enabled for only approved cloud storage services
# CISControlVer : v8
# CISControl : 3.3
# CISDescription : Configure Data Access Control Lists
# IG1 : True
# IG2 : True
# IG3 : True
# Result : False
# Details : Non-Compliant Items: 2
# FailureReason : Non-compliant items:`nUsername | Roles | HybridStatus | Missing Licence
}
end {
# Return the audit result
return $auditResult
}
}

View File

@@ -2,6 +2,8 @@ class CISAuditResult {
[string]$Status [string]$Status
[string]$ELevel [string]$ELevel
[string]$ProfileLevel [string]$ProfileLevel
[bool]$Automated
[string]$Connection
[string]$Rec [string]$Rec
[string]$RecDescription [string]$RecDescription
[string]$CISControlVer = 'v8' [string]$CISControlVer = 'v8'

View File

@@ -0,0 +1,45 @@
function Initialize-CISAuditResult {
param (
[Parameter(Mandatory = $true)]
[string]$Rec,
[Parameter(Mandatory = $true)]
[bool]$Result,
[Parameter(Mandatory = $true)]
[string]$Status,
[Parameter(Mandatory = $true)]
[string]$Details,
[Parameter(Mandatory = $true)]
[string]$FailureReason
)
# Import the test definitions CSV file
$testDefinitions = $script:TestDefinitionsObject
# Find the row that matches the provided recommendation (Rec)
$testDefinition = $testDefinitions | Where-Object { $_.Rec -eq $Rec }
# Create an instance of CISAuditResult and populate it
$auditResult = [CISAuditResult]::new()
$auditResult.Rec = $Rec
$auditResult.ELevel = $testDefinition.ELevel
$auditResult.ProfileLevel = $testDefinition.ProfileLevel
$auditResult.IG1 = [bool]::Parse($testDefinition.IG1)
$auditResult.IG2 = [bool]::Parse($testDefinition.IG2)
$auditResult.IG3 = [bool]::Parse($testDefinition.IG3)
$auditResult.RecDescription = $testDefinition.RecDescription
$auditResult.CISControl = $testDefinition.CISControl
$auditResult.CISDescription = $testDefinition.CISDescription
$auditResult.Automated = [bool]::Parse($testDefinition.Automated)
$auditResult.Connection = $testDefinition.Connection
$auditResult.CISControlVer = 'v8'
$auditResult.Result = $Result
$auditResult.Status = $Status
$auditResult.Details = $Details
$auditResult.FailureReason = $FailureReason
return $auditResult
}

View File

@@ -36,8 +36,8 @@ function Get-AdminRoleUserLicense {
Connect-MgGraph -Scopes "Directory.Read.All", "Domain.Read.All", "Policy.Read.All", "Organization.Read.All" -NoWelcome Connect-MgGraph -Scopes "Directory.Read.All", "Domain.Read.All", "Policy.Read.All", "Organization.Read.All" -NoWelcome
} }
$adminRoleUsers = @() $adminRoleUsers = [System.Collections.ArrayList]::new()
$userIds = @() $userIds = [System.Collections.ArrayList]::new()
} }
Process { Process {
@@ -50,8 +50,10 @@ function Get-AdminRoleUserLicense {
$userDetails = Get-MgUser -UserId $user.PrincipalId -Property "DisplayName, UserPrincipalName, Id, onPremisesSyncEnabled" -ErrorAction SilentlyContinue $userDetails = Get-MgUser -UserId $user.PrincipalId -Property "DisplayName, UserPrincipalName, Id, onPremisesSyncEnabled" -ErrorAction SilentlyContinue
if ($userDetails) { if ($userDetails) {
$userIds += $user.PrincipalId [void]($userIds.Add($user.PrincipalId))
$adminRoleUsers += [PSCustomObject]@{ [void](
$adminRoleUsers.Add(
[PSCustomObject]@{
RoleName = $role.DisplayName RoleName = $role.DisplayName
UserName = $userDetails.DisplayName UserName = $userDetails.DisplayName
UserPrincipalName = $userDetails.UserPrincipalName UserPrincipalName = $userDetails.UserPrincipalName
@@ -59,15 +61,17 @@ function Get-AdminRoleUserLicense {
HybridUser = $userDetails.onPremisesSyncEnabled HybridUser = $userDetails.onPremisesSyncEnabled
Licenses = $null # Initialize as $null Licenses = $null # Initialize as $null
} }
)
)
} }
} }
} }
foreach ($userId in $userIds | Select-Object -Unique) { foreach ($userId in $userIds.ToArray() | Select-Object -Unique) {
$licenses = Get-MgUserLicenseDetail -UserId $userId -ErrorAction SilentlyContinue $licenses = Get-MgUserLicenseDetail -UserId $userId -ErrorAction SilentlyContinue
if ($licenses) { if ($licenses) {
$licenseList = ($licenses.SkuPartNumber -join '|') $licenseList = ($licenses.SkuPartNumber -join '|')
$adminRoleUsers | Where-Object { $_.UserId -eq $userId } | ForEach-Object { $adminRoleUsers.ToArray() | Where-Object { $_.UserId -eq $userId } | ForEach-Object {
$_.Licenses = $licenseList $_.Licenses = $licenseList
} }
} }

View File

@@ -57,7 +57,7 @@
- For full license details, visit: https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en - For full license details, visit: https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en
- Register for CIS Benchmarks at: https://www.cisecurity.org/cis-benchmarks - Register for CIS Benchmarks at: https://www.cisecurity.org/cis-benchmarks
.LINK .LINK
Online Version: https://github.com/CriticalSolutionsNetwork/M365FoundationsCISReport https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Invoke-M365SecurityAudit
#> #>
function Invoke-M365SecurityAudit { function Invoke-M365SecurityAudit {
@@ -161,7 +161,8 @@ function Invoke-M365SecurityAudit {
# Load test definitions from CSV # Load test definitions from CSV
$testDefinitionsPath = Join-Path -Path $PSScriptRoot -ChildPath "helper\TestDefinitions.csv" $testDefinitionsPath = Join-Path -Path $PSScriptRoot -ChildPath "helper\TestDefinitions.csv"
$testDefinitions = Import-Csv -Path $testDefinitionsPath $testDefinitions = Import-Csv -Path $testDefinitionsPath
# Load the Test Definitions into the script scope for use in other functions
$script:TestDefinitionsObject = $testDefinitions
# Apply filters based on parameter sets # Apply filters based on parameter sets
switch ($PSCmdlet.ParameterSetName) { switch ($PSCmdlet.ParameterSetName) {
'ELevelFilter' { 'ELevelFilter' {
@@ -209,7 +210,7 @@ function Invoke-M365SecurityAudit {
} # End Begin } # End Begin
Process { Process {
$allAuditResults = @() # Initialize a collection to hold all results $allAuditResults = [System.Collections.ArrayList]::new() #@() # Initialize a collection to hold all results
# Dynamically dot-source the test scripts # Dynamically dot-source the test scripts
$testsFolderPath = Join-Path -Path $PSScriptRoot -ChildPath "tests" $testsFolderPath = Join-Path -Path $PSScriptRoot -ChildPath "tests"
@@ -242,7 +243,7 @@ function Invoke-M365SecurityAudit {
Write-Host "Running $functionName..." Write-Host "Running $functionName..."
$result = & $functionName @paramList $result = & $functionName @paramList
# Assuming each function returns an array of CISAuditResult or a single CISAuditResult # Assuming each function returns an array of CISAuditResult or a single CISAuditResult
$allAuditResults += $result [void]($allAuditResults.add($Result))
} }
} }
} }
@@ -253,7 +254,7 @@ function Invoke-M365SecurityAudit {
Disconnect-M365Suite Disconnect-M365Suite
} }
# Return all collected audit results # Return all collected audit results
return $allAuditResults return $allAuditResults.ToArray()
# Check if the Disconnect switch is present # Check if the Disconnect switch is present
} }
} }

View File

@@ -1,52 +1,52 @@
Index,TestFileName,Rec,ELevel,ProfileLevel,IG1,IG2,IG3,Automated Index,TestFileName,Rec,RecDescription,ELevel,ProfileLevel,CISControl,CISDescription,IG1,IG2,IG3,Automated,Connection
1,Test-AdministrativeAccountCompliance.ps1,1.1.1,E3,L1,TRUE,TRUE,TRUE,FALSE 1,Test-AdministrativeAccountCompliance.ps1,1.1.1,Ensure Administrative accounts are separate and cloud-only,E3,L1,5.4,Restrict Administrator Privileges to Dedicated Administrator Accounts,TRUE,TRUE,TRUE,FALSE,AzureAD
2,Test-GlobalAdminsCount.ps1,1.1.3,E3,L1,TRUE,TRUE,TRUE,TRUE 2,Test-GlobalAdminsCount.ps1,1.1.3,Ensure that between two and four global admins are designated,E3,L1,5.1,Establish and Maintain an Inventory of Accounts,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
3,Test-ManagedApprovedPublicGroups.ps1,1.2.1,E3,L2,TRUE,TRUE,TRUE,TRUE 3,Test-ManagedApprovedPublicGroups.ps1,1.2.1,Ensure that only organizationally managed/approved public groups exist,E3,L2,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
4,Test-BlockSharedMailboxSignIn.ps1,1.2.2,E3,L1,FALSE,FALSE,FALSE,TRUE 4,Test-BlockSharedMailboxSignIn.ps1,1.2.2,Ensure sign-in to shared mailboxes is blocked,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,AzureAD | EXO
5,Test-PasswordNeverExpirePolicy.ps1,1.3.1,E3,L1,TRUE,TRUE,TRUE,TRUE 5,Test-PasswordNeverExpirePolicy.ps1,1.3.1,Ensure the 'Password expiration policy' is set to 'Set passwords to never expire',E3,L1,5.2,Use Unique Passwords,TRUE,TRUE,TRUE,TRUE,Microsoft Graph
6,Test-ExternalSharingCalendars.ps1,1.3.3,E3,L2,FALSE,TRUE,TRUE,TRUE 6,Test-ExternalSharingCalendars.ps1,1.3.3,Ensure 'External sharing' of calendars is not available,E3,L2,4.8,Uninstall or Disable Unnecessary Services on Enterprise Assets and Software,FALSE,TRUE,TRUE,TRUE,EXO
7,Test-CustomerLockbox.ps1,1.3.6,E5,L2,FALSE,FALSE,FALSE,TRUE 7,Test-CustomerLockbox.ps1,1.3.6,Ensure the customer lockbox feature is enabled,E5,L2,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,EXO
8,Test-SafeLinksOfficeApps.ps1,2.1.1,E5,L2,TRUE,TRUE,TRUE,TRUE 8,Test-SafeLinksOfficeApps.ps1,2.1.1,Ensure Safe Links for Office Applications is Enabled,E5,L2,10.1,Deploy and Maintain Anti-Malware Software,TRUE,TRUE,TRUE,TRUE,EXO
9,Test-CommonAttachmentFilter.ps1,2.1.2,E3,L1,FALSE,TRUE,TRUE,TRUE 9,Test-CommonAttachmentFilter.ps1,2.1.2,Ensure the Common Attachment Types Filter is enabled,E3,L1,9.6,Block Unnecessary File Types,FALSE,TRUE,TRUE,TRUE,EXO
10,Test-NotifyMalwareInternal.ps1,2.1.3,E3,L1,FALSE,TRUE,TRUE,TRUE 10,Test-NotifyMalwareInternal.ps1,2.1.3,Ensure notifications for internal users sending malware is Enabled,E3,L1,17.5,Assign Key Roles and Responsibilities,FALSE,TRUE,TRUE,TRUE,EXO
11,Test-SafeAttachmentsPolicy.ps1,2.1.4,E5,L2,FALSE,FALSE,TRUE,TRUE 11,Test-SafeAttachmentsPolicy.ps1,2.1.4,Ensure Safe Attachments policy is enabled,E5,L2,9.7,Deploy and Maintain Email Server Anti-Malware Protections,FALSE,FALSE,TRUE,TRUE,EXO
12,Test-SafeAttachmentsTeams.ps1,2.1.5,E5,L2,TRUE,TRUE,TRUE,TRUE 12,Test-SafeAttachmentsTeams.ps1,2.1.5,"Ensure Safe Attachments for SharePoint, OneDrive, and Microsoft Teams is Enabled",E5,L2,"9.7, 10.1","Deploy and Maintain Email Server Anti-Malware Protections, Deploy and Maintain Anti-Malware Software",TRUE,TRUE,TRUE,TRUE,EXO
13,Test-SpamPolicyAdminNotify.ps1,2.1.6,E3,L1,FALSE,TRUE,TRUE,TRUE 13,Test-SpamPolicyAdminNotify.ps1,2.1.6,Ensure Exchange Online Spam Policies are set to notify administrators,E3,L1,17.5,Assign Key Roles and Responsibilities,FALSE,TRUE,TRUE,TRUE,EXO
14,Test-AntiPhishingPolicy.ps1,2.1.7,E5,L1,FALSE,FALSE,TRUE,TRUE 14,Test-AntiPhishingPolicy.ps1,2.1.7,Ensure that an anti-phishing policy has been created,E5,L1,9.7,Deploy and Maintain Email Server Anti-Malware Protections,FALSE,FALSE,TRUE,TRUE,EXO
15,Test-EnableDKIM.ps1,2.1.9,E3,L1,FALSE,TRUE,TRUE,TRUE 15,Test-EnableDKIM.ps1,2.1.9,Ensure that DKIM is enabled for all Exchange Online Domains,E3,L1,9.5,Implement DMARC,FALSE,TRUE,TRUE,TRUE,EXO
16,Test-AuditLogSearch.ps1,3.1.1,E3,L1,TRUE,TRUE,TRUE,TRUE 16,Test-AuditLogSearch.ps1,3.1.1,Ensure Microsoft 365 audit log search is Enabled,E3,L1,8.2,Collect Audit Logs,TRUE,TRUE,TRUE,TRUE,EXO
17,Test-RestrictTenantCreation.ps1,5.1.2.3,E3,L1,FALSE,FALSE,FALSE,TRUE 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,E3,L1,FALSE,TRUE,TRUE,TRUE 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,E3,L1,TRUE,TRUE,TRUE,TRUE 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,E3,L1,TRUE,TRUE,TRUE,TRUE 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
21,Test-MailboxAuditingE5.ps1,6.1.3,E5,L1,TRUE,TRUE,TRUE,TRUE 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
22,Test-BlockMailForwarding.ps1,6.2.1,E3,L1,FALSE,FALSE,FALSE,TRUE 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,E3,L1,FALSE,FALSE,FALSE,TRUE 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,E3,L1,FALSE,FALSE,FALSE,TRUE 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
25,Test-RestrictOutlookAddins.ps1,6.3.1,E3,L2,FALSE,TRUE,TRUE,TRUE 25,Test-RestrictOutlookAddins.ps1,6.3.1,Ensure users installing Outlook add-ins is not allowed,E3,L2,9.4,Restrict Unnecessary or Unauthorized Browser and Email Client Extensions,FALSE,TRUE,TRUE,TRUE,EXO
26,Test-ModernAuthExchangeOnline.ps1,6.5.1,E3,L1,FALSE,TRUE,TRUE,TRUE 26,Test-ModernAuthExchangeOnline.ps1,6.5.1,Ensure modern authentication for Exchange Online is enabled (Automated),E3,L1,3.1,Encrypt Sensitive Data in Transit,FALSE,TRUE,TRUE,TRUE,EXO
27,Test-MailTipsEnabled.ps1,6.5.2,E3,L2,FALSE,FALSE,FALSE,TRUE 27,Test-MailTipsEnabled.ps1,6.5.2,Ensure MailTips are enabled for end users,E3,L2,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,EXO
28,Test-RestrictStorageProvidersOutlook.ps1,6.5.3,E3,L2,TRUE,TRUE,TRUE,TRUE 28,Test-RestrictStorageProvidersOutlook.ps1,6.5.3,Ensure additional storage providers are restricted in Outlook on the web,E3,L2,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,EXO
29,Test-ModernAuthSharePoint.ps1,7.2.1,E3,L1,FALSE,TRUE,TRUE,TRUE 29,Test-ModernAuthSharePoint.ps1,7.2.1,Modern Authentication for SharePoint Applications,E3,L1,3.1,Encrypt Sensitive Data in Transit,FALSE,TRUE,TRUE,TRUE,SPO
30,Test-SharePointAADB2B.ps1,7.2.2,E3,L1,FALSE,FALSE,FALSE,TRUE 30,Test-SharePointAADB2B.ps1,7.2.2,Ensure reauthentication with verification code is restricted,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,SPO
31,Test-RestrictExternalSharing.ps1,7.2.3,E3,L1,TRUE,TRUE,TRUE,TRUE 31,Test-RestrictExternalSharing.ps1,7.2.3,Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled,E3,L1,0,Explicitly Not Mapped,TRUE,TRUE,TRUE,TRUE,SPO
32,Test-OneDriveContentRestrictions.ps1,7.2.4,E3,L2,TRUE,TRUE,TRUE,TRUE 32,Test-OneDriveContentRestrictions.ps1,7.2.4,Ensure external content sharing is restricted,E3,L2,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,SPO
33,Test-SharePointGuestsItemSharing.ps1,7.2.5,E3,L2,TRUE,TRUE,TRUE,TRUE 33,Test-SharePointGuestsItemSharing.ps1,7.2.5,Ensure OneDrive content sharing is restricted,E3,L2,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,SPO
34,Test-SharePointExternalSharingDomains.ps1,7.2.6,E3,L2,TRUE,TRUE,TRUE,TRUE 34,Test-SharePointExternalSharingDomains.ps1,7.2.6,Ensure that SharePoint guest users cannot share items they don't own,E3,L2,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,SPO
35,Test-LinkSharingRestrictions.ps1,7.2.7,E3,L1,TRUE,TRUE,TRUE,TRUE 35,Test-LinkSharingRestrictions.ps1,7.2.7,Ensure SharePoint external sharing is managed through domain whitelist/blacklists,E3,L1,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,SPO
36,Test-GuestAccessExpiration.ps1,7.2.9,E3,L1,FALSE,FALSE,FALSE,TRUE 36,Test-GuestAccessExpiration.ps1,7.2.9,Ensure link sharing is restricted in SharePoint and OneDrive,E3,L1,3.3,Configure Data Access Control Lists,FALSE,FALSE,FALSE,TRUE,SPO
37,Test-ReauthWithCode.ps1,7.2.10,E3,L1,FALSE,FALSE,FALSE,TRUE 37,Test-ReauthWithCode.ps1,7.2.10,Ensure guest access to a site or OneDrive will expire automatically,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,SPO
38,Test-DisallowInfectedFilesDownload.ps1,7.3.1,E5,L2,TRUE,TRUE,TRUE,TRUE 38,Test-DisallowInfectedFilesDownload.ps1,7.3.1,Ensure Office 365 SharePoint infected files are disallowed for download,E5,L2,10.1,Deploy and Maintain Anti-Malware Software,TRUE,TRUE,TRUE,TRUE,SPO
39,Test-OneDriveSyncRestrictions.ps1,7.3.2,E3,L2,FALSE,FALSE,FALSE,TRUE 39,Test-OneDriveSyncRestrictions.ps1,7.3.2,Ensure OneDrive sync is restricted for unmanaged devices,E3,L2,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,SPO
40,Test-RestrictCustomScripts.ps1,7.3.4,E3,L1,FALSE,FALSE,TRUE,TRUE 40,Test-RestrictCustomScripts.ps1,7.3.4,Ensure custom script execution is restricted on site collections,E3,L1,2.7,Allowlist Authorized Scripts,FALSE,FALSE,TRUE,TRUE,SPO
41,Test-TeamsExternalFileSharing.ps1,8.1.1,E3,L2,TRUE,TRUE,TRUE,TRUE 41,Test-TeamsExternalFileSharing.ps1,8.1.1,Ensure external file sharing in Teams is enabled for only approved cloud storage services,E3,L2,3.3,Configure Data Access Control Lists,TRUE,TRUE,TRUE,TRUE,Microsoft Teams
42,Test-BlockChannelEmails.ps1,8.1.2,E3,L1,FALSE,FALSE,FALSE,TRUE 42,Test-BlockChannelEmails.ps1,8.1.2,Ensure users can't send emails to a channel email address,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams
43,Test-TeamsExternalAccess.ps1,8.2.1,E3,L2,FALSE,FALSE,FALSE,TRUE 43,Test-TeamsExternalAccess.ps1,8.2.1,Ensure 'external access' is restricted in the Teams admin center,E3,L2,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams
44,Test-NoAnonymousMeetingJoin.ps1,8.5.1,E3,L2,FALSE,FALSE,FALSE,TRUE 44,Test-NoAnonymousMeetingJoin.ps1,8.5.1,Ensure anonymous users can't join a meeting,E3,L2,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams
45,Test-NoAnonymousMeetingStart.ps1,8.5.2,E3,L1,FALSE,FALSE,FALSE,TRUE 45,Test-NoAnonymousMeetingStart.ps1,8.5.2,Ensure anonymous users and dial-in callers can't start a meeting,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams
46,Test-OrgOnlyBypassLobby.ps1,8.5.3,E3,L1,FALSE,FALSE,TRUE,TRUE 46,Test-OrgOnlyBypassLobby.ps1,8.5.3,Ensure only people in my org can bypass the lobby,E3,L1,6.8,Define and Maintain Role-Based Access Control,FALSE,FALSE,TRUE,TRUE,Microsoft Teams
47,Test-DialInBypassLobby.ps1,8.5.4,E3,L1,FALSE,FALSE,FALSE,TRUE 47,Test-DialInBypassLobby.ps1,8.5.4,Ensure users dialing in can't bypass the lobby,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams
48,Test-MeetingChatNoAnonymous.ps1,8.5.5,E3,L1,FALSE,FALSE,FALSE,TRUE 48,Test-MeetingChatNoAnonymous.ps1,8.5.5,Ensure meeting chat does not allow anonymous users,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams
49,Test-OrganizersPresent.ps1,8.5.6,E3,L1,FALSE,FALSE,FALSE,TRUE 49,Test-OrganizersPresent.ps1,8.5.6,Ensure only organizers and co-organizers can present,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams
50,Test-ExternalNoControl.ps1,8.5.7,E3,L1,FALSE,FALSE,FALSE,TRUE 50,Test-ExternalNoControl.ps1,8.5.7,Ensure external participants can't give or request control,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams
51,Test-ReportSecurityInTeams.ps1,8.6.1,E3,L1,FALSE,FALSE,FALSE,TRUE 51,Test-ReportSecurityInTeams.ps1,8.6.1,Ensure users can report security concerns in Teams,E3,L1,0,Explicitly Not Mapped,FALSE,FALSE,FALSE,TRUE,Microsoft Teams | EXO
1 Index TestFileName Rec RecDescription ELevel ProfileLevel CISControl CISDescription IG1 IG2 IG3 Automated Connection
2 1 Test-AdministrativeAccountCompliance.ps1 1.1.1 Ensure Administrative accounts are separate and cloud-only E3 L1 5.4 Restrict Administrator Privileges to Dedicated Administrator Accounts TRUE TRUE TRUE FALSE AzureAD
3 2 Test-GlobalAdminsCount.ps1 1.1.3 Ensure that between two and four global admins are designated E3 L1 5.1 Establish and Maintain an Inventory of Accounts TRUE TRUE TRUE TRUE Microsoft Graph
4 3 Test-ManagedApprovedPublicGroups.ps1 1.2.1 Ensure that only organizationally managed/approved public groups exist E3 L2 3.3 Configure Data Access Control Lists TRUE TRUE TRUE TRUE Microsoft Graph
5 4 Test-BlockSharedMailboxSignIn.ps1 1.2.2 Ensure sign-in to shared mailboxes is blocked E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE AzureAD | EXO
6 5 Test-PasswordNeverExpirePolicy.ps1 1.3.1 Ensure the 'Password expiration policy' is set to 'Set passwords to never expire' E3 L1 5.2 Use Unique Passwords TRUE TRUE TRUE TRUE Microsoft Graph
7 6 Test-ExternalSharingCalendars.ps1 1.3.3 Ensure 'External sharing' of calendars is not available E3 L2 4.8 Uninstall or Disable Unnecessary Services on Enterprise Assets and Software FALSE TRUE TRUE TRUE EXO
8 7 Test-CustomerLockbox.ps1 1.3.6 Ensure the customer lockbox feature is enabled E5 L2 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE EXO
9 8 Test-SafeLinksOfficeApps.ps1 2.1.1 Ensure Safe Links for Office Applications is Enabled E5 L2 10.1 Deploy and Maintain Anti-Malware Software TRUE TRUE TRUE TRUE EXO
10 9 Test-CommonAttachmentFilter.ps1 2.1.2 Ensure the Common Attachment Types Filter is enabled E3 L1 9.6 Block Unnecessary File Types FALSE TRUE TRUE TRUE EXO
11 10 Test-NotifyMalwareInternal.ps1 2.1.3 Ensure notifications for internal users sending malware is Enabled E3 L1 17.5 Assign Key Roles and Responsibilities FALSE TRUE TRUE TRUE EXO
12 11 Test-SafeAttachmentsPolicy.ps1 2.1.4 Ensure Safe Attachments policy is enabled E5 L2 9.7 Deploy and Maintain Email Server Anti-Malware Protections FALSE FALSE TRUE TRUE EXO
13 12 Test-SafeAttachmentsTeams.ps1 2.1.5 Ensure Safe Attachments for SharePoint, OneDrive, and Microsoft Teams is Enabled E5 L2 9.7, 10.1 Deploy and Maintain Email Server Anti-Malware Protections, Deploy and Maintain Anti-Malware Software TRUE TRUE TRUE TRUE EXO
14 13 Test-SpamPolicyAdminNotify.ps1 2.1.6 Ensure Exchange Online Spam Policies are set to notify administrators E3 L1 17.5 Assign Key Roles and Responsibilities FALSE TRUE TRUE TRUE EXO
15 14 Test-AntiPhishingPolicy.ps1 2.1.7 Ensure that an anti-phishing policy has been created E5 L1 9.7 Deploy and Maintain Email Server Anti-Malware Protections FALSE FALSE TRUE TRUE EXO
16 15 Test-EnableDKIM.ps1 2.1.9 Ensure that DKIM is enabled for all Exchange Online Domains E3 L1 9.5 Implement DMARC FALSE TRUE TRUE TRUE EXO
17 16 Test-AuditLogSearch.ps1 3.1.1 Ensure Microsoft 365 audit log search is Enabled E3 L1 8.2 Collect Audit Logs TRUE TRUE TRUE TRUE EXO
18 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
19 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
20 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
21 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
22 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
23 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
24 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
25 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
26 25 Test-RestrictOutlookAddins.ps1 6.3.1 Ensure users installing Outlook add-ins is not allowed E3 L2 9.4 Restrict Unnecessary or Unauthorized Browser and Email Client Extensions FALSE TRUE TRUE TRUE EXO
27 26 Test-ModernAuthExchangeOnline.ps1 6.5.1 Ensure modern authentication for Exchange Online is enabled (Automated) E3 L1 3.1 Encrypt Sensitive Data in Transit FALSE TRUE TRUE TRUE EXO
28 27 Test-MailTipsEnabled.ps1 6.5.2 Ensure MailTips are enabled for end users E3 L2 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE EXO
29 28 Test-RestrictStorageProvidersOutlook.ps1 6.5.3 Ensure additional storage providers are restricted in Outlook on the web E3 L2 3.3 Configure Data Access Control Lists TRUE TRUE TRUE TRUE EXO
30 29 Test-ModernAuthSharePoint.ps1 7.2.1 Modern Authentication for SharePoint Applications E3 L1 3.1 Encrypt Sensitive Data in Transit FALSE TRUE TRUE TRUE SPO
31 30 Test-SharePointAADB2B.ps1 7.2.2 Ensure reauthentication with verification code is restricted E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE SPO
32 31 Test-RestrictExternalSharing.ps1 7.2.3 Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled E3 L1 0 Explicitly Not Mapped TRUE TRUE TRUE TRUE SPO
33 32 Test-OneDriveContentRestrictions.ps1 7.2.4 Ensure external content sharing is restricted E3 L2 3.3 Configure Data Access Control Lists TRUE TRUE TRUE TRUE SPO
34 33 Test-SharePointGuestsItemSharing.ps1 7.2.5 Ensure OneDrive content sharing is restricted E3 L2 3.3 Configure Data Access Control Lists TRUE TRUE TRUE TRUE SPO
35 34 Test-SharePointExternalSharingDomains.ps1 7.2.6 Ensure that SharePoint guest users cannot share items they don't own E3 L2 3.3 Configure Data Access Control Lists TRUE TRUE TRUE TRUE SPO
36 35 Test-LinkSharingRestrictions.ps1 7.2.7 Ensure SharePoint external sharing is managed through domain whitelist/blacklists E3 L1 3.3 Configure Data Access Control Lists TRUE TRUE TRUE TRUE SPO
37 36 Test-GuestAccessExpiration.ps1 7.2.9 Ensure link sharing is restricted in SharePoint and OneDrive E3 L1 3.3 Configure Data Access Control Lists FALSE FALSE FALSE TRUE SPO
38 37 Test-ReauthWithCode.ps1 7.2.10 Ensure guest access to a site or OneDrive will expire automatically E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE SPO
39 38 Test-DisallowInfectedFilesDownload.ps1 7.3.1 Ensure Office 365 SharePoint infected files are disallowed for download E5 L2 10.1 Deploy and Maintain Anti-Malware Software TRUE TRUE TRUE TRUE SPO
40 39 Test-OneDriveSyncRestrictions.ps1 7.3.2 Ensure OneDrive sync is restricted for unmanaged devices E3 L2 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE SPO
41 40 Test-RestrictCustomScripts.ps1 7.3.4 Ensure custom script execution is restricted on site collections E3 L1 2.7 Allowlist Authorized Scripts FALSE FALSE TRUE TRUE SPO
42 41 Test-TeamsExternalFileSharing.ps1 8.1.1 Ensure external file sharing in Teams is enabled for only approved cloud storage services E3 L2 3.3 Configure Data Access Control Lists TRUE TRUE TRUE TRUE Microsoft Teams
43 42 Test-BlockChannelEmails.ps1 8.1.2 Ensure users can't send emails to a channel email address E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams
44 43 Test-TeamsExternalAccess.ps1 8.2.1 Ensure 'external access' is restricted in the Teams admin center E3 L2 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams
45 44 Test-NoAnonymousMeetingJoin.ps1 8.5.1 Ensure anonymous users can't join a meeting E3 L2 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams
46 45 Test-NoAnonymousMeetingStart.ps1 8.5.2 Ensure anonymous users and dial-in callers can't start a meeting E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams
47 46 Test-OrgOnlyBypassLobby.ps1 8.5.3 Ensure only people in my org can bypass the lobby E3 L1 6.8 Define and Maintain Role-Based Access Control FALSE FALSE TRUE TRUE Microsoft Teams
48 47 Test-DialInBypassLobby.ps1 8.5.4 Ensure users dialing in can't bypass the lobby E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams
49 48 Test-MeetingChatNoAnonymous.ps1 8.5.5 Ensure meeting chat does not allow anonymous users E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams
50 49 Test-OrganizersPresent.ps1 8.5.6 Ensure only organizers and co-organizers can present E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams
51 50 Test-ExternalNoControl.ps1 8.5.7 Ensure external participants can't give or request control E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams
52 51 Test-ReportSecurityInTeams.ps1 8.6.1 Ensure users can report security concerns in Teams E3 L1 0 Explicitly Not Mapped FALSE FALSE FALSE TRUE Microsoft Teams | EXO

View File

@@ -1,12 +1,15 @@
function Test-AdministrativeAccountCompliance { function Test-AdministrativeAccountCompliance {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
#. C:\Temp\CISAuditResult.ps1 #. .\source\Classes\CISAuditResult.ps1
$validLicenses = @('AAD_PREMIUM', 'AAD_PREMIUM_P2') $validLicenses = @('AAD_PREMIUM', 'AAD_PREMIUM_P2')
} }
process { process {
$adminRoles = Get-MgRoleManagementDirectoryRoleDefinition | Where-Object { $_.DisplayName -like "*Admin*" } $adminRoles = Get-MgRoleManagementDirectoryRoleDefinition | Where-Object { $_.DisplayName -like "*Admin*" }
$adminRoleUsers = @() $adminRoleUsers = @()
@@ -50,22 +53,27 @@ function Test-AdministrativeAccountCompliance {
"$($_.UserName)|$($_.Roles)|$accountType|Missing: $($missingLicenses -join ',')" "$($_.UserName)|$($_.Roles)|$accountType|Missing: $($missingLicenses -join ',')"
} }
$failureReasons = $failureReasons -join "`n" $failureReasons = $failureReasons -join "`n"
$details = if ($nonCompliantUsers) {
"Non-Compliant Accounts: $($nonCompliantUsers.Count)`nDetails:`n" + ($nonCompliantUsers | ForEach-Object { $_.UserName }) -join "`n"
}
else {
"Compliant Accounts: $($uniqueAdminRoleUsers.Count)"
}
$auditResult = [CISAuditResult]::new() $result = $nonCompliantUsers.Count -eq 0
$auditResult.Status = if ($nonCompliantUsers) { 'Fail' } else { 'Pass' } $status = if ($result) { 'Pass' } else { 'Fail' }
$auditResult.ELevel = 'E3' $failureReason = if ($nonCompliantUsers) { "Non-compliant accounts: `nUsername | Roles | HybridStatus | Missing Licence`n$failureReasons" } else { "N/A" }
$auditResult.ProfileLevel = 'L1'
$auditResult.Rec = '1.1.1' # Create the parameter splat
$auditResult.RecDescription = "Ensure Administrative accounts are separate and cloud-only" $params = @{
$auditResult.CISControlVer = 'v8' Rec = "1.1.1"
$auditResult.CISControl = "5.4" Result = $result
$auditResult.CISDescription = "Restrict Administrator Privileges to Dedicated Administrator Accounts" Status = $status
$auditResult.IG1 = $true Details = $details
$auditResult.IG2 = $true FailureReason = $failureReason
$auditResult.IG3 = $true }
$auditResult.Result = $nonCompliantUsers.Count -eq 0
$auditResult.Details = "Compliant Accounts: $($uniqueAdminRoleUsers.Count - $nonCompliantUsers.Count); Non-Compliant Accounts: $($nonCompliantUsers.Count)" $auditResult = Initialize-CISAuditResult @params
$auditResult.FailureReason = if ($nonCompliantUsers) { "Non-compliant accounts: `nUsername | Roles | HybridStatus | Missing Licence`n$failureReasons" } else { "N/A" }
} }
end { end {

View File

@@ -1,13 +1,15 @@
function Test-AntiPhishingPolicy { function Test-AntiPhishingPolicy {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
#$auditResults = @()
} }
process { process {
@@ -24,37 +26,54 @@ function Test-AntiPhishingPolicy {
} }
# Check if there is at least one policy that meets the requirements # Check if there is at least one policy that meets the requirements
$isCompliant = $validatedPolicies.Count -gt 0 $nonCompliantItems = $antiPhishPolicies | Where-Object {
$_.Enabled -ne $true -or
$_.PhishThresholdLevel -lt 2 -or
$_.EnableMailboxIntelligenceProtection -ne $true -or
$_.EnableMailboxIntelligence -ne $true -or
$_.EnableSpoofIntelligence -ne $true
}
$compliantItems = $validatedPolicies
$isCompliant = $compliantItems.Count -gt 0
# Prepare failure details if policies are not compliant # Prepare failure reasons for non-compliant items
$failureDetails = if (-not $isCompliant) { $nonCompliantNames = $nonCompliantItems | ForEach-Object { $_.Name }
"No anti-phishing policy is fully compliant with CIS benchmark requirements." $failureReasons = if ($nonCompliantNames.Count -gt 0) {
} else { "Reason: Does not meet one or more compliance criteria.`nNon-compliant Policies:`n" + ($nonCompliantNames -join "`n")
"Compliant Anti-Phish Policy Names: " + ($validatedPolicies.Name -join ', ') }
else {
"N/A"
} }
# Create an instance of CISAuditResult and populate it # Prepare details for non-compliant items
$auditResult = [CISAuditResult]::new() $nonCompliantDetails = $nonCompliantItems | ForEach-Object {
$auditResult.Status = if ($isCompliant) { "Pass" } else { "Fail" } "Policy: $($_.Name)"
$auditResult.ELevel = "E5" }
$auditResult.ProfileLevel = "L1" $nonCompliantDetails = $nonCompliantDetails -join "`n"
$auditResult.Rec = "2.1.7"
$auditResult.RecDescription = "Ensure that an anti-phishing policy has been created"
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "9.7"
$auditResult.CISDescription = "Deploy and Maintain Email Server Anti-Malware Protections"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $true
$auditResult.Result = $isCompliant
$auditResult.Details = $failureDetails
$auditResult.FailureReason = if (-not $isCompliant) { "Anti-phishing policies do not meet CIS benchmark requirements." } else { "N/A" }
$auditResults += $auditResult # Prepare details based on compliance
$details = if ($nonCompliantItems) {
"Non-Compliant Items: $($nonCompliantItems.Count)`nDetails:`n$nonCompliantDetails"
}
else {
"Compliant Items: $($compliantItems.Count)"
}
# Parameter splat for Initialize-CISAuditResult function
$params = @{
Rec = "2.1.7"
Result = $nonCompliantItems.Count -eq 0
Status = if ($isCompliant) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
# Create and populate the CISAuditResult object
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return auditResult
return $auditResults return $auditResult
} }
} }

View File

@@ -1,43 +1,51 @@
function Test-AuditDisabledFalse { function Test-AuditDisabledFalse {
[CmdletBinding()] [CmdletBinding()]
# Aligned
param ( param (
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 6.1.1 (L1) Ensure 'AuditDisabled' organizationally is set to 'False' # 6.1.1 (L1) Ensure 'AuditDisabled' organizationally is set to 'False'
# Pass if AuditDisabled is False. Fail otherwise.
# Retrieve the AuditDisabled configuration
$auditDisabledConfig = Get-OrganizationConfig | Select-Object AuditDisabled $auditDisabledConfig = Get-OrganizationConfig | Select-Object AuditDisabled
$auditNotDisabled = -not $auditDisabledConfig.AuditDisabled $auditNotDisabled = -not $auditDisabledConfig.AuditDisabled
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $auditNotDisabled) {
$auditResult.Status = if ($auditNotDisabled) { "Pass" } else { "Fail" } "AuditDisabled is set to True"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1" else {
$auditResult.Rec = "6.1.1" "N/A"
$auditResult.RecDescription = "Ensure 'AuditDisabled' organizationally is set to 'False'" }
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "8.2"
$auditResult.CISDescription = "Collect Audit Logs"
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.Result = $auditNotDisabled
$auditResult.Details = if ($auditNotDisabled) { "Audit is not disabled organizationally" } else { "Audit is disabled organizationally" }
$auditResult.FailureReason = if (-not $auditNotDisabled) { "AuditDisabled is set to True" } else { "N/A" }
$auditResults += $auditResult $details = if ($auditNotDisabled) {
"Audit is not disabled organizationally"
}
else {
"Audit is disabled organizationally"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "6.1.1"
Result = $auditNotDisabled
Status = if ($auditNotDisabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,43 +1,52 @@
function Test-AuditLogSearch { function Test-AuditLogSearch {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 3.1.1 (L1) Ensure Microsoft 365 audit log search is Enabled # 3.1.1 (L1) Ensure Microsoft 365 audit log search is Enabled
# Pass if UnifiedAuditLogIngestionEnabled is True. Fail otherwise.
# Retrieve the audit log configuration
$auditLogConfig = Get-AdminAuditLogConfig | Select-Object UnifiedAuditLogIngestionEnabled $auditLogConfig = Get-AdminAuditLogConfig | Select-Object UnifiedAuditLogIngestionEnabled
$auditLogResult = $auditLogConfig.UnifiedAuditLogIngestionEnabled $auditLogResult = $auditLogConfig.UnifiedAuditLogIngestionEnabled
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $auditLogResult) {
$auditResult.Status = if ($auditLogResult) { "Pass" } else { "Fail" } "Audit log search is not enabled"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1" else {
$auditResult.Rec = "3.1.1" "N/A"
$auditResult.RecDescription = "Ensure Microsoft 365 audit log search is Enabled" }
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "8.2" $details = if ($auditLogResult) {
$auditResult.CISDescription = "Collect Audit Logs" "UnifiedAuditLogIngestionEnabled: True"
$auditResult.IG1 = $true }
$auditResult.IG2 = $true else {
$auditResult.IG3 = $true "UnifiedAuditLogIngestionEnabled: False"
$auditResult.Result = $auditLogResult }
$auditResult.Details = "UnifiedAuditLogIngestionEnabled: $($auditLogConfig.UnifiedAuditLogIngestionEnabled)"
$auditResult.FailureReason = if (-not $auditLogResult) { "Audit log search is not enabled" } else { "N/A" } # Create and populate the CISAuditResult object
$params = @{
Rec = "3.1.1"
Result = $auditLogResult
Status = if ($auditLogResult) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
$auditResults += $auditResult
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,44 +1,51 @@
function Test-BlockChannelEmails { function Test-BlockChannelEmails {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added here if needed # Parameters can be added here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 8.1.2 (L1) Ensure users can't send emails to a channel email address # 8.1.2 (L1) Ensure users can't send emails to a channel email address
# Connect to Teams PowerShell using Connect-MicrosoftTeams
# Retrieve Teams client configuration
$teamsClientConfig = Get-CsTeamsClientConfiguration -Identity Global $teamsClientConfig = Get-CsTeamsClientConfiguration -Identity Global
$allowEmailIntoChannel = $teamsClientConfig.AllowEmailIntoChannel $allowEmailIntoChannel = $teamsClientConfig.AllowEmailIntoChannel
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($allowEmailIntoChannel) {
$auditResult.CISControlVer = "v8" "Emails can be sent to a channel email address"
$auditResult.CISControl = "0.0" # This control is Explicitly Not Mapped as per the image provided }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "8.1.2" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Set based on the benchmark
$auditResult.IG2 = $false # Set based on the benchmark
$auditResult.IG3 = $false # Set based on the benchmark
$auditResult.RecDescription = "Ensure users can't send emails to a channel email address"
$auditResult.Result = -not $allowEmailIntoChannel
$auditResult.Details = "AllowEmailIntoChannel is set to $allowEmailIntoChannel"
$auditResult.FailureReason = if ($allowEmailIntoChannel) { "Emails can be sent to a channel email address" } else { "N/A" }
$auditResult.Status = if (-not $allowEmailIntoChannel) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = if ($allowEmailIntoChannel) {
"AllowEmailIntoChannel is set to True"
}
else {
"AllowEmailIntoChannel is set to False"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "8.1.2"
Result = -not $allowEmailIntoChannel
Status = if (-not $allowEmailIntoChannel) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,51 +1,52 @@
function Test-BlockMailForwarding { function Test-BlockMailForwarding {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned Compare
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script if necessary
$auditResult = [CISAuditResult]::new() #. .\source\Classes\CISAuditResult.ps1
$auditResult.Rec = "6.2.1" # Initialization code, if needed
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L1"
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "0.0"
$auditResult.CISDescription = "Explicitly Not Mapped"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $false
$auditResult.RecDescription = "Ensure all forms of mail forwarding are blocked and/or disabled"
} }
process { process {
# Verify that no rules are forwarding the email to external domains # 6.2.1 (L1) Ensure all forms of mail forwarding are blocked and/or disabled
$transportRules = Get-TransportRule | Where-Object { $_.RedirectMessageTo -ne $null }
# Retrieve the transport rules that redirect messages
$transportRules = Get-TransportRule | Where-Object { $null -ne $_.RedirectMessageTo }
$forwardingBlocked = $transportRules.Count -eq 0 $forwardingBlocked = $transportRules.Count -eq 0
$auditResult.Result = $forwardingBlocked # Prepare failure reasons and details based on compliance
$auditResult.Details = if ($transportRules.Count -gt 0) { $failureReasons = if ($transportRules.Count -gt 0) {
"Mail forwarding rules found: $($transportRules.Name -join ', ')"
}
else {
"N/A"
}
$details = if ($transportRules.Count -gt 0) {
$transportRules | ForEach-Object { $transportRules | ForEach-Object {
"$($_.Name) redirects to $($_.RedirectMessageTo)" "$($_.Name) redirects to $($_.RedirectMessageTo)"
} -join " | " } -join " | "
} else { }
else {
"Step 1: No forwarding rules found. Please proceed with Step 2 described in CIS Benchmark." "Step 1: No forwarding rules found. Please proceed with Step 2 described in CIS Benchmark."
} }
$auditResult.FailureReason = if (-not $forwardingBlocked) {
"Mail forwarding rules found: $($transportRules.Name -join ', ')" $params = @{
} else { Rec = "6.2.1"
"N/A" Result = $forwardingBlocked
Status = if ($forwardingBlocked) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
} }
$auditResult.Status = if ($forwardingBlocked) { "Pass" } else { "Fail" } $auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return the result object # Return the audit result
return $auditResult return $auditResult
} }
} }

View File

@@ -1,48 +1,53 @@
function Test-BlockSharedMailboxSignIn { function Test-BlockSharedMailboxSignIn {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 1.2.2 (L1) Ensure sign-in to shared mailboxes is blocked # 1.2.2 (L1) Ensure sign-in to shared mailboxes is blocked
# Pass if all shared mailboxes have AccountEnabled set to False.
# Fail if any shared mailbox has AccountEnabled set to True.
# Review: Details property - Add verbosity.
# Retrieve shared mailbox details
$MBX = Get-EXOMailbox -RecipientTypeDetails SharedMailbox $MBX = Get-EXOMailbox -RecipientTypeDetails SharedMailbox
$sharedMailboxDetails = $MBX | ForEach-Object { Get-AzureADUser -ObjectId $_.ExternalDirectoryObjectId } $sharedMailboxDetails = $MBX | ForEach-Object { Get-AzureADUser -ObjectId $_.ExternalDirectoryObjectId }
$enabledMailboxes = $sharedMailboxDetails | Where-Object { $_.AccountEnabled } | ForEach-Object { $_.DisplayName } $enabledMailboxes = $sharedMailboxDetails | Where-Object { $_.AccountEnabled } | ForEach-Object { $_.DisplayName }
$allBlocked = $enabledMailboxes.Count -eq 0 $allBlocked = $enabledMailboxes.Count -eq 0
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $allBlocked) {
$auditResult.CISControlVer = "v8" "Some mailboxes have sign-in enabled: $($enabledMailboxes -join ', ')"
$auditResult.CISControl = "0.0" # Control is explicitly not mapped }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "1.2.2" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Control is not mapped, hence IG1 is false
$auditResult.IG2 = $false # Control is not mapped, hence IG2 is false
$auditResult.IG3 = $false # Control is not mapped, hence IG3 is false
$auditResult.RecDescription = "Ensure sign-in to shared mailboxes is blocked"
$auditResult.Result = $allBlocked
$auditResult.Details = "Enabled Mailboxes: $($enabledMailboxes -join ', ')"
$auditResult.FailureReason = if ($allBlocked) { "N/A" } else { "Some mailboxes have sign-in enabled: $($enabledMailboxes -join ', ')" }
$auditResult.Status = if ($allBlocked) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = if ($allBlocked) {
"All shared mailboxes have sign-in blocked."
}
else {
"Enabled Mailboxes: $($enabledMailboxes -join ', ')"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "1.2.2"
Result = $allBlocked
Status = if ($allBlocked) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,46 +1,51 @@
function Test-CommonAttachmentFilter { function Test-CommonAttachmentFilter {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script if necessary
$auditResults = @() #. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
} }
process { process {
# 2.1.2 (L1) Ensure the Common Attachment Types Filter is enabled # 2.1.2 (L1) Ensure the Common Attachment Types Filter is enabled
# Pass if EnableFileFilter is set to True. Fail otherwise.
# Retrieve the attachment filter policy
$attachmentFilter = Get-MalwareFilterPolicy -Identity Default | Select-Object EnableFileFilter $attachmentFilter = Get-MalwareFilterPolicy -Identity Default | Select-Object EnableFileFilter
$result = $attachmentFilter.EnableFileFilter $result = $attachmentFilter.EnableFileFilter
$details = "File Filter Enabled: $($attachmentFilter.EnableFileFilter)"
$failureReason = if ($result) { "N/A" } else { "Common Attachment Types Filter is disabled" }
$status = if ($result) { "Pass" } else { "Fail" }
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $result) {
$auditResult.Status = $status "Common Attachment Types Filter is disabled"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1" else {
$auditResult.Rec = "2.1.2" "N/A"
$auditResult.RecDescription = "Ensure the Common Attachment Types Filter is enabled" }
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "9.6"
$auditResult.CISDescription = "Block Unnecessary File Types"
$auditResult.IG1 = $false
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.Result = $result
$auditResult.Details = $details
$auditResult.FailureReason = $failureReason
$auditResults += $auditResult $details = if ($result) {
"File Filter Enabled: True"
}
else {
"File Filter Enabled: False"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "2.1.2"
Result = $result
Status = if ($result) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,40 +1,51 @@
function Test-CustomerLockbox { function Test-CustomerLockbox {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Define your parameters here # Aligned
# Define your parameters here if needed
) )
begin { begin {
# Dot source the class script if necessary
$auditResults = @() #. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
} }
process { process {
# 1.3.6 (L2) Ensure the customer lockbox feature is enabled # 1.3.6 (L2) Ensure the customer lockbox feature is enabled
# Retrieve the organization configuration
$orgConfig = Get-OrganizationConfig | Select-Object CustomerLockBoxEnabled $orgConfig = Get-OrganizationConfig | Select-Object CustomerLockBoxEnabled
$customerLockboxEnabled = $orgConfig.CustomerLockBoxEnabled $customerLockboxEnabled = $orgConfig.CustomerLockBoxEnabled
$auditResult = [CISAuditResult]::new() # Prepare failure reasons and details based on compliance
$auditResult.Status = if ($customerLockboxEnabled) { "Pass" } else { "Fail" } $failureReasons = if (-not $customerLockboxEnabled) {
$auditResult.ELevel = "E5" "Customer lockbox feature is not enabled."
$auditResult.ProfileLevel = "L2" }
$auditResult.Rec = "1.3.6" else {
$auditResult.RecDescription = "Ensure the customer lockbox feature is enabled" "N/A"
$auditResult.CISControlVer = 'v8' }
$auditResult.CISControl = "0.0" # As per the snapshot provided, this is explicitly not mapped
$auditResult.CISDescription = "Explicitly Not Mapped"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $false
$auditResult.Result = $customerLockboxEnabled
$auditResult.Details = "Customer Lockbox Enabled: $customerLockboxEnabled"
$auditResult.FailureReason = if ($customerLockboxEnabled) { "N/A" } else { "Customer lockbox feature is not enabled." }
$auditResults += $auditResult $details = if ($customerLockboxEnabled) {
"Customer Lockbox Enabled: True"
}
else {
"Customer Lockbox Enabled: False"
}
# Create and populate the CISAuditResult object #
$params = @{
Rec = "1.3.6"
Result = $customerLockboxEnabled
Status = if ($customerLockboxEnabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,45 +1,51 @@
function Test-DialInBypassLobby { function Test-DialInBypassLobby {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 8.5.4 (L1) Ensure users dialing in can't bypass the lobby # 8.5.4 (L1) Ensure users dialing in can't bypass the lobby
# Connect to Teams PowerShell using Connect-MicrosoftTeams # Retrieve Teams meeting policy for PSTN users
$CsTeamsMeetingPolicyPSTN = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property AllowPSTNUsersToBypassLobby $CsTeamsMeetingPolicyPSTN = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property AllowPSTNUsersToBypassLobby
$PSTNBypassDisabled = -not $CsTeamsMeetingPolicyPSTN.AllowPSTNUsersToBypassLobby $PSTNBypassDisabled = -not $CsTeamsMeetingPolicyPSTN.AllowPSTNUsersToBypassLobby
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $PSTNBypassDisabled) {
$auditResult.CISControlVer = "v8" "Users dialing in can bypass the lobby"
$auditResult.CISControl = "0.0" # Explicitly Not Mapped as per the image provided }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "8.5.4" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Set based on the CIS Controls image
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $false # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure users dialing in can't bypass the lobby"
$auditResult.Result = $PSTNBypassDisabled
$auditResult.Details = "AllowPSTNUsersToBypassLobby is set to $($CsTeamsMeetingPolicyPSTN.AllowPSTNUsersToBypassLobby)"
$auditResult.FailureReason = if ($PSTNBypassDisabled) { "N/A" } else { "Users dialing in can bypass the lobby" }
$auditResult.Status = if ($PSTNBypassDisabled) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = if ($PSTNBypassDisabled) {
"AllowPSTNUsersToBypassLobby is set to False"
}
else {
"AllowPSTNUsersToBypassLobby is set to True"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "8.5.4"
Result = $PSTNBypassDisabled
Status = if ($PSTNBypassDisabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,41 +1,53 @@
function Test-DisallowInfectedFilesDownload { function Test-DisallowInfectedFilesDownload {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Define your parameters here # Aligned
# Define your parameters here if needed
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download # 7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download
# Retrieve the SharePoint tenant configuration
$SPOTenantDisallowInfectedFileDownload = Get-SPOTenant | Select-Object DisallowInfectedFileDownload $SPOTenantDisallowInfectedFileDownload = Get-SPOTenant | Select-Object DisallowInfectedFileDownload
$isDisallowInfectedFileDownloadEnabled = $SPOTenantDisallowInfectedFileDownload.DisallowInfectedFileDownload $isDisallowInfectedFileDownloadEnabled = $SPOTenantDisallowInfectedFileDownload.DisallowInfectedFileDownload
# Populate the auditResult object with the required properties # Prepare failure reasons and details based on compliance
$auditResult.CISControlVer = "v8" $failureReasons = if (-not $isDisallowInfectedFileDownloadEnabled) {
$auditResult.CISControl = "10.1" "Downloading infected files is not disallowed."
$auditResult.CISDescription = "Deploy and Maintain Anti-Malware Software" }
else {
"N/A"
}
$auditResult.Rec = "7.3.1" $details = if ($isDisallowInfectedFileDownloadEnabled) {
$auditResult.ELevel = "E5" "DisallowInfectedFileDownload: True"
$auditResult.ProfileLevel = "L2" }
$auditResult.IG1 = $true else {
$auditResult.IG2 = $true "DisallowInfectedFileDownload: False"
$auditResult.IG3 = $true }
$auditResult.RecDescription = "Ensure Office 365 SharePoint infected files are disallowed for download"
# Create and populate the CISAuditResult object
$params = @{
Rec = "7.3.1"
Result = $isDisallowInfectedFileDownloadEnabled
Status = if ($isDisallowInfectedFileDownloadEnabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
$auditResult.Result = $isDisallowInfectedFileDownloadEnabled
$auditResult.Details = "DisallowInfectedFileDownload: $($SPOTenantDisallowInfectedFileDownload.DisallowInfectedFileDownload)"
$auditResult.FailureReason = if (-not $isDisallowInfectedFileDownloadEnabled) { "Downloading infected files is not disallowed." } else { "N/A" }
$auditResult.Status = if ($isDisallowInfectedFileDownloadEnabled) { "Pass" } else { "Fail" }
} }
end { end {
# Return auditResult # Return the audit result
return $auditResult return $auditResult
} }
} }

View File

@@ -1,44 +1,52 @@
function Test-EnableDKIM { function Test-EnableDKIM {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 2.1.9 (L1) Ensure DKIM is enabled for all Exchange Online Domains # 2.1.9 (L1) Ensure DKIM is enabled for all Exchange Online Domains
# Pass if Enabled is True for all domains. Fail if any domain has Enabled set to False.
# Retrieve DKIM configuration for all domains
$dkimConfig = Get-DkimSigningConfig | Select-Object Domain, Enabled $dkimConfig = Get-DkimSigningConfig | Select-Object Domain, Enabled
$dkimResult = ($dkimConfig | ForEach-Object { $_.Enabled }) -notcontains $false $dkimResult = ($dkimConfig | ForEach-Object { $_.Enabled }) -notcontains $false
$dkimFailedDomains = $dkimConfig | Where-Object { -not $_.Enabled } | ForEach-Object { $_.Domain } $dkimFailedDomains = $dkimConfig | Where-Object { -not $_.Enabled } | ForEach-Object { $_.Domain }
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $dkimResult) {
$auditResult.Status = if ($dkimResult) { "Pass" } else { "Fail" } "DKIM is not enabled for some domains"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1" else {
$auditResult.Rec = "2.1.9" "N/A"
$auditResult.RecDescription = "Ensure that DKIM is enabled for all Exchange Online Domains" }
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "9.5"
$auditResult.CISDescription = "Implement DMARC"
$auditResult.IG1 = $false
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.Result = $dkimResult
$auditResult.Details = if (-not $dkimResult) { "DKIM not enabled for: $($dkimFailedDomains -join ', ')" } else { "All domains have DKIM enabled" }
$auditResult.FailureReason = if (-not $dkimResult) { "DKIM is not enabled for some domains" } else { "N/A" }
$auditResults += $auditResult $details = if ($dkimResult) {
"All domains have DKIM enabled"
}
else {
"DKIM not enabled for: $($dkimFailedDomains -join ', ')"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "2.1.9"
Result = $dkimResult
Status = if ($dkimResult) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,45 +1,52 @@
function Test-ExternalNoControl { function Test-ExternalNoControl {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 8.5.7 (L1) Ensure external participants can't give or request control # 8.5.7 (L1) Ensure external participants can't give or request control
# Connect to Teams PowerShell using Connect-MicrosoftTeams # Retrieve Teams meeting policy for external participant control
$CsTeamsMeetingPolicyControl = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property AllowExternalParticipantGiveRequestControl $CsTeamsMeetingPolicyControl = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property AllowExternalParticipantGiveRequestControl
$externalControlRestricted = -not $CsTeamsMeetingPolicyControl.AllowExternalParticipantGiveRequestControl $externalControlRestricted = -not $CsTeamsMeetingPolicyControl.AllowExternalParticipantGiveRequestControl
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $externalControlRestricted) {
$auditResult.CISControlVer = "v8" "External participants can give or request control"
$auditResult.CISControl = "0.0" # Explicitly Not Mapped as per the image provided }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "8.5.7" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Set based on the CIS Controls image
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $false # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure external participants can't give or request control"
$auditResult.Result = $externalControlRestricted
$auditResult.Details = "AllowExternalParticipantGiveRequestControl is set to $($CsTeamsMeetingPolicyControl.AllowExternalParticipantGiveRequestControl)"
$auditResult.FailureReason = if ($externalControlRestricted) { "N/A" } else { "External participants can give or request control" }
$auditResult.Status = if ($externalControlRestricted) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = if ($externalControlRestricted) {
"AllowExternalParticipantGiveRequestControl is set to False"
}
else {
"AllowExternalParticipantGiveRequestControl is set to True"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "8.5.7"
Result = $externalControlRestricted
Status = if ($externalControlRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,17 +1,21 @@
function Test-ExternalSharingCalendars { function Test-ExternalSharingCalendars {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 1.3.3 (L2) Ensure 'External sharing' of calendars is not available (Automated) # 1.3.3 (L2) Ensure 'External sharing' of calendars is not available (Automated)
# Retrieve sharing policies related to calendar sharing
$sharingPolicies = Get-SharingPolicy | Where-Object { $_.Domains -like '*CalendarSharing*' } $sharingPolicies = Get-SharingPolicy | Where-Object { $_.Domains -like '*CalendarSharing*' }
# Check if calendar sharing is disabled in all applicable policies # Check if calendar sharing is disabled in all applicable policies
@@ -24,30 +28,34 @@ function Test-ExternalSharingCalendars {
} }
} }
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $isExternalSharingDisabled) {
$auditResult.Rec = "1.3.3" "Calendar sharing with external users is enabled in one or more policies."
$auditResult.RecDescription = "Ensure 'External sharing' of calendars is not available" }
$auditResult.ELevel = "E3" else {
$auditResult.ProfileLevel = "L2" "N/A"
# The following IG values are placeholders. Replace with actual values when known. }
$auditResult.IG1 = $false
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.CISControlVer = "v8"
# Placeholder for CIS Control, to be replaced with the actual value when available
$auditResult.CISControl = "4.8"
$auditResult.CISDescription = "Uninstall or Disable Unnecessary Services on Enterprise Assets and Software"
$auditResult.Result = $isExternalSharingDisabled
$auditResult.Details = if ($isExternalSharingDisabled) { "Calendar sharing with external users is disabled." } else { "Enabled Sharing Policies: $($sharingPolicyDetails -join ', ')" }
$auditResult.FailureReason = if ($isExternalSharingDisabled) { "N/A" } else { "Calendar sharing with external users is enabled in one or more policies." }
$auditResult.Status = if ($isExternalSharingDisabled) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = if ($isExternalSharingDisabled) {
"Calendar sharing with external users is disabled."
}
else {
"Enabled Sharing Policies: $($sharingPolicyDetails -join ', ')"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "1.3.3"
Result = $isExternalSharingDisabled
Status = if ($isExternalSharingDisabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,46 +1,52 @@
function Test-GlobalAdminsCount { function Test-GlobalAdminsCount {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Define your parameters here # Aligned
# Define your parameters here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 1.1.3 (L1) Ensure that between two and four global admins are designated # 1.1.3 (L1) Ensure that between two and four global admins are designated
# Pass if the count of global admins is between 2 and 4. Fail otherwise.
# Retrieve global admin role and members
$globalAdminRole = Get-MgDirectoryRole -Filter "RoleTemplateId eq '62e90394-69f5-4237-9190-012177145e10'" $globalAdminRole = Get-MgDirectoryRole -Filter "RoleTemplateId eq '62e90394-69f5-4237-9190-012177145e10'"
$globalAdmins = Get-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id $globalAdmins = Get-MgDirectoryRoleMember -DirectoryRoleId $globalAdminRole.Id
$globalAdminCount = $globalAdmins.AdditionalProperties.Count $globalAdminCount = $globalAdmins.AdditionalProperties.Count
$globalAdminUsernames = ($globalAdmins | ForEach-Object { $_.AdditionalProperties["displayName"] }) -join ', ' $globalAdminUsernames = ($globalAdmins | ForEach-Object { $_.AdditionalProperties["displayName"] }) -join ', '
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($globalAdminCount -lt 2) {
$auditResult.CISControlVer = "v8" "Less than 2 global admins: $globalAdminUsernames"
$auditResult.CISControl = "5.1" }
$auditResult.CISDescription = "Establish and Maintain an Inventory of Accounts" elseif ($globalAdminCount -gt 4) {
$auditResult.Rec = "1.1.3" "More than 4 global admins: $globalAdminUsernames"
$auditResult.ELevel = "E3" # Based on your environment (E3, E5, etc.) }
$auditResult.ProfileLevel = "L1" else {
$auditResult.IG1 = $true # Set based on the benchmark "N/A"
$auditResult.IG2 = $true # Set based on the benchmark }
$auditResult.IG3 = $true # Set based on the benchmark
$auditResult.RecDescription = "Ensure that between two and four global admins are designated"
$auditResult.Result = $globalAdminCount -ge 2 -and $globalAdminCount -le 4
$auditResult.Details = "Count: $globalAdminCount; Users: $globalAdminUsernames"
$auditResult.FailureReason = if ($globalAdminCount -lt 2) { "Less than 2 global admins: $globalAdminUsernames" } elseif ($globalAdminCount -gt 4) { "More than 4 global admins: $globalAdminUsernames" } else { "N/A" }
$auditResult.Status = if ($globalAdminCount -ge 2 -and $globalAdminCount -le 4) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = "Count: $globalAdminCount; Users: $globalAdminUsernames"
# Create and populate the CISAuditResult object
$params = @{
Rec = "1.1.3"
Result = $globalAdminCount -ge 2 -and $globalAdminCount -le 4
Status = if ($globalAdminCount -ge 2 -and $globalAdminCount -le 4) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,41 +1,47 @@
function Test-GuestAccessExpiration { function Test-GuestAccessExpiration {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Define your parameters here # Aligned
# Define your parameters here if needed
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically # 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically
# Retrieve SharePoint tenant settings related to guest access expiration
$SPOTenantGuestAccess = Get-SPOTenant | Select-Object ExternalUserExpirationRequired, ExternalUserExpireInDays $SPOTenantGuestAccess = Get-SPOTenant | Select-Object ExternalUserExpirationRequired, ExternalUserExpireInDays
$isGuestAccessExpirationConfiguredCorrectly = $SPOTenantGuestAccess.ExternalUserExpirationRequired -and $SPOTenantGuestAccess.ExternalUserExpireInDays -le 30 $isGuestAccessExpirationConfiguredCorrectly = $SPOTenantGuestAccess.ExternalUserExpirationRequired -and $SPOTenantGuestAccess.ExternalUserExpireInDays -le 30
# Populate the auditResult object with the required properties # Prepare failure reasons and details based on compliance
$auditResult.CISControlVer = "v8" $failureReasons = if (-not $isGuestAccessExpirationConfiguredCorrectly) {
$auditResult.CISControl = "0.0" "Guest access expiration is not configured to automatically expire within 30 days or less."
$auditResult.CISDescription = "Explicitly Not Mapped" }
else {
"N/A"
}
$auditResult.Rec = "7.2.9" $details = "ExternalUserExpirationRequired: $($SPOTenantGuestAccess.ExternalUserExpirationRequired); ExternalUserExpireInDays: $($SPOTenantGuestAccess.ExternalUserExpireInDays)"
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $false
$auditResult.RecDescription = "Ensure guest access to a site or OneDrive will expire automatically"
$auditResult.Result = $isGuestAccessExpirationConfiguredCorrectly # Create and populate the CISAuditResult object
$auditResult.Details = "ExternalUserExpirationRequired: $($SPOTenantGuestAccess.ExternalUserExpirationRequired); ExternalUserExpireInDays: $($SPOTenantGuestAccess.ExternalUserExpireInDays)" $params = @{
$auditResult.FailureReason = if (-not $isGuestAccessExpirationConfiguredCorrectly) { "Guest access expiration is not configured to automatically expire within 30 days or less." } else { "N/A" } Rec = "7.2.9"
$auditResult.Status = if ($isGuestAccessExpirationConfiguredCorrectly) { "Pass" } else { "Fail" } Result = $isGuestAccessExpirationConfiguredCorrectly
Status = if ($isGuestAccessExpirationConfiguredCorrectly) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResult # Return the audit result
return $auditResult return $auditResult
} }
} }

View File

@@ -1,61 +1,54 @@
function Test-GuestUsersBiweeklyReview { function Test-GuestUsersBiweeklyReview {
[CmdletBinding()] [CmdletBinding()]
param () param (
# Aligned
# Define your parameters here if needed
)
begin { begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1 #. .\source\Classes\CISAuditResult.ps1
$auditResults = @()
# Initialization code, if needed
} }
process { process {
# 1.1.4 (L1) Ensure Guest Users are reviewed at least biweekly # 1.1.4 (L1) Ensure Guest Users are reviewed at least biweekly
# The function will fail if guest users are found since they should be reviewed manually biweekly.
try {
# Connect to Microsoft Graph - placeholder for connection command # Retrieve guest users from Microsoft Graph
# Connect-MgGraph -Scopes "User.Read.All" # Connect-MgGraph -Scopes "User.Read.All"
$guestUsers = Get-MgUser -All -Filter "UserType eq 'Guest'" $guestUsers = Get-MgUser -All -Filter "UserType eq 'Guest'"
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($guestUsers) {
$auditResult.CISControl = "5.1, 5.3" "Guest users present: $($guestUsers.Count)"
$auditResult.CISDescription = "Establish and Maintain an Inventory of Accounts, Disable Dormant Accounts" }
$auditResult.Rec = "1.1.4" else {
$auditResult.RecDescription = "Ensure Guest Users are reviewed at least biweekly" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.CISControlVer = 'v8'
if ($guestUsers) { $details = if ($guestUsers) {
$auditCommand = "Get-MgUser -All -Property UserType,UserPrincipalName | Where {`$_.UserType -ne 'Member'} | Format-Table UserPrincipalName, UserType" $auditCommand = "Get-MgUser -All -Property UserType,UserPrincipalName | Where {`$_.UserType -ne 'Member'} | Format-Table UserPrincipalName, UserType"
$auditResult.Status = "Fail" "Manual review required. To list guest users, run: `"$auditCommand`"."
$auditResult.Result = $false
$auditResult.Details = "Manual review required. To list guest users, run: `"$auditCommand`"."
$auditResult.FailureReason = "Guest users present: $($guestUsers.Count)"
} else {
$auditResult.Status = "Pass"
$auditResult.Result = $true
$auditResult.Details = "No guest users found."
$auditResult.FailureReason = "N/A"
} }
} else {
catch { "No guest users found."
$auditResult.Status = "Error"
$auditResult.Result = $false
$auditResult.Details = "Error while attempting to check guest users. Error message: $($_.Exception.Message)"
$auditResult.FailureReason = "An error occurred during the audit check."
} }
$auditResults += $auditResult # Create and populate the CISAuditResult object
$params = @{
Rec = "1.1.4"
Result = -not $guestUsers
Status = if ($guestUsers) { "Fail" } else { "Pass" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,45 +1,47 @@
function Test-IdentifyExternalEmail { function Test-IdentifyExternalEmail {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 6.2.3 (L1) Ensure email from external senders is identified # 6.2.3 (L1) Ensure email from external senders is identified
# Requirement is to have external sender tagging enabled
# Review
# Retrieve external sender tagging configuration
$externalInOutlook = Get-ExternalInOutlook $externalInOutlook = Get-ExternalInOutlook
$externalTaggingEnabled = ($externalInOutlook | ForEach-Object { $_.Enabled }) -contains $true $externalTaggingEnabled = ($externalInOutlook | ForEach-Object { $_.Enabled }) -contains $true
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $externalTaggingEnabled) {
$auditResult.Status = if ($externalTaggingEnabled) { "Pass" } else { "Fail" } "External sender tagging is disabled"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1" else {
$auditResult.Rec = "6.2.3" "N/A"
$auditResult.RecDescription = "Ensure email from external senders is identified" }
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "0.0"
$auditResult.CISDescription = "Explicitly Not Mapped"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $false
$auditResult.Result = $externalTaggingEnabled
$auditResult.Details = "Enabled: $($externalTaggingEnabled); AllowList: $($externalInOutlook.AllowList)"
$auditResult.FailureReason = if (-not $externalTaggingEnabled) { "External sender tagging is disabled" } else { "N/A" }
$auditResults += $auditResult $details = "Enabled: $($externalTaggingEnabled); AllowList: $($externalInOutlook.AllowList)"
# Create and populate the CISAuditResult object
$params = @{
Rec = "6.2.3"
Result = $externalTaggingEnabled
Status = if ($externalTaggingEnabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,42 +1,47 @@
function Test-LinkSharingRestrictions { function Test-LinkSharingRestrictions {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
# Test behavior in prod # Test behavior in prod
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive # 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive
# Retrieve link sharing configuration for SharePoint and OneDrive
$SPOTenantLinkSharing = Get-SPOTenant | Select-Object DefaultSharingLinkType $SPOTenantLinkSharing = Get-SPOTenant | Select-Object DefaultSharingLinkType
$isLinkSharingRestricted = $SPOTenantLinkSharing.DefaultSharingLinkType -eq 'Direct' # Or 'SpecificPeople' as per the recommendation $isLinkSharingRestricted = $SPOTenantLinkSharing.DefaultSharingLinkType -eq 'Direct' # Or 'SpecificPeople' as per the recommendation
# Populate the auditResult object with the required properties # Prepare failure reasons and details based on compliance
$auditResult.CISControlVer = "v8" $failureReasons = if (-not $isLinkSharingRestricted) {
$auditResult.CISControl = "3.3" "Link sharing is not restricted to 'Specific people'. Current setting: $($SPOTenantLinkSharing.DefaultSharingLinkType)"
$auditResult.CISDescription = "Configure Data Access Control Lists" }
else {
"N/A"
}
$auditResult.Rec = "7.2.7" $details = "DefaultSharingLinkType: $($SPOTenantLinkSharing.DefaultSharingLinkType)"
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.RecDescription = "Ensure link sharing is restricted in SharePoint and OneDrive"
$auditResult.Result = $isLinkSharingRestricted # Create and populate the CISAuditResult object
$auditResult.Details = "DefaultSharingLinkType: $($SPOTenantLinkSharing.DefaultSharingLinkType)" $params = @{
$auditResult.FailureReason = if (-not $isLinkSharingRestricted) { "Link sharing is not restricted to 'Specific people'. Current setting: $($SPOTenantLinkSharing.DefaultSharingLinkType)" } else { "N/A" } Rec = "7.2.7"
$auditResult.Status = if ($isLinkSharingRestricted) { "Pass" } else { "Fail" } Result = $isLinkSharingRestricted
Status = if ($isLinkSharingRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResult # Return the audit result
return $auditResult return $auditResult
} }
} }

View File

@@ -1,43 +1,54 @@
function Test-MailTipsEnabled { function Test-MailTipsEnabled {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Define your parameters here # Aligned
# Parameters can be added if needed
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResult = [CISAuditResult]::new() $auditResult = [CISAuditResult]::new()
} }
process { process {
# 6.5.2 (L2) Ensure MailTips are enabled for end users # 6.5.2 (L2) Ensure MailTips are enabled for end users
# Retrieve organization configuration for MailTips settings
$orgConfig = Get-OrganizationConfig | Select-Object MailTipsAllTipsEnabled, MailTipsExternalRecipientsTipsEnabled, MailTipsGroupMetricsEnabled, MailTipsLargeAudienceThreshold $orgConfig = Get-OrganizationConfig | Select-Object MailTipsAllTipsEnabled, MailTipsExternalRecipientsTipsEnabled, MailTipsGroupMetricsEnabled, MailTipsLargeAudienceThreshold
$allTipsEnabled = $orgConfig.MailTipsAllTipsEnabled -and $orgConfig.MailTipsGroupMetricsEnabled -and $orgConfig.MailTipsLargeAudienceThreshold -eq 25 $allTipsEnabled = $orgConfig.MailTipsAllTipsEnabled -and $orgConfig.MailTipsGroupMetricsEnabled -and $orgConfig.MailTipsLargeAudienceThreshold -eq 25
$externalRecipientsTipsEnabled = $orgConfig.MailTipsExternalRecipientsTipsEnabled $externalRecipientsTipsEnabled = $orgConfig.MailTipsExternalRecipientsTipsEnabled
# Since there is no direct CIS Control mapping, the control will be set as not applicable. # Prepare failure reasons and details based on compliance
$auditResult.CISControl = "0" $failureReasons = if (-not ($allTipsEnabled -and $externalRecipientsTipsEnabled)) {
$auditResult.CISControlVer = "v8" "One or more MailTips settings are not configured as required."
$auditResult.CISDescription = "Explicitly Not Mapped" }
else {
"N/A"
}
$auditResult.Rec = "6.5.2" $details = if ($allTipsEnabled -and $externalRecipientsTipsEnabled) {
$auditResult.ELevel = "E3" "MailTipsAllTipsEnabled: $($orgConfig.MailTipsAllTipsEnabled); MailTipsExternalRecipientsTipsEnabled: $($orgConfig.MailTipsExternalRecipientsTipsEnabled); MailTipsGroupMetricsEnabled: $($orgConfig.MailTipsGroupMetricsEnabled); MailTipsLargeAudienceThreshold: $($orgConfig.MailTipsLargeAudienceThreshold)"
$auditResult.ProfileLevel = "L2" }
$auditResult.IG1 = $false else {
$auditResult.IG2 = $false "One or more MailTips settings are not configured as required."
$auditResult.IG3 = $false }
$auditResult.RecDescription = "Ensure MailTips are enabled for end users"
$auditResult.Result = $allTipsEnabled -and $externalRecipientsTipsEnabled # Create and populate the CISAuditResult object
$auditResult.Details = "MailTipsAllTipsEnabled: $($orgConfig.MailTipsAllTipsEnabled); MailTipsExternalRecipientsTipsEnabled: $($orgConfig.MailTipsExternalRecipientsTipsEnabled); MailTipsGroupMetricsEnabled: $($orgConfig.MailTipsGroupMetricsEnabled); MailTipsLargeAudienceThreshold: $($orgConfig.MailTipsLargeAudienceThreshold)" $params = @{
$auditResult.FailureReason = if (-not $auditResult.Result) { "One or more MailTips settings are not configured as required." } else { "N/A" } Rec = "6.5.2"
$auditResult.Status = if ($auditResult.Result) { "Pass" } else { "Fail" } Result = $allTipsEnabled -and $externalRecipientsTipsEnabled
Status = if ($allTipsEnabled -and $externalRecipientsTipsEnabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResult # Return the audit result
return $auditResult return $auditResult
} }
} }

View File

@@ -1,26 +1,20 @@
function Test-MailboxAuditingE3 { function Test-MailboxAuditingE3 {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Create Table for Details
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$e3SkuPartNumbers = @("ENTERPRISEPACK", "OFFICESUBSCRIPTION") $e3SkuPartNumbers = @("ENTERPRISEPACK", "OFFICESUBSCRIPTION")
$AdminActions = @("ApplyRecord", "Copy", "Create", "FolderBind", "HardDelete", "Move", "MoveToDeletedItems", "SendAs", "SendOnBehalf", "SoftDelete", "Update", "UpdateCalendarDelegation", "UpdateFolderPermissions", "UpdateInboxRules") $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") $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") $OwnerActions = @("ApplyRecord", "Create", "HardDelete", "MailboxLogin", "Move", "MoveToDeletedItems", "SoftDelete", "Update", "UpdateCalendarDelegation", "UpdateFolderPermissions", "UpdateInboxRules")
$auditResult = [CISAuditResult]::new()
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L1"
$auditResult.Rec = "6.1.2"
$auditResult.RecDescription = "Ensure mailbox auditing for Office E3 users is Enabled"
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "8.2"
$auditResult.CISDescription = "Collect audit logs."
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$allFailures = @() $allFailures = @()
$allUsers = Get-AzureADUser -All $true $allUsers = Get-AzureADUser -All $true
@@ -72,10 +66,19 @@ function Test-MailboxAuditingE3 {
} }
} }
$auditResult.Result = $allFailures.Count -eq 0 # Prepare failure reasons and details based on compliance
$auditResult.Status = if ($auditResult.Result) { "Pass" } else { "Fail" } $failureReasons = if ($allFailures.Count -eq 0) { "N/A" } else { "Audit issues detected." }
$auditResult.Details = if ($auditResult.Result) { "All Office E3 users have correct mailbox audit settings." } else { $allFailures -join " | " } $details = if ($allFailures.Count -eq 0) { "All Office E3 users have correct mailbox audit settings." } else { $allFailures -join " | " }
$auditResult.FailureReason = if (-not $auditResult.Result) { "Audit issues detected." } else { "N/A" }
# Populate the audit result
$params = @{
Rec = "6.1.2"
Result = $allFailures.Count -eq 0
Status = if ($allFailures.Count -eq 0) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {

View File

@@ -1,23 +1,21 @@
function Test-MailboxAuditingE5 { function Test-MailboxAuditingE5 {
[CmdletBinding()] [CmdletBinding()]
param () param (
# Aligned
# Create Table for Details
# Parameters can be added if needed
)
begin { begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$e5SkuPartNumbers = @("SPE_E5", "ENTERPRISEPREMIUM", "OFFICEE5")
$AdminActions = @("ApplyRecord", "Copy", "Create", "FolderBind", "HardDelete", "MailItemsAccessed", "Move", "MoveToDeletedItems", "SendAs", "SendOnBehalf", "Send", "SoftDelete", "Update", "UpdateCalendarDelegation", "UpdateFolderPermissions", "UpdateInboxRules") $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") $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") $OwnerActions = @("ApplyRecord", "Create", "HardDelete", "MailboxLogin", "Move", "MailItemsAccessed", "MoveToDeletedItems", "Send", "SoftDelete", "Update", "UpdateCalendarDelegation", "UpdateFolderPermissions", "UpdateInboxRules")
$auditResult = [CISAuditResult]::new()
$auditResult.ELevel = "E5"
$auditResult.ProfileLevel = "L1"
$auditResult.Rec = "6.1.3"
$auditResult.RecDescription = "Ensure mailbox auditing for Office E5 users is Enabled"
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "8.2"
$auditResult.CISDescription = "Collect audit logs."
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$allFailures = @() $allFailures = @()
$allUsers = Get-AzureADUser -All $true $allUsers = Get-AzureADUser -All $true
@@ -31,15 +29,11 @@ function Test-MailboxAuditingE5 {
} }
try { try {
# Define SKU Part Numbers for Office E5 licenses
# Define SKU Part Numbers for Office E5 licenses
$e5SkuPartNumbers = @("SPE_E5", "ENTERPRISEPREMIUM", "OFFICEE5")
$licenseDetails = Get-MgUserLicenseDetail -UserId $user.UserPrincipalName $licenseDetails = Get-MgUserLicenseDetail -UserId $user.UserPrincipalName
$hasOfficeE5 = ($licenseDetails | Where-Object { $_.SkuPartNumber -in $e5SkuPartNumbers }).Count -gt 0 $hasOfficeE5 = ($licenseDetails | Where-Object { $_.SkuPartNumber -in $e5SkuPartNumbers }).Count -gt 0
Write-Verbose "Evaluating user $($user.UserPrincipalName) for Office E5 license." Write-Verbose "Evaluating user $($user.UserPrincipalName) for Office E5 license."
if ($hasOfficeE5) { if ($hasOfficeE5) {
$userUPN = $user.UserPrincipalName $userUPN = $user.UserPrincipalName
$mailbox = Get-EXOMailbox -Identity $userUPN -PropertySets Audit $mailbox = Get-EXOMailbox -Identity $userUPN -PropertySets Audit
$missingActions = @() $missingActions = @()
@@ -78,13 +72,19 @@ function Test-MailboxAuditingE5 {
} }
} }
if ($allFailures.Count -eq 0) { # Prepare failure reasons and details based on compliance
Write-Verbose "All evaluated E5 users have correct mailbox audit settings." $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." } else { $allFailures -join " | " }
# Populate the audit result
$params = @{
Rec = "6.1.3"
Result = $allFailures.Count -eq 0
Status = if ($allFailures.Count -eq 0) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
} }
$auditResult.Result = $allFailures.Count -eq 0 $auditResult = Initialize-CISAuditResult @params
$auditResult.Status = if ($auditResult.Result) { "Pass" } else { "Fail" }
$auditResult.Details = if ($auditResult.Result) { "All Office E5 users have correct mailbox audit settings." } else { $allFailures -join " | " }
$auditResult.FailureReason = if (-not $auditResult.Result) { "Audit issues detected." } else { "N/A" }
} }
end { end {

View File

@@ -1,54 +1,52 @@
function Test-ManagedApprovedPublicGroups { function Test-ManagedApprovedPublicGroups {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Define your parameters here # Aligned
# Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResults = @()
} }
process { process {
# 1.2.1 (L2) Ensure that only organizationally managed/approved public groups exist (Automated) # 1.2.1 (L2) Ensure that only organizationally managed/approved public groups exist (Automated)
# Retrieve all public groups
$allGroups = Get-MgGroup -All | Where-Object { $_.Visibility -eq "Public" } | Select-Object DisplayName, Visibility $allGroups = Get-MgGroup -All | Where-Object { $_.Visibility -eq "Public" } | Select-Object DisplayName, Visibility
# Check if there are public groups and if they are organizationally managed/approved # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($null -ne $allGroups -and $allGroups.Count -gt 0) {
$auditResult.CISControlVer = "v8" "There are public groups present that are not organizationally managed/approved."
$auditResult.CISControl = "3.3" }
$auditResult.CISDescription = "Configure Data Access Control Lists" else {
$auditResult.Rec = "1.2.1" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L2"
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true # Based on the provided CIS Control image, IG3 is not applicable
$auditResult.RecDescription = "Ensure that only organizationally managed/approved public groups exist"
if ($null -eq $allGroups -or $allGroups.Count -eq 0) { $details = if ($null -eq $allGroups -or $allGroups.Count -eq 0) {
$auditResult.Result = $true "No public groups found."
$auditResult.Details = "No public groups found."
$auditResult.FailureReason = "N/A"
$auditResult.Status = "Pass"
} }
else { else {
$groupDetails = $allGroups | ForEach-Object { $_.DisplayName + " (" + $_.Visibility + ")" } $groupDetails = $allGroups | ForEach-Object { $_.DisplayName + " (" + $_.Visibility + ")" }
$detailsString = $groupDetails -join ', ' "Public groups found: $($groupDetails -join ', ')"
$auditResult.Result = $false
$auditResult.Details = "Public groups found: $detailsString"
$auditResult.FailureReason = "There are public groups present that are not organizationally managed/approved."
$auditResult.Status = "Fail"
} }
$auditResults += $auditResult # Create and populate the CISAuditResult object
$params = @{
Rec = "1.2.1"
Result = $null -eq $allGroups -or $allGroups.Count -eq 0
Status = if ($null -eq $allGroups -or $allGroups.Count -eq 0) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return auditResults
return $auditResults return $auditResult
} }
} }

View File

@@ -1,46 +1,48 @@
function Test-MeetingChatNoAnonymous { function Test-MeetingChatNoAnonymous {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 8.5.5 (L2) Ensure meeting chat does not allow anonymous users # 8.5.5 (L2) Ensure meeting chat does not allow anonymous users
# Name doesn't match profile level in benchmarks either.
# Connect to Teams PowerShell using Connect-MicrosoftTeams # Connect to Teams PowerShell using Connect-MicrosoftTeams
# Retrieve the Teams meeting policy for meeting chat
$CsTeamsMeetingPolicyChat = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property MeetingChatEnabledType $CsTeamsMeetingPolicyChat = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property MeetingChatEnabledType
$chatAnonDisabled = $CsTeamsMeetingPolicyChat.MeetingChatEnabledType -eq 'EnabledExceptAnonymous' $chatAnonDisabled = $CsTeamsMeetingPolicyChat.MeetingChatEnabledType -eq 'EnabledExceptAnonymous'
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($chatAnonDisabled) {
$auditResult.CISControlVer = "v8" "N/A"
$auditResult.CISControl = "0.0" # Explicitly Not Mapped as per the image provided }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "8.5.5" "Meeting chat allows anonymous users"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Set based on the CIS Controls image
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $false # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure meeting chat does not allow anonymous users"
$auditResult.Result = $chatAnonDisabled
$auditResult.Details = "MeetingChatEnabledType is set to $($CsTeamsMeetingPolicyChat.MeetingChatEnabledType)"
$auditResult.FailureReason = if ($chatAnonDisabled) { "N/A" } else { "Meeting chat allows anonymous users" }
$auditResult.Status = if ($chatAnonDisabled) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = "MeetingChatEnabledType is set to $($CsTeamsMeetingPolicyChat.MeetingChatEnabledType)"
# Create and populate the CISAuditResult object
$params = @{
Rec = "8.5.5"
Result = $chatAnonDisabled
Status = if ($chatAnonDisabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,40 +1,42 @@
function Test-ModernAuthExchangeOnline { function Test-ModernAuthExchangeOnline {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Dot source the class script if necessary
$auditResults = [CISAuditResult]::new() #. .\source\Classes\CISAuditResult.ps1
# Initialization code # Initialization code, if needed
} }
process { process {
try { try {
# Ensuring the ExchangeOnlineManagement module is available # Ensuring the ExchangeOnlineManagement module is available
# 6.5.1 (L1) Ensure modern authentication for Exchange Online is enabled # 6.5.1 (L1) Ensure modern authentication for Exchange Online is enabled
$orgConfig = Get-OrganizationConfig | Select-Object -Property Name, OAuth2ClientProfileEnabled $orgConfig = Get-OrganizationConfig | Select-Object -Property Name, OAuth2ClientProfileEnabled
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$failureReasons = if (-not $orgConfig.OAuth2ClientProfileEnabled) {
"Modern authentication is disabled"
}
else {
"N/A"
}
$auditResults.CISControlVer = "v8" $details = "OAuth2ClientProfileEnabled: $($orgConfig.OAuth2ClientProfileEnabled) for Organization: $($orgConfig.Name)"
$auditResults.CISControl = "3.10"
$auditResults.CISDescription = "Encrypt Sensitive Data in Transit"
$auditResults.IG1 = $false # As per CIS Control v8 mapping for IG1
$auditResults.IG2 = $true # As per CIS Control v8 mapping for IG2
$auditResults.IG3 = $true # As per CIS Control v8 mapping for IG3
$auditResults.ELevel = "E3" # Based on your environment (E3, E5, etc.)
$auditResults.ProfileLevel = "L1"
$auditResults.Rec = "6.5.1"
$auditResults.RecDescription = "Ensure modern authentication for Exchange Online is enabled (Automated)"
$auditResults.Result = $orgConfig.OAuth2ClientProfileEnabled
$auditResults.Details = $auditResults.Details = $orgConfig.Name + " OAuth2ClientProfileEnabled: " + $orgConfig.OAuth2ClientProfileEnabled
$auditResults.FailureReason = if (-not $orgConfig.OAuth2ClientProfileEnabled) { "Modern authentication is disabled" } else { "N/A" }
$auditResults.Status = if ($orgConfig.OAuth2ClientProfileEnabled) { "Pass" } else { "Fail" }
# Create and populate the CISAuditResult object
$params = @{
Rec = "6.5.1"
Result = $orgConfig.OAuth2ClientProfileEnabled
Status = if ($orgConfig.OAuth2ClientProfileEnabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
catch { catch {
@@ -43,12 +45,7 @@ function Test-ModernAuthExchangeOnline {
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,13 +1,14 @@
function Test-ModernAuthSharePoint { function Test-ModernAuthSharePoint {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
@@ -15,25 +16,29 @@ function Test-ModernAuthSharePoint {
$SPOTenant = Get-SPOTenant | Select-Object -Property LegacyAuthProtocolsEnabled $SPOTenant = Get-SPOTenant | Select-Object -Property LegacyAuthProtocolsEnabled
$modernAuthForSPRequired = -not $SPOTenant.LegacyAuthProtocolsEnabled $modernAuthForSPRequired = -not $SPOTenant.LegacyAuthProtocolsEnabled
# Populate the auditResult object with the required properties # Prepare failure reasons and details based on compliance
$auditResult.CISControlVer = "v8" $failureReasons = if (-not $modernAuthForSPRequired) {
$auditResult.CISControl = "3.10" "Legacy authentication protocols are enabled"
$auditResult.CISDescription = "Encrypt Sensitive Data in Transit" }
$auditResult.Rec = "7.2.1" else {
$auditResult.ELevel = "E3" "N/A"
$auditResult.ProfileLevel = "L1" }
$auditResult.IG1 = $false
$auditResult.IG2 = $true $details = "LegacyAuthProtocolsEnabled: $($SPOTenant.LegacyAuthProtocolsEnabled)"
$auditResult.IG3 = $true
$auditResult.RecDescription = "Modern Authentication for SharePoint Applications" # Create and populate the CISAuditResult object
$auditResult.Result = $modernAuthForSPRequired $params = @{
$auditResult.Details = "LegacyAuthProtocolsEnabled: $($SPOTenant.LegacyAuthProtocolsEnabled)" Rec = "7.2.1"
$auditResult.FailureReason = if (-not $modernAuthForSPRequired) { "Legacy authentication protocols are enabled" } else { "N/A" } Result = $modernAuthForSPRequired
$auditResult.Status = if ($modernAuthForSPRequired) { "Pass" } else { "Fail" } Status = if ($modernAuthForSPRequired) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResult # Return the audit result
return $auditResult return $auditResult
} }
} }

View File

@@ -1,13 +1,14 @@
function Test-NoAnonymousMeetingJoin { function Test-NoAnonymousMeetingJoin {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
@@ -18,28 +19,29 @@ function Test-NoAnonymousMeetingJoin {
$teamsMeetingPolicy = Get-CsTeamsMeetingPolicy -Identity Global $teamsMeetingPolicy = Get-CsTeamsMeetingPolicy -Identity Global
$allowAnonymousUsersToJoinMeeting = $teamsMeetingPolicy.AllowAnonymousUsersToJoinMeeting $allowAnonymousUsersToJoinMeeting = $teamsMeetingPolicy.AllowAnonymousUsersToJoinMeeting
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($allowAnonymousUsersToJoinMeeting) {
$auditResult.CISControlVer = "v8" "Anonymous users are allowed to join meetings"
$auditResult.CISControl = "0.0" # The control is Explicitly Not Mapped as per the image provided }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "8.5.1" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L2"
$auditResult.IG1 = $false # Set based on the CIS Controls image
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $false # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure anonymous users can't join a meeting"
$auditResult.Result = -not $allowAnonymousUsersToJoinMeeting
$auditResult.Details = "AllowAnonymousUsersToJoinMeeting is set to $allowAnonymousUsersToJoinMeeting"
$auditResult.FailureReason = if ($allowAnonymousUsersToJoinMeeting) { "Anonymous users are allowed to join meetings" } else { "N/A" }
$auditResult.Status = if (-not $allowAnonymousUsersToJoinMeeting) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = "AllowAnonymousUsersToJoinMeeting is set to $allowAnonymousUsersToJoinMeeting"
# Create and populate the CISAuditResult object
$params = @{
Rec = "8.5.1"
Result = -not $allowAnonymousUsersToJoinMeeting
Status = if (-not $allowAnonymousUsersToJoinMeeting) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,13 +1,14 @@
function Test-NoAnonymousMeetingStart { function Test-NoAnonymousMeetingStart {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
@@ -18,28 +19,29 @@ function Test-NoAnonymousMeetingStart {
$CsTeamsMeetingPolicyAnonymous = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property AllowAnonymousUsersToStartMeeting $CsTeamsMeetingPolicyAnonymous = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property AllowAnonymousUsersToStartMeeting
$anonymousStartDisabled = -not $CsTeamsMeetingPolicyAnonymous.AllowAnonymousUsersToStartMeeting $anonymousStartDisabled = -not $CsTeamsMeetingPolicyAnonymous.AllowAnonymousUsersToStartMeeting
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($anonymousStartDisabled) {
$auditResult.CISControlVer = "v8" "N/A"
$auditResult.CISControl = "0.0" # Explicitly Not Mapped as per the image provided }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "8.5.2" "Anonymous users and dial-in callers can start a meeting"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Set based on the CIS Controls image
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $false # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure anonymous users and dial-in callers can't start a meeting"
$auditResult.Result = $anonymousStartDisabled
$auditResult.Details = "AllowAnonymousUsersToStartMeeting is set to $($CsTeamsMeetingPolicyAnonymous.AllowAnonymousUsersToStartMeeting)"
$auditResult.FailureReason = if ($anonymousStartDisabled) { "N/A" } else { "Anonymous users and dial-in callers can start a meeting" }
$auditResult.Status = if ($anonymousStartDisabled) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = "AllowAnonymousUsersToStartMeeting is set to $($CsTeamsMeetingPolicyAnonymous.AllowAnonymousUsersToStartMeeting)"
# Create and populate the CISAuditResult object
$params = @{
Rec = "8.5.2"
Result = $anonymousStartDisabled
Status = if ($anonymousStartDisabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,43 +1,47 @@
function Test-NoWhitelistDomains { function Test-NoWhitelistDomains {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 6.2.2 (L1) Ensure mail transport rules do not whitelist specific domains # 6.2.2 (L1) Ensure mail transport rules do not whitelist specific domains
$whitelistedRules = Get-TransportRule | Where-Object { $_.SetSCL -eq -1 -and $_.SenderDomainIs -ne $null }
$auditResult.CISControl = "0.0" # Retrieve transport rules that whitelist specific domains
$auditResult.CISControlVer = "v8" $whitelistedRules = Get-TransportRule | Where-Object { $_.SetSCL -eq -1 -and $null -ne $_.SenderDomainIs }
$auditResult.CISDescription = "Explicitly Not Mapped"
$auditResult.Rec = "6.2.2" # Prepare failure reasons and details based on compliance
$auditResult.ELevel = "E3" $failureReasons = if ($whitelistedRules) {
$auditResult.ProfileLevel = "L1" "There are transport rules whitelisting specific domains."
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $false
$auditResult.RecDescription = "Ensure mail transport rules do not whitelist specific domains"
if ($whitelistedRules) {
$ruleDetails = $whitelistedRules | ForEach-Object { "{0}: {1}" -f $_.Name, ($_.SenderDomainIs -join ', ') }
$auditResult.Result = $false
$auditResult.Details = "Whitelisted Rules: $($ruleDetails -join '; ')"
$auditResult.FailureReason = "There are transport rules whitelisting specific domains."
$auditResult.Status = "Fail"
} else {
$auditResult.Result = $true
$auditResult.Details = "No transport rules whitelisting specific domains found."
$auditResult.FailureReason = "N/A"
$auditResult.Status = "Pass"
} }
else {
"N/A"
}
$details = if ($whitelistedRules) {
$ruleDetails = $whitelistedRules | ForEach-Object { "{0}: {1}" -f $_.Name, ($_.SenderDomainIs -join ', ') }
"Whitelisted Rules: $($ruleDetails -join '; ')"
}
else {
"No transport rules whitelisting specific domains found."
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "6.2.2"
Result = -not $whitelistedRules
Status = if ($whitelistedRules) { "Fail" } else { "Pass" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {

View File

@@ -1,12 +1,14 @@
function Test-NotifyMalwareInternal { function Test-NotifyMalwareInternal {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script if necessary
$auditResults = @() #. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
} }
process { process {
@@ -24,31 +26,35 @@ function Test-NotifyMalwareInternal {
# Determine the result based on the presence of custom policies without notifications # Determine the result based on the presence of custom policies without notifications
$result = $policiesToReport.Count -eq 0 $result = $policiesToReport.Count -eq 0
$details = if ($result) { "All custom malware policies have notifications enabled." } else { "Misconfigured Policies: $($policiesToReport -join ', ')" }
$failureReason = if ($result) { "N/A" } else { "Some custom policies do not have notifications for internal users sending malware enabled." }
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($result) {
$auditResult.Status = if ($result) { "Pass" } else { "Fail" } "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1" else {
$auditResult.Rec = "2.1.3" "Some custom policies do not have notifications for internal users sending malware enabled."
$auditResult.RecDescription = "Ensure notifications for internal users sending malware is Enabled" }
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "17.5"
$auditResult.CISDescription = "Assign Key Roles and Responsibilities"
$auditResult.IG1 = $false
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.Result = $result
$auditResult.Details = $details
$auditResult.FailureReason = $failureReason
$auditResults += $auditResult $details = if ($result) {
"All custom malware policies have notifications enabled."
}
else {
"Misconfigured Policies: $($policiesToReport -join ', ')"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "2.1.3"
Result = $result
Status = if ($result) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,37 +1,47 @@
function Test-OneDriveContentRestrictions { function Test-OneDriveContentRestrictions {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 7.2.4 (L2) Ensure OneDrive content sharing is restricted # 7.2.4 (L2) Ensure OneDrive content sharing is restricted
# Retrieve OneDrive sharing capability settings
$SPOTenant = Get-SPOTenant | Select-Object OneDriveSharingCapability $SPOTenant = Get-SPOTenant | Select-Object OneDriveSharingCapability
$isOneDriveSharingRestricted = $SPOTenant.OneDriveSharingCapability -eq 'Disabled' $isOneDriveSharingRestricted = $SPOTenant.OneDriveSharingCapability -eq 'Disabled'
# Populate the auditResult object with the required properties # Prepare failure reasons and details based on compliance
$auditResult.CISControlVer = "v8" $failureReasons = if (-not $isOneDriveSharingRestricted) {
$auditResult.CISControl = "3.3" "OneDrive content sharing is not restricted to 'Disabled'. Current setting: $($SPOTenant.OneDriveSharingCapability)"
$auditResult.CISDescription = "Configure Data Access Control Lists" }
else {
"N/A"
}
$auditResult.Rec = "7.2.4" $details = if ($isOneDriveSharingRestricted) {
$auditResult.ELevel = "E3" "OneDrive content sharing is restricted."
$auditResult.ProfileLevel = "L2" }
$auditResult.IG1 = $true else {
$auditResult.IG2 = $true "OneDriveSharingCapability: $($SPOTenant.OneDriveSharingCapability)"
$auditResult.IG3 = $true }
$auditResult.RecDescription = "Ensure OneDrive content sharing is restricted"
$auditResult.Result = $isOneDriveSharingRestricted # Create and populate the CISAuditResult object
$auditResult.Details = "OneDriveSharingCapability: $($SPOTenant.OneDriveSharingCapability)" $params = @{
$auditResult.FailureReason = if (-not $isOneDriveSharingRestricted) { "OneDrive content sharing is not restricted to 'Disabled'. Current setting: $($SPOTenant.OneDriveSharingCapability)" } else { "N/A" } Rec = "7.2.4"
$auditResult.Status = if ($isOneDriveSharingRestricted) { "Pass" } else { "Fail" } Result = $isOneDriveSharingRestricted
Status = if ($isOneDriveSharingRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {

View File

@@ -1,37 +1,47 @@
function Test-OneDriveSyncRestrictions { function Test-OneDriveSyncRestrictions {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 7.3.2 (L2) Ensure OneDrive sync is restricted for unmanaged devices # 7.3.2 (L2) Ensure OneDrive sync is restricted for unmanaged devices
# Retrieve OneDrive sync client restriction settings
$SPOTenantSyncClientRestriction = Get-SPOTenantSyncClientRestriction | Select-Object TenantRestrictionEnabled, AllowedDomainList $SPOTenantSyncClientRestriction = Get-SPOTenantSyncClientRestriction | Select-Object TenantRestrictionEnabled, AllowedDomainList
$isSyncRestricted = $SPOTenantSyncClientRestriction.TenantRestrictionEnabled -and $SPOTenantSyncClientRestriction.AllowedDomainList $isSyncRestricted = $SPOTenantSyncClientRestriction.TenantRestrictionEnabled -and $SPOTenantSyncClientRestriction.AllowedDomainList
# Populate the auditResult object with the required properties # Prepare failure reasons and details based on compliance
$auditResult.CISControlVer = "v8" $failureReasons = if (-not $isSyncRestricted) {
$auditResult.CISControl = "0.0" "OneDrive sync is not restricted to managed devices. TenantRestrictionEnabled should be True and AllowedDomainList should contain trusted domains GUIDs."
$auditResult.CISDescription = "Explicitly Not Mapped" }
else {
"N/A"
}
$auditResult.Rec = "7.3.2" $details = if ($isSyncRestricted) {
$auditResult.ELevel = "E3" "OneDrive sync is restricted for unmanaged devices."
$auditResult.ProfileLevel = "L2" }
$auditResult.IG1 = $false else {
$auditResult.IG2 = $false "TenantRestrictionEnabled: $($SPOTenantSyncClientRestriction.TenantRestrictionEnabled); AllowedDomainList: $($SPOTenantSyncClientRestriction.AllowedDomainList -join ', ')"
$auditResult.IG3 = $false }
$auditResult.RecDescription = "Ensure OneDrive sync is restricted for unmanaged devices"
$auditResult.Result = $isSyncRestricted # Create and populate the CISAuditResult object
$auditResult.Details = "TenantRestrictionEnabled: $($SPOTenantSyncClientRestriction.TenantRestrictionEnabled); AllowedDomainList: $($SPOTenantSyncClientRestriction.AllowedDomainList -join ', ')" $params = @{
$auditResult.FailureReason = if (-not $isSyncRestricted) { "OneDrive sync is not restricted to managed devices. TenantRestrictionEnabled should be True and AllowedDomainList should contain trusted domains GUIDs." } else { "N/A" } Rec = "7.3.2"
$auditResult.Status = if ($isSyncRestricted) { "Pass" } else { "Fail" } Result = $isSyncRestricted
Status = if ($isSyncRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {

View File

@@ -1,13 +1,14 @@
function Test-OrgOnlyBypassLobby { function Test-OrgOnlyBypassLobby {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
@@ -15,31 +16,38 @@ function Test-OrgOnlyBypassLobby {
# Connect to Teams PowerShell using Connect-MicrosoftTeams # Connect to Teams PowerShell using Connect-MicrosoftTeams
# Retrieve the Teams meeting policy for lobby bypass settings
$CsTeamsMeetingPolicyLobby = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property AutoAdmittedUsers $CsTeamsMeetingPolicyLobby = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property AutoAdmittedUsers
$lobbyBypassRestricted = $CsTeamsMeetingPolicyLobby.AutoAdmittedUsers -eq 'EveryoneInCompanyExcludingGuests' $lobbyBypassRestricted = $CsTeamsMeetingPolicyLobby.AutoAdmittedUsers -eq 'EveryoneInCompanyExcludingGuests'
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $lobbyBypassRestricted) {
$auditResult.CISControlVer = "v8" "External participants can bypass the lobby"
$auditResult.CISControl = "6.8" }
$auditResult.CISDescription = "Define and Maintain Role-Based Access Control" else {
$auditResult.Rec = "8.5.3" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Set based on the CIS Controls image
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $true # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure only people in my org can bypass the lobby"
$auditResult.Result = $lobbyBypassRestricted
$auditResult.Details = "AutoAdmittedUsers is set to $($CsTeamsMeetingPolicyLobby.AutoAdmittedUsers)"
$auditResult.FailureReason = if ($lobbyBypassRestricted) { "N/A" } else { "External participants can bypass the lobby" }
$auditResult.Status = if ($lobbyBypassRestricted) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = if ($lobbyBypassRestricted) {
"Only people in the organization can bypass the lobby."
}
else {
"AutoAdmittedUsers is set to $($CsTeamsMeetingPolicyLobby.AutoAdmittedUsers)"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "8.5.3"
Result = $lobbyBypassRestricted
Status = if ($lobbyBypassRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,13 +1,14 @@
function Test-OrganizersPresent { function Test-OrganizersPresent {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
@@ -15,31 +16,38 @@ function Test-OrganizersPresent {
# Connect to Teams PowerShell using Connect-MicrosoftTeams # Connect to Teams PowerShell using Connect-MicrosoftTeams
# Retrieve the Teams meeting policy for presenters
$CsTeamsMeetingPolicyPresenters = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property DesignatedPresenterRoleMode $CsTeamsMeetingPolicyPresenters = Get-CsTeamsMeetingPolicy -Identity Global | Select-Object -Property DesignatedPresenterRoleMode
$presenterRoleRestricted = $CsTeamsMeetingPolicyPresenters.DesignatedPresenterRoleMode -eq 'OrganizerOnlyUserOverride' $presenterRoleRestricted = $CsTeamsMeetingPolicyPresenters.DesignatedPresenterRoleMode -eq 'OrganizerOnlyUserOverride'
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $presenterRoleRestricted) {
$auditResult.CISControlVer = "v8" "Others besides organizers and co-organizers can present"
$auditResult.CISControl = "0.0" # Explicitly Not Mapped as per the image provided }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "8.5.6" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Set based on the CIS Controls image
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $false # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure only organizers and co-organizers can present"
$auditResult.Result = $presenterRoleRestricted
$auditResult.Details = "DesignatedPresenterRoleMode is set to $($CsTeamsMeetingPolicyPresenters.DesignatedPresenterRoleMode)"
$auditResult.FailureReason = if ($presenterRoleRestricted) { "N/A" } else { "Others besides organizers and co-organizers can present" }
$auditResult.Status = if ($presenterRoleRestricted) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = if ($presenterRoleRestricted) {
"Only organizers and co-organizers can present."
}
else {
"DesignatedPresenterRoleMode is set to $($CsTeamsMeetingPolicyPresenters.DesignatedPresenterRoleMode)"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "8.5.6"
Result = $presenterRoleRestricted
Status = if ($presenterRoleRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,43 +1,47 @@
function Test-PasswordHashSync { function Test-PasswordHashSync {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 5.1.8.1 (L1) Ensure password hash sync is enabled for hybrid deployments # 5.1.8.1 (L1) Ensure password hash sync is enabled for hybrid deployments
# Pass if OnPremisesSyncEnabled is True. Fail otherwise. # Pass if OnPremisesSyncEnabled is True. Fail otherwise.
$passwordHashSync = Get-MgOrganization | Select-Object OnPremisesSyncEnabled
$hashSyncResult = $passwordHashSync.OnPremisesSyncEnabled
# Create an instance of CISAuditResult and populate it # Retrieve password hash sync status
$auditResult = [CISAuditResult]::new() $passwordHashSync = Get-MgOrganization | Select-Object -ExpandProperty OnPremisesSyncEnabled
$auditResult.Status = if ($hashSyncResult) { "Pass" } else { "Fail" } $hashSyncResult = $passwordHashSync
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L1"
$auditResult.Rec = "5.1.8.1"
$auditResult.RecDescription = "Ensure password hash sync is enabled for hybrid deployments"
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "6.7"
$auditResult.CISDescription = "Centralize Access Control"
$auditResult.IG1 = $false
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.Result = $hashSyncResult
$auditResult.Details = "OnPremisesSyncEnabled: $($passwordHashSync.OnPremisesSyncEnabled)"
$auditResult.FailureReason = if (-not $hashSyncResult) { "Password hash sync for hybrid deployments is not enabled" } else { "N/A" }
$auditResults += $auditResult # Prepare failure reasons and details based on compliance
$failureReasons = if (-not $hashSyncResult) {
"Password hash sync for hybrid deployments is not enabled"
}
else {
"N/A"
}
$details = "OnPremisesSyncEnabled: $($passwordHashSync)"
# Create and populate the CISAuditResult object
$params = @{
Rec = "5.1.8.1"
Result = $hashSyncResult
Status = if ($hashSyncResult) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,45 +1,47 @@
function Test-PasswordNeverExpirePolicy { function Test-PasswordNeverExpirePolicy {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
[Parameter(Mandatory)] [Parameter(Mandatory)]
[string]$DomainName # DomainName parameter is now mandatory [string]$DomainName # DomainName parameter is now mandatory
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 1.3.1 (L1) Ensure the 'Password expiration policy' is set to 'Set passwords to never expire' # 1.3.1 (L1) Ensure the 'Password expiration policy' is set to 'Set passwords to never expire'
# Pass if PasswordValidityPeriodInDays is 0. # Pass if PasswordValidityPeriodInDays is 0. Fail otherwise.
# Fail otherwise.
$passwordPolicy = Get-MgDomain -DomainId $DomainName | Select-Object PasswordValidityPeriodInDays # Retrieve password expiration policy
$passwordPolicy = Get-MgDomain -DomainId $DomainName | Select-Object -ExpandProperty PasswordValidityPeriodInDays
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($passwordPolicy -ne 0) {
$auditResult.Rec = "1.3.1" "Password expiration is not set to never expire"
$auditResult.RecDescription = "Ensure the 'Password expiration policy' is set to 'Set passwords to never expire'" }
$auditResult.ELevel = "E3" else {
$auditResult.ProfileLevel = "L1" "N/A"
$auditResult.CISControlVer = "v8" }
$auditResult.CISControl = "5.2"
$auditResult.CISDescription = "Use Unique Passwords"
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true # All are true
$auditResult.Result = $passwordPolicy.PasswordValidityPeriodInDays -eq 0
$auditResult.Details = "Validity Period: $($passwordPolicy.PasswordValidityPeriodInDays) days"
$auditResult.FailureReason = if ($passwordPolicy.PasswordValidityPeriodInDays -eq 0) { "N/A" } else { "Password expiration is not set to never expire" }
$auditResult.Status = if ($passwordPolicy.PasswordValidityPeriodInDays -eq 0) { "Pass" } else { "Fail" }
$auditResults += $auditResult $details = "Validity Period: $passwordPolicy days"
# Create and populate the CISAuditResult object
$params = @{
Rec = "1.3.1"
Result = $passwordPolicy -eq 0
Status = if ($passwordPolicy -eq 0) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,37 +1,42 @@
function Test-ReauthWithCode { function Test-ReauthWithCode {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 7.2.10 (L1) Ensure reauthentication with verification code is restricted # 7.2.10 (L1) Ensure reauthentication with verification code is restricted
# Retrieve reauthentication settings for SharePoint Online
$SPOTenantReauthentication = Get-SPOTenant | Select-Object EmailAttestationRequired, EmailAttestationReAuthDays $SPOTenantReauthentication = Get-SPOTenant | Select-Object EmailAttestationRequired, EmailAttestationReAuthDays
$isReauthenticationRestricted = $SPOTenantReauthentication.EmailAttestationRequired -and $SPOTenantReauthentication.EmailAttestationReAuthDays -le 15 $isReauthenticationRestricted = $SPOTenantReauthentication.EmailAttestationRequired -and $SPOTenantReauthentication.EmailAttestationReAuthDays -le 15
# Populate the auditResult object with the required properties # Prepare failure reasons and details based on compliance
$auditResult.CISControlVer = "v8" $failureReasons = if (-not $isReauthenticationRestricted) {
$auditResult.CISControl = "0.0" "Reauthentication with verification code does not require reauthentication within 15 days or less."
$auditResult.CISDescription = "Explicitly Not Mapped" }
else {
"N/A"
}
$auditResult.Rec = "7.2.10" $details = "EmailAttestationRequired: $($SPOTenantReauthentication.EmailAttestationRequired); EmailAttestationReAuthDays: $($SPOTenantReauthentication.EmailAttestationReAuthDays)"
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $false
$auditResult.RecDescription = "Ensure reauthentication with verification code is restricted"
$auditResult.Result = $isReauthenticationRestricted # Create and populate the CISAuditResult object
$auditResult.Details = "EmailAttestationRequired: $($SPOTenantReauthentication.EmailAttestationRequired); EmailAttestationReAuthDays: $($SPOTenantReauthentication.EmailAttestationReAuthDays)" $params = @{
$auditResult.FailureReason = if (-not $isReauthenticationRestricted) { "Reauthentication with verification code does not require reauthentication within 15 days or less." } else { "N/A" } Rec = "7.2.10"
$auditResult.Status = if ($isReauthenticationRestricted) { "Pass" } else { "Fail" } Result = $isReauthenticationRestricted
Status = if ($isReauthenticationRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {

View File

@@ -1,21 +1,20 @@
function Test-ReportSecurityInTeams { function Test-ReportSecurityInTeams {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 8.6.1 (L1) Ensure users can report security concerns in Teams # 8.6.1 (L1) Ensure users can report security concerns in Teams
# Connect to Teams PowerShell using Connect-MicrosoftTeams # Retrieve the necessary settings for Teams and Exchange Online
# Connect to Exchange Online PowerShell using Connect-ExchangeOnline
$CsTeamsMessagingPolicy = Get-CsTeamsMessagingPolicy -Identity Global | Select-Object -Property AllowSecurityEndUserReporting $CsTeamsMessagingPolicy = Get-CsTeamsMessagingPolicy -Identity Global | Select-Object -Property AllowSecurityEndUserReporting
$ReportSubmissionPolicy = Get-ReportSubmissionPolicy | Select-Object -Property ReportJunkToCustomizedAddress, ReportNotJunkToCustomizedAddress, ReportPhishToCustomizedAddress, ReportChatMessageToCustomizedAddressEnabled $ReportSubmissionPolicy = Get-ReportSubmissionPolicy | Select-Object -Property ReportJunkToCustomizedAddress, ReportNotJunkToCustomizedAddress, ReportPhishToCustomizedAddress, ReportChatMessageToCustomizedAddressEnabled
@@ -25,32 +24,33 @@ function Test-ReportSecurityInTeams {
$ReportSubmissionPolicy.ReportPhishToCustomizedAddress -and $ReportSubmissionPolicy.ReportPhishToCustomizedAddress -and
$ReportSubmissionPolicy.ReportChatMessageToCustomizedAddressEnabled $ReportSubmissionPolicy.ReportChatMessageToCustomizedAddressEnabled
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $securityReportEnabled) {
$auditResult.CISControlVer = "v8" "Users cannot report security concerns in Teams due to one or more incorrect settings"
$auditResult.CISControl = "0.0" # Explicitly Not Mapped as per the image provided }
$auditResult.CISDescription = "Explicitly Not Mapped" else {
$auditResult.Rec = "8.6.1" "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false # Set based on the CIS Controls image $details = "AllowSecurityEndUserReporting: $($CsTeamsMessagingPolicy.AllowSecurityEndUserReporting); " +
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $false # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure users can report security concerns in Teams"
$auditResult.Result = $securityReportEnabled
$auditResult.Details = "AllowSecurityEndUserReporting: $($CsTeamsMessagingPolicy.AllowSecurityEndUserReporting); " +
"ReportJunkToCustomizedAddress: $($ReportSubmissionPolicy.ReportJunkToCustomizedAddress); " + "ReportJunkToCustomizedAddress: $($ReportSubmissionPolicy.ReportJunkToCustomizedAddress); " +
"ReportNotJunkToCustomizedAddress: $($ReportSubmissionPolicy.ReportNotJunkToCustomizedAddress); " + "ReportNotJunkToCustomizedAddress: $($ReportSubmissionPolicy.ReportNotJunkToCustomizedAddress); " +
"ReportPhishToCustomizedAddress: $($ReportSubmissionPolicy.ReportPhishToCustomizedAddress); " + "ReportPhishToCustomizedAddress: $($ReportSubmissionPolicy.ReportPhishToCustomizedAddress); " +
"ReportChatMessageToCustomizedAddressEnabled: $($ReportSubmissionPolicy.ReportChatMessageToCustomizedAddressEnabled)" "ReportChatMessageToCustomizedAddressEnabled: $($ReportSubmissionPolicy.ReportChatMessageToCustomizedAddressEnabled)"
$auditResult.FailureReason = if (-not $securityReportEnabled) { "Users cannot report security concerns in Teams due to one or more incorrect settings" } else { "N/A" }
$auditResult.Status = if ($securityReportEnabled) { "Pass" } else { "Fail" }
$auditResults += $auditResult # Create and populate the CISAuditResult object
$params = @{
Rec = "8.6.1"
Result = $securityReportEnabled
Status = if ($securityReportEnabled) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return auditResult
return $auditResults return $auditResult
} }
} }

View File

@@ -1,21 +1,20 @@
function Test-RestrictCustomScripts { function Test-RestrictCustomScripts {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here if needed # Define your parameters here if needed
) )
#Limit All
begin {
# .TODO Test behavior in Prod
# Dot source the class script
$auditResults = @() begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
} }
process { process {
# CIS 2.7 Ensure custom script execution is restricted on site collections # 7.3.4 (L1) Ensure custom script execution is restricted on site collections
# Pass if DenyAddAndCustomizePages is set to true (Enabled). Fail otherwise.
# Get all site collections and select necessary properties # Retrieve all site collections and select necessary properties
$SPOSitesCustomScript = Get-SPOSite -Limit All | Select-Object Title, Url, DenyAddAndCustomizePages $SPOSitesCustomScript = Get-SPOSite -Limit All | Select-Object Title, Url, DenyAddAndCustomizePages
# Find sites where custom scripts are allowed (DenyAddAndCustomizePages is not 'Enabled') # Find sites where custom scripts are allowed (DenyAddAndCustomizePages is not 'Enabled')
@@ -29,42 +28,34 @@ function Test-RestrictCustomScripts {
"$($_.Title) ($($_.Url)): Custom Script Allowed" "$($_.Title) ($($_.Url)): Custom Script Allowed"
} }
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if (-not $complianceResult) {
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "2.7"
$auditResult.CISDescription = "Allowlist Authorized Scripts"
$auditResult.Rec = "7.3.4"
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $true
$auditResult.RecDescription = "Ensure custom script execution is restricted on site collections"
$auditResult.Result = $complianceResult
$auditResult.Details = if (-not $complianceResult) {
$nonCompliantSiteDetails -join "; "
} else {
"All site collections have custom script execution restricted"
}
$auditResult.FailureReason = if (-not $complianceResult) {
"The following site collections allow custom script execution: " + ($nonCompliantSiteDetails -join "; ") "The following site collections allow custom script execution: " + ($nonCompliantSiteDetails -join "; ")
} else { }
else {
"N/A" "N/A"
} }
$auditResult.Status = if ($complianceResult) {
"Pass" $details = if ($complianceResult) {
} else { "All site collections have custom script execution restricted"
"Fail" }
else {
$nonCompliantSiteDetails -join "; "
} }
$auditResults += $auditResult # Create and populate the CISAuditResult object
$params = @{
Rec = "7.3.4"
Result = $complianceResult
Status = if ($complianceResult) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return auditResult
return $auditResults return $auditResult
} }
} }

View File

@@ -1,37 +1,42 @@
function Test-RestrictExternalSharing { function Test-RestrictExternalSharing {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 7.2.3 (L1) Ensure external content sharing is restricted # 7.2.3 (L1) Ensure external content sharing is restricted
# Retrieve the SharingCapability setting for the SharePoint tenant
$SPOTenantSharingCapability = Get-SPOTenant | Select-Object SharingCapability $SPOTenantSharingCapability = Get-SPOTenant | Select-Object SharingCapability
$isRestricted = $SPOTenantSharingCapability.SharingCapability -in @('ExternalUserSharingOnly', 'ExistingExternalUserSharingOnly', 'Disabled') $isRestricted = $SPOTenantSharingCapability.SharingCapability -in @('ExternalUserSharingOnly', 'ExistingExternalUserSharingOnly', 'Disabled')
# Populate the auditResult object with the required properties # Prepare failure reasons and details based on compliance
$auditResult.CISControlVer = "v8" $failureReasons = if (-not $isRestricted) {
$auditResult.CISControl = "3.3" "External content sharing is not adequately restricted. Current setting: $($SPOTenantSharingCapability.SharingCapability)"
$auditResult.CISDescription = "Configure Data Access Control Lists" }
else {
"N/A"
}
$auditResult.Rec = "7.2.3" $details = "SharingCapability: $($SPOTenantSharingCapability.SharingCapability)"
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L1"
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.RecDescription = "Ensure external content sharing is restricted"
$auditResult.Result = $isRestricted # Create and populate the CISAuditResult object
$auditResult.Details = "SharingCapability: $($SPOTenantSharingCapability.SharingCapability)" $params = @{
$auditResult.FailureReason = if (-not $isRestricted) { "External content sharing is not adequately restricted. Current setting: $($SPOTenantSharingCapability.SharingCapability)" } else { "N/A" } Rec = "7.2.3"
$auditResult.Status = if ($isRestricted) { "Pass" } else { "Fail" } Result = $isRestricted
Status = if ($isRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {

View File

@@ -1,20 +1,20 @@
function Test-RestrictOutlookAddins { function Test-RestrictOutlookAddins {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters could include credentials or other necessary data # Parameters could include credentials or other necessary data
) )
begin { begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code # Initialization code
$auditResult = [CISAuditResult]::new()
$customPolicyFailures = @() $customPolicyFailures = @()
$defaultPolicyFailureDetails = @() $defaultPolicyFailureDetails = @()
$relevantRoles = @('My Custom Apps', 'My Marketplace Apps', 'My ReadWriteMailbox Apps') $relevantRoles = @('My Custom Apps', 'My Marketplace Apps', 'My ReadWriteMailbox Apps')
} }
process { process {
# Main functionality
# 6.3.1 (L2) Ensure users installing Outlook add-ins is not allowed # 6.3.1 (L2) Ensure users installing Outlook add-ins is not allowed
# Check all mailboxes for custom policies with unallowed add-ins # Check all mailboxes for custom policies with unallowed add-ins
@@ -38,24 +38,11 @@ function Test-RestrictOutlookAddins {
if ($defaultPolicyRoles) { if ($defaultPolicyRoles) {
$defaultPolicyFailureDetails = $defaultPolicyRoles $defaultPolicyFailureDetails = $defaultPolicyRoles
} }
}
end {
# Prepare result object
$auditResult.Rec = "6.3.1"
$auditResult.CISControl = "9.4"
$auditResult.CISDescription = "Restrict Unnecessary or Unauthorized Browser and Email Client Extensions"
$auditResult.ELevel = "E3"
$auditResult.ProfileLevel = "L2"
$auditResult.IG1 = $false
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.RecDescription = "Ensure users installing Outlook add-ins is not allowed"
# Prepare result details string
$detailsString = "" $detailsString = ""
if ($customPolicyFailures) { if ($customPolicyFailures) {
$detailsString += "Custom Policy Failures: | " $detailsString += "Custom Policy Failures: | "
# Use pipes or tabs here instead of newlines
$detailsString += ($customPolicyFailures -join " | ") $detailsString += ($customPolicyFailures -join " | ")
} }
else { else {
@@ -70,20 +57,22 @@ function Test-RestrictOutlookAddins {
$detailsString += "Compliant" $detailsString += "Compliant"
} }
if ($customPolicyFailures -or $defaultPolicyFailureDetails) { # Determine result based on findings
$auditResult.Result = $false $isCompliant = -not ($customPolicyFailures -or $defaultPolicyFailureDetails)
$auditResult.Status = "Fail"
$auditResult.Details = $detailsString # Create and populate the CISAuditResult object
$auditResult.FailureReason = "Unauthorized Outlook add-ins found in custom or default policies." $params = @{
Rec = "6.3.1"
Result = $isCompliant
Status = if ($isCompliant) { "Pass" } else { "Fail" }
Details = $detailsString
FailureReason = if ($isCompliant) { "N/A" } else { "Unauthorized Outlook add-ins found in custom or default policies." }
} }
else { $auditResult = Initialize-CISAuditResult @params
$auditResult.Result = $true
$auditResult.Status = "Pass"
$auditResult.Details = "No unauthorized Outlook add-ins found in custom or default policies."
$auditResult.FailureReason = "N/A"
} }
# Return auditResult end {
# Return the audit result
return $auditResult return $auditResult
} }
} }

View File

@@ -1,48 +1,56 @@
function Test-RestrictStorageProvidersOutlook { function Test-RestrictStorageProvidersOutlook {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added here if needed # Parameters can be added here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResult = [CISAuditResult]::new() # Initialization code, if needed
} }
process { process {
# 6.5.3 (L2) Ensure additional storage providers are restricted in Outlook on the web # 6.5.3 (L2) Ensure additional storage providers are restricted in Outlook on the web
$owaPolicies = Get-OwaMailboxPolicy
$allPoliciesRestricted = $owaPolicies | ForEach-Object { $_.AdditionalStorageProvidersAvailable } | ForEach-Object { -not $_ }
# Create an instance of CISAuditResult and populate it # Retrieve all OwaMailbox policies
$auditResult.CISControlVer = "v8" $owaPolicies = Get-OwaMailboxPolicy
$auditResult.CISControl = "3.3" $nonCompliantPolicies = $owaPolicies | Where-Object { $_.AdditionalStorageProvidersAvailable }
$auditResult.CISDescription = "Configure Data Access Control Lists"
$auditResult.Rec = "6.5.3" # Determine compliance
$auditResult.ELevel = "E3" # Based on your environment $allPoliciesRestricted = $nonCompliantPolicies.Count -eq 0
$auditResult.ProfileLevel = "L2"
$auditResult.IG1 = $true # Prepare failure reasons and details based on compliance
$auditResult.IG2 = $true $failureReasons = if ($allPoliciesRestricted) {
$auditResult.IG3 = $true "N/A"
$auditResult.RecDescription = "Ensure additional storage providers are restricted in Outlook on the web"
$auditResult.Result = $allPoliciesRestricted
$auditResult.Details = if($allPoliciesRestricted) {
"All OwaMailbox policies restrict AdditionalStorageProvidersAvailable"
} else {
$nonCompliantPolicies = $owaPolicies | Where-Object { $_.AdditionalStorageProvidersAvailable } | Select-Object -ExpandProperty Name
"Non-compliant OwaMailbox policies: $($nonCompliantPolicies -join ', ')"
} }
$auditResult.FailureReason = if(-not $allPoliciesRestricted) { "One or more OwaMailbox policies allow AdditionalStorageProvidersAvailable." } else { "N/A" } else {
$auditResult.Status = if($allPoliciesRestricted) { "Pass" } else { "Fail" } "One or more OwaMailbox policies allow AdditionalStorageProvidersAvailable."
}
$details = if ($allPoliciesRestricted) {
"All OwaMailbox policies restrict AdditionalStorageProvidersAvailable"
}
else {
"Non-compliant OwaMailbox policies: $($nonCompliantPolicies.Name -join ', ')"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = "6.5.3"
Result = $allPoliciesRestricted
Status = if ($allPoliciesRestricted) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResult # Return the audit result
return $auditResult return $auditResult
} }
} }
# Additional helper functions (if any) # Additional helper functions (if any)

View File

@@ -1,43 +1,48 @@
function Test-RestrictTenantCreation { function Test-RestrictTenantCreation {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 5.1.2.3 (L1) Ensure 'Restrict non-admin users from creating tenants' is set to 'Yes' # 5.1.2.3 (L1) Ensure 'Restrict non-admin users from creating tenants' is set to 'Yes'
# Pass if AllowedToCreateTenants is False. Fail otherwise.
# Retrieve the tenant creation policy
$tenantCreationPolicy = (Get-MgPolicyAuthorizationPolicy).DefaultUserRolePermissions | Select-Object AllowedToCreateTenants $tenantCreationPolicy = (Get-MgPolicyAuthorizationPolicy).DefaultUserRolePermissions | Select-Object AllowedToCreateTenants
$tenantCreationResult = -not $tenantCreationPolicy.AllowedToCreateTenants $tenantCreationResult = -not $tenantCreationPolicy.AllowedToCreateTenants
# Create an instance of CISAuditResult and populate it # Prepare failure reasons and details based on compliance
$auditResult = [CISAuditResult]::new() $failureReasons = if ($tenantCreationResult) {
$auditResult.Status = if ($tenantCreationResult) { "Pass" } else { "Fail" } "N/A"
$auditResult.ELevel = "E3" }
$auditResult.ProfileLevel = "L1" else {
$auditResult.Rec = "5.1.2.3" "Non-admin users can create tenants"
$auditResult.RecDescription = "Ensure 'Restrict non-admin users from creating tenants' is set to 'Yes'" }
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "0.0"
$auditResult.CISDescription = "Explicitly Not Mapped"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $false
$auditResult.Result = $tenantCreationResult
$auditResult.Details = "AllowedToCreateTenants: $($tenantCreationPolicy.AllowedToCreateTenants)"
$auditResult.FailureReason = if (-not $tenantCreationResult) { "Non-admin users can create tenants" } else { "N/A" }
$auditResults += $auditResult $details = "AllowedToCreateTenants: $($tenantCreationPolicy.AllowedToCreateTenants)"
# Create and populate the CISAuditResult object
$params = @{
Rec = "5.1.2.3"
Result = $tenantCreationResult
Status = if ($tenantCreationResult) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }
# Additional helper functions (if any)

View File

@@ -1,49 +1,53 @@
function Test-SafeAttachmentsPolicy { function Test-SafeAttachmentsPolicy {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script if necessary
$auditResults = @() #. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
} }
process { process {
# 2.1.4 (L2) Ensure Safe Attachments policy is enabled
# Retrieve all Safe Attachment policies where Enable is set to True # Retrieve all Safe Attachment policies where Enable is set to True
$safeAttachmentPolicies = Get-SafeAttachmentPolicy | Where-Object { $_.Enable -eq $true } $safeAttachmentPolicies = Get-SafeAttachmentPolicy | Where-Object { $_.Enable -eq $true }
# If there are any enabled policies, the result is Pass. If not, it's Fail. # Determine result and details based on the presence of enabled policies
$result = $safeAttachmentPolicies -ne $null -and $safeAttachmentPolicies.Count -gt 0 $result = $null -ne $safeAttachmentPolicies -and $safeAttachmentPolicies.Count -gt 0
$details = if ($result) { $details = if ($result) {
"Enabled Safe Attachments Policies: $($safeAttachmentPolicies.Name -join ', ')" "Enabled Safe Attachments Policies: $($safeAttachmentPolicies.Name -join ', ')"
} else { }
else {
"No Safe Attachments Policies are enabled." "No Safe Attachments Policies are enabled."
} }
$failureReason = if ($result) { "N/A" } else { "Safe Attachments policy is not enabled." }
# Create an instance of CISAuditResult and populate it $failureReasons = if ($result) {
$auditResult = [CISAuditResult]::new() "N/A"
$auditResult.Status = if ($result) { "Pass" } else { "Fail" } }
$auditResult.ELevel = "E5" else {
$auditResult.ProfileLevel = "L2" "Safe Attachments policy is not enabled."
$auditResult.Rec = "2.1.4" }
$auditResult.RecDescription = "Ensure Safe Attachments policy is enabled"
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "9.7"
$auditResult.CISDescription = "Deploy and Maintain Email Server Anti-Malware Protections"
$auditResult.IG1 = $false
$auditResult.IG2 = $false
$auditResult.IG3 = $true
$auditResult.Result = $result
$auditResult.Details = $details
$auditResult.FailureReason = $failureReason
$auditResults += $auditResult # Create and populate the CISAuditResult object
$params = @{
Rec = "2.1.4"
Result = $result
Status = if ($result) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }
# Additional helper functions (if any)

View File

@@ -1,16 +1,19 @@
function Test-SafeAttachmentsTeams { function Test-SafeAttachmentsTeams {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script if necessary
$auditResults = @() #. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
} }
process { process {
# Requires E5 license # 2.1.5 (L2) Ensure Safe Attachments for SharePoint, OneDrive, and Microsoft Teams is Enabled
# Retrieve the ATP policies for Office 365 and check Safe Attachments settings # Retrieve the ATP policies for Office 365 and check Safe Attachments settings
$atpPolicies = Get-AtpPolicyForO365 $atpPolicies = Get-AtpPolicyForO365
@@ -25,33 +28,33 @@ function Test-SafeAttachmentsTeams {
$result = $null -ne $atpPolicyResult $result = $null -ne $atpPolicyResult
$details = if ($result) { $details = if ($result) {
"ATP for SharePoint, OneDrive, and Teams is enabled with correct settings." "ATP for SharePoint, OneDrive, and Teams is enabled with correct settings."
} else { }
else {
"ATP for SharePoint, OneDrive, and Teams is not enabled with correct settings." "ATP for SharePoint, OneDrive, and Teams is not enabled with correct settings."
} }
$failureReason = if ($result) { "N/A" } else { "ATP policy for SharePoint, OneDrive, and Microsoft Teams is not correctly configured." }
# Create an instance of CISAuditResult and populate it $failureReasons = if ($result) {
$auditResult = [CISAuditResult]::new() "N/A"
$auditResult.Status = if ($result) { "Pass" } else { "Fail" } }
$auditResult.ELevel = "E5" else {
$auditResult.ProfileLevel = "L2" "ATP policy for SharePoint, OneDrive, and Microsoft Teams is not correctly configured."
$auditResult.Rec = "2.1.5" }
$auditResult.RecDescription = "Ensure Safe Attachments for SharePoint, OneDrive, and Microsoft Teams is Enabled"
$auditResult.CISControlVer = "v8"
$auditResult.CISControl = "9.7, 10.1"
$auditResult.CISDescription = "Deploy and Maintain Email Server Anti-Malware Protections, Deploy and Maintain Anti-Malware Software"
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.Result = $result
$auditResult.Details = $details
$auditResult.FailureReason = $failureReason
$auditResults += $auditResult # Create and populate the CISAuditResult object
$params = @{
Rec = "2.1.5"
Result = $result
Status = if ($result) { "Pass" } else { "Fail" }
Details = $details
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }
# Additional helper functions (if any)

View File

@@ -1,16 +1,19 @@
function Test-SafeLinksOfficeApps { function Test-SafeLinksOfficeApps {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here if needed # Define your parameters here if needed
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
$auditResults = @() # Initialization code, if needed
} }
process { process {
# 2.1.1 (L2) Ensure Safe Links for Office Applications is Enabled
# Retrieve all Safe Links policies # Retrieve all Safe Links policies
$policies = Get-SafeLinksPolicy $policies = Get-SafeLinksPolicy
@@ -42,29 +45,21 @@ function Test-SafeLinksOfficeApps {
# Prepare the final result # Prepare the final result
$result = $misconfiguredDetails.Count -eq 0 $result = $misconfiguredDetails.Count -eq 0
$details = if ($result) { "All Safe Links policies are correctly configured." } else { $misconfiguredDetails -join ' | ' } $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 ' | ')" }
# Create the audit result object # Create and populate the CISAuditResult object
$auditResult = [CISAuditResult]::new() $params = @{
$auditResult.Status = if ($result) { "Pass" } else { "Fail" } Rec = "2.1.1"
$auditResult.ELevel = "E5" Result = $result
$auditResult.ProfileLevel = "L2" Status = if ($result) { "Pass" } else { "Fail" }
$auditResult.Rec = "2.1.1" Details = $details
$auditResult.RecDescription = "Ensure Safe Links for Office Applications is Enabled" FailureReason = $failureReasons
$auditResult.CISControlVer = "v8" }
$auditResult.CISControl = "10.1" $auditResult = Initialize-CISAuditResult @params
$auditResult.CISDescription = "Deploy and Maintain Anti-Malware Software"
$auditResult.IG1 = $true
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.Result = $result
$auditResult.Details = $details
$auditResult.FailureReason = if ($result) { "N/A" } else { "The following Safe Links policies settings do not meet the recommended configuration: $($misconfiguredDetails -join ' | ')" }
$auditResults += $auditResult
} }
end { end {
# Return auditResults # Return the audit result
return $auditResults return $auditResult
} }
} }

View File

@@ -1,11 +1,14 @@
function Test-SharePointAADB2B { function Test-SharePointAADB2B {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResult = [CISAuditResult]::new() $auditResult = [CISAuditResult]::new()
} }
@@ -15,22 +18,14 @@ function Test-SharePointAADB2B {
$SPOTenantAzureADB2B = Get-SPOTenant | Select-Object EnableAzureADB2BIntegration $SPOTenantAzureADB2B = Get-SPOTenant | Select-Object EnableAzureADB2BIntegration
# Populate the auditResult object with the required properties # Populate the auditResult object with the required properties
$auditResult.CISControlVer = "v8" $params = @{
$auditResult.CISControl = "0.0" Rec = "7.2.2"
$auditResult.CISDescription = "Explicitly Not Mapped" Result = $SPOTenantAzureADB2B.EnableAzureADB2BIntegration
Status = if ($SPOTenantAzureADB2B.EnableAzureADB2BIntegration) { "Pass" } else { "Fail" }
$auditResult.Rec = "7.2.2" Details = "EnableAzureADB2BIntegration: $($SPOTenantAzureADB2B.EnableAzureADB2BIntegration)"
$auditResult.ELevel = "E3" FailureReason = if (-not $SPOTenantAzureADB2B.EnableAzureADB2BIntegration) { "Azure AD B2B integration is not enabled" } else { "N/A" }
$auditResult.ProfileLevel = "L1" }
$auditResult.IG1 = $false $auditResult = Initialize-CISAuditResult @params
$auditResult.IG2 = $false
$auditResult.IG3 = $false
$auditResult.RecDescription = "Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled"
$auditResult.Result = $SPOTenantAzureADB2B.EnableAzureADB2BIntegration
$auditResult.Details = "EnableAzureADB2BIntegration: $($SPOTenantAzureADB2B.EnableAzureADB2BIntegration)"
$auditResult.FailureReason = if (-not $SPOTenantAzureADB2B.EnableAzureADB2BIntegration) { "Azure AD B2B integration is not enabled" } else { "N/A" }
$auditResult.Status = if ($SPOTenantAzureADB2B.EnableAzureADB2BIntegration) { "Pass" } else { "Fail" }
} }
end { end {

View File

@@ -1,11 +1,14 @@
function Test-SharePointExternalSharingDomains { function Test-SharePointExternalSharingDomains {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResult = [CISAuditResult]::new() $auditResult = [CISAuditResult]::new()
} }
@@ -16,22 +19,14 @@ function Test-SharePointExternalSharingDomains {
$isDomainRestrictionConfigured = $SPOTenant.SharingDomainRestrictionMode -eq 'AllowList' $isDomainRestrictionConfigured = $SPOTenant.SharingDomainRestrictionMode -eq 'AllowList'
# Populate the auditResult object with the required properties # Populate the auditResult object with the required properties
$auditResult.CISControlVer = "v8" $params = @{
$auditResult.CISControl = "3.3" Rec = "7.2.6"
$auditResult.CISDescription = "Configure Data Access Control Lists" Result = $isDomainRestrictionConfigured
Status = if ($isDomainRestrictionConfigured) { "Pass" } else { "Fail" }
$auditResult.Rec = "7.2.6" Details = "SharingDomainRestrictionMode: $($SPOTenant.SharingDomainRestrictionMode); SharingAllowedDomainList: $($SPOTenant.SharingAllowedDomainList)"
$auditResult.ELevel = "E3" FailureReason = if (-not $isDomainRestrictionConfigured) { "Domain restrictions for SharePoint external sharing are not configured to 'AllowList'. Current setting: $($SPOTenant.SharingDomainRestrictionMode)" } else { "N/A" }
$auditResult.ProfileLevel = "L2" }
$auditResult.IG1 = $true $auditResult = Initialize-CISAuditResult @params
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.RecDescription = "Ensure SharePoint external sharing is managed through domain whitelist/blacklists"
$auditResult.Result = $isDomainRestrictionConfigured
$auditResult.Details = "SharingDomainRestrictionMode: $($SPOTenant.SharingDomainRestrictionMode); SharingAllowedDomainList: $($SPOTenant.SharingAllowedDomainList)"
$auditResult.FailureReason = if (-not $isDomainRestrictionConfigured) { "Domain restrictions for SharePoint external sharing are not configured to 'AllowList'. Current setting: $($SPOTenant.SharingDomainRestrictionMode)" } else { "N/A" }
$auditResult.Status = if ($isDomainRestrictionConfigured) { "Pass" } else { "Fail" }
} }
end { end {

View File

@@ -1,11 +1,14 @@
function Test-SharePointGuestsItemSharing { function Test-SharePointGuestsItemSharing {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Define your parameters here # Define your parameters here
) )
begin { begin {
# Initialization code # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResult = [CISAuditResult]::new() $auditResult = [CISAuditResult]::new()
} }
@@ -16,22 +19,14 @@ function Test-SharePointGuestsItemSharing {
$isGuestResharingPrevented = $SPOTenant.PreventExternalUsersFromResharing $isGuestResharingPrevented = $SPOTenant.PreventExternalUsersFromResharing
# Populate the auditResult object with the required properties # Populate the auditResult object with the required properties
$auditResult.CISControlVer = "v8" $params = @{
$auditResult.CISControl = "3.3" Rec = "7.2.5"
$auditResult.CISDescription = "Configure Data Access Control Lists" Result = $isGuestResharingPrevented
Status = if ($isGuestResharingPrevented) { "Pass" } else { "Fail" }
$auditResult.Rec = "7.2.5" Details = "PreventExternalUsersFromResharing: $isGuestResharingPrevented"
$auditResult.ELevel = "E3" FailureReason = if (-not $isGuestResharingPrevented) { "Guest users can reshare items they don't own." } else { "N/A" }
$auditResult.ProfileLevel = "L2" }
$auditResult.IG1 = $true $auditResult = Initialize-CISAuditResult @params
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.RecDescription = "Ensure that SharePoint guest users cannot share items they don't own"
$auditResult.Result = $isGuestResharingPrevented
$auditResult.Details = "PreventExternalUsersFromResharing: $isGuestResharingPrevented"
$auditResult.FailureReason = if (-not $isGuestResharingPrevented) { "Guest users can reshare items they don't own." } else { "N/A" }
$auditResult.Status = if ($isGuestResharingPrevented) { "Pass" } else { "Fail" }
} }
end { end {

View File

@@ -1,12 +1,16 @@
function Test-SpamPolicyAdminNotify { function Test-SpamPolicyAdminNotify {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added if needed # Parameters can be added if needed
) )
begin { begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResults = @() $auditResult = [CISAuditResult]::new()
} }
process { process {
@@ -30,29 +34,18 @@ function Test-SpamPolicyAdminNotify {
} }
# Create an instance of CISAuditResult and populate it # Create an instance of CISAuditResult and populate it
$auditResult = [CISAuditResult]::new() $params = @{
$auditResult.Status = if ($areSettingsEnabled) { "Pass" } else { "Fail" } Rec = "2.1.6"
$auditResult.ELevel = "E3" Result = $areSettingsEnabled
$auditResult.ProfileLevel = "L1" Status = if ($areSettingsEnabled) { "Pass" } else { "Fail" }
$auditResult.Rec = "2.1.6" Details = if ($areSettingsEnabled) { "Both BccSuspiciousOutboundMail and NotifyOutboundSpam are enabled." } else { $failureDetails -join ' ' }
$auditResult.RecDescription = "Ensure Exchange Online Spam Policies are set to notify administrators" FailureReason = if (-not $areSettingsEnabled) { "One or both spam policies are not set to notify administrators." } else { "N/A" }
$auditResult.CISControlVer = "v8" }
$auditResult.CISControl = "17.5" $auditResult = Initialize-CISAuditResult @params
$auditResult.CISDescription = "Assign Key Roles and Responsibilities"
$auditResult.IG1 = $false
$auditResult.IG2 = $true
$auditResult.IG3 = $true
$auditResult.Result = $areSettingsEnabled
$auditResult.Details = if ($areSettingsEnabled) { "Both BccSuspiciousOutboundMail and NotifyOutboundSpam are enabled." } else { $failureDetails -join ' ' }
$auditResult.FailureReason = if (-not $areSettingsEnabled) { "One or both spam policies are not set to notify administrators." } else { "N/A" }
$auditResults += $auditResult
} }
end { end {
# Return auditResults # Return auditResult
return $auditResults return $auditResult
} }
} }

View File

@@ -1,13 +1,16 @@
function Test-TeamsExternalAccess { function Test-TeamsExternalAccess {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be defined here if needed # Parameters can be defined here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResults = @() $auditResult = [CISAuditResult]::new()
} }
process { process {
@@ -26,27 +29,18 @@ function Test-TeamsExternalAccess {
$isCompliant = -not $externalAccessConfig.AllowTeamsConsumer -and -not $externalAccessConfig.AllowPublicUsers -and (-not $externalAccessConfig.AllowFederatedUsers -or $allowedDomainsLimited) $isCompliant = -not $externalAccessConfig.AllowTeamsConsumer -and -not $externalAccessConfig.AllowPublicUsers -and (-not $externalAccessConfig.AllowFederatedUsers -or $allowedDomainsLimited)
# Create an instance of CISAuditResult and populate it # Create an instance of CISAuditResult and populate it
$auditResult = [CISAuditResult]::new() $params = @{
$auditResult.CISControlVer = "v8" Rec = "8.2.1"
$auditResult.CISControl = "0.0" # The control is Explicitly Not Mapped as per the image provided Result = $isCompliant
$auditResult.CISDescription = "Explicitly Not Mapped" Status = if ($isCompliant) { "Pass" } else { "Fail" }
$auditResult.Rec = "8.2.1" Details = "AllowTeamsConsumer: $($externalAccessConfig.AllowTeamsConsumer); AllowPublicUsers: $($externalAccessConfig.AllowPublicUsers); AllowFederatedUsers: $($externalAccessConfig.AllowFederatedUsers); AllowedDomains limited: $allowedDomainsLimited"
$auditResult.ELevel = "E3" FailureReason = if (-not $isCompliant) { "One or more external access configurations are not compliant." } else { "N/A" }
$auditResult.ProfileLevel = "L2" }
$auditResult.IG1 = $false # Set based on the CIS Controls image $auditResult = Initialize-CISAuditResult @params
$auditResult.IG2 = $false # Set based on the CIS Controls image
$auditResult.IG3 = $false # Set based on the CIS Controls image
$auditResult.RecDescription = "Ensure 'external access' is restricted in the Teams admin center"
$auditResult.Result = $isCompliant
$auditResult.Details = "AllowTeamsConsumer: $($externalAccessConfig.AllowTeamsConsumer); AllowPublicUsers: $($externalAccessConfig.AllowPublicUsers); AllowFederatedUsers: $($externalAccessConfig.AllowFederatedUsers); AllowedDomains limited: $allowedDomainsLimited"
$auditResult.FailureReason = if (-not $isCompliant) { "One or more external access configurations are not compliant." } else { "N/A" }
$auditResult.Status = if ($isCompliant) { "Pass" } else { "Fail" }
$auditResults += $auditResult
} }
end { end {
# Return auditResults # Return auditResult
return $auditResults return $auditResult
} }
} }

View File

@@ -1,13 +1,16 @@
function Test-TeamsExternalFileSharing { function Test-TeamsExternalFileSharing {
[CmdletBinding()] [CmdletBinding()]
param ( param (
# Aligned
# Parameters can be added here if needed # Parameters can be added here if needed
) )
begin { begin {
# Dot source the class script # Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$auditResults = @() $auditResult = [CISAuditResult]::new()
} }
process { process {
@@ -30,27 +33,18 @@ function Test-TeamsExternalFileSharing {
} }
# Create an instance of CISAuditResult and populate it # Create an instance of CISAuditResult and populate it
$auditResult = [CISAuditResult]::new() $params = @{
$auditResult.CISControlVer = "v8" Rec = "8.1.1"
$auditResult.CISControl = "3.3" Result = $isCompliant
$auditResult.CISDescription = "Configure Data Access Control Lists" Status = if ($isCompliant) { "Pass" } else { "Fail" }
$auditResult.Rec = "8.1.1" Details = if (-not $isCompliant) { "Non-approved providers enabled: $($nonCompliantProviders -join ', ')" } else { "All cloud storage services are approved providers" }
$auditResult.ELevel = "E3" FailureReason = if (-not $isCompliant) { "The following non-approved providers are enabled: $($nonCompliantProviders -join ', ')" } else { "N/A" }
$auditResult.ProfileLevel = "L2" }
$auditResult.IG1 = $true # Set based on the benchmark $auditResult = Initialize-CISAuditResult @params
$auditResult.IG2 = $true # Set based on the benchmark
$auditResult.IG3 = $true # Set based on the benchmark
$auditResult.RecDescription = "Ensure external file sharing in Teams is enabled for only approved cloud storage services"
$auditResult.Result = $isCompliant
$auditResult.Details = if (-not $isCompliant) { "Non-approved providers enabled: $($nonCompliantProviders -join ', ')" } else { "All cloud storage services are approved providers" }
$auditResult.FailureReason = if (-not $isCompliant) { "The following non-approved providers are enabled: $($nonCompliantProviders -join ', ')" } else { "N/A" }
$auditResult.Status = if ($isCompliant) { "Pass" } else { "Fail" }
$auditResults += $auditResult
} }
end { end {
# Return auditResults # Return auditResult
return $auditResults return $auditResult
} }
} }

View File

@@ -0,0 +1,27 @@
$ProjectPath = "$PSScriptRoot\..\..\.." | Convert-Path
$ProjectName = ((Get-ChildItem -Path $ProjectPath\*\*.psd1).Where{
($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and
$(try { Test-ModuleManifest $_.FullName -ErrorAction Stop } catch { $false } )
}).BaseName
Import-Module $ProjectName
InModuleScope $ProjectName {
Describe Get-PrivateFunction {
Context 'Default' {
BeforeEach {
$return = Get-PrivateFunction -PrivateData 'string'
}
It 'Returns a single object' {
($return | Measure-Object).Count | Should -Be 1
}
It 'Returns a string based on the parameter PrivateData' {
$return | Should -Be 'string'
}
}
}
}