From 2fd993dd574d309bc04d2819d31246d7c954b2fa Mon Sep 17 00:00:00 2001 From: Henrik Piecha Date: Mon, 9 Feb 2026 12:24:23 +0100 Subject: [PATCH 01/31] Added CIS M365v5 SPO tests --- powershell/Maester.psd1 | 3 +- .../maester/spo/Test-MtSpoB2BIntegration.md | 13 ++++++ .../maester/spo/Test-MtSpoB2BIntegration.ps1 | 39 ++++++++++++++++ ...poCustomScriptExecutionOnSiteCollection.md | 21 +++++++++ ...oCustomScriptExecutionOnSiteCollection.ps1 | 45 +++++++++++++++++++ .../spo/Test-MtSpoDefaultSharingLink.md | 13 ++++++ .../spo/Test-MtSpoDefaultSharingLink.ps1 | 37 +++++++++++++++ .../Test-MtSpoDefaultSharingLinkPermission.md | 12 +++++ ...Test-MtSpoDefaultSharingLinkPermission.ps1 | 37 +++++++++++++++ .../spo/Test-MtSpoGuestAccessExpiry.md | 18 ++++++++ .../spo/Test-MtSpoGuestAccessExpiry.ps1 | 38 ++++++++++++++++ .../Test-MtSpoGuestCannotShareUnownedItem.md | 16 +++++++ .../Test-MtSpoGuestCannotShareUnownedItem.ps1 | 37 +++++++++++++++ .../Test-MtSpoPreventDownloadMaliciousFile.md | 15 +++++++ ...Test-MtSpoPreventDownloadMaliciousFile.ps1 | 37 +++++++++++++++ tests/Maester/Spo/Test-SpoTenant.Tests.ps1 | 44 ++++++++++++++++++ tests/maester-config.json | 35 +++++++++++++++ website/docs/tests/maester/MT.1113.md | 19 ++++++++ website/docs/tests/maester/MT.1114.md | 29 ++++++++++++ website/docs/tests/maester/MT.1115.md | 21 +++++++++ website/docs/tests/maester/MT.1116.md | 20 +++++++++ website/docs/tests/maester/MT.1117.md | 26 +++++++++++ website/docs/tests/maester/MT.1118.md | 24 ++++++++++ website/docs/tests/maester/MT.1119.md | 23 ++++++++++ 24 files changed, 621 insertions(+), 1 deletion(-) create mode 100644 powershell/public/maester/spo/Test-MtSpoB2BIntegration.md create mode 100644 powershell/public/maester/spo/Test-MtSpoB2BIntegration.ps1 create mode 100644 powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.md create mode 100644 powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 create mode 100644 powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.md create mode 100644 powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 create mode 100644 powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.md create mode 100644 powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 create mode 100644 powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.md create mode 100644 powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 create mode 100644 powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.md create mode 100644 powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 create mode 100644 powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.md create mode 100644 powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 create mode 100644 tests/Maester/Spo/Test-SpoTenant.Tests.ps1 create mode 100644 website/docs/tests/maester/MT.1113.md create mode 100644 website/docs/tests/maester/MT.1114.md create mode 100644 website/docs/tests/maester/MT.1115.md create mode 100644 website/docs/tests/maester/MT.1116.md create mode 100644 website/docs/tests/maester/MT.1117.md create mode 100644 website/docs/tests/maester/MT.1118.md create mode 100644 website/docs/tests/maester/MT.1119.md diff --git a/powershell/Maester.psd1 b/powershell/Maester.psd1 index 2f2cac855..e3b31ba02 100644 --- a/powershell/Maester.psd1 +++ b/powershell/Maester.psd1 @@ -186,7 +186,8 @@ 'Test-MtXspmCriticalCredsOnDevicesWithNonCriticalAccounts', 'Test-MtXspmPublicRemotelyExploitableHighExposureDevices', 'Test-MtXspmCriticalCredentialsOnNonTpmProtectedDevices', - 'Test-MtXspmCriticalCredentialsOnNonCredGuardProtectedDevices' + 'Test-MtXspmCriticalCredentialsOnNonCredGuardProtectedDevices', + 'Test-MtSpoB2BIntegration', 'Test-MtSpoCustomScriptExecutionOnSiteCollection', 'Test-MtSpoDefaultSharingLink', 'Test-MtSpoDefaultSharingLinkPermission', 'Test-MtSpoGuestAccessExpiry', 'Test-MtSpoGuestCannotShareUnownedItem', 'Test-MtSpoPreventDownloadMaliciousFile' # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() diff --git a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md new file mode 100644 index 000000000..e9f48f6f8 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md @@ -0,0 +1,13 @@ +7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled + +Before integration SharePoint Online with Microsoft Entra B2B external users authenticated via one-time passcode, directly to SharePoint. +This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitoring in Auditing-logs. + +With SharePoint and OneDrive integrated with Microsoft Entra B2B Invitation Manager, invited people outside the organization are each given a guest account in the directory and are subject to Microsoft Entra ID access policies such as conditional access. +Invitations to a SharePoint site use Microsoft Entra B2B and no longer require users to have or create a personal Microsoft account. + +## Related Links + +* [SharePoint and OneDrive integration with Microsoft Entra B2B | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/sharepoint-azureb2b-integration) +* [Secure external sharing recipient experience | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/what-s-new-in-sharing-in-targeted-release) +* CIS 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.ps1 b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.ps1 new file mode 100644 index 000000000..74408aa37 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.ps1 @@ -0,0 +1,39 @@ +<# +.SYNOPSIS + Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing. + +.DESCRIPTION + Microsoft Entra B2B integration allows you to manage external sharing in SharePoint Online using Microsoft Entra. With this integration, you can use Microsoft Entra to control access to your SharePoint Online resources, including sites, lists, and libraries. This provides a more secure and streamlined way to manage external sharing in SharePoint Online. + When Microsoft Entra B2B integration is enabled, you can use Microsoft Entra to create and manage guest users, assign permissions, and monitor access to your SharePoint Online resources. This allows you to have better control over who can access your SharePoint Online resources and what they can do with them. + The recommended state is EnableAzureADB2BIntegration set to $true. + +.EXAMPLE + Test-MtSpoB2BIntegration + + Returns true if the SharePoint tenant is integrated with Microsoft Entra B2B, false otherwise. + +.LINK + https://maester.dev/docs/commands/Test-MtSpoB2BIntegration +#> +function Test-MtSpoB2BIntegration { + [CmdletBinding()] + [OutputType([bool])] + param() + Write-Verbose "Testing SharePoint Entra B2B integration..." + + $return = $true + try { + $B2BIntegration = Get-SPOTenant | Select-Object -ExpandProperty EnableAzureADB2BIntegration + if ($B2BIntegration) { + $testResult = "Well done. Your SharePoint tenant is integrated with Microsoft Entra B2B." + } else { + $testResult = "Your SharePoint tenant is not integrated with Microsoft Entra B2B." + $return = $false + } + Add-MtTestResultDetail -Result $testResult + return $return + } catch { + Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ + return $null + } +} \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.md b/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.md new file mode 100644 index 000000000..0e3120c8d --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.md @@ -0,0 +1,21 @@ +7.3.4 (L1) Ensure custom script execution is restricted on site collections + +Description: +This setting controls custom script execution on a particular site (previously called "site collection"). +Custom scripts can allow users to change the look, feel and behavior of sites and pages. Every script that runs in a SharePoint page (whether it's an HTML page in a document library or a JavaScript in a Script Editor Web Part) always runs in the context of the user visiting the page and the SharePoint application. This means: +* Scripts have access to everything the user has access to. +* Scripts can access content across several Microsoft 365 services and even +beyond with Microsoft Graph integration. The recommended state is DenyAddAndCustomizePages set to $true. + +Rationale: +Custom scripts could contain malicious instructions unknown to the user or administrator. When users are allowed to run custom script, the organization can no longer enforce governance, scope the capabilities of inserted code, block specific parts of code, or block all custom code that has been deployed. If scripting is allowed the following things can't be audited: +* What code has been inserted +* Where the code has been inserted +* Who inserted the code + +Note: Microsoft recommends using the SharePoint Framework instead of custom scripts + +## Related Links + +* [Allow or prevent custom script | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script) +* CIS 7.3.4 (L1) Ensure custom script execution is restricted on site collections \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 b/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 new file mode 100644 index 000000000..344771e9f --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 @@ -0,0 +1,45 @@ +<# +.SYNOPSIS + 7.3.4 (L1) Ensure custom script execution is restricted on site collections + +.DESCRIPTION + This setting controls custom script execution on a particular site (previously called "site collection"). + Custom scripts can allow users to change the look, feel and behavior of sites and pages. Every script that runs in a SharePoint page (whether it's an HTML page in a document library or a JavaScript in a Script Editor Web Part) always runs in the context of the user visiting the page and the SharePoint application. This means: + * Scripts have access to everything the user has access to. + * Scripts can access content across several Microsoft 365 services and even beyond with Microsoft Graph integration. The recommended state is DenyAddAndCustomizePages set to $true. + +.EXAMPLE + Test-MtSpoCustomScriptExecutionOnSiteCollection + + Returns true if custom script execution is restricted on all site collections, false otherwise. + +.LINK + https://maester.dev/docs/commands/Test-MtSpoCustomScriptExecutionOnSiteCollection +#> +function Test-MtSpoCustomScriptExecutionOnSiteCollection { + [CmdletBinding()] + [OutputType([bool])] + param() + Write-Verbose "Testing default sharing link type in SharePoint Online..." + + $return = $true + try { + $noncompliantSites = Get-SPOSite | Where-Object { $_.DenyAddAndCustomizePages -eq "Disabled" -and $_.Url -notlike "*-my.sharepoint.com/" } + if ($noncompliantSites | Measure-Object | Select-Object -ExpandProperty Count -eq 0) { + $testResult = "Well done. Custom script execution is restricted on all site collections." + } else { + $result = "Title | URL | DenyAddAndCustomizePages |`n" + $result += "--- | --- | --- |`n" + foreach ($site in $noncompliantSites) { + $result += "$($site.Title) | $($site.Url) | $($site.DenyAddAndCustomizePages) |`n" + } + $testResult = "Custom script execution is not restricted on the following site collections:`n`n$($result)" + $return = $false + } + Add-MtTestResultDetail -Result $testResult + return $return + } catch { + Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ + return $null + } +} \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.md b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.md new file mode 100644 index 000000000..9536db153 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.md @@ -0,0 +1,13 @@ +7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive + +Description: +This setting sets the default link type that a user will see when sharing content in OneDrive or SharePoint. It does not restrict or exclude any other options. +The recommended state is Specific people (only the people the user specifies) or Only people in your organization (more restrictive). + +Rationale: +By defaulting to specific people, the user will first need to consider whether or not the content being shared should be accessible by the entire organization versus select individuals. This aids in reinforcing the concept of least privilege. + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* CIS 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 new file mode 100644 index 000000000..c8eef8e18 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 @@ -0,0 +1,37 @@ +<# +.SYNOPSIS + 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive + +.DESCRIPTION + By default, the sharing link experience in SharePoint and OneDrive is set to "Anyone with the link". This means that when users share files or folders, the default option allows anyone with the link to access the content, which can lead to unintentional overexposure of sensitive information. By changing the default sharing link type to "Specific people", users are encouraged to be more deliberate about who they share content with, reducing the risk of unauthorized access and supporting a more secure sharing environment. + +.EXAMPLE + Test-MtSpoDefaultSharingLink + + Returns true if the default sharing link type is set to a restrictive option, false otherwise. + +.LINK + https://maester.dev/docs/commands/Test-MtSpoDefaultSharingLink +#> +function Test-MtSpoDefaultSharingLink { + [CmdletBinding()] + [OutputType([bool])] + param() + Write-Verbose "Testing default sharing link type in SharePoint Online..." + + $return = $true + try { + $DefaultSharingLinkType = Get-SPOTenant | Select-Object -ExpandProperty DefaultSharingLinkType + if ($DefaultSharingLinkType -eq "Direct" -or $DefaultSharingLinkType -eq "Internal") { + $testResult = "Well done. Default sharing link type is set to a restrictive option." + } else { + $testResult = "Default sharing link type is not set to a restrictive option." + $return = $false + } + Add-MtTestResultDetail -Result $testResult + return $return + } catch { + Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ + return $null + } +} \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.md b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.md new file mode 100644 index 000000000..0f9496261 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.md @@ -0,0 +1,12 @@ +7.2.11 (L1) Ensure the SharePoint default sharing link permission is set + +Description: +This setting configures the permission that is selected by default for sharing link from a SharePoint site. The recommended state is View. + +Rationale: +Setting the view permission as the default ensures that users must deliberately select the edit permission when sharing a link. This approach reduces the risk of unintentionally granting edit privileges to a resource that only requires read access, supporting the principle of least privilege. + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* CIS 7.2.11 (L1) Ensure the SharePoint default sharing link permission is set \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 new file mode 100644 index 000000000..d4976f039 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 @@ -0,0 +1,37 @@ +<# +.SYNOPSIS + 7.2.11 (L1) Ensure the SharePoint default sharing link permission is set + +.DESCRIPTION + By default, the sharing link permission in SharePoint and OneDrive is set to "Edit". This means that when users share files or folders, the default option allows recipients to edit the content, which can lead to unintentional modifications or deletions of sensitive information. By changing the default sharing link permission to "View", users are encouraged to be more deliberate about granting edit permissions, reducing the risk of unauthorized changes and supporting a more secure sharing environment. + +.EXAMPLE + Test-MtSpoDefaultSharingLinkPermission + + Returns true if the default sharing link permission is set to a restrictive option, false otherwise. + +.LINK + https://maester.dev/docs/commands/Test-MtSpoDefaultSharingLinkPermission +#> +function Test-MtSpoDefaultSharingLinkPermission { + [CmdletBinding()] + [OutputType([bool])] + param() + Write-Verbose "Testing default sharing link permission in SharePoint Online..." + + $return = $true + try { + $DefaultLinkPermission = Get-SPOTenant | Select-Object -ExpandProperty DefaultLinkPermission + if ($DefaultLinkPermission -eq "View") { + $testResult = "Well done. Default sharing link permission is set to View." + } else { + $testResult = "Default sharing link permission is not set to View." + $return = $false + } + Add-MtTestResultDetail -Result $testResult + return $return + } catch { + Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ + return $null + } +} \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.md b/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.md new file mode 100644 index 000000000..9e89028d9 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.md @@ -0,0 +1,18 @@ +7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically + +Description: +This policy setting configures the expiration time for each guest that is invited to the SharePoint site or with whom users share individual files and folders with. +The recommended state is 30 or less. + +Rationale: +This setting ensures that guests who no longer need access to the site or link no longer have access after a set period of time. Allowing guest access for an indefinite amount of time could lead to loss of data confidentiality and oversight. +Note: Guest membership applies at the Microsoft 365 group level. Guests who have permission to view a SharePoint site or use a sharing link may also have access to a Microsoft Teams team or security group. + +Impact: +Site collection administrators will have to renew access to guests who still need access after 30 days. They will receive an e-mail notification once per week about guest access that is about to expire. +**Note:** The guest expiration policy only applies to guests who use sharing links or guests who have direct permissions to a SharePoint site after the guest policy is enabled. The guest policy does not apply to guest users that have pre-existing permissions or access through a sharing link before the guest expiration policy is applied + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* CIS 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 b/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 new file mode 100644 index 000000000..21a4c3f08 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 @@ -0,0 +1,38 @@ +<# +.SYNOPSIS + 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically + +.DESCRIPTION + By default, guest access to a SharePoint site or OneDrive does not expire. + This means that once a guest user is granted access to a site or OneDrive, they will have indefinite access until manually removed by an administrator. Enabling automatic expiration of guest access helps to ensure that external users do not retain access to sensitive information longer than necessary, reducing the risk of unauthorized access and supporting a more secure sharing environment. The recommended state is to enable guest access expiration and set it to 30 days or less. + +.EXAMPLE + Test-MtSpoGuestAccessExpiry + + Returns true if guest access expiration is enabled and set to 30 days or less, false otherwise. + +.LINK + https://maester.dev/docs/commands/Test-MtSpoGuestAccessExpiry +#> +function Test-MtSpoGuestAccessExpiry { + [CmdletBinding()] + [OutputType([bool])] + param() + Write-Verbose "Testing guest access expiration settings in SharePoint Online..." + + $return = $true + try { + $spoTenant = Get-SPOTenant + if ($spoTenant.ExternalUserExpirationRequired -eq $true -and $spoTenant.ExternalUserExpireInDays -le 30) { + $testResult = "Well done. Guest access expiration is enabled and set to 30 days or less ($($spoTenant.ExternalUserExpireInDays) days)." + } else { + $testResult = "Guest access expiration is not enabled or set to more than 30 days." + $return = $false + } + Add-MtTestResultDetail -Result $testResult + return $return + } catch { + Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ + return $null + } +} \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.md b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.md new file mode 100644 index 000000000..c0afcd9e6 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.md @@ -0,0 +1,16 @@ +7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own + +Description: +SharePoint gives users the ability to share files, folders, and site collections. Internal users can share with external collaborators, and with the right permissions could share to other external parties. + +Rationale: +Sharing and collaboration are key; however, file, folder, or site collection owners should have the authority over what external users get shared with to prevent unauthorized disclosures of information. + +Impact: +The impact associated with this change is highly dependent upon current practices. If users do not regularly share with external parties, then minimal impact is likely. +However, if users do regularly share with guests/externally, minimum impacts could occur as those external users will be unable to 're-share' content. + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* CIS 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 new file mode 100644 index 000000000..ce68a56ce --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 @@ -0,0 +1,37 @@ +<# +.SYNOPSIS + Ensure that SharePoint guest users cannot share items they don't own + +.DESCRIPTION + By default, external users can share items they don't own. This means that if a guest user has access to an item, they can share it with others, potentially leading to unauthorized access and data leaks. By preventing external users from resharing items they don't own, you can help protect sensitive information and maintain better control over who has access to your SharePoint resources. The recommended state is PreventExternalUsersFromResharing set to $true. + +.EXAMPLE + Test-MtSpoGuestCannotShareUnownedItem + + Returns true if the SharePoint tenant is integrated with Microsoft Entra B2B, false otherwise. + +.LINK + https://maester.dev/docs/commands/Test-MtSpoGuestCannotShareUnownedItem +#> +function Test-MtSpoGuestCannotShareUnownedItem { + [CmdletBinding()] + [OutputType([bool])] + param() + Write-Verbose "Testing that SharePoint guest users cannot share items they don't own..." + + $return = $true + try { + $PreventExternalUsersFromResharing = Get-SPOTenant | Select-Object -ExpandProperty PreventExternalUsersFromResharing + if ($PreventExternalUsersFromResharing) { + $testResult = "Well done. External users cannot share items they don't own." + } else { + $testResult = "External users can share items they don't own." + $return = $false + } + Add-MtTestResultDetail -Result $testResult + return $return + } catch { + Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ + return $null + } +} \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.md b/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.md new file mode 100644 index 000000000..fc18b40e2 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.md @@ -0,0 +1,15 @@ +7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download + +Description: +By default, SharePoint online allows files that Defender for Office 365 has detected as infected to be downloaded. + +Rationale: +Defender for Office 365 for SharePoint, OneDrive, and Microsoft Teams protects your organization from inadvertently sharing malicious files. When an infected file is detected that file is blocked so that no one can open, copy, move, or share it until further actions are taken by the organization's security team. + +Impact: +The only potential impact associated with implementation of this setting is potential inconvenience associated with the small percentage of false positive detections that may occur. + +## Related Links + +* [Safe Attachments for SharePoint, OneDrive, and Microsoft Teams](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-configure?view=o365-worldwide#step-2-recommended-use-sharepoint-online-powershell-to-prevent-users-from-downloading-malicious-files) +* CIS 7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 b/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 new file mode 100644 index 000000000..4834c90c9 --- /dev/null +++ b/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 @@ -0,0 +1,37 @@ +<# +.SYNOPSIS + Ensure malicious file download prevention is Enabled in SharePoint Online + +.DESCRIPTION + By default, users can't open, move, copy, or share* malicious files that are detected by Safe Attachments for SharePoint, OneDrive, and Microsoft Teams. However, they can delete and download malicious files. + +.EXAMPLE + Test-MtSpoPreventDownloadMaliciousFile + + Returns true if malicious file download prevention is enabled in your SharePoint tenant, false otherwise. + +.LINK + https://maester.dev/docs/commands/Test-MtSpoPreventDownloadMaliciousFile + #> +function Test-MtSpoPreventDownloadMaliciousFile { + [CmdletBinding()] + [OutputType([bool])] + param() + Write-Verbose "Testing malicious file download prevention in SharePoint Online..." + + $return = $true + try { + $DisallowInfectedFileDownload = Get-SPOTenant | Select-Object -ExpandProperty DisallowInfectedFileDownload + if ($DisallowInfectedFileDownload) { + $testResult = "Well done. Malicious file download prevention is enabled in your SharePoint tenant." + } else { + $testResult = "Malicious file download prevention is not enabled in your SharePoint tenant." + $return = $false + } + Add-MtTestResultDetail -Result $testResult + return $return + } catch { + Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ + return $null + } +} \ No newline at end of file diff --git a/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 b/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 new file mode 100644 index 000000000..ac1c0fdc4 --- /dev/null +++ b/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 @@ -0,0 +1,44 @@ +Describe 'Maester/SpoTenant' -Tag 'Maester', 'SpoTenant' { + It 'MT.1113: Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing.' -Tag 'MT.1113', 'CIS', 'CIS M365v5', 'CIS 7.2.2', 'Severity:Medium' { + $result = Test-MtSpoB2BIntegration + if ($null -ne $result) { + $result | Should -Be $true -Because 'SharePoint tenant is integrated with Microsoft Entra B2B.' + } + } + It 'MT.1114: Ensure custom script execution is restricted on site collections' -Tag 'MT.1114', 'CIS', 'CIS M365v5', 'CIS 7.3.4', 'Severity:Medium' { + $result = Test-MtSpoCustomScriptExecutionOnSiteCollection + if ($null -ne $result) { + $result | Should -Be $true -Because 'custom script execution is restricted on site collections.' + } + } + It 'MT.1115: Ensure link sharing is restricted in SharePoint and OneDrive' -Tag 'MT.1115', 'CIS', 'CIS M365v5', 'CIS 7.2.7', 'Severity:Low' { + $result = Test-MtSpoDefaultSharingLink + if ($null -ne $result) { + $result | Should -Be $true -Because 'link sharing is restricted in SharePoint and OneDrive.' + } + } + It 'MT.1116: Ensure the SharePoint default sharing link permission is set' -Tag 'MT.1116', 'CIS', 'CIS M365v5', 'CIS 7.2.11', 'Severity:Low' { + $result = Test-MtSpoDefaultSharingLinkPermission + if ($null -ne $result) { + $result | Should -Be $true -Because 'the SharePoint default sharing link permission is set.' + } + } + It 'MT.1117: Ensure guest access to a site or OneDrive will expire automatically' -Tag 'MT.1117', 'CIS', 'CIS M365v5', 'CIS 7.2.9', 'Severity:Low' { + $result = Test-MtSpoGuestAccessExpiry + if ($null -ne $result) { + $result | Should -Be $true -Because 'guest access to a site or OneDrive will expire automatically.' + } + } + It 'MT.1118: Ensure that SharePoint guest users cannot share items they dont own' -Tag 'MT.1118', 'CIS', 'CIS M365v5', 'CIS 7.2.5', 'Severity:High' { + $result = Test-MtSpoGuestCannotShareUnownedItem + if ($null -ne $result) { + $result | Should -Be $true -Because 'SharePoint guest users cannot share items they dont own.' + } + } + It 'MT.1119: Ensure Office 365 SharePoint infected files are disallowed for download' -Tag 'MT.1119', 'CIS', 'CIS M365v5', 'CIS 7.3.1', 'Severity:High' { + $result = Test-MtSpoPreventDownloadMaliciousFile + if ($null -ne $result) { + $result | Should -Be $true -Because 'Office 365 SharePoint infected files are disallowed for download.' + } + } +} \ No newline at end of file diff --git a/tests/maester-config.json b/tests/maester-config.json index 7d5b39c63..b47eeec80 100644 --- a/tests/maester-config.json +++ b/tests/maester-config.json @@ -1273,6 +1273,41 @@ "Severity": "Medium", "Title": "Privileged user accounts should not remain enabled when the linked primary account is disabled" }, + { + "Id": "MT.1113", + "Severity": "Medium", + "Title": "Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing." + }, + { + "Id": "MT.1114", + "Severity": "Medium", + "Title": "Ensure custom script execution is restricted on site collections" + }, + { + "Id": "MT.1115", + "Severity": "Low", + "Title": "Ensure link sharing is restricted in SharePoint and OneDrive" + }, + { + "Id": "MT.1116", + "Severity": "Low", + "Title": "Ensure the SharePoint default sharing link permission is set" + }, + { + "Id": "MT.1117", + "Severity": "Low", + "Title": "Ensure guest access to a site or OneDrive will expire automatically" + }, + { + "Id": "MT.1118", + "Severity": "High", + "Title": "Ensure that SharePoint guest users cannot share items they don't own" + }, + { + "Id": "MT.1119", + "Severity": "High", + "Title": "Ensure Office 365 SharePoint infected files are disallowed for download" + }, { "Id": "ORCA.100", "Severity": "Medium", diff --git a/website/docs/tests/maester/MT.1113.md b/website/docs/tests/maester/MT.1113.md new file mode 100644 index 000000000..bdc596dec --- /dev/null +++ b/website/docs/tests/maester/MT.1113.md @@ -0,0 +1,19 @@ +--- +title: MT.1113 - Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing. +description: Microsoft Entra B2B integration allows you to manage external sharing in SharePoint Online using Microsoft Entra. With this integration, you can use Microsoft Entra to control access to your SharePoint Online resources, including sites, lists, and libraries. This provides a more secure and streamlined way to manage external sharing in SharePoint Online. +slug: /tests/MT.1113 +sidebar_class_name: hidden +--- + +## Description +Before integration SharePoint Online with Microsoft Entra B2B external users authenticated via one-time passcode, directly to SharePoint. +This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitoring in Auditing-logs. + +With SharePoint and OneDrive integrated with Microsoft Entra B2B Invitation Manager, invited people outside the organization are each given a guest account in the directory and are subject to Microsoft Entra ID access policies such as conditional access. +Invitations to a SharePoint site use Microsoft Entra B2B and no longer require users to have or create a personal Microsoft account. + +## Related Links + +* [SharePoint and OneDrive integration with Microsoft Entra B2B | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/sharepoint-azureb2b-integration) +* [Secure external sharing recipient experience | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/what-s-new-in-sharing-in-targeted-release) +* CIS 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1114.md b/website/docs/tests/maester/MT.1114.md new file mode 100644 index 000000000..8f5eec158 --- /dev/null +++ b/website/docs/tests/maester/MT.1114.md @@ -0,0 +1,29 @@ +--- +title: MT.1114 - Ensure custom script execution is restricted on site collections +description: Ensure custom script execution is restricted on site collections +slug: /tests/MT.1114 +sidebar_class_name: hidden +--- + +## Description +7.3.4 (L1) Ensure custom script execution is restricted on site collections + +Description: +This setting controls custom script execution on a particular site (previously called "site collection"). +Custom scripts can allow users to change the look, feel and behavior of sites and pages. Every script that runs in a SharePoint page (whether it's an HTML page in a document library or a JavaScript in a Script Editor Web Part) always runs in the context of the user visiting the page and the SharePoint application. This means: +* Scripts have access to everything the user has access to. +* Scripts can access content across several Microsoft 365 services and even +beyond with Microsoft Graph integration. The recommended state is DenyAddAndCustomizePages set to $true. + +Rationale: +Custom scripts could contain malicious instructions unknown to the user or administrator. When users are allowed to run custom script, the organization can no longer enforce governance, scope the capabilities of inserted code, block specific parts of code, or block all custom code that has been deployed. If scripting is allowed the following things can't be audited: +* What code has been inserted +* Where the code has been inserted +* Who inserted the code + +Note: Microsoft recommends using the SharePoint Framework instead of custom scripts + +## Related Links + +* [Allow or prevent custom script | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script) +* CIS 7.3.4 (L1) Ensure custom script execution is restricted on site collections \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1115.md b/website/docs/tests/maester/MT.1115.md new file mode 100644 index 000000000..4bc1a8df0 --- /dev/null +++ b/website/docs/tests/maester/MT.1115.md @@ -0,0 +1,21 @@ +--- +title: MT.1115 - Ensure link sharing is restricted in SharePoint and OneDrive +description: Ensure link sharing is restricted in SharePoint and OneDrive +slug: /tests/MT.1115 +sidebar_class_name: hidden +--- + +## Description +7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive + +Description: +This setting sets the default link type that a user will see when sharing content in OneDrive or SharePoint. It does not restrict or exclude any other options. +The recommended state is Specific people (only the people the user specifies) or Only people in your organization (more restrictive). + +Rationale: +By defaulting to specific people, the user will first need to consider whether or not the content being shared should be accessible by the entire organization versus select individuals. This aids in reinforcing the concept of least privilege. + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* CIS 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1116.md b/website/docs/tests/maester/MT.1116.md new file mode 100644 index 000000000..ca958356a --- /dev/null +++ b/website/docs/tests/maester/MT.1116.md @@ -0,0 +1,20 @@ +--- +title: MT.1116 - Ensure the SharePoint default sharing link permission is set +description: Ensure the SharePoint default sharing link permission is set +slug: /tests/MT.1116 +sidebar_class_name: hidden +--- + +## Description +7.2.11 (L1) Ensure the SharePoint default sharing link permission is set + +Description: +This setting configures the permission that is selected by default for sharing link from a SharePoint site. The recommended state is View. + +Rationale: +Setting the view permission as the default ensures that users must deliberately select the edit permission when sharing a link. This approach reduces the risk of unintentionally granting edit privileges to a resource that only requires read access, supporting the principle of least privilege. + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* CIS 7.2.11 (L1) Ensure the SharePoint default sharing link permission is set \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1117.md b/website/docs/tests/maester/MT.1117.md new file mode 100644 index 000000000..25887dadf --- /dev/null +++ b/website/docs/tests/maester/MT.1117.md @@ -0,0 +1,26 @@ +--- +title: MT.1117 - Ensure guest access to a site or OneDrive will expire automatically +description: Ensure guest access to a site or OneDrive will expire automatically +slug: /tests/MT.1117 +sidebar_class_name: hidden +--- + +## Description +7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically + +Description: +This policy setting configures the expiration time for each guest that is invited to the SharePoint site or with whom users share individual files and folders with. +The recommended state is 30 or less. + +Rationale: +This setting ensures that guests who no longer need access to the site or link no longer have access after a set period of time. Allowing guest access for an indefinite amount of time could lead to loss of data confidentiality and oversight. +Note: Guest membership applies at the Microsoft 365 group level. Guests who have permission to view a SharePoint site or use a sharing link may also have access to a Microsoft Teams team or security group. + +Impact: +Site collection administrators will have to renew access to guests who still need access after 30 days. They will receive an e-mail notification once per week about guest access that is about to expire. +**Note:** The guest expiration policy only applies to guests who use sharing links or guests who have direct permissions to a SharePoint site after the guest policy is enabled. The guest policy does not apply to guest users that have pre-existing permissions or access through a sharing link before the guest expiration policy is applied + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* CIS 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1118.md b/website/docs/tests/maester/MT.1118.md new file mode 100644 index 000000000..ed74ad172 --- /dev/null +++ b/website/docs/tests/maester/MT.1118.md @@ -0,0 +1,24 @@ +--- +title: MT.1118 - Ensure that SharePoint guest users cannot share items they dont own +description: Ensure that SharePoint guest users cannot share items they dont own +slug: /tests/MT.1118 +sidebar_class_name: hidden +--- + +## Description +7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own + +Description: +SharePoint gives users the ability to share files, folders, and site collections. Internal users can share with external collaborators, and with the right permissions could share to other external parties. + +Rationale: +Sharing and collaboration are key; however, file, folder, or site collection owners should have the authority over what external users get shared with to prevent unauthorized disclosures of information. + +Impact: +The impact associated with this change is highly dependent upon current practices. If users do not regularly share with external parties, then minimal impact is likely. +However, if users do regularly share with guests/externally, minimum impacts could occur as those external users will be unable to 're-share' content. + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* CIS 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1119.md b/website/docs/tests/maester/MT.1119.md new file mode 100644 index 000000000..4b052193b --- /dev/null +++ b/website/docs/tests/maester/MT.1119.md @@ -0,0 +1,23 @@ +--- +title: MT.1119 - Ensure Office 365 SharePoint infected files are disallowed for download +description: Ensure Office 365 SharePoint infected files are disallowed for download +slug: /tests/MT.1119 +sidebar_class_name: hidden +--- + +## Description +7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download + +Description: +By default, SharePoint online allows files that Defender for Office 365 has detected as infected to be downloaded. + +Rationale: +Defender for Office 365 for SharePoint, OneDrive, and Microsoft Teams protects your organization from inadvertently sharing malicious files. When an infected file is detected that file is blocked so that no one can open, copy, move, or share it until further actions are taken by the organization's security team. + +Impact: +The only potential impact associated with implementation of this setting is potential inconvenience associated with the small percentage of false positive detections that may occur. + +## Related Links + +* [Safe Attachments for SharePoint, OneDrive, and Microsoft Teams](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-configure?view=o365-worldwide#step-2-recommended-use-sharepoint-online-powershell-to-prevent-users-from-downloading-malicious-files) +* CIS 7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download \ No newline at end of file From 76e88b38b1c89153d97336578bb2a21041fe8521 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:13:52 -0500 Subject: [PATCH 02/31] Update powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 index c8eef8e18..2a49883ea 100644 --- a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 +++ b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 @@ -28,7 +28,7 @@ function Test-MtSpoDefaultSharingLink { $testResult = "Default sharing link type is not set to a restrictive option." $return = $false } - Add-MtTestResultDetail -Result $testResult + Add-MtTestResultDetail -Result $testResult return $return } catch { Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ From ac83443d56db4a3325fe9c8f99253dfd0c5d0ffb Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:14:43 -0500 Subject: [PATCH 03/31] Update powershell/public/maester/spo/Test-MtSpoB2BIntegration.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- powershell/public/maester/spo/Test-MtSpoB2BIntegration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md index e9f48f6f8..d77ca3fb5 100644 --- a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md +++ b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md @@ -1,6 +1,6 @@ 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled -Before integration SharePoint Online with Microsoft Entra B2B external users authenticated via one-time passcode, directly to SharePoint. +Before integrating SharePoint Online with Microsoft Entra B2B, external users authenticated via one-time passcode connect directly to SharePoint. This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitoring in Auditing-logs. With SharePoint and OneDrive integrated with Microsoft Entra B2B Invitation Manager, invited people outside the organization are each given a guest account in the directory and are subject to Microsoft Entra ID access policies such as conditional access. From f7dd0704c2d65f5004acc3e37f1ff40a07195e13 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:15:17 -0500 Subject: [PATCH 04/31] Update website/docs/tests/maester/MT.1113.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- website/docs/tests/maester/MT.1113.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/tests/maester/MT.1113.md b/website/docs/tests/maester/MT.1113.md index bdc596dec..7654aa566 100644 --- a/website/docs/tests/maester/MT.1113.md +++ b/website/docs/tests/maester/MT.1113.md @@ -6,7 +6,7 @@ sidebar_class_name: hidden --- ## Description -Before integration SharePoint Online with Microsoft Entra B2B external users authenticated via one-time passcode, directly to SharePoint. +Before integrating SharePoint Online with Microsoft Entra B2B, external users authenticated via one-time passcode, directly to SharePoint. This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitoring in Auditing-logs. With SharePoint and OneDrive integrated with Microsoft Entra B2B Invitation Manager, invited people outside the organization are each given a guest account in the directory and are subject to Microsoft Entra ID access policies such as conditional access. From 786916505c05876f864efcd79a8c448c42878587 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 17 Feb 2026 13:15:42 -0500 Subject: [PATCH 05/31] Update website/docs/tests/maester/MT.1118.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- website/docs/tests/maester/MT.1118.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/tests/maester/MT.1118.md b/website/docs/tests/maester/MT.1118.md index ed74ad172..2c7785baf 100644 --- a/website/docs/tests/maester/MT.1118.md +++ b/website/docs/tests/maester/MT.1118.md @@ -1,6 +1,6 @@ --- -title: MT.1118 - Ensure that SharePoint guest users cannot share items they dont own -description: Ensure that SharePoint guest users cannot share items they dont own +title: MT.1118 - Ensure that SharePoint guest users cannot share items they don't own +description: Ensure that SharePoint guest users cannot share items they don't own slug: /tests/MT.1118 sidebar_class_name: hidden --- From 5c88be688ae82b55129bfd407381b0cef5bebbd1 Mon Sep 17 00:00:00 2001 From: Henrik Piecha Date: Mon, 2 Mar 2026 09:36:55 +0100 Subject: [PATCH 06/31] changed invoke logic for spo tests --- powershell/public/Connect-Maester.ps1 | 32 ++++++++++++- ...poCustomScriptExecutionOnSiteCollection.md | 21 --------- ...oCustomScriptExecutionOnSiteCollection.ps1 | 45 ------------------- .../Test-MtSpoGuestCannotShareUnownedItem.ps1 | 2 +- tests/Maester/Spo/Test-SpoTenant.Tests.ps1 | 36 +++++++++++++-- website/docs/installation.md | 4 ++ 6 files changed, 68 insertions(+), 72 deletions(-) delete mode 100644 powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.md delete mode 100644 powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index 16ed5aa49..a7d71cf18 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -104,7 +104,7 @@ [string]$TeamsEnvironmentName = $null, #ToValidate: Don't use this parameter, this is the default. # The services to connect to such as Azure and EXO. Default is Graph. - [ValidateSet('All', 'Azure', 'ExchangeOnline', 'Graph', 'SecurityCompliance', 'Teams')] + [ValidateSet('All', 'Azure', 'ExchangeOnline', 'Graph', 'SecurityCompliance', 'Teams', 'SharePointOnline')] [string[]]$Service = 'Graph', # The Tenant ID to connect to, if not specified the sign-in user's default tenant is used. @@ -116,7 +116,7 @@ $__MtSession.Connections = $Service - $OrderedImport = Get-ModuleImportOrder -Name @('Az.Accounts', 'ExchangeOnlineManagement', 'Microsoft.Graph.Authentication', 'MicrosoftTeams') + $OrderedImport = Get-ModuleImportOrder -Name @('Az.Accounts', 'ExchangeOnlineManagement', 'Microsoft.Graph.Authentication', 'MicrosoftTeams', 'Microsoft.Online.SharePoint.PowerShell') switch ($OrderedImport.Name) { 'Az.Accounts' { @@ -289,6 +289,34 @@ } } } + + 'Microsoft.Online.SharePoint.PowerShell' { + if ($Service -contains 'SharePointOnline' -or $Service -contains 'All') { + if ( + ( $PSVersionTable.OS -match "Windows" -or [System.Environment]::OSVersion.VersionString -match "Windows" ) -and + ( $PSVersionTable.PSVersion.Major -eq 5 ) -and + ( Get-MtUserInteractive ) + ) { + Write-Verbose 'Connecting to SharePoint Online' + try { + $tenantDomain = Read-Host -Prompt "Conencting to SharePoint Online requires the onmicrosoft.com domain name of your tenant. Please enter the tenant domain (e.g. contoso.onmicrosoft.com)" + if ($tenantDomain -notmatch "^[\w-]+\.onmicrosoft\.com$") { + Write-Host "The tenant domain must be in the format contoso.onmicrosoft.com" -ForegroundColor Red + return + } + $spoUri = "https://$(($tenantDomain).Replace(".onmicrosoft.com",$null))-admin.sharepoint.com" + Connect-SpoService -Url $spoUri -UseSystemBrowser $true + } catch [Management.Automation.CommandNotFoundException] { + Write-Host "`nThe SharePoint Online PowerShell module is not installed or imported. Please install and import the module using the following command. For more information see https://learn.microsoft.com/en-us/powershell/module/microsoft.online.sharepoint.powershell/connect-sposervice" -ForegroundColor Red + Write-Host "`Install-Module Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser`n" -ForegroundColor Yellow + Write-Host "`Import-Module Microsoft.Online.SharePoint.PowerShell`n" -ForegroundColor Yellow + } + } else { + Write-Host "`nThe SharePoint Online PowerShell module is currently limited in its functionality and can only be used on interactive sessions on a Windows machine with PowerShell 5" -ForegroundColor Red + Write-Host "Please connect to SharePoint Online using Connect-SpoService in a separate PowerShell session." -ForegroundColor Yellow + } + } + } } # end switch OrderedImport } # end function Connect-Maester diff --git a/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.md b/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.md deleted file mode 100644 index 0e3120c8d..000000000 --- a/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.md +++ /dev/null @@ -1,21 +0,0 @@ -7.3.4 (L1) Ensure custom script execution is restricted on site collections - -Description: -This setting controls custom script execution on a particular site (previously called "site collection"). -Custom scripts can allow users to change the look, feel and behavior of sites and pages. Every script that runs in a SharePoint page (whether it's an HTML page in a document library or a JavaScript in a Script Editor Web Part) always runs in the context of the user visiting the page and the SharePoint application. This means: -* Scripts have access to everything the user has access to. -* Scripts can access content across several Microsoft 365 services and even -beyond with Microsoft Graph integration. The recommended state is DenyAddAndCustomizePages set to $true. - -Rationale: -Custom scripts could contain malicious instructions unknown to the user or administrator. When users are allowed to run custom script, the organization can no longer enforce governance, scope the capabilities of inserted code, block specific parts of code, or block all custom code that has been deployed. If scripting is allowed the following things can't be audited: -* What code has been inserted -* Where the code has been inserted -* Who inserted the code - -Note: Microsoft recommends using the SharePoint Framework instead of custom scripts - -## Related Links - -* [Allow or prevent custom script | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script) -* CIS 7.3.4 (L1) Ensure custom script execution is restricted on site collections \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 b/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 deleted file mode 100644 index 344771e9f..000000000 --- a/powershell/public/maester/spo/Test-MtSpoCustomScriptExecutionOnSiteCollection.ps1 +++ /dev/null @@ -1,45 +0,0 @@ -<# -.SYNOPSIS - 7.3.4 (L1) Ensure custom script execution is restricted on site collections - -.DESCRIPTION - This setting controls custom script execution on a particular site (previously called "site collection"). - Custom scripts can allow users to change the look, feel and behavior of sites and pages. Every script that runs in a SharePoint page (whether it's an HTML page in a document library or a JavaScript in a Script Editor Web Part) always runs in the context of the user visiting the page and the SharePoint application. This means: - * Scripts have access to everything the user has access to. - * Scripts can access content across several Microsoft 365 services and even beyond with Microsoft Graph integration. The recommended state is DenyAddAndCustomizePages set to $true. - -.EXAMPLE - Test-MtSpoCustomScriptExecutionOnSiteCollection - - Returns true if custom script execution is restricted on all site collections, false otherwise. - -.LINK - https://maester.dev/docs/commands/Test-MtSpoCustomScriptExecutionOnSiteCollection -#> -function Test-MtSpoCustomScriptExecutionOnSiteCollection { - [CmdletBinding()] - [OutputType([bool])] - param() - Write-Verbose "Testing default sharing link type in SharePoint Online..." - - $return = $true - try { - $noncompliantSites = Get-SPOSite | Where-Object { $_.DenyAddAndCustomizePages -eq "Disabled" -and $_.Url -notlike "*-my.sharepoint.com/" } - if ($noncompliantSites | Measure-Object | Select-Object -ExpandProperty Count -eq 0) { - $testResult = "Well done. Custom script execution is restricted on all site collections." - } else { - $result = "Title | URL | DenyAddAndCustomizePages |`n" - $result += "--- | --- | --- |`n" - foreach ($site in $noncompliantSites) { - $result += "$($site.Title) | $($site.Url) | $($site.DenyAddAndCustomizePages) |`n" - } - $testResult = "Custom script execution is not restricted on the following site collections:`n`n$($result)" - $return = $false - } - Add-MtTestResultDetail -Result $testResult - return $return - } catch { - Add-MtTestResultDetail -SkippedBecause Error -SkippedError $_ - return $null - } -} \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 index ce68a56ce..2a122b436 100644 --- a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 @@ -25,7 +25,7 @@ function Test-MtSpoGuestCannotShareUnownedItem { if ($PreventExternalUsersFromResharing) { $testResult = "Well done. External users cannot share items they don't own." } else { - $testResult = "External users can share items they don't own." + $testResult = "External users can share items they dont own." $return = $false } Add-MtTestResultDetail -Result $testResult diff --git a/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 b/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 index ac1c0fdc4..71e02d449 100644 --- a/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 +++ b/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 @@ -1,4 +1,34 @@ -Describe 'Maester/SpoTenant' -Tag 'Maester', 'SpoTenant' { +BeforeDiscovery { + + # Check for prerequisite before running the tests. If the prerequisites are not met, return $null to skip the tests. + # Following checks are performed to to current limitations of the Microsoft.Online.SharePoint.PowerShell module: + # - Run on Windows OS + # - Run in PowerShell 5 not 7 + # - Check if the module is installed and loaded + # - Check if the user is connected to SharePoint Online with Connect-SpoService + if (-not ($PSVersionTable.OS -match "Windows" -or [System.Environment]::OSVersion.VersionString -match "Windows")) { + Write-Host "SharePoint Online tests can only be run on Windows OS. Skipping tests..." -ForegroundColor Yellow + return $null + } + if ($PSVersionTable.PSVersion.Major -ne 5) { + Write-Host "SharePoint Online tests can only be run in PowerShell 5. Skipping tests..." -ForegroundColor Yellow + return $null + } + if (-not (Get-Module -Name Microsoft.Online.SharePoint.PowerShell -ListAvailable)) { + Write-Host "Microsoft.Online.SharePoint.PowerShell module is not installed. Skipping tests..." -ForegroundColor Yellow + return $null + } + if (-not (Get-Module -Name Microsoft.Online.SharePoint.PowerShell)) { + Write-Host "Microsoft.Online.SharePoint.PowerShell module is not imported. Skipping tests..." -ForegroundColor Yellow + return $null + } + if (-not (Get-SpoTenant)) { + Write-Host "Not connected to SharePoint Online. Please connect using Connect-SpoService before running the tests. Skipping tests..." -ForegroundColor Yellow + return $null + } +} + +Describe 'Maester/SpoTenant' -Tag 'Maester', 'SpoTenant' { It 'MT.1113: Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing.' -Tag 'MT.1113', 'CIS', 'CIS M365v5', 'CIS 7.2.2', 'Severity:Medium' { $result = Test-MtSpoB2BIntegration if ($null -ne $result) { @@ -29,10 +59,10 @@ $result | Should -Be $true -Because 'guest access to a site or OneDrive will expire automatically.' } } - It 'MT.1118: Ensure that SharePoint guest users cannot share items they dont own' -Tag 'MT.1118', 'CIS', 'CIS M365v5', 'CIS 7.2.5', 'Severity:High' { + It "MT.1118: Ensure that SharePoint guest users cannot share items they don't own" -Tag 'MT.1118', 'CIS', 'CIS M365v5', 'CIS 7.2.5', 'Severity:High' { $result = Test-MtSpoGuestCannotShareUnownedItem if ($null -ne $result) { - $result | Should -Be $true -Because 'SharePoint guest users cannot share items they dont own.' + $result | Should -Be $true -Because "SharePoint guest users cannot share items they don't own." } } It 'MT.1119: Ensure Office 365 SharePoint infected files are disallowed for download' -Tag 'MT.1119', 'CIS', 'CIS M365v5', 'CIS 7.3.1', 'Severity:High' { diff --git a/website/docs/installation.md b/website/docs/installation.md index cc88b7f3b..2f43605b9 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -35,9 +35,11 @@ Maester includes optional [CISA](tests/cisa/) tests that require additional perm Install-Module Az.Accounts -Scope CurrentUser Install-Module ExchangeOnlineManagement -Scope CurrentUser Install-Module MicrosoftTeams -Scope CurrentUser +Install-Module Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser ``` > The Security & Compliance PowerShell module is dependent on the ExchangeOnlineManagement `Connect-IPPSSession` cmdlet. +> The Microsoft.Online.SharePoint.PowerShell module is currently limited in its functionality and can only be used on a Windows machine with PowerShell 5. ### Connecting to Azure, Exchange and other services @@ -58,6 +60,8 @@ Exchange Online implements a [role-based access control model](https://learn.mic * View-Only Configuration OR * O365SupportViewConfig +SharePoint Online requires the user to be at least a SharePoint Administrator to connect and run the tests that interact with SharePoint Online Powershell. + ## Next Steps - Monitoring with Maester From ff612849cc553520809abe6b095d1502ead1d7b9 Mon Sep 17 00:00:00 2001 From: Henrik Piecha Date: Mon, 2 Mar 2026 09:46:37 +0100 Subject: [PATCH 07/31] removed test that has been flagged as obsolet by cis --- tests/Maester/Spo/Test-SpoTenant.Tests.ps1 | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 b/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 index 71e02d449..0a045aa35 100644 --- a/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 +++ b/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 @@ -35,10 +35,10 @@ Describe 'Maester/SpoTenant' -Tag 'Maester', 'SpoTenant' { $result | Should -Be $true -Because 'SharePoint tenant is integrated with Microsoft Entra B2B.' } } - It 'MT.1114: Ensure custom script execution is restricted on site collections' -Tag 'MT.1114', 'CIS', 'CIS M365v5', 'CIS 7.3.4', 'Severity:Medium' { - $result = Test-MtSpoCustomScriptExecutionOnSiteCollection + It 'MT.1114: Ensure Office 365 SharePoint infected files are disallowed for download' -Tag 'MT.1114', 'CIS', 'CIS M365v5', 'CIS 7.3.1', 'Severity:High' { + $result = Test-MtSpoPreventDownloadMaliciousFile if ($null -ne $result) { - $result | Should -Be $true -Because 'custom script execution is restricted on site collections.' + $result | Should -Be $true -Because 'Office 365 SharePoint infected files are disallowed for download.' } } It 'MT.1115: Ensure link sharing is restricted in SharePoint and OneDrive' -Tag 'MT.1115', 'CIS', 'CIS M365v5', 'CIS 7.2.7', 'Severity:Low' { @@ -65,10 +65,5 @@ Describe 'Maester/SpoTenant' -Tag 'Maester', 'SpoTenant' { $result | Should -Be $true -Because "SharePoint guest users cannot share items they don't own." } } - It 'MT.1119: Ensure Office 365 SharePoint infected files are disallowed for download' -Tag 'MT.1119', 'CIS', 'CIS M365v5', 'CIS 7.3.1', 'Severity:High' { - $result = Test-MtSpoPreventDownloadMaliciousFile - if ($null -ne $result) { - $result | Should -Be $true -Because 'Office 365 SharePoint infected files are disallowed for download.' - } - } + } \ No newline at end of file From f3dcbedcb3e12af60ab3e68ebc2dd2fe6e72dd6e Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:07:32 -0400 Subject: [PATCH 08/31] Update powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 b/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 index 21a4c3f08..61db94791 100644 --- a/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 +++ b/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 @@ -23,7 +23,7 @@ function Test-MtSpoGuestAccessExpiry { $return = $true try { $spoTenant = Get-SPOTenant - if ($spoTenant.ExternalUserExpirationRequired -eq $true -and $spoTenant.ExternalUserExpireInDays -le 30) { + if ($spoTenant.ExternalUserExpirationRequired -eq $true -and $spoTenant.ExternalUserExpireInDays -gt 0 -and $spoTenant.ExternalUserExpireInDays -le 30) { $testResult = "Well done. Guest access expiration is enabled and set to 30 days or less ($($spoTenant.ExternalUserExpireInDays) days)." } else { $testResult = "Guest access expiration is not enabled or set to more than 30 days." From 772b7c007993dcf3e394d93ae5b2fe98c2ae282a Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:08:54 -0400 Subject: [PATCH 09/31] Update powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 index 2a122b436..625b83357 100644 --- a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 @@ -21,7 +21,7 @@ function Test-MtSpoGuestCannotShareUnownedItem { $return = $true try { - $PreventExternalUsersFromResharing = Get-SPOTenant | Select-Object -ExpandProperty PreventExternalUsersFromResharing + $PreventExternalUsersFromResharing = Get-SPOTenant | Select-Object -ExpandProperty PreventExternalUsersFromResharing if ($PreventExternalUsersFromResharing) { $testResult = "Well done. External users cannot share items they don't own." } else { From 6850f8ecfe2c7d5d1d296cb7b6030d585aab5f9d Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:09:12 -0400 Subject: [PATCH 10/31] Update powershell/public/maester/spo/Test-MtSpoB2BIntegration.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- powershell/public/maester/spo/Test-MtSpoB2BIntegration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md index d77ca3fb5..54cd68267 100644 --- a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md +++ b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md @@ -1,7 +1,7 @@ 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled Before integrating SharePoint Online with Microsoft Entra B2B, external users authenticated via one-time passcode connect directly to SharePoint. -This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitoring in Auditing-logs. +This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitored in Auditing-logs. With SharePoint and OneDrive integrated with Microsoft Entra B2B Invitation Manager, invited people outside the organization are each given a guest account in the directory and are subject to Microsoft Entra ID access policies such as conditional access. Invitations to a SharePoint site use Microsoft Entra B2B and no longer require users to have or create a personal Microsoft account. From 36ac2fa9563dc8c3eb386dc27ba89822d7b59f60 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:09:40 -0400 Subject: [PATCH 11/31] Update powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 index 625b83357..ab62e25b6 100644 --- a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 @@ -8,7 +8,7 @@ .EXAMPLE Test-MtSpoGuestCannotShareUnownedItem - Returns true if the SharePoint tenant is integrated with Microsoft Entra B2B, false otherwise. + Returns true if external users are prevented from resharing items they don't own, false otherwise. .LINK https://maester.dev/docs/commands/Test-MtSpoGuestCannotShareUnownedItem From c3ac6d7d52283ffd13e7c46013600d8b5980d8db Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:09:54 -0400 Subject: [PATCH 12/31] Update powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 b/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 index 4834c90c9..22b9ec063 100644 --- a/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 +++ b/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 @@ -21,7 +21,7 @@ function Test-MtSpoPreventDownloadMaliciousFile { $return = $true try { - $DisallowInfectedFileDownload = Get-SPOTenant | Select-Object -ExpandProperty DisallowInfectedFileDownload + $DisallowInfectedFileDownload = Get-SPOTenant | Select-Object -ExpandProperty DisallowInfectedFileDownload if ($DisallowInfectedFileDownload) { $testResult = "Well done. Malicious file download prevention is enabled in your SharePoint tenant." } else { From 7b6f32ebbc771bd1d237e86ecc1000246b96a407 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Wed, 29 Apr 2026 07:10:31 -0400 Subject: [PATCH 13/31] Update website/docs/tests/maester/MT.1113.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- website/docs/tests/maester/MT.1113.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/docs/tests/maester/MT.1113.md b/website/docs/tests/maester/MT.1113.md index 7654aa566..5ef27e4c3 100644 --- a/website/docs/tests/maester/MT.1113.md +++ b/website/docs/tests/maester/MT.1113.md @@ -7,7 +7,7 @@ sidebar_class_name: hidden ## Description Before integrating SharePoint Online with Microsoft Entra B2B, external users authenticated via one-time passcode, directly to SharePoint. -This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitoring in Auditing-logs. +This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitored in Auditing-logs. With SharePoint and OneDrive integrated with Microsoft Entra B2B Invitation Manager, invited people outside the organization are each given a guest account in the directory and are subject to Microsoft Entra ID access policies such as conditional access. Invitations to a SharePoint site use Microsoft Entra B2B and no longer require users to have or create a personal Microsoft account. From 389f31a65bebf0bb667c8afedbf10c3e08c71c49 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 5 May 2026 06:51:32 -0400 Subject: [PATCH 14/31] Update powershell/public/Connect-Maester.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- powershell/public/Connect-Maester.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index a7d71cf18..3af48d475 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -299,7 +299,7 @@ ) { Write-Verbose 'Connecting to SharePoint Online' try { - $tenantDomain = Read-Host -Prompt "Conencting to SharePoint Online requires the onmicrosoft.com domain name of your tenant. Please enter the tenant domain (e.g. contoso.onmicrosoft.com)" + $tenantDomain = Read-Host -Prompt "Connecting to SharePoint Online requires the onmicrosoft.com domain name of your tenant. Please enter the tenant domain (e.g. contoso.onmicrosoft.com)" if ($tenantDomain -notmatch "^[\w-]+\.onmicrosoft\.com$") { Write-Host "The tenant domain must be in the format contoso.onmicrosoft.com" -ForegroundColor Red return From 6b2f02b81b1c65a2c828c968d4f280691985fb4e Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 5 May 2026 06:51:57 -0400 Subject: [PATCH 15/31] Update powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 index ab62e25b6..efcfeb525 100644 --- a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 @@ -25,7 +25,7 @@ function Test-MtSpoGuestCannotShareUnownedItem { if ($PreventExternalUsersFromResharing) { $testResult = "Well done. External users cannot share items they don't own." } else { - $testResult = "External users can share items they dont own." + $testResult = "External users can share items they don't own." $return = $false } Add-MtTestResultDetail -Result $testResult From 9ebb6bee0fae3ec92eba80cf33aa9b10ea214685 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 5 May 2026 06:52:35 -0400 Subject: [PATCH 16/31] Update powershell/Maester.psd1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- powershell/Maester.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/powershell/Maester.psd1 b/powershell/Maester.psd1 index 53a09b3dd..b73136656 100644 --- a/powershell/Maester.psd1 +++ b/powershell/Maester.psd1 @@ -187,7 +187,7 @@ 'Test-MtXspmPublicRemotelyExploitableHighExposureDevices', 'Test-MtXspmCriticalCredentialsOnNonTpmProtectedDevices', 'Test-MtXspmCriticalCredentialsOnNonCredGuardProtectedDevices', - 'Test-MtSpoB2BIntegration', 'Test-MtSpoCustomScriptExecutionOnSiteCollection', 'Test-MtSpoDefaultSharingLink', 'Test-MtSpoDefaultSharingLinkPermission', 'Test-MtSpoGuestAccessExpiry', 'Test-MtSpoGuestCannotShareUnownedItem', 'Test-MtSpoPreventDownloadMaliciousFile' + 'Test-MtSpoB2BIntegration', 'Test-MtSpoDefaultSharingLink', 'Test-MtSpoDefaultSharingLinkPermission', 'Test-MtSpoGuestAccessExpiry', 'Test-MtSpoGuestCannotShareUnownedItem', 'Test-MtSpoPreventDownloadMaliciousFile' 'Test-MtEntitlementManagementDeletedGroups', 'Test-MtEntitlementManagementInactivePolicies', 'Test-MtEntitlementManagementOrphanedResources', From 328e18c6bd1ef746eccbd7181774a736ab84de42 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 5 May 2026 06:53:10 -0400 Subject: [PATCH 17/31] Update powershell/public/Connect-Maester.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- powershell/public/Connect-Maester.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index 3af48d475..c322bb603 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -304,6 +304,7 @@ Write-Host "The tenant domain must be in the format contoso.onmicrosoft.com" -ForegroundColor Red return } + $tenantDomain = $tenantDomain.ToLowerInvariant() $spoUri = "https://$(($tenantDomain).Replace(".onmicrosoft.com",$null))-admin.sharepoint.com" Connect-SpoService -Url $spoUri -UseSystemBrowser $true } catch [Management.Automation.CommandNotFoundException] { From bbfc7e751dfefa0f57eefd330f04c6b1417ca7e7 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Tue, 5 May 2026 06:53:37 -0400 Subject: [PATCH 18/31] Update powershell/public/Connect-Maester.ps1 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- powershell/public/Connect-Maester.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index c322bb603..39e1b9ed8 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -302,7 +302,8 @@ $tenantDomain = Read-Host -Prompt "Connecting to SharePoint Online requires the onmicrosoft.com domain name of your tenant. Please enter the tenant domain (e.g. contoso.onmicrosoft.com)" if ($tenantDomain -notmatch "^[\w-]+\.onmicrosoft\.com$") { Write-Host "The tenant domain must be in the format contoso.onmicrosoft.com" -ForegroundColor Red - return + Write-Host "Skipping SharePoint Online connection and continuing with any remaining services." -ForegroundColor Yellow + break } $tenantDomain = $tenantDomain.ToLowerInvariant() $spoUri = "https://$(($tenantDomain).Replace(".onmicrosoft.com",$null))-admin.sharepoint.com" From ada778160f3c0695f1b830b28d0c3916c62fe8b8 Mon Sep 17 00:00:00 2001 From: -Mynster Date: Fri, 8 May 2026 23:07:58 +0200 Subject: [PATCH 19/31] Initial cleanup and update to the PR #1433 - Removed references to MT cmdlets along with the MT docs for these cmdlets as these are CIS tests and follows the CIS implementation. - Moved md and ps1 files to the correct folder - Deleted the single test file and split out to multiple for CIS - Updated .md files to allign with the others - Updated function names to Test-MtCis prefix For now i removed the connection part for sharepoint for Connect-Maester and removed the section in Installation as we are switching from 'Microsoft.Online.SharePoint.PowerShell' to 'PnP PowerShell' for cross platform compatibility Co-authored-by: Henrik --- powershell/Maester.psd1 | 2 +- powershell/public/Connect-Maester.ps1 | 28 +------- .../public/cis/Test-MtCisSpoB2BIntegration.md | 31 +++++++++ .../Test-MtCisSpoB2BIntegration.ps1} | 6 +- .../cis/Test-MtCisSpoDefaultSharingLink.md | 37 ++++++++++ .../Test-MtCisSpoDefaultSharingLink.ps1} | 6 +- ...st-MtCisSpoDefaultSharingLinkPermission.md | 36 ++++++++++ ...-MtCisSpoDefaultSharingLinkPermission.ps1} | 6 +- .../cis/Test-MtCisSpoGuestAccessExpiry.md | 41 +++++++++++ .../Test-MtCisSpoGuestAccessExpiry.ps1} | 6 +- ...est-MtCisSpoGuestCannotShareUnownedItem.md | 35 ++++++++++ ...t-MtCisSpoGuestCannotShareUnownedItem.ps1} | 6 +- ...st-MtCisSpoPreventDownloadMaliciousFile.md | 32 +++++++++ ...-MtCisSpoPreventDownloadMaliciousFile.ps1} | 6 +- .../maester/spo/Test-MtSpoB2BIntegration.md | 13 ---- .../spo/Test-MtSpoDefaultSharingLink.md | 13 ---- .../Test-MtSpoDefaultSharingLinkPermission.md | 12 ---- .../spo/Test-MtSpoGuestAccessExpiry.md | 18 ----- .../Test-MtSpoGuestCannotShareUnownedItem.md | 16 ----- .../Test-MtSpoPreventDownloadMaliciousFile.md | 15 ---- tests/Maester/Spo/Test-SpoTenant.Tests.ps1 | 69 ------------------- .../cis/Test-MtCisSpoB2BIntegration.Tests.ps1 | 10 +++ .../Test-MtCisSpoDefaultSharingLink.Tests.ps1 | 10 +++ ...sSpoDefaultSharingLinkPermission.Tests.ps1 | 10 +++ .../Test-MtCisSpoGuestAccessExpiry.Tests.ps1 | 10 +++ ...isSpoGuestCannotShareUnownedItem.Tests.ps1 | 10 +++ ...sSpoPreventDownloadMaliciousFile.Tests.ps1 | 10 +++ tests/maester-config.json | 35 ---------- website/docs/installation.md | 4 -- website/docs/tests/maester/MT.1113.md | 19 ----- website/docs/tests/maester/MT.1114.md | 29 -------- website/docs/tests/maester/MT.1115.md | 21 ------ website/docs/tests/maester/MT.1116.md | 20 ------ website/docs/tests/maester/MT.1117.md | 26 ------- website/docs/tests/maester/MT.1118.md | 24 ------- website/docs/tests/maester/MT.1119.md | 23 ------- 36 files changed, 293 insertions(+), 402 deletions(-) create mode 100644 powershell/public/cis/Test-MtCisSpoB2BIntegration.md rename powershell/public/{maester/spo/Test-MtSpoB2BIntegration.ps1 => cis/Test-MtCisSpoB2BIntegration.ps1} (92%) create mode 100644 powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md rename powershell/public/{maester/spo/Test-MtSpoDefaultSharingLink.ps1 => cis/Test-MtCisSpoDefaultSharingLink.ps1} (91%) create mode 100644 powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.md rename powershell/public/{maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 => cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1} (89%) create mode 100644 powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md rename powershell/public/{maester/spo/Test-MtSpoGuestAccessExpiry.ps1 => cis/Test-MtCisSpoGuestAccessExpiry.ps1} (91%) create mode 100644 powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md rename powershell/public/{maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 => cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1} (89%) create mode 100644 powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.md rename powershell/public/{maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 => cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1} (87%) delete mode 100644 powershell/public/maester/spo/Test-MtSpoB2BIntegration.md delete mode 100644 powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.md delete mode 100644 powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.md delete mode 100644 powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.md delete mode 100644 powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.md delete mode 100644 powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.md delete mode 100644 tests/Maester/Spo/Test-SpoTenant.Tests.ps1 create mode 100644 tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 create mode 100644 tests/cis/Test-MtCisSpoDefaultSharingLink.Tests.ps1 create mode 100644 tests/cis/Test-MtCisSpoDefaultSharingLinkPermission.Tests.ps1 create mode 100644 tests/cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 create mode 100644 tests/cis/Test-MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 create mode 100644 tests/cis/Test-MtCisSpoPreventDownloadMaliciousFile.Tests.ps1 delete mode 100644 website/docs/tests/maester/MT.1113.md delete mode 100644 website/docs/tests/maester/MT.1114.md delete mode 100644 website/docs/tests/maester/MT.1115.md delete mode 100644 website/docs/tests/maester/MT.1116.md delete mode 100644 website/docs/tests/maester/MT.1117.md delete mode 100644 website/docs/tests/maester/MT.1118.md delete mode 100644 website/docs/tests/maester/MT.1119.md diff --git a/powershell/Maester.psd1 b/powershell/Maester.psd1 index b73136656..d16d8a84c 100644 --- a/powershell/Maester.psd1 +++ b/powershell/Maester.psd1 @@ -187,7 +187,7 @@ 'Test-MtXspmPublicRemotelyExploitableHighExposureDevices', 'Test-MtXspmCriticalCredentialsOnNonTpmProtectedDevices', 'Test-MtXspmCriticalCredentialsOnNonCredGuardProtectedDevices', - 'Test-MtSpoB2BIntegration', 'Test-MtSpoDefaultSharingLink', 'Test-MtSpoDefaultSharingLinkPermission', 'Test-MtSpoGuestAccessExpiry', 'Test-MtSpoGuestCannotShareUnownedItem', 'Test-MtSpoPreventDownloadMaliciousFile' + 'Test-MtCisSpoB2BIntegration', 'Test-MtCisSpoDefaultSharingLink', 'Test-MtCisSpoDefaultSharingLinkPermission', 'Test-MtCisSpoGuestAccessExpiry', 'Test-MtCisSpoGuestCannotShareUnownedItem', 'Test-MtCisSpoPreventDownloadMaliciousFile' 'Test-MtEntitlementManagementDeletedGroups', 'Test-MtEntitlementManagementInactivePolicies', 'Test-MtEntitlementManagementOrphanedResources', diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index 39e1b9ed8..1bdf7ae8a 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -116,7 +116,7 @@ $__MtSession.Connections = $Service - $OrderedImport = Get-ModuleImportOrder -Name @('Az.Accounts', 'ExchangeOnlineManagement', 'Microsoft.Graph.Authentication', 'MicrosoftTeams', 'Microsoft.Online.SharePoint.PowerShell') + $OrderedImport = Get-ModuleImportOrder -Name @('Az.Accounts', 'ExchangeOnlineManagement', 'Microsoft.Graph.Authentication', 'MicrosoftTeams') switch ($OrderedImport.Name) { 'Az.Accounts' { @@ -292,31 +292,7 @@ 'Microsoft.Online.SharePoint.PowerShell' { if ($Service -contains 'SharePointOnline' -or $Service -contains 'All') { - if ( - ( $PSVersionTable.OS -match "Windows" -or [System.Environment]::OSVersion.VersionString -match "Windows" ) -and - ( $PSVersionTable.PSVersion.Major -eq 5 ) -and - ( Get-MtUserInteractive ) - ) { - Write-Verbose 'Connecting to SharePoint Online' - try { - $tenantDomain = Read-Host -Prompt "Connecting to SharePoint Online requires the onmicrosoft.com domain name of your tenant. Please enter the tenant domain (e.g. contoso.onmicrosoft.com)" - if ($tenantDomain -notmatch "^[\w-]+\.onmicrosoft\.com$") { - Write-Host "The tenant domain must be in the format contoso.onmicrosoft.com" -ForegroundColor Red - Write-Host "Skipping SharePoint Online connection and continuing with any remaining services." -ForegroundColor Yellow - break - } - $tenantDomain = $tenantDomain.ToLowerInvariant() - $spoUri = "https://$(($tenantDomain).Replace(".onmicrosoft.com",$null))-admin.sharepoint.com" - Connect-SpoService -Url $spoUri -UseSystemBrowser $true - } catch [Management.Automation.CommandNotFoundException] { - Write-Host "`nThe SharePoint Online PowerShell module is not installed or imported. Please install and import the module using the following command. For more information see https://learn.microsoft.com/en-us/powershell/module/microsoft.online.sharepoint.powershell/connect-sposervice" -ForegroundColor Red - Write-Host "`Install-Module Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser`n" -ForegroundColor Yellow - Write-Host "`Import-Module Microsoft.Online.SharePoint.PowerShell`n" -ForegroundColor Yellow - } - } else { - Write-Host "`nThe SharePoint Online PowerShell module is currently limited in its functionality and can only be used on interactive sessions on a Windows machine with PowerShell 5" -ForegroundColor Red - Write-Host "Please connect to SharePoint Online using Connect-SpoService in a separate PowerShell session." -ForegroundColor Yellow - } + } } } # end switch OrderedImport diff --git a/powershell/public/cis/Test-MtCisSpoB2BIntegration.md b/powershell/public/cis/Test-MtCisSpoB2BIntegration.md new file mode 100644 index 000000000..0d8cb2c78 --- /dev/null +++ b/powershell/public/cis/Test-MtCisSpoB2BIntegration.md @@ -0,0 +1,31 @@ +7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled + +Entra ID B2B provides authentication and management of guests. Authentication happens via one-time passcode when they don't already have a work or school account or a Microsoft account. Integration with SharePoint and OneDrive allows for more granular control of how guest user accounts are managed in the organization's AAD, unifying a similar guest experience already deployed in other Microsoft 365 services such as Teams. + +>Note: Global Reader role currently can't access SharePoint using PowerShell. + +## Rationale + +External users assigned guest accounts will be subject to Entra ID access policies, such as multi-factor authentication. This provides a way to manage guest identities and control access to SharePoint and OneDrive resources. Without this integration, files can be shared without account registration, making it more challenging to audit and manage who has access to the organization's data. + +## Impact + +B2B collaboration is used with other Entra services so should not be new or unusual. Microsoft also has made the experience seamless when turning on integration on SharePoint sites that already have active files shared with guest users. The referenced Microsoft article on the subject has more details on this. + +## Remediation + +1. Connect to SharePoint Online using `Connect-SPOService` +2. Run the following command: + +```powershell +Set-SPOTenant -EnableAzureADB2BIntegration $true +``` + +>Default Value: False + +## Related Links + +* [Enabling the integration](https://learn.microsoft.com/en-us/sharepoint/sharepoint-azureb2b-integration#enabling-the-integration) +* [What is Microsoft Entra B2B collaboration?](https://learn.microsoft.com/en-us/entra/external-id/what-is-b2b) +* [Set-SPOTenant](https://learn.microsoft.com/en-us/powershell/module/microsoft.online.sharepoint.powershell/set-spotenant?view=sharepoint-ps) +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 368](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.ps1 b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 similarity index 92% rename from powershell/public/maester/spo/Test-MtSpoB2BIntegration.ps1 rename to powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 index 74408aa37..e7d4a11aa 100644 --- a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.ps1 +++ b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 @@ -8,14 +8,14 @@ The recommended state is EnableAzureADB2BIntegration set to $true. .EXAMPLE - Test-MtSpoB2BIntegration + Test-MtCisSpoB2BIntegration Returns true if the SharePoint tenant is integrated with Microsoft Entra B2B, false otherwise. .LINK - https://maester.dev/docs/commands/Test-MtSpoB2BIntegration + https://maester.dev/docs/commands/Test-MtCisSpoB2BIntegration #> -function Test-MtSpoB2BIntegration { +function Test-MtCisSpoB2BIntegration { [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md new file mode 100644 index 000000000..c3f024e41 --- /dev/null +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md @@ -0,0 +1,37 @@ +7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive + +This setting sets the default link type that a user will see when sharing content in OneDrive or SharePoint. It does not restrict or exclude any other options. The recommended state is **Specific people (only the people the user specifies) or Only people in your organization** (more restrictive). + +## Rationale + +By defaulting to specific people, the user will first need to consider whether or not the content being shared should be accessible by the entire organization versus select individuals. This aids in reinforcing the concept of least privilege. + +## Remediation + +1. Navigate to [SharePoint admin center](https://admin.microsoft.com/sharepoint) +2. Click to expand **Policies** > **Sharing**. +3. Scroll to **File and folder links.** +4. Set **Choose the type of link that's selected by default when users share files and folders in SharePoint and OneDrive to Specific people (only the people the user specifies) or Only people in your organization.** + + +### PowerShell + +1. Connect to SharePoint Online using `Connect-SPOService` +2. Run the following command: + +```powershell +Set-SPOTenant -DefaultSharingLinkType Direct +``` + +3. Or, to set a more restrictive state: + +```powershell +Set-SPOTenant -DefaultSharingLinkType Internal +``` + +>Default Value: Only people in your organization (Internal) + +## Related Links + +* [Set-SPOTenant](https://learn.microsoft.com/en-us/powershell/module/microsoft.online.sharepoint.powershell/set-spotenant?view=sharepoint-ps) +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 381](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 similarity index 91% rename from powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 rename to powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 index 2a49883ea..19e3bb96b 100644 --- a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 @@ -6,14 +6,14 @@ By default, the sharing link experience in SharePoint and OneDrive is set to "Anyone with the link". This means that when users share files or folders, the default option allows anyone with the link to access the content, which can lead to unintentional overexposure of sensitive information. By changing the default sharing link type to "Specific people", users are encouraged to be more deliberate about who they share content with, reducing the risk of unauthorized access and supporting a more secure sharing environment. .EXAMPLE - Test-MtSpoDefaultSharingLink + Test-MtCisSpoDefaultSharingLink Returns true if the default sharing link type is set to a restrictive option, false otherwise. .LINK - https://maester.dev/docs/commands/Test-MtSpoDefaultSharingLink + https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLink #> -function Test-MtSpoDefaultSharingLink { +function Test-MtCisSpoDefaultSharingLink { [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.md b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.md new file mode 100644 index 000000000..2a6481fe8 --- /dev/null +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.md @@ -0,0 +1,36 @@ +7.2.11 (L1) Ensure the SharePoint default sharing link permission is set + +This setting configures the permission that is selected by default for sharing link from a SharePoint site. + +The recommended state is **View**. + +## Rationale + +Setting the view permission as the default ensures that users must deliberately select the edit permission when sharing a link. This approach reduces the risk of unintentionally granting edit privileges to a resource that only requires read access, supporting the principle of least privilege. + +## Impact + +Not applicable. + +## Remediation + +1. Navigate to [SharePoint admin center](https://admin.microsoft.com/sharepoint) +2. Click to expand **Policies** > **Sharing**. +3. Scroll to **File and folder links.** +4. Ensure **Choose the permission that's selected by default for sharing links** is set to **View**. + +### PowerShell + +1. Connect to SharePoint Online using `Connect-SPOService` +2. Run the following command: + +```powershell +Set-SPOTenant -DefaultLinkPermission View +``` + +>Default Value: DefaultLinkPermission : Edit + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#file-and-folder-links) +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 391](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 similarity index 89% rename from powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 rename to powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 index d4976f039..4a91c1a80 100644 --- a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 @@ -6,14 +6,14 @@ By default, the sharing link permission in SharePoint and OneDrive is set to "Edit". This means that when users share files or folders, the default option allows recipients to edit the content, which can lead to unintentional modifications or deletions of sensitive information. By changing the default sharing link permission to "View", users are encouraged to be more deliberate about granting edit permissions, reducing the risk of unauthorized changes and supporting a more secure sharing environment. .EXAMPLE - Test-MtSpoDefaultSharingLinkPermission + Test-MtCisSpoDefaultSharingLinkPermission Returns true if the default sharing link permission is set to a restrictive option, false otherwise. .LINK - https://maester.dev/docs/commands/Test-MtSpoDefaultSharingLinkPermission + https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission #> -function Test-MtSpoDefaultSharingLinkPermission { +function Test-MtCisSpoDefaultSharingLinkPermission { [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md new file mode 100644 index 000000000..28c56184b --- /dev/null +++ b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md @@ -0,0 +1,41 @@ +7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically + +This policy setting configures the expiration time for each guest that is invited to the SharePoint site or with whom users share individual files and folders with. + +The recommended state is **30** or less. + +## Rationale + +This setting ensures that guests who no longer need access to the site or link no longer have access after a set period of time. Allowing guest access for an indefinite amount of time could lead to loss of data confidentiality and oversight. + +>Note: Guest membership applies at the Microsoft 365 group level. Guests who have permission to view a SharePoint site or use a sharing link may also have access to a Microsoft Teams team or security group. + +## Impact + +Site collection administrators will have to renew access to guests who still need access after 30 days. They will receive an e-mail notification once per week about guest access that is about to expire. + +>Note: The guest expiration policy only applies to guests who use sharing links or guests who have direct permissions to a SharePoint site after the guest policy is enabled. The guest policy does not apply to guest users that have pre-existing permissions or access through a sharing link before the guest expiration policy is applied. + +## Remediation + +1. Navigate to [SharePoint admin center](https://admin.microsoft.com/sharepoint) +2. Click to expand **Policies** > **Sharing**. +3. Scroll to and expand **More external sharing settings.** +4. Set **Guest access to a site or OneDrive will expire automatically after this many days** to ***30*** + +### PowerShell + +1. Connect to SharePoint Online using `Connect-SPOService` +2. Run the following command: + +```powershell +Set-SPOTenant -ExternalUserExpireInDays 30 -ExternalUserExpirationRequired $True +``` + +>Default Value: ExternalUserExpirationRequired $false, ExternalUserExpireInDays 60 days + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* [Managing SharePoint Online Security: A Team Effort](https://learn.microsoft.com/en-us/microsoft-365/community/sharepoint-security-a-team-effort) +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 385](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 similarity index 91% rename from powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 rename to powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 index 61db94791..d21ffa650 100644 --- a/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 @@ -7,14 +7,14 @@ This means that once a guest user is granted access to a site or OneDrive, they will have indefinite access until manually removed by an administrator. Enabling automatic expiration of guest access helps to ensure that external users do not retain access to sensitive information longer than necessary, reducing the risk of unauthorized access and supporting a more secure sharing environment. The recommended state is to enable guest access expiration and set it to 30 days or less. .EXAMPLE - Test-MtSpoGuestAccessExpiry + Test-MtCisSpoGuestAccessExpiry Returns true if guest access expiration is enabled and set to 30 days or less, false otherwise. .LINK - https://maester.dev/docs/commands/Test-MtSpoGuestAccessExpiry + https://maester.dev/docs/commands/Test-MtCisSpoGuestAccessExpiry #> -function Test-MtSpoGuestAccessExpiry { +function Test-MtCisSpoGuestAccessExpiry { [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md new file mode 100644 index 000000000..16b04e755 --- /dev/null +++ b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md @@ -0,0 +1,35 @@ +7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own + +SharePoint gives users the ability to share files, folders, and site collections. Internal users can share with external collaborators, and with the right permissions could share to other external parties. + +## Rationale + +Sharing and collaboration are key; however, file, folder, or site collection owners should have the authority over what external users get shared with to prevent unauthorized disclosures of information. + +## Impact + +The impact associated with this change is highly dependent upon current practices. If users do not regularly share with external parties, then minimal impact is likely. However, if users do regularly share with guests/externally, minimum impacts could occur as those external users will be unable to 're-share' content. + +## Remediation + +1. Navigate to [SharePoint admin center](https://admin.microsoft.com/sharepoint) +2. Click to expand **Policies** > **Sharing**. +3. Scroll to and expand **More external sharing settings.**, uncheck **Allow guests to share items they don't own.** +4. Click **Save**. + +### PowerShell + +1. Connect to SharePoint Online using `Connect-SPOService` +2. Run the following command: + +```powershell +Set-SPOTenant -PreventExternalUsersFromResharing $True +``` + +>Default Value: Checked (False) + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* [Overview of external sharing in SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/external-sharing-overview) +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 376](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 similarity index 89% rename from powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 rename to powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 index efcfeb525..4b81779ff 100644 --- a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 @@ -6,14 +6,14 @@ By default, external users can share items they don't own. This means that if a guest user has access to an item, they can share it with others, potentially leading to unauthorized access and data leaks. By preventing external users from resharing items they don't own, you can help protect sensitive information and maintain better control over who has access to your SharePoint resources. The recommended state is PreventExternalUsersFromResharing set to $true. .EXAMPLE - Test-MtSpoGuestCannotShareUnownedItem + Test-MtCisSpoGuestCannotShareUnownedItem Returns true if external users are prevented from resharing items they don't own, false otherwise. .LINK - https://maester.dev/docs/commands/Test-MtSpoGuestCannotShareUnownedItem + https://maester.dev/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem #> -function Test-MtSpoGuestCannotShareUnownedItem { +function Test-MtCisSpoGuestCannotShareUnownedItem { [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.md b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.md new file mode 100644 index 000000000..221450b87 --- /dev/null +++ b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.md @@ -0,0 +1,32 @@ +7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download + +By default, SharePoint online allows files that Defender for Office 365 has detected as infected to be downloaded. + +## Rationale + +Defender for Office 365 for SharePoint, OneDrive, and Microsoft Teams protects your organization from inadvertently sharing malicious files. When an infected file is detected that file is blocked so that no one can open, copy, move, or share it until further actions are taken by the organization's security team. + +## Impact + +The only potential impact associated with implementation of this setting is potential inconvenience associated with the small percentage of false positive detections that may occur. + +## Remediation + +### PowerShell + +1. Connect to SharePoint Online using `Connect-SPOService -Url https://tenant-admin.sharepoint.com`, replacing "tenant" with the appropriate value. +2. Run the following PowerShell command to set the recommended value: + +```powershell +Set-SPOTenant –DisallowInfectedFileDownload $true +``` + +>Note: The Global Reader role cannot access SharePoint using PowerShell according to Microsoft. See the reference section for more information. + +>Default Value: False + +## Related Links + +* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) +* [Overview of external sharing in SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/external-sharing-overview) +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 394](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 similarity index 87% rename from powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 rename to powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 index 22b9ec063..14cf43ea7 100644 --- a/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.ps1 +++ b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 @@ -6,14 +6,14 @@ By default, users can't open, move, copy, or share* malicious files that are detected by Safe Attachments for SharePoint, OneDrive, and Microsoft Teams. However, they can delete and download malicious files. .EXAMPLE - Test-MtSpoPreventDownloadMaliciousFile + Test-MtCisSpoPreventDownloadMaliciousFile Returns true if malicious file download prevention is enabled in your SharePoint tenant, false otherwise. .LINK - https://maester.dev/docs/commands/Test-MtSpoPreventDownloadMaliciousFile + https://maester.dev/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile #> -function Test-MtSpoPreventDownloadMaliciousFile { +function Test-MtCisSpoPreventDownloadMaliciousFile { [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md b/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md deleted file mode 100644 index 54cd68267..000000000 --- a/powershell/public/maester/spo/Test-MtSpoB2BIntegration.md +++ /dev/null @@ -1,13 +0,0 @@ -7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled - -Before integrating SharePoint Online with Microsoft Entra B2B, external users authenticated via one-time passcode connect directly to SharePoint. -This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitored in Auditing-logs. - -With SharePoint and OneDrive integrated with Microsoft Entra B2B Invitation Manager, invited people outside the organization are each given a guest account in the directory and are subject to Microsoft Entra ID access policies such as conditional access. -Invitations to a SharePoint site use Microsoft Entra B2B and no longer require users to have or create a personal Microsoft account. - -## Related Links - -* [SharePoint and OneDrive integration with Microsoft Entra B2B | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/sharepoint-azureb2b-integration) -* [Secure external sharing recipient experience | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/what-s-new-in-sharing-in-targeted-release) -* CIS 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.md b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.md deleted file mode 100644 index 9536db153..000000000 --- a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLink.md +++ /dev/null @@ -1,13 +0,0 @@ -7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive - -Description: -This setting sets the default link type that a user will see when sharing content in OneDrive or SharePoint. It does not restrict or exclude any other options. -The recommended state is Specific people (only the people the user specifies) or Only people in your organization (more restrictive). - -Rationale: -By defaulting to specific people, the user will first need to consider whether or not the content being shared should be accessible by the entire organization versus select individuals. This aids in reinforcing the concept of least privilege. - -## Related Links - -* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) -* CIS 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.md b/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.md deleted file mode 100644 index 0f9496261..000000000 --- a/powershell/public/maester/spo/Test-MtSpoDefaultSharingLinkPermission.md +++ /dev/null @@ -1,12 +0,0 @@ -7.2.11 (L1) Ensure the SharePoint default sharing link permission is set - -Description: -This setting configures the permission that is selected by default for sharing link from a SharePoint site. The recommended state is View. - -Rationale: -Setting the view permission as the default ensures that users must deliberately select the edit permission when sharing a link. This approach reduces the risk of unintentionally granting edit privileges to a resource that only requires read access, supporting the principle of least privilege. - -## Related Links - -* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) -* CIS 7.2.11 (L1) Ensure the SharePoint default sharing link permission is set \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.md b/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.md deleted file mode 100644 index 9e89028d9..000000000 --- a/powershell/public/maester/spo/Test-MtSpoGuestAccessExpiry.md +++ /dev/null @@ -1,18 +0,0 @@ -7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically - -Description: -This policy setting configures the expiration time for each guest that is invited to the SharePoint site or with whom users share individual files and folders with. -The recommended state is 30 or less. - -Rationale: -This setting ensures that guests who no longer need access to the site or link no longer have access after a set period of time. Allowing guest access for an indefinite amount of time could lead to loss of data confidentiality and oversight. -Note: Guest membership applies at the Microsoft 365 group level. Guests who have permission to view a SharePoint site or use a sharing link may also have access to a Microsoft Teams team or security group. - -Impact: -Site collection administrators will have to renew access to guests who still need access after 30 days. They will receive an e-mail notification once per week about guest access that is about to expire. -**Note:** The guest expiration policy only applies to guests who use sharing links or guests who have direct permissions to a SharePoint site after the guest policy is enabled. The guest policy does not apply to guest users that have pre-existing permissions or access through a sharing link before the guest expiration policy is applied - -## Related Links - -* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) -* CIS 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.md b/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.md deleted file mode 100644 index c0afcd9e6..000000000 --- a/powershell/public/maester/spo/Test-MtSpoGuestCannotShareUnownedItem.md +++ /dev/null @@ -1,16 +0,0 @@ -7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own - -Description: -SharePoint gives users the ability to share files, folders, and site collections. Internal users can share with external collaborators, and with the right permissions could share to other external parties. - -Rationale: -Sharing and collaboration are key; however, file, folder, or site collection owners should have the authority over what external users get shared with to prevent unauthorized disclosures of information. - -Impact: -The impact associated with this change is highly dependent upon current practices. If users do not regularly share with external parties, then minimal impact is likely. -However, if users do regularly share with guests/externally, minimum impacts could occur as those external users will be unable to 're-share' content. - -## Related Links - -* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) -* CIS 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own \ No newline at end of file diff --git a/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.md b/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.md deleted file mode 100644 index fc18b40e2..000000000 --- a/powershell/public/maester/spo/Test-MtSpoPreventDownloadMaliciousFile.md +++ /dev/null @@ -1,15 +0,0 @@ -7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download - -Description: -By default, SharePoint online allows files that Defender for Office 365 has detected as infected to be downloaded. - -Rationale: -Defender for Office 365 for SharePoint, OneDrive, and Microsoft Teams protects your organization from inadvertently sharing malicious files. When an infected file is detected that file is blocked so that no one can open, copy, move, or share it until further actions are taken by the organization's security team. - -Impact: -The only potential impact associated with implementation of this setting is potential inconvenience associated with the small percentage of false positive detections that may occur. - -## Related Links - -* [Safe Attachments for SharePoint, OneDrive, and Microsoft Teams](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-configure?view=o365-worldwide#step-2-recommended-use-sharepoint-online-powershell-to-prevent-users-from-downloading-malicious-files) -* CIS 7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download \ No newline at end of file diff --git a/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 b/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 deleted file mode 100644 index 0a045aa35..000000000 --- a/tests/Maester/Spo/Test-SpoTenant.Tests.ps1 +++ /dev/null @@ -1,69 +0,0 @@ -BeforeDiscovery { - - # Check for prerequisite before running the tests. If the prerequisites are not met, return $null to skip the tests. - # Following checks are performed to to current limitations of the Microsoft.Online.SharePoint.PowerShell module: - # - Run on Windows OS - # - Run in PowerShell 5 not 7 - # - Check if the module is installed and loaded - # - Check if the user is connected to SharePoint Online with Connect-SpoService - if (-not ($PSVersionTable.OS -match "Windows" -or [System.Environment]::OSVersion.VersionString -match "Windows")) { - Write-Host "SharePoint Online tests can only be run on Windows OS. Skipping tests..." -ForegroundColor Yellow - return $null - } - if ($PSVersionTable.PSVersion.Major -ne 5) { - Write-Host "SharePoint Online tests can only be run in PowerShell 5. Skipping tests..." -ForegroundColor Yellow - return $null - } - if (-not (Get-Module -Name Microsoft.Online.SharePoint.PowerShell -ListAvailable)) { - Write-Host "Microsoft.Online.SharePoint.PowerShell module is not installed. Skipping tests..." -ForegroundColor Yellow - return $null - } - if (-not (Get-Module -Name Microsoft.Online.SharePoint.PowerShell)) { - Write-Host "Microsoft.Online.SharePoint.PowerShell module is not imported. Skipping tests..." -ForegroundColor Yellow - return $null - } - if (-not (Get-SpoTenant)) { - Write-Host "Not connected to SharePoint Online. Please connect using Connect-SpoService before running the tests. Skipping tests..." -ForegroundColor Yellow - return $null - } -} - -Describe 'Maester/SpoTenant' -Tag 'Maester', 'SpoTenant' { - It 'MT.1113: Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing.' -Tag 'MT.1113', 'CIS', 'CIS M365v5', 'CIS 7.2.2', 'Severity:Medium' { - $result = Test-MtSpoB2BIntegration - if ($null -ne $result) { - $result | Should -Be $true -Because 'SharePoint tenant is integrated with Microsoft Entra B2B.' - } - } - It 'MT.1114: Ensure Office 365 SharePoint infected files are disallowed for download' -Tag 'MT.1114', 'CIS', 'CIS M365v5', 'CIS 7.3.1', 'Severity:High' { - $result = Test-MtSpoPreventDownloadMaliciousFile - if ($null -ne $result) { - $result | Should -Be $true -Because 'Office 365 SharePoint infected files are disallowed for download.' - } - } - It 'MT.1115: Ensure link sharing is restricted in SharePoint and OneDrive' -Tag 'MT.1115', 'CIS', 'CIS M365v5', 'CIS 7.2.7', 'Severity:Low' { - $result = Test-MtSpoDefaultSharingLink - if ($null -ne $result) { - $result | Should -Be $true -Because 'link sharing is restricted in SharePoint and OneDrive.' - } - } - It 'MT.1116: Ensure the SharePoint default sharing link permission is set' -Tag 'MT.1116', 'CIS', 'CIS M365v5', 'CIS 7.2.11', 'Severity:Low' { - $result = Test-MtSpoDefaultSharingLinkPermission - if ($null -ne $result) { - $result | Should -Be $true -Because 'the SharePoint default sharing link permission is set.' - } - } - It 'MT.1117: Ensure guest access to a site or OneDrive will expire automatically' -Tag 'MT.1117', 'CIS', 'CIS M365v5', 'CIS 7.2.9', 'Severity:Low' { - $result = Test-MtSpoGuestAccessExpiry - if ($null -ne $result) { - $result | Should -Be $true -Because 'guest access to a site or OneDrive will expire automatically.' - } - } - It "MT.1118: Ensure that SharePoint guest users cannot share items they don't own" -Tag 'MT.1118', 'CIS', 'CIS M365v5', 'CIS 7.2.5', 'Severity:High' { - $result = Test-MtSpoGuestCannotShareUnownedItem - if ($null -ne $result) { - $result | Should -Be $true -Because "SharePoint guest users cannot share items they don't own." - } - } - -} \ No newline at end of file diff --git a/tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 b/tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 new file mode 100644 index 000000000..e28e40e52 --- /dev/null +++ b/tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 @@ -0,0 +1,10 @@ +Describe "CIS" -Tag "CIS.M365.7.2.2", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { + It "CIS.M365.7.2.2: Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled" { + + $result = Test-MtCisSpoB2BIntegration + + if ($null -ne $result) { + $result | Should -Be $true -Because "SharePoint and OneDrive integration with Azure AD B2B is enabled" + } + } +} diff --git a/tests/cis/Test-MtCisSpoDefaultSharingLink.Tests.ps1 b/tests/cis/Test-MtCisSpoDefaultSharingLink.Tests.ps1 new file mode 100644 index 000000000..027a36e77 --- /dev/null +++ b/tests/cis/Test-MtCisSpoDefaultSharingLink.Tests.ps1 @@ -0,0 +1,10 @@ +Describe "CIS" -Tag "CIS.M365.7.2.7", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { + It "CIS.M365.7.2.7: Ensure link sharing is restricted in SharePoint and OneDrive" { + + $result = Test-MtCisSpoDefaultSharingLink + + if ($null -ne $result) { + $result | Should -Be $true -Because "Link sharing is restricted in SharePoint and OneDrive" + } + } +} diff --git a/tests/cis/Test-MtCisSpoDefaultSharingLinkPermission.Tests.ps1 b/tests/cis/Test-MtCisSpoDefaultSharingLinkPermission.Tests.ps1 new file mode 100644 index 000000000..64ad70cf9 --- /dev/null +++ b/tests/cis/Test-MtCisSpoDefaultSharingLinkPermission.Tests.ps1 @@ -0,0 +1,10 @@ +Describe "CIS" -Tag "CIS.M365.7.2.11", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { + It "CIS.M365.7.2.11: Ensure the SharePoint default sharing link permission is set" { + + $result = Test-MtCisSpoDefaultSharingLinkPermission + + if ($null -ne $result) { + $result | Should -Be $true -Because "The SharePoint default sharing link permission is set" + } + } +} diff --git a/tests/cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 b/tests/cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 new file mode 100644 index 000000000..0bfc06ae8 --- /dev/null +++ b/tests/cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 @@ -0,0 +1,10 @@ +Describe "CIS" -Tag "CIS.M365.7.2.9", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { + It "CIS.M365.7.2.9: Ensure guest access to a site or OneDrive will expire automatically" { + + $result = Test-MtCisSpoGuestAccessExpiry + + if ($null -ne $result) { + $result | Should -Be $true -Because "Guest access to a site or OneDrive will expire automatically" + } + } +} diff --git a/tests/cis/Test-MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 b/tests/cis/Test-MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 new file mode 100644 index 000000000..7b9d2d655 --- /dev/null +++ b/tests/cis/Test-MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 @@ -0,0 +1,10 @@ +Describe "CIS" -Tag "CIS.M365.7.2.5", "L2", "CIS E3 Level 2", "CIS E3", "CIS E5 Level 2", "CIS E5", "CIS", "CIS M365 v6.0.1" { + It "CIS.M365.7.2.5: Ensure that SharePoint guest users cannot share items they don't own" { + + $result = Test-MtCisSpoGuestCannotShareUnownedItem + + if ($null -ne $result) { + $result | Should -Be $true -Because "SharePoint guest users cannot share items they don't own" + } + } +} diff --git a/tests/cis/Test-MtCisSpoPreventDownloadMaliciousFile.Tests.ps1 b/tests/cis/Test-MtCisSpoPreventDownloadMaliciousFile.Tests.ps1 new file mode 100644 index 000000000..180ac4aac --- /dev/null +++ b/tests/cis/Test-MtCisSpoPreventDownloadMaliciousFile.Tests.ps1 @@ -0,0 +1,10 @@ +Describe "CIS" -Tag "CIS.M365.7.3.1", "L2", "CIS E5 Level 2", "CIS E5", "CIS", "CIS M365 v6.0.1" { + It "CIS.M365.7.3.1: Ensure Office 365 SharePoint infected files are disallowed for download" { + + $result = Test-MtCisSpoPreventDownloadMaliciousFile + + if ($null -ne $result) { + $result | Should -Be $true -Because "Office 365 SharePoint infected files are disallowed for download" + } + } +} diff --git a/tests/maester-config.json b/tests/maester-config.json index c17f78952..899398135 100644 --- a/tests/maester-config.json +++ b/tests/maester-config.json @@ -1298,41 +1298,6 @@ "Severity": "Medium", "Title": "Privileged user accounts should not remain enabled when the linked primary account is disabled" }, - { - "Id": "MT.1113", - "Severity": "Medium", - "Title": "Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing." - }, - { - "Id": "MT.1114", - "Severity": "Medium", - "Title": "Ensure custom script execution is restricted on site collections" - }, - { - "Id": "MT.1115", - "Severity": "Low", - "Title": "Ensure link sharing is restricted in SharePoint and OneDrive" - }, - { - "Id": "MT.1116", - "Severity": "Low", - "Title": "Ensure the SharePoint default sharing link permission is set" - }, - { - "Id": "MT.1117", - "Severity": "Low", - "Title": "Ensure guest access to a site or OneDrive will expire automatically" - }, - { - "Id": "MT.1118", - "Severity": "High", - "Title": "Ensure that SharePoint guest users cannot share items they don't own" - }, - { - "Id": "MT.1119", - "Severity": "High", - "Title": "Ensure Office 365 SharePoint infected files are disallowed for download" - }, { "Id": "ORCA.100", "Severity": "Medium", diff --git a/website/docs/installation.md b/website/docs/installation.md index 2f43605b9..cc88b7f3b 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -35,11 +35,9 @@ Maester includes optional [CISA](tests/cisa/) tests that require additional perm Install-Module Az.Accounts -Scope CurrentUser Install-Module ExchangeOnlineManagement -Scope CurrentUser Install-Module MicrosoftTeams -Scope CurrentUser -Install-Module Microsoft.Online.SharePoint.PowerShell -Scope CurrentUser ``` > The Security & Compliance PowerShell module is dependent on the ExchangeOnlineManagement `Connect-IPPSSession` cmdlet. -> The Microsoft.Online.SharePoint.PowerShell module is currently limited in its functionality and can only be used on a Windows machine with PowerShell 5. ### Connecting to Azure, Exchange and other services @@ -60,8 +58,6 @@ Exchange Online implements a [role-based access control model](https://learn.mic * View-Only Configuration OR * O365SupportViewConfig -SharePoint Online requires the user to be at least a SharePoint Administrator to connect and run the tests that interact with SharePoint Online Powershell. - ## Next Steps - Monitoring with Maester diff --git a/website/docs/tests/maester/MT.1113.md b/website/docs/tests/maester/MT.1113.md deleted file mode 100644 index 5ef27e4c3..000000000 --- a/website/docs/tests/maester/MT.1113.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: MT.1113 - Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing. -description: Microsoft Entra B2B integration allows you to manage external sharing in SharePoint Online using Microsoft Entra. With this integration, you can use Microsoft Entra to control access to your SharePoint Online resources, including sites, lists, and libraries. This provides a more secure and streamlined way to manage external sharing in SharePoint Online. -slug: /tests/MT.1113 -sidebar_class_name: hidden ---- - -## Description -Before integrating SharePoint Online with Microsoft Entra B2B, external users authenticated via one-time passcode, directly to SharePoint. -This authentication bypasses all configurations from Microsoft Entra as well as sign-in logs and can only be monitored in Auditing-logs. - -With SharePoint and OneDrive integrated with Microsoft Entra B2B Invitation Manager, invited people outside the organization are each given a guest account in the directory and are subject to Microsoft Entra ID access policies such as conditional access. -Invitations to a SharePoint site use Microsoft Entra B2B and no longer require users to have or create a personal Microsoft account. - -## Related Links - -* [SharePoint and OneDrive integration with Microsoft Entra B2B | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/sharepoint-azureb2b-integration) -* [Secure external sharing recipient experience | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/what-s-new-in-sharing-in-targeted-release) -* CIS 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1114.md b/website/docs/tests/maester/MT.1114.md deleted file mode 100644 index 8f5eec158..000000000 --- a/website/docs/tests/maester/MT.1114.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: MT.1114 - Ensure custom script execution is restricted on site collections -description: Ensure custom script execution is restricted on site collections -slug: /tests/MT.1114 -sidebar_class_name: hidden ---- - -## Description -7.3.4 (L1) Ensure custom script execution is restricted on site collections - -Description: -This setting controls custom script execution on a particular site (previously called "site collection"). -Custom scripts can allow users to change the look, feel and behavior of sites and pages. Every script that runs in a SharePoint page (whether it's an HTML page in a document library or a JavaScript in a Script Editor Web Part) always runs in the context of the user visiting the page and the SharePoint application. This means: -* Scripts have access to everything the user has access to. -* Scripts can access content across several Microsoft 365 services and even -beyond with Microsoft Graph integration. The recommended state is DenyAddAndCustomizePages set to $true. - -Rationale: -Custom scripts could contain malicious instructions unknown to the user or administrator. When users are allowed to run custom script, the organization can no longer enforce governance, scope the capabilities of inserted code, block specific parts of code, or block all custom code that has been deployed. If scripting is allowed the following things can't be audited: -* What code has been inserted -* Where the code has been inserted -* Who inserted the code - -Note: Microsoft recommends using the SharePoint Framework instead of custom scripts - -## Related Links - -* [Allow or prevent custom script | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/allow-or-prevent-custom-script) -* CIS 7.3.4 (L1) Ensure custom script execution is restricted on site collections \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1115.md b/website/docs/tests/maester/MT.1115.md deleted file mode 100644 index 4bc1a8df0..000000000 --- a/website/docs/tests/maester/MT.1115.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: MT.1115 - Ensure link sharing is restricted in SharePoint and OneDrive -description: Ensure link sharing is restricted in SharePoint and OneDrive -slug: /tests/MT.1115 -sidebar_class_name: hidden ---- - -## Description -7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive - -Description: -This setting sets the default link type that a user will see when sharing content in OneDrive or SharePoint. It does not restrict or exclude any other options. -The recommended state is Specific people (only the people the user specifies) or Only people in your organization (more restrictive). - -Rationale: -By defaulting to specific people, the user will first need to consider whether or not the content being shared should be accessible by the entire organization versus select individuals. This aids in reinforcing the concept of least privilege. - -## Related Links - -* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) -* CIS 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1116.md b/website/docs/tests/maester/MT.1116.md deleted file mode 100644 index ca958356a..000000000 --- a/website/docs/tests/maester/MT.1116.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: MT.1116 - Ensure the SharePoint default sharing link permission is set -description: Ensure the SharePoint default sharing link permission is set -slug: /tests/MT.1116 -sidebar_class_name: hidden ---- - -## Description -7.2.11 (L1) Ensure the SharePoint default sharing link permission is set - -Description: -This setting configures the permission that is selected by default for sharing link from a SharePoint site. The recommended state is View. - -Rationale: -Setting the view permission as the default ensures that users must deliberately select the edit permission when sharing a link. This approach reduces the risk of unintentionally granting edit privileges to a resource that only requires read access, supporting the principle of least privilege. - -## Related Links - -* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) -* CIS 7.2.11 (L1) Ensure the SharePoint default sharing link permission is set \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1117.md b/website/docs/tests/maester/MT.1117.md deleted file mode 100644 index 25887dadf..000000000 --- a/website/docs/tests/maester/MT.1117.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: MT.1117 - Ensure guest access to a site or OneDrive will expire automatically -description: Ensure guest access to a site or OneDrive will expire automatically -slug: /tests/MT.1117 -sidebar_class_name: hidden ---- - -## Description -7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically - -Description: -This policy setting configures the expiration time for each guest that is invited to the SharePoint site or with whom users share individual files and folders with. -The recommended state is 30 or less. - -Rationale: -This setting ensures that guests who no longer need access to the site or link no longer have access after a set period of time. Allowing guest access for an indefinite amount of time could lead to loss of data confidentiality and oversight. -Note: Guest membership applies at the Microsoft 365 group level. Guests who have permission to view a SharePoint site or use a sharing link may also have access to a Microsoft Teams team or security group. - -Impact: -Site collection administrators will have to renew access to guests who still need access after 30 days. They will receive an e-mail notification once per week about guest access that is about to expire. -**Note:** The guest expiration policy only applies to guests who use sharing links or guests who have direct permissions to a SharePoint site after the guest policy is enabled. The guest policy does not apply to guest users that have pre-existing permissions or access through a sharing link before the guest expiration policy is applied - -## Related Links - -* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) -* CIS 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1118.md b/website/docs/tests/maester/MT.1118.md deleted file mode 100644 index 2c7785baf..000000000 --- a/website/docs/tests/maester/MT.1118.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: MT.1118 - Ensure that SharePoint guest users cannot share items they don't own -description: Ensure that SharePoint guest users cannot share items they don't own -slug: /tests/MT.1118 -sidebar_class_name: hidden ---- - -## Description -7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own - -Description: -SharePoint gives users the ability to share files, folders, and site collections. Internal users can share with external collaborators, and with the right permissions could share to other external parties. - -Rationale: -Sharing and collaboration are key; however, file, folder, or site collection owners should have the authority over what external users get shared with to prevent unauthorized disclosures of information. - -Impact: -The impact associated with this change is highly dependent upon current practices. If users do not regularly share with external parties, then minimal impact is likely. -However, if users do regularly share with guests/externally, minimum impacts could occur as those external users will be unable to 're-share' content. - -## Related Links - -* [Manage sharing settings for SharePoint and OneDrive in Microsoft 365 | Microsoft Learn](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) -* CIS 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own \ No newline at end of file diff --git a/website/docs/tests/maester/MT.1119.md b/website/docs/tests/maester/MT.1119.md deleted file mode 100644 index 4b052193b..000000000 --- a/website/docs/tests/maester/MT.1119.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: MT.1119 - Ensure Office 365 SharePoint infected files are disallowed for download -description: Ensure Office 365 SharePoint infected files are disallowed for download -slug: /tests/MT.1119 -sidebar_class_name: hidden ---- - -## Description -7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download - -Description: -By default, SharePoint online allows files that Defender for Office 365 has detected as infected to be downloaded. - -Rationale: -Defender for Office 365 for SharePoint, OneDrive, and Microsoft Teams protects your organization from inadvertently sharing malicious files. When an infected file is detected that file is blocked so that no one can open, copy, move, or share it until further actions are taken by the organization's security team. - -Impact: -The only potential impact associated with implementation of this setting is potential inconvenience associated with the small percentage of false positive detections that may occur. - -## Related Links - -* [Safe Attachments for SharePoint, OneDrive, and Microsoft Teams](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-configure?view=o365-worldwide#step-2-recommended-use-sharepoint-online-powershell-to-prevent-users-from-downloading-malicious-files) -* CIS 7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download \ No newline at end of file From e8f8ff68ed5c1b0250fdc01ba0dfe91ea69dbb27 Mon Sep 17 00:00:00 2001 From: -Mynster Date: Sun, 10 May 2026 13:04:11 +0200 Subject: [PATCH 20/31] intial fixes to markdown files --- powershell/public/cis/Test-MtCisSpoB2BIntegration.md | 5 ++++- powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md | 5 ++++- .../cis/Test-MtCisSpoDefaultSharingLinkPermission.md | 5 ++++- powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md | 5 ++++- .../public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md | 5 ++++- .../cis/Test-MtCisSpoPreventDownloadMaliciousFile.md | 7 +++++-- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/powershell/public/cis/Test-MtCisSpoB2BIntegration.md b/powershell/public/cis/Test-MtCisSpoB2BIntegration.md index 0d8cb2c78..0f14fe987 100644 --- a/powershell/public/cis/Test-MtCisSpoB2BIntegration.md +++ b/powershell/public/cis/Test-MtCisSpoB2BIntegration.md @@ -28,4 +28,7 @@ Set-SPOTenant -EnableAzureADB2BIntegration $true * [Enabling the integration](https://learn.microsoft.com/en-us/sharepoint/sharepoint-azureb2b-integration#enabling-the-integration) * [What is Microsoft Entra B2B collaboration?](https://learn.microsoft.com/en-us/entra/external-id/what-is-b2b) * [Set-SPOTenant](https://learn.microsoft.com/en-us/powershell/module/microsoft.online.sharepoint.powershell/set-spotenant?view=sharepoint-ps) -* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 368](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 368](https://www.cisecurity.org/benchmark/microsoft_365) + + +%TestResult% diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md index c3f024e41..71e7bc700 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.md @@ -34,4 +34,7 @@ Set-SPOTenant -DefaultSharingLinkType Internal ## Related Links * [Set-SPOTenant](https://learn.microsoft.com/en-us/powershell/module/microsoft.online.sharepoint.powershell/set-spotenant?view=sharepoint-ps) -* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 381](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 381](https://www.cisecurity.org/benchmark/microsoft_365) + + +%TestResult% diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.md b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.md index 2a6481fe8..27ce2ecbf 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.md +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.md @@ -33,4 +33,7 @@ Set-SPOTenant -DefaultLinkPermission View ## Related Links * [Manage sharing settings for SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#file-and-folder-links) -* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 391](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 391](https://www.cisecurity.org/benchmark/microsoft_365) + + +%TestResult% diff --git a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md index 28c56184b..f3c21dc1a 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md +++ b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.md @@ -38,4 +38,7 @@ Set-SPOTenant -ExternalUserExpireInDays 30 -ExternalUserExpirationRequired $True * [Manage sharing settings for SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) * [Managing SharePoint Online Security: A Team Effort](https://learn.microsoft.com/en-us/microsoft-365/community/sharepoint-security-a-team-effort) -* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 385](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 385](https://www.cisecurity.org/benchmark/microsoft_365) + + +%TestResult% diff --git a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md index 16b04e755..db979aae4 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md +++ b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.md @@ -32,4 +32,7 @@ Set-SPOTenant -PreventExternalUsersFromResharing $True * [Manage sharing settings for SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) * [Overview of external sharing in SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/external-sharing-overview) -* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 376](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 376](https://www.cisecurity.org/benchmark/microsoft_365) + + +%TestResult% diff --git a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.md b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.md index 221450b87..0b8385b17 100644 --- a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.md +++ b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.md @@ -18,7 +18,7 @@ The only potential impact associated with implementation of this setting is pote 2. Run the following PowerShell command to set the recommended value: ```powershell -Set-SPOTenant –DisallowInfectedFileDownload $true +Set-SPOTenant -DisallowInfectedFileDownload $true ``` >Note: The Global Reader role cannot access SharePoint using PowerShell according to Microsoft. See the reference section for more information. @@ -29,4 +29,7 @@ Set-SPOTenant –DisallowInfectedFileDownload $true * [Manage sharing settings for SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off#change-the-organization-level-external-sharing-setting) * [Overview of external sharing in SharePoint and OneDrive in Microsoft 365](https://learn.microsoft.com/en-us/sharepoint/external-sharing-overview) -* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 394](https://www.cisecurity.org/benchmark/microsoft_365) \ No newline at end of file +* [CIS Microsoft 365 Foundations Benchmark v6.0.1 - Page 394](https://www.cisecurity.org/benchmark/microsoft_365) + + +%TestResult% From 7e339992dd7fbd7e7ed368e7a6ea5a8fafa0bf18 Mon Sep 17 00:00:00 2001 From: -Mynster Date: Sun, 10 May 2026 13:10:35 +0200 Subject: [PATCH 21/31] update command based help --- .../cis/Test-MtCisSpoB2BIntegration.ps1 | 27 +++++++++---------- .../cis/Test-MtCisSpoDefaultSharingLink.ps1 | 25 ++++++++--------- ...t-MtCisSpoDefaultSharingLinkPermission.ps1 | 25 ++++++++--------- .../cis/Test-MtCisSpoGuestAccessExpiry.ps1 | 26 +++++++++--------- ...st-MtCisSpoGuestCannotShareUnownedItem.ps1 | 25 ++++++++--------- ...t-MtCisSpoPreventDownloadMaliciousFile.ps1 | 23 ++++++++-------- 6 files changed, 77 insertions(+), 74 deletions(-) diff --git a/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 index e7d4a11aa..e79b3a11c 100644 --- a/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 +++ b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 @@ -1,21 +1,20 @@ -<# -.SYNOPSIS - Ensure your SharePoint tenant is integrated with Microsoft Entra B2B for external sharing. +function Test-MtCisSpoB2BIntegration { + <# + .SYNOPSIS + Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled -.DESCRIPTION - Microsoft Entra B2B integration allows you to manage external sharing in SharePoint Online using Microsoft Entra. With this integration, you can use Microsoft Entra to control access to your SharePoint Online resources, including sites, lists, and libraries. This provides a more secure and streamlined way to manage external sharing in SharePoint Online. - When Microsoft Entra B2B integration is enabled, you can use Microsoft Entra to create and manage guest users, assign permissions, and monitor access to your SharePoint Online resources. This allows you to have better control over who can access your SharePoint Online resources and what they can do with them. - The recommended state is EnableAzureADB2BIntegration set to $true. + .DESCRIPTION + 7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled + CIS Microsoft 365 Foundations Benchmark v6.0.1 -.EXAMPLE - Test-MtCisSpoB2BIntegration + .EXAMPLE + Test-MtCisSpoB2BIntegration - Returns true if the SharePoint tenant is integrated with Microsoft Entra B2B, false otherwise. + Returns true if SharePoint and OneDrive integration with Azure AD B2B is enabled -.LINK - https://maester.dev/docs/commands/Test-MtCisSpoB2BIntegration -#> -function Test-MtCisSpoB2BIntegration { + .LINK + https://maester.dev/docs/commands/Test-MtCisSpoB2BIntegration + #> [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 index 19e3bb96b..61c96ccff 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 @@ -1,19 +1,20 @@ -<# -.SYNOPSIS - 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive +function Test-MtCisSpoDefaultSharingLink { + <# + .SYNOPSIS + Ensure link sharing is restricted in SharePoint and OneDrive -.DESCRIPTION - By default, the sharing link experience in SharePoint and OneDrive is set to "Anyone with the link". This means that when users share files or folders, the default option allows anyone with the link to access the content, which can lead to unintentional overexposure of sensitive information. By changing the default sharing link type to "Specific people", users are encouraged to be more deliberate about who they share content with, reducing the risk of unauthorized access and supporting a more secure sharing environment. + .DESCRIPTION + 7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive + CIS Microsoft 365 Foundations Benchmark v6.0.1 -.EXAMPLE - Test-MtCisSpoDefaultSharingLink + .EXAMPLE + Test-MtCisSpoDefaultSharingLink - Returns true if the default sharing link type is set to a restrictive option, false otherwise. + Returns true if link sharing is restricted in SharePoint and OneDrive -.LINK - https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLink -#> -function Test-MtCisSpoDefaultSharingLink { + .LINK + https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLink + #> [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 index 4a91c1a80..dca67d5f3 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 @@ -1,19 +1,20 @@ -<# -.SYNOPSIS - 7.2.11 (L1) Ensure the SharePoint default sharing link permission is set +function Test-MtCisSpoDefaultSharingLinkPermission { + <# + .SYNOPSIS + Ensure the SharePoint default sharing link permission is set -.DESCRIPTION - By default, the sharing link permission in SharePoint and OneDrive is set to "Edit". This means that when users share files or folders, the default option allows recipients to edit the content, which can lead to unintentional modifications or deletions of sensitive information. By changing the default sharing link permission to "View", users are encouraged to be more deliberate about granting edit permissions, reducing the risk of unauthorized changes and supporting a more secure sharing environment. + .DESCRIPTION + 7.2.11 (L1) Ensure the SharePoint default sharing link permission is set + CIS Microsoft 365 Foundations Benchmark v6.0.1 -.EXAMPLE - Test-MtCisSpoDefaultSharingLinkPermission + .EXAMPLE + Test-MtCisSpoDefaultSharingLinkPermission - Returns true if the default sharing link permission is set to a restrictive option, false otherwise. + Returns true if the SharePoint default sharing link permission is set to View -.LINK - https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission -#> -function Test-MtCisSpoDefaultSharingLinkPermission { + .LINK + https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission + #> [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 index d21ffa650..47cd20470 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 @@ -1,20 +1,20 @@ -<# -.SYNOPSIS - 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically +function Test-MtCisSpoGuestAccessExpiry { + <# + .SYNOPSIS + Ensure guest access to a site or OneDrive will expire automatically -.DESCRIPTION - By default, guest access to a SharePoint site or OneDrive does not expire. - This means that once a guest user is granted access to a site or OneDrive, they will have indefinite access until manually removed by an administrator. Enabling automatic expiration of guest access helps to ensure that external users do not retain access to sensitive information longer than necessary, reducing the risk of unauthorized access and supporting a more secure sharing environment. The recommended state is to enable guest access expiration and set it to 30 days or less. + .DESCRIPTION + 7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically + CIS Microsoft 365 Foundations Benchmark v6.0.1 -.EXAMPLE - Test-MtCisSpoGuestAccessExpiry + .EXAMPLE + Test-MtCisSpoGuestAccessExpiry - Returns true if guest access expiration is enabled and set to 30 days or less, false otherwise. + Returns true if guest access expiration is enabled and set to 30 days or less -.LINK - https://maester.dev/docs/commands/Test-MtCisSpoGuestAccessExpiry -#> -function Test-MtCisSpoGuestAccessExpiry { + .LINK + https://maester.dev/docs/commands/Test-MtCisSpoGuestAccessExpiry + #> [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 index 4b81779ff..e523662bc 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 @@ -1,19 +1,20 @@ -<# -.SYNOPSIS - Ensure that SharePoint guest users cannot share items they don't own +function Test-MtCisSpoGuestCannotShareUnownedItem { + <# + .SYNOPSIS + Ensure that SharePoint guest users cannot share items they don't own -.DESCRIPTION - By default, external users can share items they don't own. This means that if a guest user has access to an item, they can share it with others, potentially leading to unauthorized access and data leaks. By preventing external users from resharing items they don't own, you can help protect sensitive information and maintain better control over who has access to your SharePoint resources. The recommended state is PreventExternalUsersFromResharing set to $true. + .DESCRIPTION + 7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own + CIS Microsoft 365 Foundations Benchmark v6.0.1 -.EXAMPLE - Test-MtCisSpoGuestCannotShareUnownedItem + .EXAMPLE + Test-MtCisSpoGuestCannotShareUnownedItem - Returns true if external users are prevented from resharing items they don't own, false otherwise. + Returns true if SharePoint guest users cannot share items they don't own -.LINK - https://maester.dev/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem -#> -function Test-MtCisSpoGuestCannotShareUnownedItem { + .LINK + https://maester.dev/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem + #> [CmdletBinding()] [OutputType([bool])] param() diff --git a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 index 14cf43ea7..26035c628 100644 --- a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 +++ b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 @@ -1,19 +1,20 @@ -<# -.SYNOPSIS - Ensure malicious file download prevention is Enabled in SharePoint Online +function Test-MtCisSpoPreventDownloadMaliciousFile { + <# + .SYNOPSIS + Ensure Office 365 SharePoint infected files are disallowed for download -.DESCRIPTION - By default, users can't open, move, copy, or share* malicious files that are detected by Safe Attachments for SharePoint, OneDrive, and Microsoft Teams. However, they can delete and download malicious files. + .DESCRIPTION + 7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download + CIS Microsoft 365 Foundations Benchmark v6.0.1 -.EXAMPLE - Test-MtCisSpoPreventDownloadMaliciousFile + .EXAMPLE + Test-MtCisSpoPreventDownloadMaliciousFile - Returns true if malicious file download prevention is enabled in your SharePoint tenant, false otherwise. + Returns true if Office 365 SharePoint infected files are disallowed for download -.LINK - https://maester.dev/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile + .LINK + https://maester.dev/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile #> -function Test-MtCisSpoPreventDownloadMaliciousFile { [CmdletBinding()] [OutputType([bool])] param() From e68b36f1afed6a85b03d9a9516683ec9ba6fa295 Mon Sep 17 00:00:00 2001 From: -Mynster Date: Sun, 10 May 2026 19:42:18 +0200 Subject: [PATCH 22/31] updated code in cis tests --- powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 | 2 +- powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 | 2 +- .../public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 | 2 +- powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 | 2 +- .../public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 | 2 +- .../public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 index e79b3a11c..c74355f55 100644 --- a/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 +++ b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 @@ -22,7 +22,7 @@ $return = $true try { - $B2BIntegration = Get-SPOTenant | Select-Object -ExpandProperty EnableAzureADB2BIntegration + $B2BIntegration = Get-PnPTenant | Select-Object -ExpandProperty EnableAzureADB2BIntegration if ($B2BIntegration) { $testResult = "Well done. Your SharePoint tenant is integrated with Microsoft Entra B2B." } else { diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 index 61c96ccff..c70a5ca5c 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 @@ -22,7 +22,7 @@ $return = $true try { - $DefaultSharingLinkType = Get-SPOTenant | Select-Object -ExpandProperty DefaultSharingLinkType + $DefaultSharingLinkType = Get-PnPTenant | Select-Object -ExpandProperty DefaultSharingLinkType if ($DefaultSharingLinkType -eq "Direct" -or $DefaultSharingLinkType -eq "Internal") { $testResult = "Well done. Default sharing link type is set to a restrictive option." } else { diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 index dca67d5f3..53fd68d30 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 @@ -22,7 +22,7 @@ $return = $true try { - $DefaultLinkPermission = Get-SPOTenant | Select-Object -ExpandProperty DefaultLinkPermission + $DefaultLinkPermission = Get-PnPTenant | Select-Object -ExpandProperty DefaultLinkPermission if ($DefaultLinkPermission -eq "View") { $testResult = "Well done. Default sharing link permission is set to View." } else { diff --git a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 index 47cd20470..389824379 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 @@ -22,7 +22,7 @@ $return = $true try { - $spoTenant = Get-SPOTenant + $spoTenant = Get-PnPTenant if ($spoTenant.ExternalUserExpirationRequired -eq $true -and $spoTenant.ExternalUserExpireInDays -gt 0 -and $spoTenant.ExternalUserExpireInDays -le 30) { $testResult = "Well done. Guest access expiration is enabled and set to 30 days or less ($($spoTenant.ExternalUserExpireInDays) days)." } else { diff --git a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 index e523662bc..21a30ecf2 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 @@ -22,7 +22,7 @@ $return = $true try { - $PreventExternalUsersFromResharing = Get-SPOTenant | Select-Object -ExpandProperty PreventExternalUsersFromResharing + $PreventExternalUsersFromResharing = Get-PnPTenant | Select-Object -ExpandProperty PreventExternalUsersFromResharing if ($PreventExternalUsersFromResharing) { $testResult = "Well done. External users cannot share items they don't own." } else { diff --git a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 index 26035c628..78b74cfe6 100644 --- a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 +++ b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 @@ -22,7 +22,7 @@ $return = $true try { - $DisallowInfectedFileDownload = Get-SPOTenant | Select-Object -ExpandProperty DisallowInfectedFileDownload + $DisallowInfectedFileDownload = Get-PnPTenant | Select-Object -ExpandProperty DisallowInfectedFileDownload if ($DisallowInfectedFileDownload) { $testResult = "Well done. Malicious file download prevention is enabled in your SharePoint tenant." } else { From 1efb299702d470597d3b949c2c77cf2aef0ae06f Mon Sep 17 00:00:00 2001 From: -Mynster Date: Sun, 10 May 2026 20:12:40 +0200 Subject: [PATCH 23/31] added connection for Maester to PnP.PowerShell --- powershell/public/Connect-Maester.ps1 | 53 ++++++++++++++++++++++++-- website/docs/connect-maester/readme.md | 24 ++++++++++++ website/docs/installation.md | 4 +- 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index 82626c1a2..70398533d 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -72,6 +72,11 @@ Connects using a custom application with client ID f45ec3ad-32f0-4c06-8b69-47682afe0216 +.EXAMPLE + Connect-Maester -Service Graph,SharePointOnline + + Connects to Microsoft Graph and SharePoint Online. The SharePoint admin URL is auto-discovered from the tenant's initial domain via the Graph API. Optionally, specify -SharePointAdminUrl to override the auto-discovered URL (e.g. for custom domain or government cloud tenants). + .LINK https://maester.dev/docs/commands/Connect-Maester #> @@ -116,12 +121,16 @@ [string]$TenantId, # The Client ID of the app to connect to for Graph. If not specified, the default Graph PowerShell CLI enterprise app will be used. Reference on how to create an enterprise app: https://learn.microsoft.com/en-us/powershell/microsoftgraph/authentication-commands?view=graph-powershell-1.0#use-delegated-access-with-a-custom-application-for-microsoft-graph-powershell - [string]$GraphClientId + [string]$GraphClientId, + + # The SharePoint admin center URL to connect to when using the SharePointOnline service (e.g. https://contoso-admin.sharepoint.com). + # If not specified, the URL is auto-discovered from the tenant's initial domain via the Microsoft Graph API. + [string]$SharePointAdminUrl ) $__MtSession.Connections = $Service - $OrderedImport = Get-ModuleImportOrder -Name @('Az.Accounts', 'ExchangeOnlineManagement', 'Microsoft.Graph.Authentication', 'MicrosoftTeams') + $OrderedImport = Get-ModuleImportOrder -Name @('Az.Accounts', 'ExchangeOnlineManagement', 'Microsoft.Graph.Authentication', 'MicrosoftTeams', 'PnP.PowerShell') switch ($OrderedImport.Name) { 'Az.Accounts' { @@ -352,9 +361,47 @@ } } - 'Microsoft.Online.SharePoint.PowerShell' { + 'PnP.PowerShell' { if ($Service -contains 'SharePointOnline' -or $Service -contains 'All') { + Write-Verbose 'Connecting to SharePoint Online' + try { + $spoAdminUrl = $SharePointAdminUrl + if ([string]::IsNullOrEmpty($spoAdminUrl)) { + # Auto-discover the admin URL from the tenant's initial domain via Graph + $org = Invoke-MtGraphRequest -RelativeUri 'organization' -ErrorAction Stop + $tenantDomain = ($org.verifiedDomains | Where-Object { $_.isInitial -eq $true }) | Select-Object -ExpandProperty Name -First 1 + $spoAdminUrl = "https://$(($tenantDomain).Replace('.onmicrosoft.com', ''))-admin.sharepoint.com" + Write-Verbose "Auto-discovered SharePoint Admin URL: $spoAdminUrl" + } + + $pnpAzureEnv = switch ($AzureEnvironment) { + 'AzureChinaCloud' { 'China' } + 'AzureUSGovernment' { 'USGovernment' } + default { 'Production' } + } + + $pnpParams = @{ + Url = $spoAdminUrl + AzureEnvironment = $pnpAzureEnv + } + if ($UseDeviceCode) { + $resolveTenant = if ($TenantId) { $TenantId } else { (Get-MgContext -ErrorAction SilentlyContinue).TenantId } + if ($resolveTenant) { + $pnpParams['DeviceLogin'] = $true + $pnpParams['Tenant'] = $resolveTenant + } else { + Write-Host "`nDevice code login for SharePoint Online requires a -TenantId parameter." -ForegroundColor Red + } + } else { + $pnpParams['Interactive'] = $true + } + + Connect-PnPOnline @pnpParams + } catch [Management.Automation.CommandNotFoundException] { + Write-Host "`nThe PnP PowerShell module is not installed. Please install the module using the following command. For more information see https://pnp.github.io/powershell/" -ForegroundColor Red + Write-Host "`nInstall-Module PnP.PowerShell -Scope CurrentUser`n" -ForegroundColor Yellow + } } } } # end switch OrderedImport diff --git a/website/docs/connect-maester/readme.md b/website/docs/connect-maester/readme.md index b8392a9a9..2b4804559 100644 --- a/website/docs/connect-maester/readme.md +++ b/website/docs/connect-maester/readme.md @@ -77,6 +77,30 @@ The `-DeviceCode` switch allows you to sign in using the device code flow. This Connect-Maester -UseDeviceCode ``` +### Connect to SharePoint Online (optional) + +Maester includes SharePoint Online security tests that use the [PnP PowerShell](https://pnp.github.io/powershell/) module. + +Install the PnP PowerShell module if you haven't already: + +```powershell +Install-Module PnP.PowerShell -Scope CurrentUser +``` + +Connect to SharePoint Online together with Microsoft Graph (the admin URL is auto-discovered from your tenant's initial domain): + +```powershell +Connect-Maester -Service Graph,SharePointOnline +``` + +If auto-discovery does not work (e.g. in government or custom-domain tenants), supply the admin URL explicitly: + +```powershell +Connect-Maester -Service Graph,SharePointOnline -SharePointAdminUrl 'https://contoso-admin.sharepoint.com' +``` + +If the PnP PowerShell module is not installed or there is no active connection, all SharePoint Online tests are skipped automatically. + ### Connect to Azure, Exchange Online, Copilot Studio and Teams `Connect-Maester` also provides options to connect to Azure, Copilot Studio (via the Dataverse API), Exchange Online and Teams for running tests that use the Azure PowerShell, Dataverse OData API, Exchange Online PowerShell or Teams PowerShell modules. diff --git a/website/docs/installation.md b/website/docs/installation.md index 653c9e91f..505aadf9f 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -28,10 +28,10 @@ To learn more about the `Invoke-Maester` cmdlet including how to filter tests, a Maester includes optional [CISA](tests/cisa/) tests that require additional permissions and modules to run. These optional tests are skipped if the modules are not installed or there is no active connection. -### Installing Azure, Exchange Online, and Teams modules +### Installing Azure, Exchange Online, Teams and PnP.PowerShell modules ```powershell -Install-Module Az.Accounts, ExchangeOnlineManagement, MicrosoftTeams -Scope CurrentUser +Install-Module Az.Accounts, ExchangeOnlineManagement, MicrosoftTeams, PnP.PowerShell -Scope CurrentUser ``` > The Security & Compliance PowerShell module is dependent on the ExchangeOnlineManagement `Connect-IPPSSession` cmdlet. From eb4c6b828b0772c1070d75b5ad6c7686545c50a7 Mon Sep 17 00:00:00 2001 From: -Mynster Date: Sun, 10 May 2026 20:13:10 +0200 Subject: [PATCH 24/31] added test and skip reason for NotConnectedSharePointOnline --- powershell/internal/Get-MtSkippedReason.ps1 | 55 ++++++++++---------- powershell/public/Add-MtTestResultDetail.ps1 | 18 +++---- powershell/public/core/Test-MtConnection.ps1 | 37 +++++++++---- 3 files changed, 63 insertions(+), 47 deletions(-) diff --git a/powershell/internal/Get-MtSkippedReason.ps1 b/powershell/internal/Get-MtSkippedReason.ps1 index 3e7c806ac..381c05b27 100644 --- a/powershell/internal/Get-MtSkippedReason.ps1 +++ b/powershell/internal/Get-MtSkippedReason.ps1 @@ -8,32 +8,33 @@ [string] $SkippedBecause ) - switch($SkippedBecause){ - "NotConnectedAzure" { "Not connected to Azure. See [Connecting to Azure](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break} - "NotConnectedExchange" { "Not connected to Exchange Online. See [Connecting to Exchange Online](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break} - "NotConnectedSecurityCompliance" { "Not connected to Security & Compliance. See [Connecting to Security & Compliance](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break} - "NotConnectedTeams" { "Not connected to Teams. See [Connecting to Teams](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break} - "NotConnectedAzureDevOps" { "Not connected to Azure DevOps. See [Connecting to Azure DevOps](https://maester.dev/docs/connect-maester/#connect-to-azure-devops-optional)"; break} - "NotConnectedGraph" { "Not connected to Graph. See [Connect-Maester](https://maester.dev/docs/commands/Connect-Maester#examples)"; break} - "NotDotGovDomain" { "This test is only for federal, executive branch, departments and agencies. To override use [Test-MtCisaDmarcAggregateCisa -Force](https://maester.dev/docs/commands/Test-MtCisaDmarcAggregateCisa)"; break} - "NotLicensedEntraIDP1" { "This test is for tenants that are licensed for Entra ID P1. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break} - "NotLicensedEntraIDP2" { "This test is for tenants that are licensed for Entra ID P2. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break} - "NotLicensedEntraIDGovernance" { "This test is for tenants that are licensed for Entra ID Governance. See [Entra ID Governance licensing](https://learn.microsoft.com/entra/fundamentals/licensing#microsoft-entra-id-governance)"; break} - "NotLicensedEntraWorkloadID" { "This test is for tenants that are licensed for Entra Workload ID. See [Entra Workload ID licensing](https://learn.microsoft.com/entra/workload-id/workload-identities-faqs)"; break} - "NotLicensedEop" { "This test is for tenants that are licensed for Exchange Online Protection. See [Exchange Online Protection service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/exchange-online-protection-service-description/exchange-online-protection-service-description)"; break} - "NotLicensedExoDlp" { "This test is for tenants that are licensed for Exchange Online DLP. See [Microsoft Purview Data Loss Prevention: Data Loss Prevention (DLP) for Exchange Online, SharePoint Online, and OneDrive for Business](https://learn.microsoft.com/en-us/office365/servicedescriptions/microsoft-365-service-descriptions/microsoft-365-tenantlevel-services-licensing-guidance/microsoft-365-security-compliance-licensing-guidance#which-licenses-provide-the-rights-for-a-user-to-benefit-from-the-service-7)"; break} - "NotLicensedMdo" { "This test is for tenants that are licensed for Defender for Office 365 Plan 2. See [Microsoft Defender for Office 365 service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/office-365-advanced-threat-protection-service-description)"; break} - "NotLicensedMdoP2" { "This test is for tenants that are licensed for Defender for Office 365 Plan 2. See [Microsoft Defender for Office 365 service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/office-365-advanced-threat-protection-service-description)"; break} - "NotLicensedMdoP1" { "This test is for tenants that are licensed for Defender for Office 365 Plan 1. See [Microsoft Defender for Office 365 service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/office-365-advanced-threat-protection-service-description)"; break} - "NotLicensedAdvAudit" { "This test is for tenants that are licensed for Advanced Audit. See [Learn about auditing solutions in Microsoft Purview](https://learn.microsoft.com/en-us/purview/audit-solutions-overview#licensing-requirements)"; break} - "LicensedEntraIDPremium" { "This test is for tenants that are not licensed for any Entra ID Premium license. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break} - "NotSupported" { "This test relies on capabilities not currently available (e.g., cmdlets that are not available on all platforms, Resolve-DnsName)"; break} - "NotSupportedAppPermission" { "This test relies on Graph APIs that don't support application permissions. Re-run Maester with a user signed in to view the results for this test."; break} - "LimitedPermissions" { "This test relies on privileged (i.e., ReadWrite) permissions."; break} - "NotLicensedDefenderXDR" { "This test is for tenants that are licensed for Microsoft Defender XDR. See [Microsoft Defender XDR prerequisites](https://learn.microsoft.com/en-us/defender-xdr/prerequisites#licensing-requirements)"; break} - "NotLicensedIntune" { "This test is for tenants that are licensed for Microsoft Intune. See [Intune licensing](https://learn.microsoft.com/intune/intune-service/fundamentals/licenses)"; break} - "NotAuthorized" { "This test was skipped because the user is not authorized to perform the required operation."; break} - "Error" { $SkippedBecause; break} - default { $SkippedBecause; break} + switch ($SkippedBecause) { + "NotConnectedAzure" { "Not connected to Azure. See [Connecting to Azure](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break } + "NotConnectedExchange" { "Not connected to Exchange Online. See [Connecting to Exchange Online](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break } + "NotConnectedSecurityCompliance" { "Not connected to Security & Compliance. See [Connecting to Security & Compliance](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break } + "NotConnectedTeams" { "Not connected to Teams. See [Connecting to Teams](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break } + "NotConnectedAzureDevOps" { "Not connected to Azure DevOps. See [Connecting to Azure DevOps](https://maester.dev/docs/connect-maester/#connect-to-azure-devops-optional)"; break } + "NotConnectedGraph" { "Not connected to Graph. See [Connect-Maester](https://maester.dev/docs/commands/Connect-Maester#examples)"; break } + "NotConnectedSharePointOnline" { "Not connected to SharePoint Online. See [Connecting to SharePoint Online](https://maester.dev/docs/connect-maester/#connect-to-sharepoint-online-optional)"; break } + "NotDotGovDomain" { "This test is only for federal, executive branch, departments and agencies. To override use [Test-MtCisaDmarcAggregateCisa -Force](https://maester.dev/docs/commands/Test-MtCisaDmarcAggregateCisa)"; break } + "NotLicensedEntraIDP1" { "This test is for tenants that are licensed for Entra ID P1. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break } + "NotLicensedEntraIDP2" { "This test is for tenants that are licensed for Entra ID P2. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break } + "NotLicensedEntraIDGovernance" { "This test is for tenants that are licensed for Entra ID Governance. See [Entra ID Governance licensing](https://learn.microsoft.com/entra/fundamentals/licensing#microsoft-entra-id-governance)"; break } + "NotLicensedEntraWorkloadID" { "This test is for tenants that are licensed for Entra Workload ID. See [Entra Workload ID licensing](https://learn.microsoft.com/entra/workload-id/workload-identities-faqs)"; break } + "NotLicensedEop" { "This test is for tenants that are licensed for Exchange Online Protection. See [Exchange Online Protection service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/exchange-online-protection-service-description/exchange-online-protection-service-description)"; break } + "NotLicensedExoDlp" { "This test is for tenants that are licensed for Exchange Online DLP. See [Microsoft Purview Data Loss Prevention: Data Loss Prevention (DLP) for Exchange Online, SharePoint Online, and OneDrive for Business](https://learn.microsoft.com/en-us/office365/servicedescriptions/microsoft-365-service-descriptions/microsoft-365-tenantlevel-services-licensing-guidance/microsoft-365-security-compliance-licensing-guidance#which-licenses-provide-the-rights-for-a-user-to-benefit-from-the-service-7)"; break } + "NotLicensedMdo" { "This test is for tenants that are licensed for Defender for Office 365 Plan 2. See [Microsoft Defender for Office 365 service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/office-365-advanced-threat-protection-service-description)"; break } + "NotLicensedMdoP2" { "This test is for tenants that are licensed for Defender for Office 365 Plan 2. See [Microsoft Defender for Office 365 service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/office-365-advanced-threat-protection-service-description)"; break } + "NotLicensedMdoP1" { "This test is for tenants that are licensed for Defender for Office 365 Plan 1. See [Microsoft Defender for Office 365 service description](https://learn.microsoft.com/en-us/office365/servicedescriptions/office-365-advanced-threat-protection-service-description)"; break } + "NotLicensedAdvAudit" { "This test is for tenants that are licensed for Advanced Audit. See [Learn about auditing solutions in Microsoft Purview](https://learn.microsoft.com/en-us/purview/audit-solutions-overview#licensing-requirements)"; break } + "LicensedEntraIDPremium" { "This test is for tenants that are not licensed for any Entra ID Premium license. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break } + "NotSupported" { "This test relies on capabilities not currently available (e.g., cmdlets that are not available on all platforms, Resolve-DnsName)"; break } + "NotSupportedAppPermission" { "This test relies on Graph APIs that don't support application permissions. Re-run Maester with a user signed in to view the results for this test."; break } + "LimitedPermissions" { "This test relies on privileged (i.e., ReadWrite) permissions."; break } + "NotLicensedDefenderXDR" { "This test is for tenants that are licensed for Microsoft Defender XDR. See [Microsoft Defender XDR prerequisites](https://learn.microsoft.com/en-us/defender-xdr/prerequisites#licensing-requirements)"; break } + "NotLicensedIntune" { "This test is for tenants that are licensed for Microsoft Intune. See [Intune licensing](https://learn.microsoft.com/intune/intune-service/fundamentals/licenses)"; break } + "NotAuthorized" { "This test was skipped because the user is not authorized to perform the required operation."; break } + "Error" { $SkippedBecause; break } + default { $SkippedBecause; break } } } diff --git a/powershell/public/Add-MtTestResultDetail.ps1 b/powershell/public/Add-MtTestResultDetail.ps1 index 93cff417e..e13da27a2 100644 --- a/powershell/public/Add-MtTestResultDetail.ps1 +++ b/powershell/public/Add-MtTestResultDetail.ps1 @@ -77,7 +77,7 @@ [ValidateSet('NotConnectedAzure', 'NotConnectedExchange', 'NotConnectedGraph', 'NotDotGovDomain', 'NotLicensedEntraIDP1', 'NotConnectedSecurityCompliance', 'NotConnectedTeams', 'NotLicensedEntraIDP2', 'NotLicensedEntraIDGovernance', 'NotLicensedEntraWorkloadID', 'NotLicensedExoDlp', "LicensedEntraIDPremium", 'NotSupported', 'Custom', 'NotLicensedMdo', 'NotLicensedMdoP2', 'NotLicensedMdoP1', 'NotLicensedAdvAudit', 'NotLicensedEop', 'Error', 'NotSupportedAppPermission', 'LimitedPermissions', 'NotLicensedDefenderXDR', - 'NotLicensedCustomerLockbox','NotAuthorized', 'NotLicensedIntune', 'NotConnectedAzureDevOps' + 'NotLicensedCustomerLockbox', 'NotAuthorized', 'NotLicensedIntune', 'NotConnectedAzureDevOps', 'NotConnectedSharePointOnline' )] [string] $SkippedBecause, @@ -197,14 +197,14 @@ $TestInvestigate = $Investigate.IsPresent $testInfo = @{ - TestTitle = $TestTitle - TestDescription = $Description - TestResult = $Result - TestSkipped = $SkippedBecause - SkippedReason = $SkippedReason - TestInvestigate = $TestInvestigate - Severity = $Severity - Service = $Service + TestTitle = $TestTitle + TestDescription = $Description + TestResult = $Result + TestSkipped = $SkippedBecause + SkippedReason = $SkippedReason + TestInvestigate = $TestInvestigate + Severity = $Severity + Service = $Service } Write-MtProgress -Activity "Running tests" -Status $testName diff --git a/powershell/public/core/Test-MtConnection.ps1 b/powershell/public/core/Test-MtConnection.ps1 index 3c2157426..4da049017 100644 --- a/powershell/public/core/Test-MtConnection.ps1 +++ b/powershell/public/core/Test-MtConnection.ps1 @@ -7,7 +7,7 @@ Tests the connection for each service and returns $true if the session is connected to the specified service. .PARAMETER Service - The service to check the connection for. Valid values are 'All', 'Azure', 'AzureDevOps', 'ExchangeOnline', 'Graph', 'SecurityCompliance' (or 'EOP'), and 'Teams'. Default is 'Graph'. + The service to check the connection for. Valid values are 'All', 'Azure', 'AzureDevOps', 'ExchangeOnline', 'Graph', 'SecurityCompliance' (or 'EOP'), 'SharePointOnline', and 'Teams'. Default is 'Graph'. .PARAMETER Details Return the full details of all connections instead of just a boolean value. @@ -15,12 +15,12 @@ .EXAMPLE Test-MtConnection -Service All - Checks if the current session is connected to all services including Azure, Microsoft Graph, Exchange Online, Exchange Online Protection (SecurityCompliance), and Microsoft Teams. Returns a Boolean value. + Checks if the current session is connected to all services including Azure, Microsoft Graph, Exchange Online, Exchange Online Protection (SecurityCompliance), SharePoint Online (PnP), and Microsoft Teams. Returns a Boolean value. .EXAMPLE Test-MtConnection -Service All -Details - Checks if the current session is connected to all services including Azure, Microsoft Graph, Exchange Online, Exchange Online Protection (SecurityCompliance), and Microsoft Teams. Returns a custom object that contains the connection details for all services. + Checks if the current session is connected to all services including Azure, Microsoft Graph, Exchange Online, Exchange Online Protection (SecurityCompliance), SharePoint Online (PnP), and Microsoft Teams. Returns a custom object that contains the connection details for all services. .EXAMPLE Test-MtConnection -Service Azure @@ -35,7 +35,7 @@ [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', 'AvoidUsingWriteHost', Justification = 'Sending colorful output to host in addition to rich object output.')] param( # Checks if the current session is connected to the specified service - [ValidateSet('All', 'Azure', 'AzureDevOps', 'ExchangeOnline', 'EOP', 'Graph', 'SecurityCompliance', 'Teams')] + [ValidateSet('All', 'Azure', 'AzureDevOps', 'ExchangeOnline', 'EOP', 'Graph', 'SecurityCompliance', 'SharePointOnline', 'Teams')] [Parameter(Position = 0)] [string[]]$Service = 'Graph', @@ -46,14 +46,15 @@ begin { $MtConnections = [PSCustomObject]@{ - PSTypeName = 'Maester.Connections' - Azure = $null - AzureDevOps = $null - Graph = $null - ExchangeOnline = $null + PSTypeName = 'Maester.Connections' + Azure = $null + AzureDevOps = $null + Graph = $null + ExchangeOnline = $null ExchangeOnlineProtection = $null - Teams = $null - AllConnected = $false + SharePointOnline = $null + Teams = $null + AllConnected = $false } # This can potentially be replaced by $MtConnections.AllConnected but all functions that reference this function would need to be updated. @@ -147,6 +148,20 @@ } #endregion Teams + #region SharePointOnline + if ($Service -contains 'SharePointOnline' -or $Service -contains 'All') { + $IsConnected = $false + try { + $MtConnections.SharePointOnline = Get-PnPConnection -ErrorAction Stop + $IsConnected = $null -ne ($MtConnections.SharePointOnline) + } catch { + Write-Debug "SharePoint Online: $false" + } + Write-Verbose "SharePoint Online: $IsConnected" + if (!$IsConnected) { $ConnectionState = $false } + } + #endregion SharePointOnline + #region AzureDevOps if ($Service -contains 'AzureDevOps' -or $Service -contains 'All') { $IsConnected = $false From 21c805dd9189054376b9a7a848b9e1038a8e951d Mon Sep 17 00:00:00 2001 From: -Mynster Date: Sun, 10 May 2026 20:13:28 +0200 Subject: [PATCH 25/31] updated commands with test for SharePointOnline --- powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 | 5 +++++ powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 | 5 +++++ .../public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 | 5 +++++ powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 | 5 +++++ .../public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 | 5 +++++ .../public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 | 5 +++++ 6 files changed, 30 insertions(+) diff --git a/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 index c74355f55..b1aa6c8c6 100644 --- a/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 +++ b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 @@ -20,6 +20,11 @@ param() Write-Verbose "Testing SharePoint Entra B2B integration..." + if (!(Test-MtConnection SharePointOnline)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + return $null + } + $return = $true try { $B2BIntegration = Get-PnPTenant | Select-Object -ExpandProperty EnableAzureADB2BIntegration diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 index c70a5ca5c..6a2e32001 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 @@ -20,6 +20,11 @@ param() Write-Verbose "Testing default sharing link type in SharePoint Online..." + if (!(Test-MtConnection SharePointOnline)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + return $null + } + $return = $true try { $DefaultSharingLinkType = Get-PnPTenant | Select-Object -ExpandProperty DefaultSharingLinkType diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 index 53fd68d30..76f6f7329 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 @@ -20,6 +20,11 @@ param() Write-Verbose "Testing default sharing link permission in SharePoint Online..." + if (!(Test-MtConnection SharePointOnline)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + return $null + } + $return = $true try { $DefaultLinkPermission = Get-PnPTenant | Select-Object -ExpandProperty DefaultLinkPermission diff --git a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 index 389824379..7e29a19a3 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 @@ -20,6 +20,11 @@ param() Write-Verbose "Testing guest access expiration settings in SharePoint Online..." + if (!(Test-MtConnection SharePointOnline)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + return $null + } + $return = $true try { $spoTenant = Get-PnPTenant diff --git a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 index 21a30ecf2..24891bd32 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 @@ -20,6 +20,11 @@ param() Write-Verbose "Testing that SharePoint guest users cannot share items they don't own..." + if (!(Test-MtConnection SharePointOnline)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + return $null + } + $return = $true try { $PreventExternalUsersFromResharing = Get-PnPTenant | Select-Object -ExpandProperty PreventExternalUsersFromResharing diff --git a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 index 78b74cfe6..bfeb22993 100644 --- a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 +++ b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 @@ -20,6 +20,11 @@ param() Write-Verbose "Testing malicious file download prevention in SharePoint Online..." + if (!(Test-MtConnection SharePointOnline)) { + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + return $null + } + $return = $true try { $DisallowInfectedFileDownload = Get-PnPTenant | Select-Object -ExpandProperty DisallowInfectedFileDownload From 9d774544f30b6ae3ddd326ec4a310b0b15e0f8f5 Mon Sep 17 00:00:00 2001 From: -Mynster Date: Sun, 10 May 2026 20:30:28 +0200 Subject: [PATCH 26/31] added files from update-commandreference due tothis error from build Exhaustive list of all broken links found: - Broken link on source page path = /docs/next/tests/CIS.M365.7.2.11: -> linking to /docs/commands/Test-MtCisSpoDefaultSharingLinkPermission - Broken link on source page path = /docs/next/tests/CIS.M365.7.2.2: -> linking to /docs/commands/Test-MtCisSpoB2BIntegration - Broken link on source page path = /docs/next/tests/CIS.M365.7.2.5: -> linking to /docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem - Broken link on source page path = /docs/next/tests/CIS.M365.7.2.7: -> linking to /docs/commands/Test-MtCisSpoDefaultSharingLink - Broken link on source page path = /docs/next/tests/CIS.M365.7.2.9: -> linking to /docs/commands/Test-MtCisSpoGuestAccessExpiry - Broken link on source page path = /docs/next/tests/CIS.M365.7.3.1: -> linking to /docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile --- .../docs/commands/Add-MtTestResultDetail.mdx | 2 +- website/docs/commands/Connect-Maester.mdx | 33 ++++++++- .../commands/Test-MtCisSpoB2BIntegration.mdx | 68 +++++++++++++++++++ .../Test-MtCisSpoDefaultSharingLink.mdx | 68 +++++++++++++++++++ ...t-MtCisSpoDefaultSharingLinkPermission.mdx | 68 +++++++++++++++++++ .../Test-MtCisSpoGuestAccessExpiry.mdx | 68 +++++++++++++++++++ ...st-MtCisSpoGuestCannotShareUnownedItem.mdx | 68 +++++++++++++++++++ ...t-MtCisSpoPreventDownloadMaliciousFile.mdx | 68 +++++++++++++++++++ website/docs/commands/Test-MtConnection.mdx | 8 +-- .../commands/Test-MtCisSpoB2BIntegration.mdx | 68 +++++++++++++++++++ .../Test-MtCisSpoDefaultSharingLink.mdx | 68 +++++++++++++++++++ ...t-MtCisSpoDefaultSharingLinkPermission.mdx | 68 +++++++++++++++++++ .../Test-MtCisSpoGuestAccessExpiry.mdx | 68 +++++++++++++++++++ ...st-MtCisSpoGuestCannotShareUnownedItem.mdx | 68 +++++++++++++++++++ ...t-MtCisSpoPreventDownloadMaliciousFile.mdx | 68 +++++++++++++++++++ 15 files changed, 852 insertions(+), 7 deletions(-) create mode 100644 website/docs/commands/Test-MtCisSpoB2BIntegration.mdx create mode 100644 website/docs/commands/Test-MtCisSpoDefaultSharingLink.mdx create mode 100644 website/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission.mdx create mode 100644 website/docs/commands/Test-MtCisSpoGuestAccessExpiry.mdx create mode 100644 website/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem.mdx create mode 100644 website/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile.mdx create mode 100644 website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoB2BIntegration.mdx create mode 100644 website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoDefaultSharingLink.mdx create mode 100644 website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoDefaultSharingLinkPermission.mdx create mode 100644 website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoGuestAccessExpiry.mdx create mode 100644 website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoGuestCannotShareUnownedItem.mdx create mode 100644 website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoPreventDownloadMaliciousFile.mdx diff --git a/website/docs/commands/Add-MtTestResultDetail.mdx b/website/docs/commands/Add-MtTestResultDetail.mdx index 204e2b5c0..f9b46d3fa 100644 --- a/website/docs/commands/Add-MtTestResultDetail.mdx +++ b/website/docs/commands/Add-MtTestResultDetail.mdx @@ -1,6 +1,6 @@ --- sidebar_class_name: hidden -description: Add detailed information about a test so that it can be displayed in the test results report. +description: "Add detailed information about a test so that it can be displayed in the test results report." id: Add-MtTestResultDetail title: Add-MtTestResultDetail hide_title: false diff --git a/website/docs/commands/Connect-Maester.mdx b/website/docs/commands/Connect-Maester.mdx index 6286938cd..4f7db824e 100644 --- a/website/docs/commands/Connect-Maester.mdx +++ b/website/docs/commands/Connect-Maester.mdx @@ -1,6 +1,6 @@ --- sidebar_class_name: hidden -description: Helper method to connect to Microsoft Graph using Connect-MgGraph with the required permission scopes as well as other services such as Azure and Exchange Online. +description: "Helper method to connect to Microsoft Graph using Connect-MgGraph with the required permission scopes as well as other services such as Azure and Exchange Online." id: Connect-Maester title: Connect-Maester hide_title: false @@ -17,7 +17,7 @@ Helper method to connect to Microsoft Graph using Connect-MgGraph with the requi ```powershell Connect-Maester [-SendMail] [-SendTeamsMessage] [-Privileged] [-UseDeviceCode] [[-Environment] ] [[-AzureEnvironment] ] [[-ExchangeEnvironmentName] ] [[-TeamsEnvironmentName] ] - [[-Service] ] [[-TenantId] ] [[-GraphClientId] ] + [[-Service] ] [[-TenantId] ] [[-GraphClientId] ] [[-SharePointAdminUrl] ] [-ProgressAction ] [] ``` @@ -133,6 +133,17 @@ Connect-Maester -GraphClientId 'f45ec3ad-32f0-4c06-8b69-47682afe0216' Connects using a custom application with client ID f45ec3ad-32f0-4c06-8b69-47682afe0216 +### EXAMPLE 13 + +```powershell +Connect-Maester -Service Graph,SharePointOnline +``` + +Connects to Microsoft Graph and SharePoint Online. +The SharePoint admin URL is auto-discovered from the tenant's initial domain via the Graph API. +Optionally, specify -SharePointAdminUrl to override the auto-discovered URL (e.g. +for custom domain or government cloud tenants). + ## PARAMETERS ### -SendMail @@ -323,6 +334,24 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -SharePointAdminUrl + +The SharePoint admin center URL to connect to when using the SharePointOnline service (e.g. +https://contoso-admin.sharepoint.com). +If not specified, the URL is auto-discovered from the tenant's initial domain via the Microsoft Graph API. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: 8 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -ProgressAction \{\{ Fill ProgressAction Description \}\} diff --git a/website/docs/commands/Test-MtCisSpoB2BIntegration.mdx b/website/docs/commands/Test-MtCisSpoB2BIntegration.mdx new file mode 100644 index 000000000..45c878619 --- /dev/null +++ b/website/docs/commands/Test-MtCisSpoB2BIntegration.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled" +id: Test-MtCisSpoB2BIntegration +title: Test-MtCisSpoB2BIntegration +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoB2BIntegration.ps1 +--- + +## SYNOPSIS + +Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled + +## SYNTAX + +```powershell +Test-MtCisSpoB2BIntegration [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoB2BIntegration +``` + +Returns true if SharePoint and OneDrive integration with Azure AD B2B is enabled + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoB2BIntegration](https://maester.dev/docs/commands/Test-MtCisSpoB2BIntegration) diff --git a/website/docs/commands/Test-MtCisSpoDefaultSharingLink.mdx b/website/docs/commands/Test-MtCisSpoDefaultSharingLink.mdx new file mode 100644 index 000000000..edebb3ef1 --- /dev/null +++ b/website/docs/commands/Test-MtCisSpoDefaultSharingLink.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure link sharing is restricted in SharePoint and OneDrive" +id: Test-MtCisSpoDefaultSharingLink +title: Test-MtCisSpoDefaultSharingLink +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoDefaultSharingLink.ps1 +--- + +## SYNOPSIS + +Ensure link sharing is restricted in SharePoint and OneDrive + +## SYNTAX + +```powershell +Test-MtCisSpoDefaultSharingLink [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoDefaultSharingLink +``` + +Returns true if link sharing is restricted in SharePoint and OneDrive + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLink](https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLink) diff --git a/website/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission.mdx b/website/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission.mdx new file mode 100644 index 000000000..e1ffc815a --- /dev/null +++ b/website/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure the SharePoint default sharing link permission is set" +id: Test-MtCisSpoDefaultSharingLinkPermission +title: Test-MtCisSpoDefaultSharingLinkPermission +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoDefaultSharingLinkPermission.ps1 +--- + +## SYNOPSIS + +Ensure the SharePoint default sharing link permission is set + +## SYNTAX + +```powershell +Test-MtCisSpoDefaultSharingLinkPermission [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.11 (L1) Ensure the SharePoint default sharing link permission is set +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoDefaultSharingLinkPermission +``` + +Returns true if the SharePoint default sharing link permission is set to View + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission](https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission) diff --git a/website/docs/commands/Test-MtCisSpoGuestAccessExpiry.mdx b/website/docs/commands/Test-MtCisSpoGuestAccessExpiry.mdx new file mode 100644 index 000000000..1480bba22 --- /dev/null +++ b/website/docs/commands/Test-MtCisSpoGuestAccessExpiry.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure guest access to a site or OneDrive will expire automatically" +id: Test-MtCisSpoGuestAccessExpiry +title: Test-MtCisSpoGuestAccessExpiry +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoGuestAccessExpiry.ps1 +--- + +## SYNOPSIS + +Ensure guest access to a site or OneDrive will expire automatically + +## SYNTAX + +```powershell +Test-MtCisSpoGuestAccessExpiry [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoGuestAccessExpiry +``` + +Returns true if guest access expiration is enabled and set to 30 days or less + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoGuestAccessExpiry](https://maester.dev/docs/commands/Test-MtCisSpoGuestAccessExpiry) diff --git a/website/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem.mdx b/website/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem.mdx new file mode 100644 index 000000000..fa1d8c865 --- /dev/null +++ b/website/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure that SharePoint guest users cannot share items they don't own" +id: Test-MtCisSpoGuestCannotShareUnownedItem +title: Test-MtCisSpoGuestCannotShareUnownedItem +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 +--- + +## SYNOPSIS + +Ensure that SharePoint guest users cannot share items they don't own + +## SYNTAX + +```powershell +Test-MtCisSpoGuestCannotShareUnownedItem [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoGuestCannotShareUnownedItem +``` + +Returns true if SharePoint guest users cannot share items they don't own + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem](https://maester.dev/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem) diff --git a/website/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile.mdx b/website/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile.mdx new file mode 100644 index 000000000..dada85944 --- /dev/null +++ b/website/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure Office 365 SharePoint infected files are disallowed for download" +id: Test-MtCisSpoPreventDownloadMaliciousFile +title: Test-MtCisSpoPreventDownloadMaliciousFile +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 +--- + +## SYNOPSIS + +Ensure Office 365 SharePoint infected files are disallowed for download + +## SYNTAX + +```powershell +Test-MtCisSpoPreventDownloadMaliciousFile [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoPreventDownloadMaliciousFile +``` + +Returns true if Office 365 SharePoint infected files are disallowed for download + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile](https://maester.dev/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile) diff --git a/website/docs/commands/Test-MtConnection.mdx b/website/docs/commands/Test-MtConnection.mdx index dd88c02f4..520190261 100644 --- a/website/docs/commands/Test-MtConnection.mdx +++ b/website/docs/commands/Test-MtConnection.mdx @@ -1,6 +1,6 @@ --- sidebar_class_name: hidden -description: Checks if the current session is connected to the specified service. +description: "Checks if the current session is connected to the specified service." id: Test-MtConnection title: Test-MtConnection hide_title: false @@ -31,7 +31,7 @@ Tests the connection for each service and returns $true if the session is connec Test-MtConnection -Service All ``` -Checks if the current session is connected to all services including Azure, Microsoft Graph, Exchange Online, Exchange Online Protection (SecurityCompliance), and Microsoft Teams. +Checks if the current session is connected to all services including Azure, Microsoft Graph, Exchange Online, Exchange Online Protection (SecurityCompliance), SharePoint Online (PnP), and Microsoft Teams. Returns a Boolean value. ### EXAMPLE 2 @@ -40,7 +40,7 @@ Returns a Boolean value. Test-MtConnection -Service All -Details ``` -Checks if the current session is connected to all services including Azure, Microsoft Graph, Exchange Online, Exchange Online Protection (SecurityCompliance), and Microsoft Teams. +Checks if the current session is connected to all services including Azure, Microsoft Graph, Exchange Online, Exchange Online Protection (SecurityCompliance), SharePoint Online (PnP), and Microsoft Teams. Returns a custom object that contains the connection details for all services. ### EXAMPLE 3 @@ -56,7 +56,7 @@ Checks if the current session is connected to Azure and returns a Boolean result ### -Service The service to check the connection for. -Valid values are 'All', 'Azure', 'AzureDevOps', 'ExchangeOnline', 'Graph', 'SecurityCompliance' (or 'EOP'), and 'Teams'. +Valid values are 'All', 'Azure', 'AzureDevOps', 'ExchangeOnline', 'Graph', 'SecurityCompliance' (or 'EOP'), 'SharePointOnline', and 'Teams'. Default is 'Graph'. ```yaml diff --git a/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoB2BIntegration.mdx b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoB2BIntegration.mdx new file mode 100644 index 000000000..45c878619 --- /dev/null +++ b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoB2BIntegration.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled" +id: Test-MtCisSpoB2BIntegration +title: Test-MtCisSpoB2BIntegration +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoB2BIntegration.ps1 +--- + +## SYNOPSIS + +Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled + +## SYNTAX + +```powershell +Test-MtCisSpoB2BIntegration [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.2 (L1) Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoB2BIntegration +``` + +Returns true if SharePoint and OneDrive integration with Azure AD B2B is enabled + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoB2BIntegration](https://maester.dev/docs/commands/Test-MtCisSpoB2BIntegration) diff --git a/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoDefaultSharingLink.mdx b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoDefaultSharingLink.mdx new file mode 100644 index 000000000..edebb3ef1 --- /dev/null +++ b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoDefaultSharingLink.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure link sharing is restricted in SharePoint and OneDrive" +id: Test-MtCisSpoDefaultSharingLink +title: Test-MtCisSpoDefaultSharingLink +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoDefaultSharingLink.ps1 +--- + +## SYNOPSIS + +Ensure link sharing is restricted in SharePoint and OneDrive + +## SYNTAX + +```powershell +Test-MtCisSpoDefaultSharingLink [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.7 (L1) Ensure link sharing is restricted in SharePoint and OneDrive +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoDefaultSharingLink +``` + +Returns true if link sharing is restricted in SharePoint and OneDrive + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLink](https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLink) diff --git a/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoDefaultSharingLinkPermission.mdx b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoDefaultSharingLinkPermission.mdx new file mode 100644 index 000000000..e1ffc815a --- /dev/null +++ b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoDefaultSharingLinkPermission.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure the SharePoint default sharing link permission is set" +id: Test-MtCisSpoDefaultSharingLinkPermission +title: Test-MtCisSpoDefaultSharingLinkPermission +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoDefaultSharingLinkPermission.ps1 +--- + +## SYNOPSIS + +Ensure the SharePoint default sharing link permission is set + +## SYNTAX + +```powershell +Test-MtCisSpoDefaultSharingLinkPermission [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.11 (L1) Ensure the SharePoint default sharing link permission is set +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoDefaultSharingLinkPermission +``` + +Returns true if the SharePoint default sharing link permission is set to View + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission](https://maester.dev/docs/commands/Test-MtCisSpoDefaultSharingLinkPermission) diff --git a/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoGuestAccessExpiry.mdx b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoGuestAccessExpiry.mdx new file mode 100644 index 000000000..1480bba22 --- /dev/null +++ b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoGuestAccessExpiry.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure guest access to a site or OneDrive will expire automatically" +id: Test-MtCisSpoGuestAccessExpiry +title: Test-MtCisSpoGuestAccessExpiry +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoGuestAccessExpiry.ps1 +--- + +## SYNOPSIS + +Ensure guest access to a site or OneDrive will expire automatically + +## SYNTAX + +```powershell +Test-MtCisSpoGuestAccessExpiry [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.9 (L1) Ensure guest access to a site or OneDrive will expire automatically +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoGuestAccessExpiry +``` + +Returns true if guest access expiration is enabled and set to 30 days or less + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoGuestAccessExpiry](https://maester.dev/docs/commands/Test-MtCisSpoGuestAccessExpiry) diff --git a/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoGuestCannotShareUnownedItem.mdx b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoGuestCannotShareUnownedItem.mdx new file mode 100644 index 000000000..fa1d8c865 --- /dev/null +++ b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoGuestCannotShareUnownedItem.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure that SharePoint guest users cannot share items they don't own" +id: Test-MtCisSpoGuestCannotShareUnownedItem +title: Test-MtCisSpoGuestCannotShareUnownedItem +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 +--- + +## SYNOPSIS + +Ensure that SharePoint guest users cannot share items they don't own + +## SYNTAX + +```powershell +Test-MtCisSpoGuestCannotShareUnownedItem [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.2.5 (L2) Ensure that SharePoint guest users cannot share items they don't own +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoGuestCannotShareUnownedItem +``` + +Returns true if SharePoint guest users cannot share items they don't own + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem](https://maester.dev/docs/commands/Test-MtCisSpoGuestCannotShareUnownedItem) diff --git a/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoPreventDownloadMaliciousFile.mdx b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoPreventDownloadMaliciousFile.mdx new file mode 100644 index 000000000..dada85944 --- /dev/null +++ b/website/versioned_docs/version-2.1.0/commands/Test-MtCisSpoPreventDownloadMaliciousFile.mdx @@ -0,0 +1,68 @@ +--- +sidebar_class_name: hidden +description: "Ensure Office 365 SharePoint infected files are disallowed for download" +id: Test-MtCisSpoPreventDownloadMaliciousFile +title: Test-MtCisSpoPreventDownloadMaliciousFile +hide_title: false +hide_table_of_contents: false +custom_edit_url: https://github.com/maester365/maester/blob/main/powershell/public/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 +--- + +## SYNOPSIS + +Ensure Office 365 SharePoint infected files are disallowed for download + +## SYNTAX + +```powershell +Test-MtCisSpoPreventDownloadMaliciousFile [-ProgressAction ] [] +``` + +## DESCRIPTION + +7.3.1 (L2) Ensure Office 365 SharePoint infected files are disallowed for download +CIS Microsoft 365 Foundations Benchmark v6.0.1 + +## EXAMPLES + +### EXAMPLE 1 + +```powershell +Test-MtCisSpoPreventDownloadMaliciousFile +``` + +Returns true if Office 365 SharePoint infected files are disallowed for download + +## PARAMETERS + +### -ProgressAction + +\{\{ Fill ProgressAction Description \}\} + +```yaml +Type: ActionPreference +Parameter Sets: (All) +Aliases: proga + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters + +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +### System.Boolean + +## NOTES + +## RELATED LINKS + +[https://maester.dev/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile](https://maester.dev/docs/commands/Test-MtCisSpoPreventDownloadMaliciousFile) From ec00f862fce69567ed59082391e26e0a49c5993f Mon Sep 17 00:00:00 2001 From: -Mynster Date: Mon, 11 May 2026 19:51:09 +0200 Subject: [PATCH 27/31] minor additions and fixes after feedback --- powershell/Maester.psd1 | 12 +++++++++--- powershell/public/Disconnect-Maester.ps1 | 16 +++++++++++----- tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 | 2 +- .../Test-MtCisSpoDefaultSharingLink.Tests.ps1 | 2 +- ...tCisSpoDefaultSharingLinkPermission.Tests.ps1 | 2 +- .../cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 | 2 +- ...MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 | 2 +- ...tCisSpoPreventDownloadMaliciousFile.Tests.ps1 | 2 +- 8 files changed, 26 insertions(+), 14 deletions(-) diff --git a/powershell/Maester.psd1 b/powershell/Maester.psd1 index 858e57b39..5bbb5744a 100644 --- a/powershell/Maester.psd1 +++ b/powershell/Maester.psd1 @@ -131,7 +131,14 @@ 'Test-MtCisFormsPhishingProtectionEnabled', 'Test-MtCisGlobalAdminCount', 'Test-MtCisHostedConnectionFilterPolicy', 'Test-MtCisInternalMalwareNotification', 'Test-MtCisOutboundSpamFilterPolicy', 'Test-MtCisPasswordExpiry', 'Test-MtCisSafeAntiPhishingPolicy', 'Test-MtCisSafeAttachment', 'Test-MtCisSafeAttachmentsAtpPolicy', - 'Test-MtCisSafeLink', 'Test-MtCisSharedMailboxSignIn', 'Test-MtCisTeamsLobbyBypass', + 'Test-MtCisSafeLink', 'Test-MtCisSharedMailboxSignIn', + 'Test-MtCisSpoB2BIntegration', + 'Test-MtCisSpoDefaultSharingLink', + 'Test-MtCisSpoDefaultSharingLinkPermission', + 'Test-MtCisSpoGuestAccessExpiry', + 'Test-MtCisSpoGuestCannotShareUnownedItem', + 'Test-MtCisSpoPreventDownloadMaliciousFile', + 'Test-MtCisTeamsLobbyBypass', 'Test-MtCisTeamsReportSecurityConcerns', 'Test-MtCisThirdPartyAndCustomApps', 'Test-MtCisThirdPartyApplicationsDisallowed', 'Test-MtCisThirdPartyFileSharing', 'Test-MtCisThirdPartyStorageServicesRestricted', 'Test-MtCisUserOwnedAppsRestricted', @@ -175,8 +182,7 @@ 'Test-ORCA221', 'Test-ORCA222', 'Test-ORCA223', 'Test-ORCA224', 'Test-ORCA225', 'Test-ORCA226', 'Test-ORCA227', 'Test-ORCA228', 'Test-ORCA229', 'Test-ORCA230', 'Test-ORCA231', 'Test-ORCA232', 'Test-ORCA233', 'Test-ORCA233_1', 'Test-ORCA234', 'Test-ORCA235', 'Test-ORCA236', 'Test-ORCA237', 'Test-ORCA238', 'Test-ORCA239', 'Test-ORCA240', - 'Test-ORCA241', 'Test-ORCA242', 'Test-ORCA243', 'Test-ORCA244', 'Update-MaesterTests', 'Update-MtMaesterApp', - 'Test-MtCisSpoB2BIntegration', 'Test-MtCisSpoDefaultSharingLink', 'Test-MtCisSpoDefaultSharingLinkPermission', 'Test-MtCisSpoGuestAccessExpiry', 'Test-MtCisSpoGuestCannotShareUnownedItem', 'Test-MtCisSpoPreventDownloadMaliciousFile' + 'Test-ORCA241', 'Test-ORCA242', 'Test-ORCA243', 'Test-ORCA244', 'Update-MaesterTests', 'Update-MtMaesterApp' ) # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. diff --git a/powershell/public/Disconnect-Maester.ps1 b/powershell/public/Disconnect-Maester.ps1 index 8918dd355..b31414cc5 100644 --- a/powershell/public/Disconnect-Maester.ps1 +++ b/powershell/public/Disconnect-Maester.ps1 @@ -1,5 +1,5 @@ function Disconnect-Maester { - <# + <# .Synopsis Helper method to sign out of the current Microsoft Graph session. Alternate for Disconnect-MgGraph. @@ -27,12 +27,12 @@ [CmdletBinding()] param() - if($__MtSession.Connections -contains "Graph" -or $__MtSession.Connections -contains "All"){ + if ($__MtSession.Connections -contains "Graph" -or $__MtSession.Connections -contains "All") { Write-Verbose -Message "Disconnecting from Microsoft Graph." Disconnect-MgGraph } - if($__MtSession.Connections -contains "Azure" -or $__MtSession.Connections -contains "Dataverse" -or $__MtSession.Connections -contains "All"){ + if ($__MtSession.Connections -contains "Azure" -or $__MtSession.Connections -contains "Dataverse" -or $__MtSession.Connections -contains "All") { Write-Verbose -Message "Disconnecting from Microsoft Azure." try { Disconnect-AzAccount -ErrorAction Stop | Out-Null @@ -41,11 +41,17 @@ } } - if($__MtSession.Connections -contains "ExchangeOnline" -or $__MtSession.Connections -contains "SecurityCompliance" -or $__MtSession.Connections -contains "All"){ + if ($__MtSession.Connections -contains "ExchangeOnline" -or $__MtSession.Connections -contains "SecurityCompliance" -or $__MtSession.Connections -contains "All") { Write-Verbose -Message "Disconnecting from Microsoft Exchange Online." Disconnect-ExchangeOnline } - if($__MtSession.Connections -contains "Teams" -or $__MtSession.Connections -contains "All"){ + + if ($__MtSession.Connections -contains "SharePointOnline" -or $__MtSession.Connections -contains "All") { + Write-Verbose -Message "Disconnecting from SharePoint Online." + Disconnect-PnPOnline + } + + if ($__MtSession.Connections -contains "Teams" -or $__MtSession.Connections -contains "All") { Write-Verbose -Message "Disconnecting from Microsoft Teams." Disconnect-MicrosoftTeams } diff --git a/tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 b/tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 index e28e40e52..76c0ff592 100644 --- a/tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 +++ b/tests/cis/Test-MtCisSpoB2BIntegration.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "CIS" -Tag "CIS.M365.7.2.2", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { +Describe "CIS" -Tag "SharePoint Online", "OneDrive", "CIS.M365.7.2.2", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { It "CIS.M365.7.2.2: Ensure SharePoint and OneDrive integration with Azure AD B2B is enabled" { $result = Test-MtCisSpoB2BIntegration diff --git a/tests/cis/Test-MtCisSpoDefaultSharingLink.Tests.ps1 b/tests/cis/Test-MtCisSpoDefaultSharingLink.Tests.ps1 index 027a36e77..f0d99e4e1 100644 --- a/tests/cis/Test-MtCisSpoDefaultSharingLink.Tests.ps1 +++ b/tests/cis/Test-MtCisSpoDefaultSharingLink.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "CIS" -Tag "CIS.M365.7.2.7", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { +Describe "CIS" -Tag "SharePoint Online", "OneDrive", "CIS.M365.7.2.7", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { It "CIS.M365.7.2.7: Ensure link sharing is restricted in SharePoint and OneDrive" { $result = Test-MtCisSpoDefaultSharingLink diff --git a/tests/cis/Test-MtCisSpoDefaultSharingLinkPermission.Tests.ps1 b/tests/cis/Test-MtCisSpoDefaultSharingLinkPermission.Tests.ps1 index 64ad70cf9..997b1b744 100644 --- a/tests/cis/Test-MtCisSpoDefaultSharingLinkPermission.Tests.ps1 +++ b/tests/cis/Test-MtCisSpoDefaultSharingLinkPermission.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "CIS" -Tag "CIS.M365.7.2.11", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { +Describe "CIS" -Tag "SharePoint Online", "OneDrive", "CIS.M365.7.2.11", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { It "CIS.M365.7.2.11: Ensure the SharePoint default sharing link permission is set" { $result = Test-MtCisSpoDefaultSharingLinkPermission diff --git a/tests/cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 b/tests/cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 index 0bfc06ae8..5d8d9f97f 100644 --- a/tests/cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 +++ b/tests/cis/Test-MtCisSpoGuestAccessExpiry.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "CIS" -Tag "CIS.M365.7.2.9", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { +Describe "CIS" -Tag "SharePoint Online", "OneDrive", "CIS.M365.7.2.9", "L1", "CIS E3 Level 1", "CIS E3", "CIS E5 Level 1", "CIS E5", "CIS", "CIS M365 v6.0.1" { It "CIS.M365.7.2.9: Ensure guest access to a site or OneDrive will expire automatically" { $result = Test-MtCisSpoGuestAccessExpiry diff --git a/tests/cis/Test-MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 b/tests/cis/Test-MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 index 7b9d2d655..28164eafe 100644 --- a/tests/cis/Test-MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 +++ b/tests/cis/Test-MtCisSpoGuestCannotShareUnownedItem.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "CIS" -Tag "CIS.M365.7.2.5", "L2", "CIS E3 Level 2", "CIS E3", "CIS E5 Level 2", "CIS E5", "CIS", "CIS M365 v6.0.1" { +Describe "CIS" -Tag "SharePoint Online", "OneDrive", "CIS.M365.7.2.5", "L2", "CIS E3 Level 2", "CIS E3", "CIS E5 Level 2", "CIS E5", "CIS", "CIS M365 v6.0.1" { It "CIS.M365.7.2.5: Ensure that SharePoint guest users cannot share items they don't own" { $result = Test-MtCisSpoGuestCannotShareUnownedItem diff --git a/tests/cis/Test-MtCisSpoPreventDownloadMaliciousFile.Tests.ps1 b/tests/cis/Test-MtCisSpoPreventDownloadMaliciousFile.Tests.ps1 index 180ac4aac..11de1a251 100644 --- a/tests/cis/Test-MtCisSpoPreventDownloadMaliciousFile.Tests.ps1 +++ b/tests/cis/Test-MtCisSpoPreventDownloadMaliciousFile.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "CIS" -Tag "CIS.M365.7.3.1", "L2", "CIS E5 Level 2", "CIS E5", "CIS", "CIS M365 v6.0.1" { +Describe "CIS" -Tag "SharePoint Online", "CIS.M365.7.3.1", "L2", "CIS E5 Level 2", "CIS E5", "CIS", "CIS M365 v6.0.1" { It "CIS.M365.7.3.1: Ensure Office 365 SharePoint infected files are disallowed for download" { $result = Test-MtCisSpoPreventDownloadMaliciousFile From d950cc5e9a4e66f793912cdba512e7f91ba94ac2 Mon Sep 17 00:00:00 2001 From: -Mynster Date: Mon, 11 May 2026 21:21:04 +0200 Subject: [PATCH 28/31] Did not see there already was a PR related to Sharepoint Online. I decided to revert my changes in regards to connection to sharepoint online and adopt the ones from #1662 added @DataAndGoliath as a co-author on this adoption Only actual change between the 2 is the location for Get-MtSpo.ps1 i have chosen to place this in the powershell\public folder as it now will relate to both CIS and CISA tests. > Co-authored-by: Simon Albers --- powershell/Maester.Format.ps1xml | 17 ++++ powershell/Maester.psd1 | 2 +- powershell/Maester.psm1 | 21 ++--- powershell/internal/Clear-ModuleVariable.ps1 | 3 +- powershell/internal/Get-MtSkippedReason.ps1 | 3 +- powershell/public/Add-MtTestResultDetail.ps1 | 2 +- powershell/public/Connect-Maester.ps1 | 87 +++++++++---------- powershell/public/Disconnect-Maester.ps1 | 9 +- powershell/public/Get-MtSpo.ps1 | 45 ++++++++++ .../cis/Test-MtCisSpoB2BIntegration.ps1 | 6 +- .../cis/Test-MtCisSpoDefaultSharingLink.ps1 | 6 +- ...t-MtCisSpoDefaultSharingLinkPermission.ps1 | 6 +- .../cis/Test-MtCisSpoGuestAccessExpiry.ps1 | 4 +- ...st-MtCisSpoGuestCannotShareUnownedItem.ps1 | 6 +- ...t-MtCisSpoPreventDownloadMaliciousFile.ps1 | 6 +- powershell/public/core/Test-MtConnection.ps1 | 16 ++-- website/docs/installation.md | 2 + website/docs/sections/create-entra-app.md | 47 ++++++++++ 18 files changed, 198 insertions(+), 90 deletions(-) create mode 100644 powershell/public/Get-MtSpo.ps1 diff --git a/powershell/Maester.Format.ps1xml b/powershell/Maester.Format.ps1xml index 57eb7dd89..088334462 100644 --- a/powershell/Maester.Format.ps1xml +++ b/powershell/Maester.Format.ps1xml @@ -85,6 +85,23 @@ } + + + + $null -ne $_.SharePoint + + + + + if ($_.SharePoint) { + "Connected`n" + + "URL: $($_.SharePoint.Url)`n" + + "Tenant: $($_.SharePoint.Tenant)`n" + } else { + '' + } + + diff --git a/powershell/Maester.psd1 b/powershell/Maester.psd1 index 5bbb5744a..64dde7bb0 100644 --- a/powershell/Maester.psd1 +++ b/powershell/Maester.psd1 @@ -63,7 +63,7 @@ 'Get-MailAuthenticationRecord', 'Get-MtAdminPortalUrl', 'Get-MtAuthenticationMethodPolicyConfig', 'Get-MtAzureManagementGroup', 'Get-MtConditionalAccessPolicy', 'Get-MtExo', 'Get-MtExoThreatPolicyMalware', 'Get-MtGraphScope', 'Get-MtGroupMember', 'Get-MtHtmlReport', 'Get-MtLicenseInformation', 'Get-MtMaesterApp', 'Get-MtRole', - 'Get-MtRoleMember', 'Get-MtSafeMarkdown', 'Get-MtSession', 'Get-MtTestInventory', 'Get-MtUser', + 'Get-MtRoleMember', 'Get-MtSafeMarkdown', 'Get-MtSession', 'Get-MtSpo', 'Get-MtTestInventory', 'Get-MtUser', 'Get-MtUserAuthenticationMethod', 'Get-MtUserAuthenticationMethodInfoByType', 'Import-MtMaesterResult', 'Install-MaesterTests', 'Invoke-Maester', 'Invoke-MtAzureRequest', 'Invoke-MtAzureResourceGraphRequest', 'Invoke-MtGraphRequest', 'Invoke-MtGraphSecurityQuery', 'Merge-MtMaesterResult', 'New-MtMaesterApp', 'Resolve-SPFRecord', diff --git a/powershell/Maester.psm1 b/powershell/Maester.psm1 index 1cb989e9f..d6a8e35d5 100644 --- a/powershell/Maester.psm1 +++ b/powershell/Maester.psm1 @@ -14,17 +14,18 @@ ## Initialize Module Variables ## Update Clear-ModuleVariable function in internal/Clear-ModuleVariable.ps1 if you add new variables here $__MtSession = @{ - GraphCache = @{} - GraphBaseUri = $null - TestResultDetail = @{} - Connections = @() - DnsCache = @() - ExoCache = @{} - OrcaCache = @{} - AIAgentInfo = $null - DataverseApiBase = $null # Resolved Dataverse OData API base URL (e.g. https://org123.api.crm.dynamics.com/api/data/v9.2) - DataverseResourceUrl = $null # Dataverse resource URL for token acquisition (e.g. https://org123.crm.dynamics.com) + GraphCache = @{} + GraphBaseUri = $null + TestResultDetail = @{} + Connections = @() + DnsCache = @() + ExoCache = @{} + OrcaCache = @{} + AIAgentInfo = $null + DataverseApiBase = $null # Resolved Dataverse OData API base URL (e.g. https://org123.api.crm.dynamics.com/api/data/v9.2) + DataverseResourceUrl = $null # Dataverse resource URL for token acquisition (e.g. https://org123.crm.dynamics.com) DataverseEnvironmentId = $null # Environment identifier for display (e.g. org123.crm.dynamics.com) + SpoCache = @{} # Cache for SharePoint Online tenant settings retrieved via PnP } New-Variable -Name __MtSession -Value $__MtSession -Scope Script -Force diff --git a/powershell/internal/Clear-ModuleVariable.ps1 b/powershell/internal/Clear-ModuleVariable.ps1 index 17879e660..cb867785b 100644 --- a/powershell/internal/Clear-ModuleVariable.ps1 +++ b/powershell/internal/Clear-ModuleVariable.ps1 @@ -9,7 +9,7 @@ This function will be called for each fresh run of Invoke-Maester. #> - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification='Module variables used in other functions.')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Module variables used in other functions.')] param() Clear-MtGraphCache @@ -21,5 +21,6 @@ Clear-MtExoCache $__MtSession.AIAgentInfo = $null $__MtSession.AzureDevOpsConnection = $null + $__MtSession.SpoCache = @{} # $__MtSession.Connections = @() # Do not clear connections as they are used to track the connection state. This module variable should only be set by Connect-Maester and Disconnect-Maester. } diff --git a/powershell/internal/Get-MtSkippedReason.ps1 b/powershell/internal/Get-MtSkippedReason.ps1 index 381c05b27..f39a95d5b 100644 --- a/powershell/internal/Get-MtSkippedReason.ps1 +++ b/powershell/internal/Get-MtSkippedReason.ps1 @@ -15,8 +15,7 @@ "NotConnectedTeams" { "Not connected to Teams. See [Connecting to Teams](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break } "NotConnectedAzureDevOps" { "Not connected to Azure DevOps. See [Connecting to Azure DevOps](https://maester.dev/docs/connect-maester/#connect-to-azure-devops-optional)"; break } "NotConnectedGraph" { "Not connected to Graph. See [Connect-Maester](https://maester.dev/docs/commands/Connect-Maester#examples)"; break } - "NotConnectedSharePointOnline" { "Not connected to SharePoint Online. See [Connecting to SharePoint Online](https://maester.dev/docs/connect-maester/#connect-to-sharepoint-online-optional)"; break } - "NotDotGovDomain" { "This test is only for federal, executive branch, departments and agencies. To override use [Test-MtCisaDmarcAggregateCisa -Force](https://maester.dev/docs/commands/Test-MtCisaDmarcAggregateCisa)"; break } + "NotConnectedSharePoint" { "Not connected to SharePoint Online. See [Connecting to SharePoint Online](https://maester.dev/docs/connect-maester/)"; break } "NotDotGovDomain" { "This test is only for federal, executive branch, departments and agencies. To override use [Test-MtCisaDmarcAggregateCisa -Force](https://maester.dev/docs/commands/Test-MtCisaDmarcAggregateCisa)"; break } "NotLicensedEntraIDP1" { "This test is for tenants that are licensed for Entra ID P1. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break } "NotLicensedEntraIDP2" { "This test is for tenants that are licensed for Entra ID P2. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break } "NotLicensedEntraIDGovernance" { "This test is for tenants that are licensed for Entra ID Governance. See [Entra ID Governance licensing](https://learn.microsoft.com/entra/fundamentals/licensing#microsoft-entra-id-governance)"; break } diff --git a/powershell/public/Add-MtTestResultDetail.ps1 b/powershell/public/Add-MtTestResultDetail.ps1 index e13da27a2..e9896f3a3 100644 --- a/powershell/public/Add-MtTestResultDetail.ps1 +++ b/powershell/public/Add-MtTestResultDetail.ps1 @@ -77,7 +77,7 @@ [ValidateSet('NotConnectedAzure', 'NotConnectedExchange', 'NotConnectedGraph', 'NotDotGovDomain', 'NotLicensedEntraIDP1', 'NotConnectedSecurityCompliance', 'NotConnectedTeams', 'NotLicensedEntraIDP2', 'NotLicensedEntraIDGovernance', 'NotLicensedEntraWorkloadID', 'NotLicensedExoDlp', "LicensedEntraIDPremium", 'NotSupported', 'Custom', 'NotLicensedMdo', 'NotLicensedMdoP2', 'NotLicensedMdoP1', 'NotLicensedAdvAudit', 'NotLicensedEop', 'Error', 'NotSupportedAppPermission', 'LimitedPermissions', 'NotLicensedDefenderXDR', - 'NotLicensedCustomerLockbox', 'NotAuthorized', 'NotLicensedIntune', 'NotConnectedAzureDevOps', 'NotConnectedSharePointOnline' + 'NotLicensedCustomerLockbox', 'NotAuthorized', 'NotLicensedIntune', 'NotConnectedAzureDevOps', 'NotConnectedSharePoint' )] [string] $SkippedBecause, diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index 70398533d..af2586e26 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -113,7 +113,7 @@ [ValidateSet('TeamsChina', 'TeamsGCCH', 'TeamsDOD')] [string]$TeamsEnvironmentName = $null, #ToValidate: Don't use this parameter, this is the default. - # The services to connect to such as Azure, Dataverse (for Copilot Studio tests), and EXO. Default is Graph. + # The services to connect to such as Azure, Dataverse (for Copilot Studio tests), EXO, and SharePoint Online. Default is Graph. [ValidateSet('All', 'Azure', 'Dataverse', 'ExchangeOnline', 'Graph', 'SecurityCompliance', 'Teams', 'SharePointOnline')] [string[]]$Service = 'Graph', @@ -123,9 +123,8 @@ # The Client ID of the app to connect to for Graph. If not specified, the default Graph PowerShell CLI enterprise app will be used. Reference on how to create an enterprise app: https://learn.microsoft.com/en-us/powershell/microsoftgraph/authentication-commands?view=graph-powershell-1.0#use-delegated-access-with-a-custom-application-for-microsoft-graph-powershell [string]$GraphClientId, - # The SharePoint admin center URL to connect to when using the SharePointOnline service (e.g. https://contoso-admin.sharepoint.com). - # If not specified, the URL is auto-discovered from the tenant's initial domain via the Microsoft Graph API. - [string]$SharePointAdminUrl + # The Client ID of the PnP Entra ID app for SharePoint Online. Required when Service includes SharePointOnline. Create the app using Register-PnPEntraIDAppForInteractiveLogin. + [string]$SharePointClientId ) $__MtSession.Connections = $Service @@ -234,27 +233,27 @@ if ($Service -contains 'SecurityCompliance' -or $Service -contains 'All') { $Environments = @{ - 'O365China' = @{ + 'O365China' = @{ ConnectionUri = 'https://ps.compliance.protection.partner.outlook.cn/powershell-liveid' AuthZEndpointUri = 'https://login.chinacloudapi.cn/common' } - 'O365GermanyCloud' = @{ + 'O365GermanyCloud' = @{ ConnectionUri = 'https://ps.compliance.protection.outlook.com/powershell-liveid/' AuthZEndpointUri = 'https://login.microsoftonline.com/common' } - 'O365Default' = @{ + 'O365Default' = @{ ConnectionUri = 'https://ps.compliance.protection.outlook.com/powershell-liveid/' AuthZEndpointUri = 'https://login.microsoftonline.com/common' } - 'O365USGovGCCHigh' = @{ + 'O365USGovGCCHigh' = @{ ConnectionUri = 'https://ps.compliance.protection.office365.us/powershell-liveid/' AuthZEndpointUri = 'https://login.microsoftonline.us/common' } - 'O365USGovDoD' = @{ + 'O365USGovDoD' = @{ ConnectionUri = 'https://l5.ps.compliance.protection.office365.us/powershell-liveid/' AuthZEndpointUri = 'https://login.microsoftonline.us/common' } - Default = @{ + Default = @{ ConnectionUri = 'https://ps.compliance.protection.outlook.com/powershell-liveid/' AuthZEndpointUri = 'https://login.microsoftonline.com/common' } @@ -297,8 +296,8 @@ # Remove the broken cmdlet and re-import the working EXO one. Remove-Item -Path 'Function:\Get-AdminAuditLogConfig' -Force -ErrorAction SilentlyContinue $ExchangeConnectionInformation | Where-Object { $_.IsEopSession -ne $true -and $_.State -eq 'Connected' } | - Select-Object -ExpandProperty ModuleName | - Import-Module -Function 'Get-AdminAuditLogConfig' > $null + Select-Object -ExpandProperty ModuleName | + Import-Module -Function 'Get-AdminAuditLogConfig' > $null } catch { Write-Error "Failed to restore Get-AdminAuditLogConfig cmdlet: $($_.Exception.Message)" } @@ -362,48 +361,40 @@ } 'PnP.PowerShell' { + # SharePoint Online via PnP — must run AFTER Graph to avoid Microsoft.Graph.Core DLL conflict if ($Service -contains 'SharePointOnline' -or $Service -contains 'All') { - Write-Verbose 'Connecting to SharePoint Online' - try { - $spoAdminUrl = $SharePointAdminUrl - if ([string]::IsNullOrEmpty($spoAdminUrl)) { - # Auto-discover the admin URL from the tenant's initial domain via Graph - $org = Invoke-MtGraphRequest -RelativeUri 'organization' -ErrorAction Stop - $tenantDomain = ($org.verifiedDomains | Where-Object { $_.isInitial -eq $true }) | Select-Object -ExpandProperty Name -First 1 - $spoAdminUrl = "https://$(($tenantDomain).Replace('.onmicrosoft.com', ''))-admin.sharepoint.com" - Write-Verbose "Auto-discovered SharePoint Admin URL: $spoAdminUrl" - } - - $pnpAzureEnv = switch ($AzureEnvironment) { - 'AzureChinaCloud' { 'China' } - 'AzureUSGovernment' { 'USGovernment' } - default { 'Production' } - } - - $pnpParams = @{ - Url = $spoAdminUrl - AzureEnvironment = $pnpAzureEnv - } + Write-Verbose 'Connecting to SharePoint Online via PnP' - if ($UseDeviceCode) { - $resolveTenant = if ($TenantId) { $TenantId } else { (Get-MgContext -ErrorAction SilentlyContinue).TenantId } - if ($resolveTenant) { + if (-not $SharePointClientId) { + Write-Host "`nSharePointOnline requires the -SharePointClientId parameter. Create a PnP app registration using Register-PnPEntraIDAppForInteractiveLogin.`nFor more information see https://maester.dev/docs/sections/create-entra-app" -ForegroundColor Red + } else { + try { + # Resolve the SharePoint admin URL from the tenant's initial domain + $domains = Invoke-MtGraphRequest -RelativeUri "domains" -ApiVersion "v1.0" + $initialDomain = ($domains | Where-Object { $_.isInitial -eq $true }).id + $tenantPrefix = ($initialDomain -split '\.')[0] + $spoAdminUrl = "https://$tenantPrefix-admin.sharepoint.com" + Write-Verbose "Resolved SharePoint admin URL: $spoAdminUrl" + Import-Module PnP.PowerShell -ErrorAction Stop + $pnpParams = @{ + Url = $spoAdminUrl + ClientId = $SharePointClientId + } + if ($UseDeviceCode) { $pnpParams['DeviceLogin'] = $true - $pnpParams['Tenant'] = $resolveTenant - } else { - Write-Host "`nDevice code login for SharePoint Online requires a -TenantId parameter." -ForegroundColor Red } - } else { - $pnpParams['Interactive'] = $true + if ($TenantId) { + $pnpParams['Tenant'] = $TenantId + } + Connect-PnPOnline @pnpParams + } catch [Management.Automation.CommandNotFoundException] { + Write-Host "`nThe PnP.PowerShell module is not installed. Please install the module using the following command.`nFor more information see https://pnp.github.io/powershell/articles/installation.html" -ForegroundColor Red + Write-Host "`nInstall-Module PnP.PowerShell -Scope CurrentUser`n" -ForegroundColor Yellow + } catch { + Write-Host "`nFailed to connect to SharePoint Online: $($_.Exception.Message)" -ForegroundColor Red } - - Connect-PnPOnline @pnpParams - } catch [Management.Automation.CommandNotFoundException] { - Write-Host "`nThe PnP PowerShell module is not installed. Please install the module using the following command. For more information see https://pnp.github.io/powershell/" -ForegroundColor Red - Write-Host "`nInstall-Module PnP.PowerShell -Scope CurrentUser`n" -ForegroundColor Yellow } } } - } # end switch OrderedImport - + } } # end function Connect-Maester diff --git a/powershell/public/Disconnect-Maester.ps1 b/powershell/public/Disconnect-Maester.ps1 index b31414cc5..9423a0dac 100644 --- a/powershell/public/Disconnect-Maester.ps1 +++ b/powershell/public/Disconnect-Maester.ps1 @@ -47,8 +47,13 @@ } if ($__MtSession.Connections -contains "SharePointOnline" -or $__MtSession.Connections -contains "All") { - Write-Verbose -Message "Disconnecting from SharePoint Online." - Disconnect-PnPOnline + Write-Verbose -Message "Disconnecting from SharePoint Online (PnP)." + try { + Disconnect-PnPOnline -ErrorAction Stop + } catch { + Write-Verbose "Disconnect-PnPOnline encountered an error: $($_.Exception.Message)" + } + $__MtSession.SpoCache = @{} } if ($__MtSession.Connections -contains "Teams" -or $__MtSession.Connections -contains "All") { diff --git a/powershell/public/Get-MtSpo.ps1 b/powershell/public/Get-MtSpo.ps1 new file mode 100644 index 000000000..c0fb15d5e --- /dev/null +++ b/powershell/public/Get-MtSpo.ps1 @@ -0,0 +1,45 @@ +function Get-MtSpo { + <# + .SYNOPSIS + Retrieves SharePoint Online tenant settings via PnP with session caching. + + .DESCRIPTION + Returns the full SPO tenant configuration from Get-PnPTenant. + Results are cached in $__MtSession.SpoCache for the duration of the session. + Use -ClearCache to force a fresh retrieval. + + .EXAMPLE + Get-MtSpo + + Returns the cached (or freshly retrieved) SPO tenant settings. + + .EXAMPLE + Get-MtSpo -ClearCache + + Clears the cached settings and retrieves fresh data from Get-PnPTenant. + + .LINK + https://maester.dev/docs/commands/Get-MtSpo + #> + [CmdletBinding()] + param( + # Clear the cached SPO tenant settings and retrieve fresh data. + [switch]$ClearCache + ) + + if ($ClearCache) { + $__MtSession.SpoCache = @{} + Write-Verbose "SPO cache cleared." + } + + if ($null -eq $__MtSession.SpoCache.SpoTenant) { + Write-Verbose "SPO tenant settings not in cache, requesting." + $response = Get-PnPTenant -ErrorAction Stop + $__MtSession.SpoCache.SpoTenant = $response + } else { + Write-Verbose "SPO tenant settings in cache." + $response = $__MtSession.SpoCache.SpoTenant + } + + return $response +} \ No newline at end of file diff --git a/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 index b1aa6c8c6..0e4edb24b 100644 --- a/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 +++ b/powershell/public/cis/Test-MtCisSpoB2BIntegration.ps1 @@ -21,14 +21,14 @@ Write-Verbose "Testing SharePoint Entra B2B integration..." if (!(Test-MtConnection SharePointOnline)) { - Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePoint return $null } $return = $true try { - $B2BIntegration = Get-PnPTenant | Select-Object -ExpandProperty EnableAzureADB2BIntegration - if ($B2BIntegration) { + $spoTenant = Get-MtSpo + if ($spoTenant.B2BIntegration.EnableAzureADB2BIntegration) { $testResult = "Well done. Your SharePoint tenant is integrated with Microsoft Entra B2B." } else { $testResult = "Your SharePoint tenant is not integrated with Microsoft Entra B2B." diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 index 6a2e32001..0de2492a5 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLink.ps1 @@ -21,14 +21,14 @@ Write-Verbose "Testing default sharing link type in SharePoint Online..." if (!(Test-MtConnection SharePointOnline)) { - Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePoint return $null } $return = $true try { - $DefaultSharingLinkType = Get-PnPTenant | Select-Object -ExpandProperty DefaultSharingLinkType - if ($DefaultSharingLinkType -eq "Direct" -or $DefaultSharingLinkType -eq "Internal") { + $spoTenant = Get-MtSpo + if ($spoTenant.DefaultSharingLinkType -eq "Direct" -or $spoTenant.DefaultSharingLinkType -eq "Internal") { $testResult = "Well done. Default sharing link type is set to a restrictive option." } else { $testResult = "Default sharing link type is not set to a restrictive option." diff --git a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 index 76f6f7329..7571d05fd 100644 --- a/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 +++ b/powershell/public/cis/Test-MtCisSpoDefaultSharingLinkPermission.ps1 @@ -21,14 +21,14 @@ Write-Verbose "Testing default sharing link permission in SharePoint Online..." if (!(Test-MtConnection SharePointOnline)) { - Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePoint return $null } $return = $true try { - $DefaultLinkPermission = Get-PnPTenant | Select-Object -ExpandProperty DefaultLinkPermission - if ($DefaultLinkPermission -eq "View") { + $spoTenant = Get-MtSpo + if ($spoTenant.DefaultLinkPermission -eq "View") { $testResult = "Well done. Default sharing link permission is set to View." } else { $testResult = "Default sharing link permission is not set to View." diff --git a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 index 7e29a19a3..32e71b13b 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestAccessExpiry.ps1 @@ -21,13 +21,13 @@ Write-Verbose "Testing guest access expiration settings in SharePoint Online..." if (!(Test-MtConnection SharePointOnline)) { - Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePoint return $null } $return = $true try { - $spoTenant = Get-PnPTenant + $spoTenant = Get-MtSpo if ($spoTenant.ExternalUserExpirationRequired -eq $true -and $spoTenant.ExternalUserExpireInDays -gt 0 -and $spoTenant.ExternalUserExpireInDays -le 30) { $testResult = "Well done. Guest access expiration is enabled and set to 30 days or less ($($spoTenant.ExternalUserExpireInDays) days)." } else { diff --git a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 index 24891bd32..2e576608a 100644 --- a/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 +++ b/powershell/public/cis/Test-MtCisSpoGuestCannotShareUnownedItem.ps1 @@ -21,14 +21,14 @@ Write-Verbose "Testing that SharePoint guest users cannot share items they don't own..." if (!(Test-MtConnection SharePointOnline)) { - Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePoint return $null } $return = $true try { - $PreventExternalUsersFromResharing = Get-PnPTenant | Select-Object -ExpandProperty PreventExternalUsersFromResharing - if ($PreventExternalUsersFromResharing) { + $spoTenant = Get-MtSpo + if ($spoTenant.PreventExternalUsersFromResharing) { $testResult = "Well done. External users cannot share items they don't own." } else { $testResult = "External users can share items they don't own." diff --git a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 index bfeb22993..4479f9645 100644 --- a/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 +++ b/powershell/public/cis/Test-MtCisSpoPreventDownloadMaliciousFile.ps1 @@ -21,14 +21,14 @@ Write-Verbose "Testing malicious file download prevention in SharePoint Online..." if (!(Test-MtConnection SharePointOnline)) { - Add-MtTestResultDetail -SkippedBecause NotConnectedSharePointOnline + Add-MtTestResultDetail -SkippedBecause NotConnectedSharePoint return $null } $return = $true try { - $DisallowInfectedFileDownload = Get-PnPTenant | Select-Object -ExpandProperty DisallowInfectedFileDownload - if ($DisallowInfectedFileDownload) { + $spoTenant = Get-MtSpo + if ($spoTenant.DisallowInfectedFileDownload) { $testResult = "Well done. Malicious file download prevention is enabled in your SharePoint tenant." } else { $testResult = "Malicious file download prevention is not enabled in your SharePoint tenant." diff --git a/powershell/public/core/Test-MtConnection.ps1 b/powershell/public/core/Test-MtConnection.ps1 index 4da049017..9695565e8 100644 --- a/powershell/public/core/Test-MtConnection.ps1 +++ b/powershell/public/core/Test-MtConnection.ps1 @@ -52,7 +52,7 @@ Graph = $null ExchangeOnline = $null ExchangeOnlineProtection = $null - SharePointOnline = $null + SharePoint = $null Teams = $null AllConnected = $false } @@ -148,19 +148,19 @@ } #endregion Teams - #region SharePointOnline - if ($Service -contains 'SharePointOnline' -or $Service -contains 'All') { + #region SharePoint + if ($Service -contains 'SharePoint' -or $Service -contains 'All') { $IsConnected = $false try { - $MtConnections.SharePointOnline = Get-PnPConnection -ErrorAction Stop - $IsConnected = $null -ne ($MtConnections.SharePointOnline) + $MtConnections.SharePoint = Get-PnPConnection + $IsConnected = $null -ne ($MtConnections.SharePoint) } catch { - Write-Debug "SharePoint Online: $false" + Write-Debug "SharePoint: $false" } - Write-Verbose "SharePoint Online: $IsConnected" + Write-Verbose "SharePoint: $IsConnected" if (!$IsConnected) { $ConnectionState = $false } } - #endregion SharePointOnline + #endregion SharePoint #region AzureDevOps if ($Service -contains 'AzureDevOps' -or $Service -contains 'All') { diff --git a/website/docs/installation.md b/website/docs/installation.md index 505aadf9f..f8ae16199 100644 --- a/website/docs/installation.md +++ b/website/docs/installation.md @@ -28,6 +28,8 @@ To learn more about the `Invoke-Maester` cmdlet including how to filter tests, a Maester includes optional [CISA](tests/cisa/) tests that require additional permissions and modules to run. These optional tests are skipped if the modules are not installed or there is no active connection. +> Also see [Create-entra-app](sections/create-entra-app.md) + ### Installing Azure, Exchange Online, Teams and PnP.PowerShell modules ```powershell diff --git a/website/docs/sections/create-entra-app.md b/website/docs/sections/create-entra-app.md index 8d17a3b8f..7e734f068 100644 --- a/website/docs/sections/create-entra-app.md +++ b/website/docs/sections/create-entra-app.md @@ -102,6 +102,53 @@ $deleteAssignment = Invoke-AzRestMethod -Path "$($assignment.RoleAssignmentId)?a ``` +
+ (Optional) Grant permissions to SharePoint Online +### (Optional) Grant permissions to SharePoint Online + +SharePoint Online tests require the **PnP.PowerShell** module and a dedicated PnP Entra ID app registration. The standard Maester app registration does not cover SharePoint tenant admin operations — PnP requires its own app with `Sites.FullControl.All` permissions. + +> The SharePoint Online permissions are necessary to support tests that validate [SharePoint Online configurations](https://maester.dev/docs/tests/cisa/spo), such as the CISA SharePoint baseline controls. + +#### Install PnP.PowerShell + +```powershell +Install-Module PnP.PowerShell -Scope CurrentUser +``` + +#### Register the PnP Entra ID app + +PnP provides a built-in cmdlet to create the required app registration for interactive login: + +```powershell +Register-PnPEntraIDAppForInteractiveLogin -ApplicationName "Maester PnP" -Tenant [yourtenant].onmicrosoft.com -SharePointDelegatePermissions "AllSites.FullControl" +``` + +This will: +- Create an Entra ID app registration with the required delegated permissions +- Prompt you to authenticate and provide consent +- Output the **Client ID** you will need for `Connect-Maester` + +> **Note:** `AllSites.FullControl` (delegated) is the minimum permission required by PnP for tenant admin cmdlets like `Get-PnPTenant`. There is no read-only equivalent. +> +> **Important:** After registering the app, open a **new PowerShell session** before running `Connect-Maester`, as the registration process loads PnP assemblies that can conflict with Microsoft Graph. + +#### Connect to SharePoint Online + +Use the Client ID from the previous step when connecting: + +```powershell +Connect-Maester -Service Graph,SharePointOnline -SharePointClientId "" +``` + +For device code flow (e.g. non-interactive sessions): + +```powershell +Connect-Maester -Service Graph,SharePointOnline -SharePointClientId "" -UseDeviceCode +``` + +
+
(Optional) Grant Dataverse permissions for Copilot Studio tests ### (Optional) Grant Dataverse permissions for Copilot Studio From 8189cb1e4d4131926a9f06ae0c25701f1727da11 Mon Sep 17 00:00:00 2001 From: Sam Erde <20478745+SamErde@users.noreply.github.com> Date: Mon, 18 May 2026 16:13:02 -0400 Subject: [PATCH 29/31] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- powershell/internal/Get-MtSkippedReason.ps1 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/powershell/internal/Get-MtSkippedReason.ps1 b/powershell/internal/Get-MtSkippedReason.ps1 index f39a95d5b..60db509ba 100644 --- a/powershell/internal/Get-MtSkippedReason.ps1 +++ b/powershell/internal/Get-MtSkippedReason.ps1 @@ -15,7 +15,8 @@ "NotConnectedTeams" { "Not connected to Teams. See [Connecting to Teams](https://maester.dev/docs/connect-maester/#connect-to-azure-exchange-online-and-teams)"; break } "NotConnectedAzureDevOps" { "Not connected to Azure DevOps. See [Connecting to Azure DevOps](https://maester.dev/docs/connect-maester/#connect-to-azure-devops-optional)"; break } "NotConnectedGraph" { "Not connected to Graph. See [Connect-Maester](https://maester.dev/docs/commands/Connect-Maester#examples)"; break } - "NotConnectedSharePoint" { "Not connected to SharePoint Online. See [Connecting to SharePoint Online](https://maester.dev/docs/connect-maester/)"; break } "NotDotGovDomain" { "This test is only for federal, executive branch, departments and agencies. To override use [Test-MtCisaDmarcAggregateCisa -Force](https://maester.dev/docs/commands/Test-MtCisaDmarcAggregateCisa)"; break } + "NotConnectedSharePoint" { "Not connected to SharePoint Online. See [Connecting to SharePoint Online](https://maester.dev/docs/connect-maester/)"; break } + "NotDotGovDomain" { "This test is only for federal, executive branch, departments and agencies. To override use [Test-MtCisaDmarcAggregateCisa -Force](https://maester.dev/docs/commands/Test-MtCisaDmarcAggregateCisa)"; break } "NotLicensedEntraIDP1" { "This test is for tenants that are licensed for Entra ID P1. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break } "NotLicensedEntraIDP2" { "This test is for tenants that are licensed for Entra ID P2. See [Entra ID licensing](https://learn.microsoft.com/entra/fundamentals/licensing)"; break } "NotLicensedEntraIDGovernance" { "This test is for tenants that are licensed for Entra ID Governance. See [Entra ID Governance licensing](https://learn.microsoft.com/entra/fundamentals/licensing#microsoft-entra-id-governance)"; break } From a2312fc2ad54a8127377a5402dd69797ac672ccb Mon Sep 17 00:00:00 2001 From: -Mynster <66535357+Mynster9361@users.noreply.github.com> Date: Tue, 19 May 2026 09:21:28 +0200 Subject: [PATCH 30/31] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- powershell/public/Connect-Maester.ps1 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index af2586e26..96ef4935d 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -129,8 +129,10 @@ $__MtSession.Connections = $Service - $OrderedImport = Get-ModuleImportOrder -Name @('Az.Accounts', 'ExchangeOnlineManagement', 'Microsoft.Graph.Authentication', 'MicrosoftTeams', 'PnP.PowerShell') - switch ($OrderedImport.Name) { + # Use an explicit module processing order so Microsoft Graph always connects before PnP.PowerShell. + # This avoids relying on Get-ModuleImportOrder, which may reorder modules by bundled DLL version. + $OrderedImport = @('Az.Accounts', 'ExchangeOnlineManagement', 'Microsoft.Graph.Authentication', 'MicrosoftTeams', 'PnP.PowerShell') + switch ($OrderedImport) { 'Az.Accounts' { if ($Service -contains 'Azure' -or $Service -contains 'Dataverse' -or $Service -contains 'All') { From 97ba82fdffb49a90bf20606a7b1ac2aed27022fb Mon Sep 17 00:00:00 2001 From: -Mynster Date: Fri, 22 May 2026 12:02:35 +0200 Subject: [PATCH 31/31] checked everything tested the 3 implementation / authentication methods updated readme --- powershell/public/Connect-Maester.ps1 | 53 ++++++++---- website/docs/connect-maester/readme.md | 6 +- website/docs/sections/create-entra-app.md | 99 +++++++++++++++++++++-- 3 files changed, 134 insertions(+), 24 deletions(-) diff --git a/powershell/public/Connect-Maester.ps1 b/powershell/public/Connect-Maester.ps1 index 96ef4935d..4a7e02ad9 100644 --- a/powershell/public/Connect-Maester.ps1 +++ b/powershell/public/Connect-Maester.ps1 @@ -123,8 +123,19 @@ # The Client ID of the app to connect to for Graph. If not specified, the default Graph PowerShell CLI enterprise app will be used. Reference on how to create an enterprise app: https://learn.microsoft.com/en-us/powershell/microsoftgraph/authentication-commands?view=graph-powershell-1.0#use-delegated-access-with-a-custom-application-for-microsoft-graph-powershell [string]$GraphClientId, - # The Client ID of the PnP Entra ID app for SharePoint Online. Required when Service includes SharePointOnline. Create the app using Register-PnPEntraIDAppForInteractiveLogin. - [string]$SharePointClientId + # The Client ID of the PnP Entra ID app for SharePoint Online. Required when Service includes SharePointOnline. + # Use Register-PnPEntraIDAppForInteractiveLogin to create a dedicated app, or reuse an existing Maester app + # registration by adding an http://localhost redirect URI and AllSites.FullControl delegated SharePoint permission. + [string]$SharePointClientId, + + # The SharePoint admin center URL to connect to when using the SharePointOnline service (e.g. https://contoso-admin.sharepoint.com). + # If not specified, the URL is auto-discovered from the tenant's initial domain via the Microsoft Graph API. + [string]$SharePointAdminUrl, + + # The certificate thumbprint for app-only authentication to SharePoint Online. + # Use together with -SharePointClientId and -TenantId for non-interactive/automation scenarios. + # The certificate must be installed in the current user's certificate store. + [string]$SharePointCertificateThumbprint ) $__MtSession.Connections = $Service @@ -368,25 +379,39 @@ Write-Verbose 'Connecting to SharePoint Online via PnP' if (-not $SharePointClientId) { - Write-Host "`nSharePointOnline requires the -SharePointClientId parameter. Create a PnP app registration using Register-PnPEntraIDAppForInteractiveLogin.`nFor more information see https://maester.dev/docs/sections/create-entra-app" -ForegroundColor Red + Write-Host "`nSharePointOnline requires the -SharePointClientId parameter. You can use a dedicated PnP app (Register-PnPEntraIDAppForInteractiveLogin) or add an http://localhost redirect URI and AllSites.Read delegated permission to your existing Maester app registration.`nFor more information see https://maester.dev/docs/sections/create-entra-app" -ForegroundColor Red } else { try { - # Resolve the SharePoint admin URL from the tenant's initial domain - $domains = Invoke-MtGraphRequest -RelativeUri "domains" -ApiVersion "v1.0" - $initialDomain = ($domains | Where-Object { $_.isInitial -eq $true }).id - $tenantPrefix = ($initialDomain -split '\.')[0] - $spoAdminUrl = "https://$tenantPrefix-admin.sharepoint.com" - Write-Verbose "Resolved SharePoint admin URL: $spoAdminUrl" + # Use the provided admin URL or auto-discover from the tenant's initial domain + if ($SharePointAdminUrl) { + $spoAdminUrl = $SharePointAdminUrl + Write-Verbose "Using provided SharePoint admin URL: $spoAdminUrl" + } else { + $domains = Invoke-MtGraphRequest -RelativeUri "domains" -ApiVersion "v1.0" + $initialDomain = ($domains | Where-Object { $_.isInitial -eq $true }).id + $tenantPrefix = ($initialDomain -split '\.')[0] + $spoAdminUrl = "https://$tenantPrefix-admin.sharepoint.com" + Write-Verbose "Resolved SharePoint admin URL: $spoAdminUrl" + } Import-Module PnP.PowerShell -ErrorAction Stop $pnpParams = @{ Url = $spoAdminUrl ClientId = $SharePointClientId } - if ($UseDeviceCode) { - $pnpParams['DeviceLogin'] = $true - } - if ($TenantId) { - $pnpParams['Tenant'] = $TenantId + if ($SharePointCertificateThumbprint) { + if (-not $TenantId) { + Write-Host "`nThe -TenantId parameter is required when using -SharePointCertificateThumbprint." -ForegroundColor Red + } else { + $pnpParams['Thumbprint'] = $SharePointCertificateThumbprint + $pnpParams['Tenant'] = $TenantId + } + } else { + if ($UseDeviceCode) { + $pnpParams['DeviceLogin'] = $true + } + if ($TenantId) { + $pnpParams['Tenant'] = $TenantId + } } Connect-PnPOnline @pnpParams } catch [Management.Automation.CommandNotFoundException] { diff --git a/website/docs/connect-maester/readme.md b/website/docs/connect-maester/readme.md index 2b4804559..dc7b54759 100644 --- a/website/docs/connect-maester/readme.md +++ b/website/docs/connect-maester/readme.md @@ -87,16 +87,18 @@ Install the PnP PowerShell module if you haven't already: Install-Module PnP.PowerShell -Scope CurrentUser ``` +A dedicated Entra ID app registration configured for PnP interactive login is required. See [Grant permissions to SharePoint Online](../sections/create-entra-app.md) for how to create or reuse one. + Connect to SharePoint Online together with Microsoft Graph (the admin URL is auto-discovered from your tenant's initial domain): ```powershell -Connect-Maester -Service Graph,SharePointOnline +Connect-Maester -Service Graph,SharePointOnline -SharePointClientId '' ``` If auto-discovery does not work (e.g. in government or custom-domain tenants), supply the admin URL explicitly: ```powershell -Connect-Maester -Service Graph,SharePointOnline -SharePointAdminUrl 'https://contoso-admin.sharepoint.com' +Connect-Maester -Service Graph,SharePointOnline -SharePointClientId '' -SharePointAdminUrl 'https://contoso-admin.sharepoint.com' ``` If the PnP PowerShell module is not installed or there is no active connection, all SharePoint Online tests are skipped automatically. diff --git a/website/docs/sections/create-entra-app.md b/website/docs/sections/create-entra-app.md index 7e734f068..112fc2f96 100644 --- a/website/docs/sections/create-entra-app.md +++ b/website/docs/sections/create-entra-app.md @@ -43,6 +43,7 @@ The Exchange Online Role Based Access Control (RBAC) implementation utilizes ser New-ServicePrincipal -AppId -ObjectId -DisplayName New-ManagementRoleAssignment -Role "View-Only Configuration" -App ``` +
@@ -75,6 +76,7 @@ The Azure Role Based Access Control (RBAC) implementation utilizes Uniform Resou > The Azure RBAC permissions are necessary to support tests that validate [Azure configurations](https://maester.dev/docs/installation#installing-azure-and-exchange-online-modules), such as the [CISA tests](https://maester.dev/docs/tests/cisa/entra#:~:text=Test%2DMtCisaDiagnosticSettings). The following PowerShell script will enable you, with a Global Administrator role assignment, to: + - Identify the Service Principal Object ID that will be authorized as a Reader (Enterprise app Object ID) - Install the necessary Az module and prompt for connection - Elevate your account access to the root scope @@ -100,13 +102,14 @@ New-AzRoleAssignment -ObjectId $servicePrincipal -Scope "/providers/Microsoft.aa $assignment = Get-AzRoleAssignment -RoleDefinitionId 18d7d88d-d35e-4fb5-a5c3-7773c20a72d9|?{$_.Scope -eq "/" -and $_.SignInName -eq (Get-AzContext).Account.Id} $deleteAssignment = Invoke-AzRestMethod -Path "$($assignment.RoleAssignmentId)?api-version=2018-07-01" -Method DELETE ``` +
(Optional) Grant permissions to SharePoint Online ### (Optional) Grant permissions to SharePoint Online -SharePoint Online tests require the **PnP.PowerShell** module and a dedicated PnP Entra ID app registration. The standard Maester app registration does not cover SharePoint tenant admin operations — PnP requires its own app with `Sites.FullControl.All` permissions. +SharePoint Online tests require the **PnP.PowerShell** module and an Entra ID app registration configured for interactive login with SharePoint delegated permissions. > The SharePoint Online permissions are necessary to support tests that validate [SharePoint Online configurations](https://maester.dev/docs/tests/cisa/spo), such as the CISA SharePoint baseline controls. @@ -116,29 +119,109 @@ SharePoint Online tests require the **PnP.PowerShell** module and a dedicated Pn Install-Module PnP.PowerShell -Scope CurrentUser ``` -#### Register the PnP Entra ID app +#### Option A — Automatically create a new PnP app registration -PnP provides a built-in cmdlet to create the required app registration for interactive login: +PnP provides a built-in cmdlet to create a dedicated app registration for interactive login: ```powershell Register-PnPEntraIDAppForInteractiveLogin -ApplicationName "Maester PnP" -Tenant [yourtenant].onmicrosoft.com -SharePointDelegatePermissions "AllSites.FullControl" ``` This will: + - Create an Entra ID app registration with the required delegated permissions +- Configure `http://localhost` as the redirect URI automatically - Prompt you to authenticate and provide consent - Output the **Client ID** you will need for `Connect-Maester` -> **Note:** `AllSites.FullControl` (delegated) is the minimum permission required by PnP for tenant admin cmdlets like `Get-PnPTenant`. There is no read-only equivalent. +> **Note:** Maester's SharePoint tests are read-only. `AllSites.FullControl` (delegated) is sufficient. > > **Important:** After registering the app, open a **new PowerShell session** before running `Connect-Maester`, as the registration process loads PnP assemblies that can conflict with Microsoft Graph. -#### Connect to SharePoint Online +#### Option B — Reuse the existing Maester app registration + +If you prefer not to create a separate app, you can update the Maester app registration you created earlier to also support PnP PowerShell interactive login. + +**1. Add the localhost redirect URI** + +- Open your Maester app registration in the [Entra admin center](https://entra.microsoft.com) +- Select **Authentication** > **Add a platform** > **Mobile and desktop applications** +- In the **Custom redirect URIs** field, enter `http://localhost` (note: `http`, not `https`) +- Select **Configure** + +**2. Add SharePoint delegated permissions** + +- Select **API permissions** > **Add a permission** +- Select **SharePoint** > **Delegated permissions** +- Search for and check `AllSites.FullControl` +- Select **Add permissions** +- Select **Grant admin consent for [your organization]** and confirm + +**3. Connect using the existing Client ID** + +You can retrieve the Client ID of your Maester app from Graph without looking it up manually. First connect to Graph, then query for the app by its display name: + +```powershell +# Connect to Graph first +Connect-Maester -Service Graph + +# Retrieve the Client ID of the Maester app registration +$clientId = (Get-MgApplication -Filter "displayName eq 'Maester DevOps Account'").AppId +``` + +Then connect to SharePoint Online in a new session using the retrieved Client ID. The SharePoint admin URL is auto-discovered from your tenant — no need to specify it manually: + +```powershell +# Open a new PowerShell session, then: +Connect-Maester -Service Graph,SharePointOnline -SharePointClientId $clientId +``` + +> **Important:** After registering the app, open a **new PowerShell session** before running `Connect-Maester`, as PnP assemblies loaded during the session can conflict with Microsoft Graph. + +#### Option C — App-only access (automation / non-interactive) + +For unattended runs (CI pipelines, scheduled tasks) where interactive login is not possible, use application permissions with certificate-based authentication. -Use the Client ID from the previous step when connecting: +**1. Add SharePoint application permission** + +- Open your app registration in the [Entra admin center](https://entra.microsoft.com) +- Select **API permissions** > **Add a permission** +- Select **SharePoint** > **Application permissions** +- Search for and check `Sites.FullControl.All` +- Select **Add permissions** +- Select **Grant admin consent for [your organization]** and confirm + +**2. Upload a certificate** + +- Select **Certificates & secrets** > **Certificates** > **Upload certificate** +- Upload the public key (`.cer`) of your certificate + +**3. Connect using Connect-Maester** + +Pass the certificate thumbprint directly to `Connect-Maester` using `-SharePointCertificateThumbprint`. `-TenantId` is required for thumbprint-based auth: ```powershell -Connect-Maester -Service Graph,SharePointOnline -SharePointClientId "" +$params = @{ + Service = "Graph,SharePointOnline" + SharePointClientId = "" + SharePointCertificateThumbprint = "" + TenantId = "" +} +Connect-Maester @params +``` + +The certificate must be present in the current user's Windows certificate store. The SharePoint admin URL is auto-discovered — supply `-SharePointAdminUrl` to override it if needed. + +Use the Client ID from Option A or Option B when connecting: + +```powershell +Connect-Maester -Service Graph,SharePointOnline -SharePointClientId "" +``` + +The SharePoint admin URL is auto-discovered from your tenant's initial domain. If auto-discovery does not work (e.g. government or custom-domain tenants), supply it explicitly: + +```powershell +Connect-Maester -Service Graph,SharePointOnline -SharePointClientId "" -SharePointAdminUrl "https://contoso-admin.sharepoint.com" ``` For device code flow (e.g. non-interactive sessions): @@ -177,4 +260,4 @@ Add the environment URL to `maester-config.json`: } ``` -
\ No newline at end of file +