11 Commits

Author SHA1 Message Date
Doug Rios
904e36c376 Merge pull request #140 from CriticalSolutionsNetwork/131-formatting-spo
131 formatting spo
2024-07-02 10:04:19 -05:00
DrIOS
d68ae22982 docs: Update CHANGELOG 2024-07-02 10:02:55 -05:00
DrIOS
50c94485e7 fix: Manual rebase export 2024-07-02 10:00:26 -05:00
DrIOS
a80e26f089 fix: Manual rebase export 2024-07-02 09:54:30 -05:00
DrIOS
5d11b46d96 fix: SPO formatting and output 2024-07-02 09:47:06 -05:00
DrIOS
5ef32eb4b8 fix: up to 7.2.6 SPO formatting and output 2024-07-02 09:00:54 -05:00
DrIOS
0e2e779c82 fix: up to 7.2.6 SPO formatting and output 2024-07-02 09:00:43 -05:00
Doug Rios
1240f74450 Merge pull request #139 from CriticalSolutionsNetwork/138-add-hash-computation-to-file-output-of-export-function-and-compress-into-archive
138 add hash computation to file output of export function and compress into archive
2024-07-01 13:22:15 -05:00
DrIOS
063124eef3 docs: Update build help/CHANGELOG 2024-07-01 13:19:44 -05:00
DrIOS
14f3889378 docs: Update Help/WikiFiles/HTML Help 2024-07-01 13:18:54 -05:00
DrIOS
3790ec00de add: Zip and hash computation to function 2024-07-01 13:12:56 -05:00
20 changed files with 421 additions and 281 deletions

View File

@@ -4,6 +4,30 @@ The format is based on and uses the types of changes according to [Keep a Change
## [Unreleased]
# Fixed
- SPO tests formatting and output.
## [0.1.22] - 2024-07-01
### Added
- Added hash and compress steps to `Export-M365SecurityAuditTable` function.
## [0.1.21] - 2024-07-01
### Fixed
- SPO tests formatting and output.
## [0.1.22] - 2024-07-01
### Added
- Added hash and compress steps to `Export-M365SecurityAuditTable` function.
## [0.1.21] - 2024-07-01
### Fixed
- Formatting for MgGraph tests.

BIN
README.md

Binary file not shown.

Binary file not shown.

View File

@@ -190,10 +190,11 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable
## INPUTS
### [CISAuditResult[]], [string]
### [CISAuditResult[]] - An array of CISAuditResult objects.
### [string] - A path to a CSV file.
## OUTPUTS
### [PSCustomObject]
### [PSCustomObject] - A custom object containing the path to the zip file and its hash.
## NOTES
## RELATED LINKS

View File

@@ -4,7 +4,7 @@ Import-Module .\output\module\M365FoundationsCISReport\*\*.psd1
<#
$ver = "v0.1.18"
$ver = "v0.1.22"
git checkout main
git pull origin main
git tag -a $ver -m "Release version $ver refactor Update"
@@ -59,6 +59,5 @@ Set-Secret -Name "GitHubToken" -Vault ModuleBuildCreds
$GalleryApiToken = Get-Secret -Name "GalleryApiToken" -Vault ModuleBuildCreds -AsPlainText
$GitHubToken = Get-Secret -Name "GitHubToken" -Vault ModuleBuildCreds -AsPlainText
$GalleryApiToken
$GitHubToken
$GitHubToken

View File

@@ -40,12 +40,24 @@ function Get-CISSpoOutput {
switch ($Rec) {
'7.2.1' {
# Test-ModernAuthSharePoint.ps1
# $SPOTenant Mock Object
<#
$SPOTenant = [PSCustomObject]@{
LegacyAuthProtocolsEnabled = $true
}
#>
$SPOTenant = Get-SPOTenant | Select-Object -Property LegacyAuthProtocolsEnabled
return $SPOTenant
}
'7.2.2' {
# Test-SharePointAADB2B.ps1
# 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled
# $SPOTenantAzureADB2B Mock Object
<#
$SPOTenantAzureADB2B = [PSCustomObject]@{
EnableAzureADB2BIntegration = $false
}
#>
$SPOTenantAzureADB2B = Get-SPOTenant | Select-Object EnableAzureADB2BIntegration
return $SPOTenantAzureADB2B
}
@@ -53,35 +65,75 @@ function Get-CISSpoOutput {
# Test-RestrictExternalSharing.ps1
# 7.2.3 (L1) Ensure external content sharing is restricted
# Retrieve the SharingCapability setting for the SharePoint tenant
# $SPOTenantSharingCapability Mock Object
<#
$SPOTenantSharingCapability = [PSCustomObject]@{
SharingCapability = "ExternalUserAndGuestSharing"
}
#>
$SPOTenantSharingCapability = Get-SPOTenant | Select-Object SharingCapability
return $SPOTenantSharingCapability
}
'7.2.4' {
# Test-OneDriveContentRestrictions.ps1
# 7.2.4 (L2) Ensure OneDrive content sharing is restricted
# $SPOTenant Mock Object
<#
$SPOTenant = [PSCustomObject]@{
OneDriveSharingCapability = "ExternalUserAndGuestSharing"
}
#>
$SPOTenant = Get-SPOTenant | Select-Object OneDriveSharingCapability
return $SPOTenant
}
'7.2.5' {
# Test-SharePointGuestsItemSharing.ps1
# 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own
# $SPOTenant Mock Object
<#
$SPOTenant = [PSCustomObject]@{
PreventExternalUsersFromResharing = $false
}
#>
$SPOTenant = Get-SPOTenant | Select-Object PreventExternalUsersFromResharing
return $SPOTenant
}
'7.2.6' {
# Test-SharePointExternalSharingDomains.ps1
# 7.2.6 (L2) Ensure SharePoint external sharing is managed through domain whitelist/blacklists
# Add Authorized Domains?
# $SPOTenant Mock Object
<#
$SPOTenant = [PSCustomObject]@{
SharingDomainRestrictionMode = "AllowList"
SharingAllowedDomainList = "domain1.com", "domain2.com"
}
#>
$SPOTenant = Get-SPOTenant | Select-Object SharingDomainRestrictionMode, SharingAllowedDomainList
return $SPOTenant
}
'7.2.7' {
# Test-LinkSharingRestrictions.ps1
# Retrieve link sharing configuration for SharePoint and OneDrive
# $SPOTenantLinkSharing Mock Object
<#
$$SPOTenantLinkSharing = [PSCustomObject]@{
DefaultSharingLinkType = "Direct"
}
#>
$SPOTenantLinkSharing = Get-SPOTenant | Select-Object DefaultSharingLinkType
return $SPOTenantLinkSharing
}
'7.2.9' {
# Test-GuestAccessExpiration.ps1
# Retrieve SharePoint tenant settings related to guest access expiration
# $SPOTenantGuestAccess Mock Object
<#
$SPOTenantGuestAccess = [PSCustomObject]@{
ExternalUserExpirationRequired = "$false"
ExternalUserExpireInDays = "60"
}
#>
$SPOTenantGuestAccess = Get-SPOTenant | Select-Object ExternalUserExpirationRequired, ExternalUserExpireInDays
return $SPOTenantGuestAccess
}
@@ -89,24 +141,53 @@ function Get-CISSpoOutput {
# Test-ReauthWithCode.ps1
# 7.2.10 (L1) Ensure reauthentication with verification code is restricted
# Retrieve reauthentication settings for SharePoint Online
# $SPOTenantReauthentication Mock Object
<#
$SPOTenantReauthentication = [PSCustomObject]@{
EmailAttestationRequired = "$false"
EmailAttestationReAuthDays = "30"
}
#>
$SPOTenantReauthentication = Get-SPOTenant | Select-Object EmailAttestationRequired, EmailAttestationReAuthDays
return $SPOTenantReauthentication
}
'7.3.1' {
# Test-DisallowInfectedFilesDownload.ps1
# Retrieve the SharePoint tenant configuration
# $SPOTenantDisallowInfectedFileDownload Mock Object
<#
$SPOTenantDisallowInfectedFileDownload = [PSCustomObject]@{
DisallowInfectedFileDownload = $false
}
#>
$SPOTenantDisallowInfectedFileDownload = Get-SPOTenant | Select-Object DisallowInfectedFileDownload
return $SPOTenantDisallowInfectedFileDownload
}
'7.3.2' {
# Test-OneDriveSyncRestrictions.ps1
# Retrieve OneDrive sync client restriction settings
# Add isHybrid paramter?
# $SPOTenantSyncClientRestriction Mock Object
<#
$SPOTenantSyncClientRestriction = [PSCustomObject]@{
TenantRestrictionEnabled = $true
AllowedDomainList = "786548DD-877B-4760-A749-6B1EFBC1190A", "877564FF-877B-4760-A749-6B1EFBC1190A"
}
#>
$SPOTenantSyncClientRestriction = Get-SPOTenantSyncClientRestriction | Select-Object TenantRestrictionEnabled, AllowedDomainList
return $SPOTenantSyncClientRestriction
}
'7.3.4' {
# Test-RestrictCustomScripts.ps1
# Retrieve all site collections and select necessary properties
# $SPOSitesCustomScript Mock Object
<#
$SPOSitesCustomScript = [PSCustomObject]@{
Title = "Site Collection 1"
Url = "https://contoso.sharepoint.com/sites/site1"
DenyAddAndCustomizePages = "Enabled"
}
#>
$SPOSitesCustomScript = Get-SPOSite -Limit All | Select-Object Title, Url, DenyAddAndCustomizePages
return $SPOSitesCustomScript
}

View File

@@ -1,47 +1,52 @@
<#
.SYNOPSIS
Exports M365 security audit results to a CSV file or outputs a specific test result as an object.
Exports Microsoft 365 security audit results to CSV or Excel files and supports outputting specific test results as objects.
.DESCRIPTION
This function exports M365 security audit results from either an array of CISAuditResult objects or a CSV file.
It can export all results to a specified path or output a specific test result as an object.
The Export-M365SecurityAuditTable function exports Microsoft 365 security audit results from an array of CISAuditResult objects or a CSV file.
It can export all results to a specified path, output a specific test result as an object, and includes options for exporting results to Excel.
Additionally, it computes hashes for the exported files and includes them in the zip archive for verification purposes.
.PARAMETER AuditResults
An array of CISAuditResult objects containing the audit results.
An array of CISAuditResult objects containing the audit results. This parameter is mandatory when exporting from audit results.
.PARAMETER CsvPath
The path to a CSV file containing the audit results.
The path to a CSV file containing the audit results. This parameter is mandatory when exporting from a CSV file.
.PARAMETER OutputTestNumber
The test number to output as an object. Valid values are "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4".
The test number to output as an object. Valid values are "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4". This parameter is used to output a specific test result.
.PARAMETER ExportAllTests
Switch to export all test results.
Switch to export all test results. When specified, all test results are exported to the specified path.
.PARAMETER ExportPath
The path where the CSV files will be exported.
The path where the CSV or Excel files will be exported. This parameter is mandatory when exporting all tests.
.PARAMETER ExportOriginalTests
Switch to export the original audit results to a CSV file.
Switch to export the original audit results to a CSV file. When specified, the original test results are exported along with the processed results.
.PARAMETER ExportToExcel
Switch to export the results to an Excel file.
Switch to export the results to an Excel file. When specified, results are exported in Excel format.
.INPUTS
[CISAuditResult[]], [string]
[CISAuditResult[]] - An array of CISAuditResult objects.
[string] - A path to a CSV file.
.OUTPUTS
[PSCustomObject]
[PSCustomObject] - A custom object containing the path to the zip file and its hash.
.EXAMPLE
Export-M365SecurityAuditTable -AuditResults $object -OutputTestNumber 6.1.2
# Output object for a single test number from audit results
Export-M365SecurityAuditTable -AuditResults $object -OutputTestNumber 6.1.2
# Outputs the result of test number 6.1.2 from the provided audit results as an object.
.EXAMPLE
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $object -ExportPath "C:\temp"
# Export all results from audit results to the specified path
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $object -ExportPath "C:\temp"
# Exports all audit results to the specified path in CSV format.
.EXAMPLE
Export-M365SecurityAuditTable -CsvPath "C:\temp\auditresultstoday1.csv" -OutputTestNumber 6.1.2
# Output object for a single test number from CSV
Export-M365SecurityAuditTable -CsvPath "C:\temp\auditresultstoday1.csv" -OutputTestNumber 6.1.2
# Outputs the result of test number 6.1.2 from the CSV file as an object.
.EXAMPLE
Export-M365SecurityAuditTable -ExportAllTests -CsvPath "C:\temp\auditresultstoday1.csv" -ExportPath "C:\temp"
# Export all results from CSV to the specified path
Export-M365SecurityAuditTable -ExportAllTests -CsvPath "C:\temp\auditresultstoday1.csv" -ExportPath "C:\temp"
# Exports all audit results from the CSV file to the specified path in CSV format.
.EXAMPLE
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $object -ExportPath "C:\temp" -ExportOriginalTests
# Export all results from audit results to the specified path along with the original tests
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $object -ExportPath "C:\temp" -ExportOriginalTests
# Exports all audit results along with the original test results to the specified path in CSV format.
.EXAMPLE
Export-M365SecurityAuditTable -ExportAllTests -CsvPath "C:\temp\auditresultstoday1.csv" -ExportPath "C:\temp" -ExportOriginalTests
# Export all results from CSV to the specified path along with the original tests
Export-M365SecurityAuditTable -ExportAllTests -CsvPath "C:\temp\auditresultstoday1.csv" -ExportPath "C:\temp" -ExportOriginalTests
# Exports all audit results from the CSV file along with the original test results to the specified path in CSV format.
.EXAMPLE
Export-M365SecurityAuditTable -ExportAllTests -AuditResults $object -ExportPath "C:\temp" -ExportToExcel
# Exports all audit results to the specified path in Excel format.
.LINK
https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Export-M365SecurityAuditTable
https://criticalsolutionsnetwork.github.io/M365FoundationsCISReport/#Export-M365SecurityAuditTable
#>
function Export-M365SecurityAuditTable {
[CmdletBinding()]
@@ -50,179 +55,206 @@ function Export-M365SecurityAuditTable {
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ExportAllResultsFromAuditResults")]
[Parameter(Mandatory = $true, Position = 2, ParameterSetName = "OutputObjectFromAuditResultsSingle")]
[CISAuditResult[]]$AuditResults,
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "ExportAllResultsFromCsv")]
[Parameter(Mandatory = $true, Position = 2, ParameterSetName = "OutputObjectFromCsvSingle")]
[ValidateScript({ (Test-Path $_) -and ((Get-Item $_).PSIsContainer -eq $false) })]
[string]$CsvPath,
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "OutputObjectFromAuditResultsSingle")]
[Parameter(Mandatory = $true, Position = 1, ParameterSetName = "OutputObjectFromCsvSingle")]
[ValidateSet("1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4")]
[string]$OutputTestNumber,
[Parameter(Mandatory = $false, Position = 0, ParameterSetName = "ExportAllResultsFromAuditResults")]
[Parameter(Mandatory = $false, Position = 0, ParameterSetName = "ExportAllResultsFromCsv")]
[switch]$ExportAllTests,
[Parameter(Mandatory = $true, ParameterSetName = "ExportAllResultsFromAuditResults")]
[Parameter(Mandatory = $true, ParameterSetName = "ExportAllResultsFromCsv")]
[string]$ExportPath,
[Parameter(Mandatory = $true, ParameterSetName = "ExportAllResultsFromAuditResults")]
[Parameter(Mandatory = $true, ParameterSetName = "ExportAllResultsFromCsv")]
[switch]$ExportOriginalTests,
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromAuditResults")]
[Parameter(Mandatory = $false, ParameterSetName = "ExportAllResultsFromCsv")]
[switch]$ExportToExcel
)
if ($ExportToExcel) {
Assert-ModuleAvailability -ModuleName ImportExcel -RequiredVersion "7.8.9"
}
if ($PSCmdlet.ParameterSetName -like "ExportAllResultsFromCsv" -or $PSCmdlet.ParameterSetName -eq "OutputObjectFromCsvSingle") {
$AuditResults = Import-Csv -Path $CsvPath | ForEach-Object {
$params = @{
Rec = $_.Rec
Result = [bool]$_.Result
Status = $_.Status
Details = $_.Details
FailureReason = $_.FailureReason
Begin {
$createdFiles = @() # Initialize an array to keep track of created files
if ($ExportToExcel) {
Assert-ModuleAvailability -ModuleName ImportExcel -RequiredVersion "7.8.9"
}
if ($PSCmdlet.ParameterSetName -like "ExportAllResultsFromCsv" -or $PSCmdlet.ParameterSetName -eq "OutputObjectFromCsvSingle") {
$AuditResults = Import-Csv -Path $CsvPath | ForEach-Object {
$params = @{
Rec = $_.Rec
Result = [bool]$_.Result
Status = $_.Status
Details = $_.Details
FailureReason = $_.FailureReason
}
Initialize-CISAuditResult @params
}
Initialize-CISAuditResult @params
}
}
if ($ExportAllTests) {
$TestNumbers = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
}
$results = @()
$testsToProcess = if ($OutputTestNumber) { @($OutputTestNumber) } else { $TestNumbers }
foreach ($test in $testsToProcess) {
$auditResult = $AuditResults | Where-Object { $_.Rec -eq $test }
if (-not $auditResult) {
Write-Information "No audit results found for the test number $test."
continue
if ($ExportAllTests) {
$TestNumbers = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
}
switch ($test) {
"6.1.2" {
$details = $auditResult.Details
if ($details -ne "No M365 E3 licenses found.") {
$csv = $details | ConvertFrom-Csv -Delimiter '|'
}
else {
$csv = $null
}
if ($null -ne $csv) {
foreach ($row in $csv) {
$row.AdminActionsMissing = (Get-Action -AbbreviatedActions $row.AdminActionsMissing.Split(',') -ReverseActionType Admin | Where-Object { $_ -notin @("MailItemsAccessed", "Send") }) -join ','
$row.DelegateActionsMissing = (Get-Action -AbbreviatedActions $row.DelegateActionsMissing.Split(',') -ReverseActionType Delegate | Where-Object { $_ -notin @("MailItemsAccessed") }) -join ','
$row.OwnerActionsMissing = (Get-Action -AbbreviatedActions $row.OwnerActionsMissing.Split(',') -ReverseActionType Owner | Where-Object { $_ -notin @("MailItemsAccessed", "Send") }) -join ','
$results = @()
$testsToProcess = if ($OutputTestNumber) { @($OutputTestNumber) } else { $TestNumbers }
}
Process {
foreach ($test in $testsToProcess) {
$auditResult = $AuditResults | Where-Object { $_.Rec -eq $test }
if (-not $auditResult) {
Write-Information "No audit results found for the test number $test."
continue
}
switch ($test) {
"6.1.2" {
$details = $auditResult.Details
if ($details -ne "No M365 E3 licenses found.") {
$csv = $details | ConvertFrom-Csv -Delimiter '|'
}
$newObjectDetails = $csv
}
else {
$newObjectDetails = $details
}
$results += [PSCustomObject]@{ TestNumber = $test; Details = $newObjectDetails }
}
"6.1.3" {
$details = $auditResult.Details
if ($details -ne "No M365 E5 licenses found.") {
$csv = $details | ConvertFrom-Csv -Delimiter '|'
}
else {
$csv = $null
}
if ($null -ne $csv) {
foreach ($row in $csv) {
$row.AdminActionsMissing = (Get-Action -AbbreviatedActions $row.AdminActionsMissing.Split(',') -ReverseActionType Admin) -join ','
$row.DelegateActionsMissing = (Get-Action -AbbreviatedActions $row.DelegateActionsMissing.Split(',') -ReverseActionType Delegate) -join ','
$row.OwnerActionsMissing = (Get-Action -AbbreviatedActions $row.OwnerActionsMissing.Split(',') -ReverseActionType Owner) -join ','
else {
$csv = $null
}
$newObjectDetails = $csv
}
else {
$newObjectDetails = $details
}
$results += [PSCustomObject]@{ TestNumber = $test; Details = $newObjectDetails }
}
Default {
$details = $auditResult.Details
$csv = $details | ConvertFrom-Csv -Delimiter '|'
$results += [PSCustomObject]@{ TestNumber = $test; Details = $csv }
}
}
}
if ($ExportPath) {
$timestamp = (Get-Date).ToString("yyyy.MM.dd_HH.mm.ss")
$exportedTests = @()
foreach ($result in $results) {
$testDef = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $result.TestNumber }
if ($testDef) {
$fileName = "$ExportPath\$($timestamp)_$($result.TestNumber).$($testDef.TestFileName -replace '\.ps1$').csv"
if ($result.Details.Count -eq 0) {
Write-Information "No results found for test number $($result.TestNumber)." -InformationAction Continue
}
else {
if (($result.Details -ne "No M365 E3 licenses found.") -and ($result.Details -ne "No M365 E5 licenses found.")) {
if ($ExportToExcel) {
$xlsxPath = [System.IO.Path]::ChangeExtension($fileName, '.xlsx')
$result.Details | Export-Excel -Path $xlsxPath -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
if ($null -ne $csv) {
foreach ($row in $csv) {
$row.AdminActionsMissing = (Get-Action -AbbreviatedActions $row.AdminActionsMissing.Split(',') -ReverseActionType Admin | Where-Object { $_ -notin @("MailItemsAccessed", "Send") }) -join ','
$row.DelegateActionsMissing = (Get-Action -AbbreviatedActions $row.DelegateActionsMissing.Split(',') -ReverseActionType Delegate | Where-Object { $_ -notin @("MailItemsAccessed") }) -join ','
$row.OwnerActionsMissing = (Get-Action -AbbreviatedActions $row.OwnerActionsMissing.Split(',') -ReverseActionType Owner | Where-Object { $_ -notin @("MailItemsAccessed", "Send") }) -join ','
}
else {
$result.Details | Export-Csv -Path $fileName -NoTypeInformation
}
$exportedTests += $result.TestNumber
$newObjectDetails = $csv
}
else {
$newObjectDetails = $details
}
$results += [PSCustomObject]@{ TestNumber = $test; Details = $newObjectDetails }
}
"6.1.3" {
$details = $auditResult.Details
if ($details -ne "No M365 E5 licenses found.") {
$csv = $details | ConvertFrom-Csv -Delimiter '|'
}
else {
$csv = $null
}
if ($null -ne $csv) {
foreach ($row in $csv) {
$row.AdminActionsMissing = (Get-Action -AbbreviatedActions $row.AdminActionsMissing.Split(',') -ReverseActionType Admin) -join ','
$row.DelegateActionsMissing = (Get-Action -AbbreviatedActions $row.DelegateActionsMissing.Split(',') -ReverseActionType Delegate) -join ','
$row.OwnerActionsMissing = (Get-Action -AbbreviatedActions $row.OwnerActionsMissing.Split(',') -ReverseActionType Owner) -join ','
}
$newObjectDetails = $csv
}
else {
$newObjectDetails = $details
}
$results += [PSCustomObject]@{ TestNumber = $test; Details = $newObjectDetails }
}
Default {
$details = $auditResult.Details
$csv = $details | ConvertFrom-Csv -Delimiter '|'
$results += [PSCustomObject]@{ TestNumber = $test; Details = $csv }
}
}
}
if ($exportedTests.Count -gt 0) {
Write-Information "The following tests were exported: $($exportedTests -join ', ')" -InformationAction Continue
}
else {
}
End {
if ($ExportPath) {
$timestamp = (Get-Date).ToString("yyyy.MM.dd_HH.mm.ss")
$exportedTests = @()
foreach ($result in $results) {
$testDef = $script:TestDefinitionsObject | Where-Object { $_.Rec -eq $result.TestNumber }
if ($testDef) {
$fileName = "$ExportPath\$($timestamp)_$($result.TestNumber).$($testDef.TestFileName -replace '\.ps1$').csv"
if ($result.Details.Count -eq 0) {
Write-Information "No results found for test number $($result.TestNumber)." -InformationAction Continue
}
else {
if (($result.Details -ne "No M365 E3 licenses found.") -and ($result.Details -ne "No M365 E5 licenses found.")) {
if ($ExportToExcel) {
$xlsxPath = [System.IO.Path]::ChangeExtension($fileName, '.xlsx')
$result.Details | Export-Excel -Path $xlsxPath -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
$createdFiles += $xlsxPath # Add the created file to the array
}
else {
$result.Details | Export-Csv -Path $fileName -NoTypeInformation
$createdFiles += $fileName # Add the created file to the array
}
$exportedTests += $result.TestNumber
}
}
}
}
if ($exportedTests.Count -gt 0) {
Write-Information "The following tests were exported: $($exportedTests -join ', ')" -InformationAction Continue
}
else {
if ($ExportOriginalTests) {
Write-Information "Full audit results exported however, none of the following tests had exports: `n1.1.1, 1.3.1, 6.1.2, 6.1.3, 7.3.4" -InformationAction Continue
}
else {
Write-Information "No specified tests were included in the export." -InformationAction Continue
}
}
if ($ExportOriginalTests) {
Write-Information "Full audit results exported however, none of the following tests had exports: `n1.1.1, 1.3.1, 6.1.2, 6.1.3, 7.3.4" -InformationAction Continue
# Define the test numbers to check
$TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
# Check for large details and update the AuditResults array
$updatedAuditResults = Get-ExceededLengthResultDetail -AuditResults $AuditResults -TestNumbersToCheck $TestNumbersToCheck -ExportedTests $exportedTests -DetailsLengthLimit 30000 -PreviewLineCount 25
$originalFileName = "$ExportPath\$timestamp`_M365FoundationsAudit.csv"
if ($ExportToExcel) {
$xlsxPath = [System.IO.Path]::ChangeExtension($originalFileName, '.xlsx')
$updatedAuditResults | Export-Excel -Path $xlsxPath -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
$createdFiles += $xlsxPath # Add the created file to the array
}
else {
$updatedAuditResults | Export-Csv -Path $originalFileName -NoTypeInformation
$createdFiles += $originalFileName # Add the created file to the array
}
}
# Hash each file and add it to a dictionary
# Hash each file and save the hashes to a text file
$hashFilePath = "$ExportPath\$timestamp`_Hashes.txt"
$fileHashes = @()
foreach ($file in $createdFiles) {
$hash = Get-FileHash -Path $file -Algorithm SHA256
$fileHashes += "$($file): $($hash.Hash)"
}
$fileHashes | Set-Content -Path $hashFilePath
$createdFiles += $hashFilePath # Add the hash file to the array
# Create a zip file and add all the created files
$zipFilePath = "$ExportPath\$timestamp`_M365FoundationsAudit.zip"
Compress-Archive -Path $createdFiles -DestinationPath $zipFilePath
# Remove the original files after they have been added to the zip
foreach ($file in $createdFiles) {
Remove-Item -Path $file -Force
}
# Compute the hash for the zip file and rename it
$zipHash = Get-FileHash -Path $zipFilePath -Algorithm SHA256
$newZipFilePath = "$ExportPath\$timestamp`_M365FoundationsAudit_$($zipHash.Hash.Substring(0, 8)).zip"
Rename-Item -Path $zipFilePath -NewName $newZipFilePath
# Output the zip file path with hash
[PSCustomObject]@{
ZipFilePath = $newZipFilePath
}
} # End of ExportPath
elseif ($OutputTestNumber) {
if ($results[0].Details) {
return $results[0].Details
}
else {
Write-Information "No specified tests were included in the export." -InformationAction Continue
Write-Information "No results found for test number $($OutputTestNumber)." -InformationAction Continue
}
}
if ($ExportOriginalTests) {
# Define the test numbers to check
$TestNumbersToCheck = "1.1.1", "1.3.1", "6.1.2", "6.1.3", "7.3.4"
# Check for large details and update the AuditResults array
$updatedAuditResults = Get-ExceededLengthResultDetail -AuditResults $AuditResults -TestNumbersToCheck $TestNumbersToCheck -ExportedTests $exportedTests -DetailsLengthLimit 30000 -PreviewLineCount 25
$originalFileName = "$ExportPath\$timestamp`_M365FoundationsAudit.csv"
if ($ExportToExcel) {
$xlsxPath = [System.IO.Path]::ChangeExtension($originalFileName, '.xlsx')
$updatedAuditResults | Export-Excel -Path $xlsxPath -WorksheetName Table -TableName Table -AutoSize -TableStyle Medium2
}
else {
$updatedAuditResults | Export-Csv -Path $originalFileName -NoTypeInformation
}
}
}
elseif ($OutputTestNumber) {
if ($results[0].Details) {
return $results[0].Details
}
else {
Write-Information "No results found for test number $($OutputTestNumber)." -InformationAction Continue
Write-Error "No valid operation specified. Please provide valid parameters."
}
# Output the created files at the end
#if ($createdFiles.Count -gt 0) {
########### $createdFiles
#}
}
else {
Write-Error "No valid operation specified. Please provide valid parameters."
}
}
}

View File

@@ -277,7 +277,15 @@
<command:inputTypes>
<command:inputType>
<dev:type>
<maml:name>[CISAuditResult[]], [string]</maml:name>
<maml:name>[CISAuditResult[]] - An array of CISAuditResult objects.</maml:name>
</dev:type>
<maml:description>
<maml:para></maml:para>
</maml:description>
</command:inputType>
<command:inputType>
<dev:type>
<maml:name>[string] - A path to a CSV file.</maml:name>
</dev:type>
<maml:description>
<maml:para></maml:para>
@@ -287,7 +295,7 @@
<command:returnValues>
<command:returnValue>
<dev:type>
<maml:name>[PSCustomObject]</maml:name>
<maml:name>[PSCustomObject] - A custom object containing the path to the zip file and its hash.</maml:name>
</dev:type>
<maml:description>
<maml:para></maml:para>

View File

@@ -5,17 +5,14 @@ function Test-DisallowInfectedFilesDownload {
# Aligned
# Define your parameters here if needed
)
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.3.1"
Write-Verbose "Running Test-DisallowInfectedFilesDownload for $recnum..."
}
process {
try {
# 7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download
#
@@ -32,28 +29,30 @@ function Test-DisallowInfectedFilesDownload {
# - Condition A: The `DisallowInfectedFileDownload` setting is not set to `True`.
# - Condition B: The setting does not prevent users from downloading infected files.
# - Condition C: Verification using the PowerShell command indicates that the setting is incorrectly configured.
# Retrieve the SharePoint tenant configuration
# $SPOTenantDisallowInfectedFileDownload Mock Object
<#
$SPOTenantDisallowInfectedFileDownload = [PSCustomObject]@{
DisallowInfectedFileDownload = $false
}
#>
$SPOTenantDisallowInfectedFileDownload = Get-CISSpoOutput -Rec $recnum
# Condition A: The `DisallowInfectedFileDownload` setting is set to `True`
$isDisallowInfectedFileDownloadEnabled = $SPOTenantDisallowInfectedFileDownload.DisallowInfectedFileDownload
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $isDisallowInfectedFileDownloadEnabled) {
"Downloading infected files is not disallowed." # Condition B: The setting does not prevent users from downloading infected files
"Downloading infected files is not disallowed. To ensure infected files cannot be downloaded, use the following command:`n" + ` # Condition B: The setting does not prevent users from downloading infected files
"Set-SPOTenant -DisallowInfectedFileDownload `$true"
}
else {
"N/A"
}
$details = if ($isDisallowInfectedFileDownloadEnabled) {
"DisallowInfectedFileDownload: True" # Condition C: Verification confirms the setting is correctly configured
}
else {
"DisallowInfectedFileDownload: False" # Condition C: Verification indicates the setting is incorrectly configured
}
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
@@ -69,9 +68,8 @@ function Test-DisallowInfectedFilesDownload {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return the audit result
return $auditResult
}
}
}

View File

@@ -5,17 +5,14 @@ function Test-GuestAccessExpiration {
# Aligned
# Define your parameters here if needed
)
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.2.9"
Write-Verbose "Running Test-GuestAccessExpiration for $recnum..."
}
process {
try {
# 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically
#
@@ -32,21 +29,25 @@ function Test-GuestAccessExpiration {
# - Condition A: The ExternalUserExpirationRequired setting in SharePoint is not set to True.
# - Condition B: The ExternalUserExpireInDays setting in SharePoint is configured to more than 30 days.
# - Condition C: Verification using the SharePoint Admin Center indicates that guest access is not set to expire automatically after the specified number of days.
# Retrieve SharePoint tenant settings related to guest access expiration
# $SPOTenantGuestAccess Mock Object
<#
$SPOTenantGuestAccess = [PSCustomObject]@{
ExternalUserExpirationRequired = "$false"
ExternalUserExpireInDays = "60"
}
#>
$SPOTenantGuestAccess = Get-CISSpoOutput -Rec $recnum
$isGuestAccessExpirationConfiguredCorrectly = $SPOTenantGuestAccess.ExternalUserExpirationRequired -and $SPOTenantGuestAccess.ExternalUserExpireInDays -le 30
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $isGuestAccessExpirationConfiguredCorrectly) {
"Guest access expiration is not configured to automatically expire within 30 days or less."
"Guest access expiration is not configured to automatically expire within 30 days or less. To remediate this setting, use the Set-SPOTenant command:`n`n" + `
"Set-SPOTenant -ExternalUserExpirationRequired `$true -ExternalUserExpireInDays 30"
}
else {
"N/A"
}
$details = "ExternalUserExpirationRequired: $($SPOTenantGuestAccess.ExternalUserExpirationRequired); ExternalUserExpireInDays: $($SPOTenantGuestAccess.ExternalUserExpireInDays)"
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
@@ -62,7 +63,6 @@ function Test-GuestAccessExpiration {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return the audit result
return $auditResult

View File

@@ -6,14 +6,13 @@ function Test-LinkSharingRestrictions {
# Define your parameters here
# Test behavior in prod
)
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.2.7"
Write-Verbose "Running Test-LinkSharingRestrictions for $recnum..."
}
process {
try {
# 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive
@@ -31,21 +30,24 @@ function Test-LinkSharingRestrictions {
# - Condition A: The `DefaultSharingLinkType` setting in SharePoint and OneDrive is not set to `Direct`.
# - Condition B: The setting `Choose the type of link that's selected by default when users share files and folders in SharePoint and OneDrive` is not set to `Specific people (only the people the user specifies)`.
# - Condition C: Verification using the UI indicates that the link sharing settings are not configured as recommended.
# Retrieve link sharing configuration for SharePoint and OneDrive
# $SPOTenantLinkSharing Mock Object
<#
$$SPOTenantLinkSharing = [PSCustomObject]@{
DefaultSharingLinkType = "Direct"
}
#>
$SPOTenantLinkSharing = Get-CISSpoOutput -Rec $recnum
$isLinkSharingRestricted = $SPOTenantLinkSharing.DefaultSharingLinkType -eq 'Direct' # Or 'SpecificPeople' as per the recommendation
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $isLinkSharingRestricted) {
"Link sharing is not restricted to 'Specific people'. Current setting: $($SPOTenantLinkSharing.DefaultSharingLinkType)"
"Link sharing is not restricted to 'Specific people'. Current setting: $($SPOTenantLinkSharing.DefaultSharingLinkType). To remediate this setting, use the Set-SPOTenant command:`n`n" + `
"Set-SPOTenant -DefaultSharingLinkType Direct"
}
else {
"N/A"
}
$details = "DefaultSharingLinkType: $($SPOTenantLinkSharing.DefaultSharingLinkType)"
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
@@ -55,14 +57,12 @@ function Test-LinkSharingRestrictions {
FailureReason = $failureReasons
}
$auditResult = Initialize-CISAuditResult @params
}
catch {
$LastError = $_
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return the audit result
return $auditResult

View File

@@ -12,16 +12,14 @@ function Test-ModernAuthSharePoint {
# Initialization code, if needed
$recnum = "7.2.1"
Write-Verbose "Running Test-ModernAuthSharePoint for $recnum..."
<#
# Conditions for 7.2.1 (L1) Ensure modern authentication for SharePoint applications is required
## Validate test for a pass:
# - Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
# - Specific conditions to check:
# - Condition A: The setting "Apps that don't use modern authentication" is set to "Block access" in the SharePoint admin center.
# - Condition B: The PowerShell command `Get-SPOTenant | ft LegacyAuthProtocolsEnabled` returns `False`.
## Validate test for a fail:
# - Confirm that the failure conditions in the automated test are consistent with the manual audit results.
# - Specific conditions to check:
@@ -29,23 +27,25 @@ function Test-ModernAuthSharePoint {
# - Condition B: The PowerShell command `Get-SPOTenant | ft LegacyAuthProtocolsEnabled` returns `True`.
#>
}
process {
try {
# 7.2.1 (L1) Ensure modern authentication for SharePoint applications is required
# $SPOTenant Mock Object
<#
$SPOTenant = [PSCustomObject]@{
LegacyAuthProtocolsEnabled = $true
}
#>
$SPOTenant = Get-CISSpoOutput -Rec $recnum
$modernAuthForSPRequired = -not $SPOTenant.LegacyAuthProtocolsEnabled
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $modernAuthForSPRequired) {
"Legacy authentication protocols are enabled" # Fail Condition B
"Legacy authentication protocols are enabled. The following command can be used to disable:`nSet-SPOTenant -LegacyAuthProtocolsEnabled `$false" # Fail Condition B
}
else {
"N/A"
}
$details = "LegacyAuthProtocolsEnabled: $($SPOTenant.LegacyAuthProtocolsEnabled)" # Details for Condition B
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
@@ -61,7 +61,6 @@ function Test-ModernAuthSharePoint {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return the audit result
return $auditResult

View File

@@ -5,7 +5,6 @@ function Test-OneDriveContentRestrictions {
# Aligned
# Define your parameters here
)
begin {
# 7.2.4 (L2) Ensure OneDrive content sharing is restricted
#
@@ -22,36 +21,38 @@ function Test-OneDriveContentRestrictions {
# - Condition A: The OneDriveSharingCapability setting is not configured to "Disabled" using the PowerShell cmdlet `Get-SPOTenant | fl OneDriveSharingCapability`.
# - Condition B: The OneDriveSharingCapability is not set to "Only people in your organization" in the SharePoint admin center under Policies > Sharing > OneDrive.
# - Condition C: OneDrive content sharing is more permissive than SharePoint content sharing.
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.2.4"
Write-Verbose "Running Test-OneDriveContentRestrictions for $recnum..."
}
process {
try {
# 7.2.4 (L2) Ensure OneDrive content sharing is restricted
# Retrieve OneDrive sharing capability settings
# $SPOTenant Mock Object
<#
$SPOTenant = [PSCustomObject]@{
OneDriveSharingCapability = "ExternalUserAndGuestSharing"
}
#>
$SPOTenant = Get-CISSpoOutput -Rec $recnum
$isOneDriveSharingRestricted = $SPOTenant.OneDriveSharingCapability -eq 'Disabled'
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $isOneDriveSharingRestricted) {
"OneDrive content sharing is not restricted to 'Disabled'. Current setting: $($SPOTenant.OneDriveSharingCapability)"
"OneDrive content sharing is not restricted to 'Disabled'. To remediate this setting, use the Set-SPOTenant command.`n`n" + `
"Set-SPOTenant -OneDriveSharingCapability Disabled"
}
else {
"N/A"
}
$details = if ($isOneDriveSharingRestricted) {
"OneDrive content sharing is restricted."
}
else {
"OneDriveSharingCapability: $($SPOTenant.OneDriveSharingCapability)"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
@@ -67,7 +68,6 @@ function Test-OneDriveContentRestrictions {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return auditResult
return $auditResult

View File

@@ -5,14 +5,13 @@ function Test-OneDriveSyncRestrictions {
# Aligned
# Define your parameters here
)
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.3.2"
Write-Verbose "Running Test-OneDriveSyncRestrictions for $recnum..."
}
process {
try {
# 7.3.2 (L2) Ensure OneDrive sync is restricted for unmanaged devices
@@ -30,20 +29,20 @@ function Test-OneDriveSyncRestrictions {
# - Condition A: "Allow syncing only on computers joined to specific domains" is not enabled.
# - Condition B: "TenantRestrictionEnabled" is set to False.
# - Condition C: "AllowedDomainList" does not contain the trusted domain GUIDs from the on-premises environment.
# Retrieve OneDrive sync client restriction settings
$SPOTenantSyncClientRestriction = Get-CISSpoOutput -Rec $recnum
$isSyncRestricted = $SPOTenantSyncClientRestriction.TenantRestrictionEnabled -and $SPOTenantSyncClientRestriction.AllowedDomainList
# Condition A: Check if TenantRestrictionEnabled is True
# Condition B: Ensure AllowedDomainList contains trusted domains GUIDs
$failureReasons = if (-not $isSyncRestricted) {
"OneDrive sync is not restricted to managed devices. TenantRestrictionEnabled should be True and AllowedDomainList should contain trusted domains GUIDs."
"OneDrive sync is not restricted to managed devices. For hybrid devices, TenantRestrictionEnabled should be True and AllowedDomainList should contain trusted domains GUIDs.`n" + `
"To remediate this setting, edit and use the Set-SPOTenantSyncClientRestriction command below:`n" + `
"Set-SPOTenantSyncClientRestriction -TenantRestrictionEnabled `$true -AllowedDomainList `"<GUID1>`",`"<GUID2>`"`n`n" + `
"Note: Utilize the -BlockMacSync:`$true parameter if you are not using conditional access to ensure Macs cannot sync."
}
else {
"N/A"
}
# Condition C: Prepare details based on whether sync is restricted
$details = if ($isSyncRestricted) {
"OneDrive sync is restricted for unmanaged devices."
@@ -51,7 +50,6 @@ function Test-OneDriveSyncRestrictions {
else {
"TenantRestrictionEnabled: $($SPOTenantSyncClientRestriction.TenantRestrictionEnabled); AllowedDomainList: $($SPOTenantSyncClientRestriction.AllowedDomainList -join ', ')"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
@@ -67,7 +65,6 @@ function Test-OneDriveSyncRestrictions {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return auditResult
return $auditResult

View File

@@ -5,7 +5,6 @@ function Test-ReauthWithCode {
# Aligned
# Define your parameters here
)
begin {
<#
Conditions for 7.2.10 (L1) Ensure reauthentication with verification code is restricted
@@ -22,31 +21,34 @@ function Test-ReauthWithCode {
# - Condition A: The `EmailAttestationRequired` property is set to `False`.
# - Condition B: The `EmailAttestationReAuthDays` property is set to more than `15`.
#>
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.2.10"
Write-Verbose "Running Test-ReauthWithCode for $recnum..."
}
process {
try {
# 7.2.10 (L1) Ensure reauthentication with verification code is restricted
# Retrieve reauthentication settings for SharePoint Online
# $SPOTenantReauthentication Mock Object
<#
$SPOTenantReauthentication = [PSCustomObject]@{
EmailAttestationRequired = "$false"
EmailAttestationReAuthDays = "30"
}
#>
$SPOTenantReauthentication = Get-CISSpoOutput -Rec $recnum
$isReauthenticationRestricted = $SPOTenantReauthentication.EmailAttestationRequired -and $SPOTenantReauthentication.EmailAttestationReAuthDays -le 15
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $isReauthenticationRestricted) {
"Reauthentication with verification code does not require reauthentication within 15 days or less."
"Reauthentication with verification code does not require reauthentication within 15 days or less. To remediate this setting, use the Set-SPOTenant command:`n" + `
"Set-SPOTenant -EmailAttestationRequired `$true -EmailAttestationReAuthDays 15"
}
else {
"N/A"
}
$details = "EmailAttestationRequired: $($SPOTenantReauthentication.EmailAttestationRequired); EmailAttestationReAuthDays: $($SPOTenantReauthentication.EmailAttestationReAuthDays)"
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
@@ -62,7 +64,6 @@ function Test-ReauthWithCode {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return auditResult
return $auditResult

View File

@@ -4,15 +4,13 @@ function Test-RestrictCustomScripts {
param (
# Define your parameters here if needed
)
begin {
# Dot source the class script if necessary
# . .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.3.4"
Write-Verbose "Running Test-RestrictCustomScripts for $recnum..."
}
process {
try {
# 7.3.4 (L1) Ensure custom script execution is restricted on site collections
@@ -30,23 +28,27 @@ function Test-RestrictCustomScripts {
# - Condition A: The `DenyAddAndCustomizePages` setting is not set to `Enabled` for any site collection.
# - Condition B: The setting is not validated through PowerShell commands, indicating misconfiguration.
# - Condition C: Verification using the SharePoint Admin Center indicates that the `DenyAddAndCustomizePages` setting is not enforced.
# Retrieve all site collections and select necessary properties
# $SPOSitesCustomScript Mock Object
<#
$SPOSitesCustomScript = [PSCustomObject]@{
Title = "Site Collection 1"
Url = "https://contoso.sharepoint.com/sites/site1"
DenyAddAndCustomizePages = "Enabled"
}
#>
$SPOSitesCustomScript = Get-CISSpoOutput -Rec $recnum
# Process URLs to replace 'sharepoint.com' with '<SPUrl>'
$processedUrls = $SPOSitesCustomScript | ForEach-Object {
$_.Url = $_.Url -replace 'sharepoint\.com', '<SPUrl>'
$_
}
# Find sites where custom scripts are allowed
$customScriptAllowedSites = $processedUrls | Where-Object { $_.DenyAddAndCustomizePages -ne 'Enabled' }
#$verbosePreference = 'Continue'
# Check the total length of URLs
$totalUrlLength = ($customScriptAllowedSites.Url -join '').Length
Write-Verbose "Total length of URLs: $totalUrlLength"
# Extract hostnames from allowed sites if the total length exceeds the limit
$mostUsedHostname = $null
if ($totalUrlLength -gt 20000) {
@@ -57,7 +59,6 @@ function Test-RestrictCustomScripts {
}
}
Write-Verbose "Extracted hostnames: $($hostnames -join ', ')"
# Find the most used hostname using the Get-MostCommonWord function
$mostUsedHostname = Get-MostCommonWord -InputStrings $hostnames
Write-Verbose "Most used hostname: $mostUsedHostname"
@@ -65,7 +66,6 @@ function Test-RestrictCustomScripts {
#$verbosePreference = 'SilentlyContinue'
# Compliance is true if no sites allow custom scripts
$complianceResult = $customScriptAllowedSites.Count -eq 0
# Gather details for non-compliant sites (where custom scripts are allowed)
$nonCompliantSiteDetails = $customScriptAllowedSites | ForEach-Object {
$url = $_.Url
@@ -74,32 +74,29 @@ function Test-RestrictCustomScripts {
}
"$(if ($_.Title) {$_.Title} else {"NoTitle"})|$url"
}
# Prepare failure reasons and details based on compliance
$failureReasons = if (-not $complianceResult) {
"Some site collections are not restricting custom script execution. Review Details property for sites that are not aligned with the benchmark."
"Some site collections are not restricting custom script execution. Review Details property for sites that are not aligned with the benchmark.`n" + `
"To remediate this setting, use the following command:`n" + `
"Set-SPOSite -Identity <SiteUrl> -DenyAddAndCustomizePages `$true"
}
else {
"N/A"
}
$details = if ($complianceResult) {
"All site collections have custom script execution restricted"
}
else {
"Title|Url`n" + ($nonCompliantSiteDetails -join "`n")
}
# Convert details to PSObject and check length
$detailsPSObject = $details | ConvertFrom-Csv -Delimiter '|'
$detailsLength = ($detailsPSObject | ForEach-Object { $_.Url }).Length
if ($detailsLength -gt 32767) {
# Create a preview of the first 10 results
$preview = $detailsPSObject | Select-Object -First 10 | ForEach-Object { "$($_.Title)|$($_.Url)" }
$details = "The output is too large. Here is a preview of the first 10 results:`n`n" + ($preview -join "`n") + "`n`nPlease run the test with the following commands to get the full details:`n`nGet-SPOSite -Limit All | Where-Object { `$.DenyAddAndCustomizePages -ne 'Enabled' } | Select-Object Title, Url"
}
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum

View File

@@ -5,18 +5,15 @@ function Test-RestrictExternalSharing {
# Aligned
# Define your parameters here
)
begin {
<#
Conditions for 7.2.3 (L1) Ensure external content sharing is restricted
Validate test for a pass:
- Confirm that the automated test results align with the manual audit steps outlined in the CIS benchmark.
- Specific conditions to check:
- Condition A: The SharingCapability is set to "ExternalUserSharingOnly" or more restrictive in the SharePoint admin center.
- Condition B: Using PowerShell, the SharingCapability property for the SharePoint tenant is set to "ExternalUserSharingOnly", "ExistingExternalUserSharingOnly", or "Disabled".
- Condition C: The external sharing settings in SharePoint Online and OneDrive are set to the same or a more restrictive level than the organizations sharing settings.
Validate test for a fail:
- Confirm that the failure conditions in the automated test are consistent with the manual audit results.
- Specific conditions to check:
@@ -24,34 +21,37 @@ function Test-RestrictExternalSharing {
- Condition B: Using PowerShell, the SharingCapability property for the SharePoint tenant is set to "Anyone" or "ExternalUserAndGuestSharing".
- Condition C: The external sharing settings in SharePoint Online and OneDrive are set to a more permissive level than the organizations sharing settings.
#>
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.2.3"
Write-Verbose "Running Test-RestrictExternalSharing for $recnum..."
}
process {
try {
# 7.2.3 (L1) Ensure external content sharing is restricted
# Retrieve the SharingCapability setting for the SharePoint tenant
<#
$SPOTenantSharingCapability = [PSCustomObject]@{
SharingCapability = "ExternalUserAndGuestSharing"
}
#>
$SPOTenantSharingCapability = Get-CISSpoOutput -Rec $recnum
$isRestricted = $SPOTenantSharingCapability.SharingCapability -in @('ExternalUserSharingOnly', 'ExistingExternalUserSharingOnly', 'Disabled')
# Prepare failure reasons and details based on compliance
# Condition B: Using PowerShell, the SharingCapability property for the SharePoint tenant is set to "ExternalUserSharingOnly", "ExistingExternalUserSharingOnly", or "Disabled".
$failureReasons = if (-not $isRestricted) {
"External content sharing is not adequately restricted. Current setting: $($SPOTenantSharingCapability.SharingCapability)"
"External content sharing is not adequately restricted. Current setting: $($SPOTenantSharingCapability.SharingCapability)`n" + `
"The acceptable values for SharingCapability are: 'ExternalUserSharingOnly', 'ExistingExternalUserSharingOnly', or 'Disabled'.`n" + `
"To remediate this setting, use the Set-SPOTenant cmdlet to set the SharingCapability property to an acceptable value:`n`n" + `
"Set-SPOTenant -SharingCapability <acceptable value from above>"
}
else {
"N/A"
}
# Condition A: The SharingCapability is set to "ExternalUserSharingOnly" or more restrictive in the SharePoint admin center.
# Condition C: The external sharing settings in SharePoint Online and OneDrive are set to the same or a more restrictive level than the organizations sharing settings.
$details = "SharingCapability: $($SPOTenantSharingCapability.SharingCapability)"
# Create and populate the CISAuditResult object
$params = @{
Rec = $recnum
@@ -67,7 +67,6 @@ function Test-RestrictExternalSharing {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return auditResult
return $auditResult

View File

@@ -5,7 +5,6 @@ function Test-SharePointAADB2B {
# Aligned
# Define your parameters here
)
begin {
# Conditions for 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled
#
@@ -22,26 +21,29 @@ function Test-SharePointAADB2B {
# - Condition A: The `EnableAzureADB2BIntegration` property is set to `False` for the SharePoint tenant.
# - Condition B: The integration between SharePoint, OneDrive, and Azure AD B2B is not active.
# - Condition C: Guest accounts are not managed in Azure AD and are not subject to access policies.
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.2.2"
Write-Verbose "Running Test-SharePointAADB2B for $recnum..."
}
process {
try {
# 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled
# $SPOTenantAzureADB2B Mock Object
<#
$SPOTenantAzureADB2B = [PSCustomObject]@{
EnableAzureADB2BIntegration = $false
}
#>
$SPOTenantAzureADB2B = Get-CISSpoOutput -Rec $recnum
# Populate the auditResult object with the required properties
$params = @{
Rec = $recnum
Result = $SPOTenantAzureADB2B.EnableAzureADB2BIntegration
Status = if ($SPOTenantAzureADB2B.EnableAzureADB2BIntegration) { "Pass" } else { "Fail" }
Details = "EnableAzureADB2BIntegration: $($SPOTenantAzureADB2B.EnableAzureADB2BIntegration)"
FailureReason = if (-not $SPOTenantAzureADB2B.EnableAzureADB2BIntegration) { "Azure AD B2B integration is not enabled" } else { "N/A" }
FailureReason = if (-not $SPOTenantAzureADB2B.EnableAzureADB2BIntegration) { "Azure AD B2B integration is not enabled. The following command can be used to enable:`nSet-SPOTenant -EnableAzureADB2BIntegration `$true" } else { "N/A" }
}
$auditResult = Initialize-CISAuditResult @params
}
@@ -50,7 +52,6 @@ function Test-SharePointAADB2B {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return auditResult
return $auditResult

View File

@@ -5,14 +5,12 @@ function Test-SharePointExternalSharingDomains {
# Aligned
# Define your parameters here
)
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.2.6"
Write-Verbose "Running Test-SharePointExternalSharingDomains for $recnum..."
# Conditions for 7.2.6 (L2) Ensure SharePoint external sharing is managed through domain whitelist/blacklists
#
# Validate test for a pass:
@@ -29,13 +27,18 @@ function Test-SharePointExternalSharingDomains {
# - Condition B: The "SharingDomainRestrictionMode" is not set to "AllowList" using PowerShell.
# - Condition C: The "SharingAllowedDomainList" does not contain the domains trusted by the organization for external sharing.
}
process {
try {
# 7.2.6 (L2) Ensure SharePoint external sharing is managed through domain whitelist/blacklists
$SPOTenant = Get-CISSpoOutput -Rec $recnum
# $SPOTenant Mock Object
<#
$SPOTenant = [PSCustomObject]@{
SharingDomainRestrictionMode = "AllowList"
SharingAllowedDomainList = "domain1.com", "domain2.com"
}
#>
$isDomainRestrictionConfigured = $SPOTenant.SharingDomainRestrictionMode -eq 'AllowList'
# Populate the auditResult object with the required properties
$params = @{
Rec = $recnum
@@ -51,7 +54,6 @@ function Test-SharePointExternalSharingDomains {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return auditResult
return $auditResult

View File

@@ -5,14 +5,12 @@ function Test-SharePointGuestsItemSharing {
# Aligned
# Define your parameters here
)
begin {
# Dot source the class script if necessary
#. .\source\Classes\CISAuditResult.ps1
# Initialization code, if needed
$recnum = "7.2.5"
Write-Verbose "Running Test-SharePointGuestsItemSharing for $recnum..."
# Conditions for 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own
#
# Validate test for a pass:
@@ -29,20 +27,24 @@ function Test-SharePointGuestsItemSharing {
# - Condition B: The SharePoint admin center setting "Allow guests to share items they don't own" is checked.
# - Condition C: Ensure that external users can re-share items they don't own.
}
process {
try {
# 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own
# $SPOTenant Mock Object
<#
$SPOTenant = [PSCustomObject]@{
PreventExternalUsersFromResharing = $false
}
#>
$SPOTenant = Get-CISSpoOutput -Rec $recnum
$isGuestResharingPrevented = $SPOTenant.PreventExternalUsersFromResharing
# Populate the auditResult object with the required properties
$params = @{
Rec = $recnum
Result = $isGuestResharingPrevented
Status = if ($isGuestResharingPrevented) { "Pass" } else { "Fail" }
Details = "PreventExternalUsersFromResharing: $isGuestResharingPrevented"
FailureReason = if (-not $isGuestResharingPrevented) { "Guest users can reshare items they don't own." } else { "N/A" }
FailureReason = if (-not $isGuestResharingPrevented) { "Guest users can reshare items they don't own. To prevent external users from resharing content they don't own,`nuse the following command:`nSet-SPOTenant -PreventExternalUsersFromResharing `$True" } else { "N/A" }
}
$auditResult = Initialize-CISAuditResult @params
}
@@ -51,7 +53,6 @@ function Test-SharePointGuestsItemSharing {
$auditResult = Get-TestError -LastError $LastError -recnum $recnum
}
}
end {
# Return auditResult
return $auditResult