mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
feat(m365): add sharepoint service with 4 checks (#7057)
Co-authored-by: MarioRgzLpz <mariorgzlpz1809@gmail.com> Co-authored-by: HugoPBrito <hugopbrit@gmail.com> Co-authored-by: MrCloudSec <hello@mistercloudsec.com>
This commit is contained in:
committed by
César Arroba
parent
8ff0c59964
commit
d3dd1644e6
+9
-11
@@ -26,14 +26,15 @@ class entra_thirdparty_integrated_apps_not_allowed(Check):
|
||||
findings = []
|
||||
auth_policy = entra_client.authorization_policy
|
||||
|
||||
report = CheckReportMicrosoft365(
|
||||
metadata=self.metadata(),
|
||||
resource=auth_policy if auth_policy else {},
|
||||
resource_name=auth_policy.name if auth_policy else "Authorization Policy",
|
||||
resource_id=auth_policy.id if auth_policy else "authorizationPolicy",
|
||||
)
|
||||
|
||||
if auth_policy:
|
||||
report = CheckReportMicrosoft365(
|
||||
metadata=self.metadata(),
|
||||
resource=auth_policy if auth_policy else {},
|
||||
resource_name=(
|
||||
auth_policy.name if auth_policy else "Authorization Policy"
|
||||
),
|
||||
resource_id=auth_policy.id if auth_policy else "authorizationPolicy",
|
||||
)
|
||||
if getattr(
|
||||
auth_policy, "default_user_role_permissions", None
|
||||
) and not getattr(
|
||||
@@ -48,10 +49,7 @@ class entra_thirdparty_integrated_apps_not_allowed(Check):
|
||||
report.status_extended = (
|
||||
"App creation is not disabled for non-admin users."
|
||||
)
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = "Authorization Policy was not found."
|
||||
|
||||
findings.append(report)
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
from prowler.providers.common.provider import Provider
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import (
|
||||
SharePoint,
|
||||
)
|
||||
|
||||
sharepoint_client = SharePoint(Provider.get_global_provider())
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "microsoft365",
|
||||
"CheckID": "sharepoint_external_sharing_managed",
|
||||
"CheckTitle": "Ensure SharePoint external sharing is managed through domain whitelists/blacklists.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "sharepoint",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "Sharepoint Settings",
|
||||
"Description": "Control the sharing of documents to external domains by either blocking specific domains or only allowing sharing with named trusted domains.",
|
||||
"Risk": "If domain-based sharing restrictions are not enforced, users may share documents with untrusted external entities, increasing the risk of data exfiltration or unauthorized access.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "Set-SPOTenant -SharingDomainRestrictionMode AllowList -SharingAllowedDomainList 'domain1.com domain2.com'",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. Navigate to SharePoint admin center https://admin.microsoft.com/sharepoint. 2. Expand Policies then click Sharing. 3. Expand More external sharing settings and check 'Limit external sharing by domain'. 4. Select 'Add domains' to configure a list of approved domains. 5. Click Save.",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Enforce domain-based restrictions for SharePoint external sharing to control document sharing with trusted domains.",
|
||||
"Url": "https://learn.microsoft.com/en-us/powershell/module/sharepoint-online/set-spotenant?view=sharepoint-ps"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportMicrosoft365
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_client import (
|
||||
sharepoint_client,
|
||||
)
|
||||
|
||||
|
||||
class sharepoint_external_sharing_managed(Check):
|
||||
"""
|
||||
Check if Microsoft 365 SharePoint external sharing is managed through domain whitelists/blacklists.
|
||||
|
||||
This check verifies that SharePoint external sharing settings are configured to restrict document sharing
|
||||
to external domains by enforcing domain-based restrictions. This means that the setting
|
||||
'sharingDomainRestrictionMode' must be set to either "AllowList" or "BlockList". If it is not, then
|
||||
external sharing is not managed via domain restrictions, increasing the risk of unauthorized access.
|
||||
|
||||
Note: This check only evaluates the domain restriction mode and does not enforce the optional check
|
||||
of verifying that the allowed/blocked domain list is not empty.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportMicrosoft365]:
|
||||
"""
|
||||
Execute the SharePoint external sharing management check.
|
||||
|
||||
Iterates over the SharePoint settings retrieved from the Microsoft 365 SharePoint client and
|
||||
generates a report indicating whether external sharing is managed via domain restrictions.
|
||||
|
||||
Returns:
|
||||
List[CheckReportMicrosoft365]: A list containing a report with the result of the check.
|
||||
"""
|
||||
findings = []
|
||||
settings = sharepoint_client.settings
|
||||
if settings:
|
||||
report = CheckReportMicrosoft365(
|
||||
self.metadata(),
|
||||
resource=settings if settings else {},
|
||||
resource_name="SharePoint Settings",
|
||||
resource_id=sharepoint_client.tenant_domain,
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = "SharePoint external sharing is not managed through domain restrictions."
|
||||
if settings.sharingDomainRestrictionMode in ["allowList", "blockList"]:
|
||||
report.status_extended = f"SharePoint external sharing is managed through domain restrictions with mode '{settings.sharingDomainRestrictionMode}' but the list is empty."
|
||||
if (
|
||||
settings.sharingDomainRestrictionMode == "allowList"
|
||||
and settings.sharingAllowedDomainList
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"SharePoint external sharing is managed through domain restrictions with mode '{settings.sharingDomainRestrictionMode}'."
|
||||
elif (
|
||||
settings.sharingDomainRestrictionMode == "blockList"
|
||||
and settings.sharingBlockedDomainList
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"SharePoint external sharing is managed through domain restrictions with mode '{settings.sharingDomainRestrictionMode}'."
|
||||
|
||||
findings.append(report)
|
||||
return findings
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "microsoft365",
|
||||
"CheckID": "sharepoint_external_sharing_restricted",
|
||||
"CheckTitle": "Ensure external content sharing is restricted.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "sharepoint",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "Sharepoint Settings",
|
||||
"Description": "Ensure that external sharing settings in SharePoint are restricted to 'New and existing guests' or a less permissive level to enforce authentication and control over shared content.",
|
||||
"Risk": "If external sharing is not restricted, unauthorized users may gain access to sensitive information, increasing the risk of data breaches and compliance violations.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "Set-SPOTenant -SharingCapability ExternalUserSharingOnly",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. Navigate to SharePoint admin center https://admin.microsoft.com/sharepoint. 2. Click to expand Policies > Sharing. 3. Locate the External sharing section. 4. Under SharePoint, move the slider bar to 'New and existing guests' or a less permissive level.",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Restrict external sharing in SharePoint to 'New and existing guests' or a more restrictive setting to enhance security.",
|
||||
"Url": "https://learn.microsoft.com/en-us/powershell/module/sharepoint-online/set-spotenant?view=sharepoint-ps"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportMicrosoft365
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_client import (
|
||||
sharepoint_client,
|
||||
)
|
||||
|
||||
|
||||
class sharepoint_external_sharing_restricted(Check):
|
||||
"""
|
||||
Check if Microsoft 365 SharePoint restricts external sharing at organization level.
|
||||
|
||||
This check verifies that external sharing settings in SharePoint are configured to allow only "New and existing guests"
|
||||
(i.e., ExternalUserSharingOnly), which enforces authentication and limits access to external users. If a more permissive
|
||||
setting is used, legacy sharing may be allowed, increasing the risk of unauthorized data access.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportMicrosoft365]:
|
||||
"""
|
||||
Execute the SharePoint external sharing restriction check.
|
||||
|
||||
Iterates over the SharePoint settings retrieved from the Microsoft 365 SharePoint client and generates a report
|
||||
indicating whether external sharing is restricted to 'New and existing guests' (ExternalUserSharingOnly).
|
||||
|
||||
Returns:
|
||||
List[Check_Report_Microsoft365]: A list containing a report with the result of the check.
|
||||
"""
|
||||
findings = []
|
||||
settings = sharepoint_client.settings
|
||||
if settings:
|
||||
report = CheckReportMicrosoft365(
|
||||
self.metadata(),
|
||||
resource=settings if settings else {},
|
||||
resource_name="SharePoint Settings",
|
||||
resource_id=sharepoint_client.tenant_domain,
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
"External sharing is not restricted and guests users can access."
|
||||
)
|
||||
|
||||
if settings.sharingCapability in [
|
||||
"ExistingExternalUserSharingOnly",
|
||||
"ExternalUserSharingOnly",
|
||||
"Disabled",
|
||||
]:
|
||||
report.status = "PASS"
|
||||
report.status_extended = "External sharing is restricted to external user sharing or more restrictive."
|
||||
|
||||
findings.append(report)
|
||||
return findings
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "microsoft365",
|
||||
"CheckID": "sharepoint_guest_sharing_restricted",
|
||||
"CheckTitle": "Ensure that SharePoint guest users cannot share items they don't own.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "sharepoint",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "Sharepoint Settings",
|
||||
"Description": "Ensure that guest users in SharePoint cannot share items they do not own, preventing unauthorized disclosure of shared content.",
|
||||
"Risk": "If guest users are allowed to share items they don't own, there is a higher risk of unauthorized data exposure, as external users could share content beyond intended recipients.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/sharepoint/external-sharing-overview",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "Set-SPOTenant -PreventExternalUsersFromResharing $True",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. Navigate to SharePoint admin center https://admin.microsoft.com/sharepoint. 2. Click to expand Policies then select Sharing. 3. Expand More external sharing settings and uncheck 'Allow guests to share items they don't own'. 4. Click Save.",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Restrict guest users from sharing items they don't own to enhance security and prevent unauthorized access.",
|
||||
"Url": "https://learn.microsoft.com/en-us/sharepoint/turn-external-sharing-on-or-off"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportMicrosoft365
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_client import (
|
||||
sharepoint_client,
|
||||
)
|
||||
|
||||
|
||||
class sharepoint_guest_sharing_restricted(Check):
|
||||
"""
|
||||
Check if Microsoft 365 SharePoint guest sharing is restricted.
|
||||
|
||||
This check verifies that guest users in SharePoint cannot share items they do not own.
|
||||
When guest resharing is enabled, external users might share content they don't own,
|
||||
increasing the risk of unauthorized data exposure. This control ensures that the setting
|
||||
to prevent external users from resharing is enabled.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportMicrosoft365]:
|
||||
"""
|
||||
Execute the SharePoint guest sharing restriction check.
|
||||
|
||||
Iterates over the SharePoint settings retrieved from the Microsoft 365 SharePoint client
|
||||
and generates a report indicating whether guest users are prevented from sharing items they do not own.
|
||||
|
||||
Returns:
|
||||
List[CheckReportMicrosoft365]: A list containing a report with the result of the check.
|
||||
"""
|
||||
findings = []
|
||||
settings = sharepoint_client.settings
|
||||
if settings:
|
||||
report = CheckReportMicrosoft365(
|
||||
self.metadata(),
|
||||
resource=settings if settings else {},
|
||||
resource_name="SharePoint Settings",
|
||||
resource_id=sharepoint_client.tenant_domain,
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = "Guest sharing is not restricted; guest users can share items they do not own."
|
||||
if not settings.resharingEnabled:
|
||||
report.status = "PASS"
|
||||
report.status_extended = "Guest sharing is restricted; guest users cannot share items they do not own."
|
||||
|
||||
findings.append(report)
|
||||
return findings
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "microsoft365",
|
||||
"CheckID": "sharepoint_modern_authentication_required",
|
||||
"CheckTitle": "Ensure modern authentication for SharePoint applications is required.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "sharepoint",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "critical",
|
||||
"ResourceType": "Sharepoint Settings",
|
||||
"Description": "Ensure that modern authentication is required for SharePoint applications in Microsoft 365, preventing the use of legacy authentication protocols and blocking access to apps that don't use modern authentication.",
|
||||
"Risk": "If modern authentication is not enforced, SharePoint applications may rely on basic authentication, which lacks strong security measures like MFA and increases the risk of credential theft.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/graph/api/resources/sharepoint?view=graph-rest-1.0",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "Set-SPOTenant -LegacyAuthProtocolsEnabled $false",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. Navigate to SharePoint admin center https://admin.microsoft.com/sharepoint. 2. Click to expand Policies select Access control. 3. Select Apps that don't use modern authentication. 4. Select the radio button for Block access. 5. Click Save.",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Block access for SharePoint applications that don't use modern authentication to ensure secure authentication mechanisms.",
|
||||
"Url": "https://learn.microsoft.com/en-us/powershell/module/sharepoint-online/set-spotenant?view=sharepoint-ps"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportMicrosoft365
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_client import (
|
||||
sharepoint_client,
|
||||
)
|
||||
|
||||
|
||||
class sharepoint_modern_authentication_required(Check):
|
||||
"""
|
||||
Check if Microsoft 365 SharePoint requires modern authentication.
|
||||
|
||||
This check verifies that modern authentication is enforced for SharePoint applications in Microsoft 365.
|
||||
Modern authentication leverages OAuth 2.0 and supports advanced security features such as multi-factor
|
||||
authentication (MFA) and conditional access. Legacy authentication protocols (e.g., basic authentication)
|
||||
do not support these features and increase the risk of credential compromise.
|
||||
|
||||
The check fails if modern authentication is not enforced, indicating that legacy protocols may be used.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportMicrosoft365]:
|
||||
"""
|
||||
Execute the SharePoint modern authentication requirement check.
|
||||
|
||||
Iterates over the SharePoint configuration retrieved from the Microsoft 365 SharePoint client and
|
||||
generates a report indicating whether modern authentication is required for SharePoint applications.
|
||||
|
||||
Returns:
|
||||
List[CheckReportMicrosoft365]: A list containing the report object with the result of the check.
|
||||
"""
|
||||
findings = []
|
||||
settings = sharepoint_client.settings
|
||||
if settings:
|
||||
report = CheckReportMicrosoft365(
|
||||
self.metadata(),
|
||||
resource=settings if settings else {},
|
||||
resource_name="SharePoint Settings",
|
||||
resource_id=sharepoint_client.tenant_domain,
|
||||
)
|
||||
report.status = "PASS"
|
||||
report.status_extended = "Microsoft 365 SharePoint does not allow access to apps that don't use modern authentication."
|
||||
|
||||
# Legacy Auth being True means that SharePoint allow access to apps that do NOT use modern authentication
|
||||
if settings.legacyAuth:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = "Microsoft 365 SharePoint allows access to apps that don't use modern authentication."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,62 @@
|
||||
from asyncio import gather, get_event_loop
|
||||
from typing import List, Optional
|
||||
|
||||
from msgraph.generated.models.o_data_errors.o_data_error import ODataError
|
||||
from pydantic import BaseModel
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.microsoft365.lib.service.service import Microsoft365Service
|
||||
from prowler.providers.microsoft365.microsoft365_provider import Microsoft365Provider
|
||||
|
||||
|
||||
class SharePoint(Microsoft365Service):
|
||||
def __init__(self, provider: Microsoft365Provider):
|
||||
super().__init__(provider)
|
||||
loop = get_event_loop()
|
||||
self.tenant_domain = provider.identity.tenant_domain
|
||||
attributes = loop.run_until_complete(
|
||||
gather(
|
||||
self._get_settings(),
|
||||
)
|
||||
)
|
||||
self.settings = attributes[0]
|
||||
|
||||
async def _get_settings(self):
|
||||
logger.info("Microsoft365 - Getting SharePoint global settings...")
|
||||
settings = None
|
||||
try:
|
||||
global_settings = await self.client.admin.sharepoint.settings.get()
|
||||
|
||||
settings = SharePointSettings(
|
||||
sharingCapability=(
|
||||
str(global_settings.sharing_capability).split(".")[-1]
|
||||
if global_settings.sharing_capability
|
||||
else None
|
||||
),
|
||||
sharingAllowedDomainList=global_settings.sharing_allowed_domain_list,
|
||||
sharingBlockedDomainList=global_settings.sharing_blocked_domain_list,
|
||||
sharingDomainRestrictionMode=global_settings.sharing_domain_restriction_mode,
|
||||
legacyAuth=global_settings.is_legacy_auth_protocols_enabled,
|
||||
resharingEnabled=global_settings.is_resharing_by_external_users_enabled,
|
||||
)
|
||||
|
||||
except ODataError as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return None
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return None
|
||||
return settings
|
||||
|
||||
|
||||
class SharePointSettings(BaseModel):
|
||||
sharingCapability: str
|
||||
sharingAllowedDomainList: Optional[List[str]]
|
||||
sharingBlockedDomainList: Optional[List[str]]
|
||||
sharingDomainRestrictionMode: str
|
||||
resharingEnabled: bool
|
||||
legacyAuth: bool
|
||||
+1
-7
@@ -33,13 +33,7 @@ class Test_entra_thirdparty_integrated_apps_not_allowed:
|
||||
|
||||
check = entra_thirdparty_integrated_apps_not_allowed()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].resource == {}
|
||||
assert result[0].resource_name == "Authorization Policy"
|
||||
assert result[0].resource_id == "authorizationPolicy"
|
||||
assert result[0].status_extended == "Authorization Policy was not found."
|
||||
assert result[0].location == "global"
|
||||
assert len(result) == 0
|
||||
|
||||
def test_entra_default_user_role_permissions_not_allowed_to_create_apps(self):
|
||||
id = str(uuid4())
|
||||
|
||||
+298
@@ -0,0 +1,298 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import (
|
||||
SharePointSettings,
|
||||
)
|
||||
from tests.providers.microsoft365.microsoft365_fixtures import (
|
||||
DOMAIN,
|
||||
set_mocked_microsoft365_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_sharepoint_external_sharing_managed:
|
||||
def test_external_sharing_invalid_mode(self):
|
||||
"""
|
||||
Test when sharingDomainRestrictionMode is set to an invalid value (not "allowList" ni "blockList"):
|
||||
The check should FAIL with the default message.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import (
|
||||
sharepoint_external_sharing_managed,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserSharingOnly",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
legacyAuth=True,
|
||||
resharingEnabled=False,
|
||||
sharingDomainRestrictionMode="none",
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_external_sharing_managed()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "SharePoint external sharing is not managed through domain restrictions."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserSharingOnly",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "none",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_allow_list_empty(self):
|
||||
"""
|
||||
Test when sharingDomainRestrictionMode is "allowList" but AllowedDomainList is empty:
|
||||
The check should FAIL with a message indicating the list is empty.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import (
|
||||
sharepoint_external_sharing_managed,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserSharingOnly",
|
||||
sharingAllowedDomainList=[],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
legacyAuth=True,
|
||||
resharingEnabled=False,
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_external_sharing_managed()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "SharePoint external sharing is managed through domain restrictions with mode 'allowList' but the list is empty."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserSharingOnly",
|
||||
"sharingAllowedDomainList": [],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "allowList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_block_list_empty(self):
|
||||
"""
|
||||
Test when sharingDomainRestrictionMode is "blockList" but BlockedDomainList is empty:
|
||||
The check should FAIL with a message indicating the list is empty.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import (
|
||||
sharepoint_external_sharing_managed,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserSharingOnly",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=[],
|
||||
legacyAuth=True,
|
||||
resharingEnabled=False,
|
||||
sharingDomainRestrictionMode="blockList",
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_external_sharing_managed()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "SharePoint external sharing is managed through domain restrictions with mode 'blockList' but the list is empty."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserSharingOnly",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": [],
|
||||
"sharingDomainRestrictionMode": "blockList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_allow_list_non_empty(self):
|
||||
"""
|
||||
Test when sharingDomainRestrictionMode is "allowList" and AllowedDomainList is not empty:
|
||||
The check should PASS.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import (
|
||||
sharepoint_external_sharing_managed,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserSharingOnly",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
legacyAuth=True,
|
||||
resharingEnabled=False,
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_external_sharing_managed()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "SharePoint external sharing is managed through domain restrictions with mode 'allowList'."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserSharingOnly",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "allowList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_block_list_non_empty(self):
|
||||
"""
|
||||
Test when sharingDomainRestrictionMode is "blockList" and BlockedDomainList is not empty:
|
||||
The check should PASS.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import (
|
||||
sharepoint_external_sharing_managed,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserSharingOnly",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
legacyAuth=True,
|
||||
resharingEnabled=False,
|
||||
sharingDomainRestrictionMode="blockList",
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_external_sharing_managed()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "SharePoint external sharing is managed through domain restrictions with mode 'blockList'."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserSharingOnly",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "blockList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_empty_settings(self):
|
||||
"""
|
||||
Test when sharepoint_client.settings is empty:
|
||||
The check should return an empty list of findings.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
sharepoint_client.settings = {}
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_managed.sharepoint_external_sharing_managed import (
|
||||
sharepoint_external_sharing_managed,
|
||||
)
|
||||
|
||||
check = sharepoint_external_sharing_managed()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import (
|
||||
SharePointSettings,
|
||||
)
|
||||
from tests.providers.microsoft365.microsoft365_fixtures import (
|
||||
DOMAIN,
|
||||
set_mocked_microsoft365_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_sharepoint_external_sharing_restricted:
|
||||
def test_external_sharing_restricted(self):
|
||||
"""
|
||||
Test when sharingCapability is set to an allowed value (e.g. "ExternalUserSharingOnly"):
|
||||
The check should PASS because external sharing is restricted.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import (
|
||||
sharepoint_external_sharing_restricted,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserSharingOnly",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
resharingEnabled=False,
|
||||
legacyAuth=True,
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_external_sharing_restricted()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].status_extended == (
|
||||
"External sharing is restricted to external user sharing or more restrictive."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserSharingOnly",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "allowList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_external_sharing_not_restricted(self):
|
||||
"""
|
||||
Test when sharingCapability is set to a non-restricted value (e.g. "ExternalUserAndGuestSharing"):
|
||||
The check should FAIL because external sharing is not restricted.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import (
|
||||
sharepoint_external_sharing_restricted,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserAndGuestSharing",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
resharingEnabled=False,
|
||||
legacyAuth=True,
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_external_sharing_restricted()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].status_extended == (
|
||||
"External sharing is not restricted and guests users can access."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserAndGuestSharing",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "allowList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_empty_settings(self):
|
||||
"""
|
||||
Test when sharepoint_client.settings is empty:
|
||||
The check should return an empty list of findings.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
sharepoint_client.settings = {}
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_external_sharing_restricted.sharepoint_external_sharing_restricted import (
|
||||
sharepoint_external_sharing_restricted,
|
||||
)
|
||||
|
||||
check = sharepoint_external_sharing_restricted()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import (
|
||||
SharePointSettings,
|
||||
)
|
||||
from tests.providers.microsoft365.microsoft365_fixtures import (
|
||||
DOMAIN,
|
||||
set_mocked_microsoft365_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_sharepoint_guest_sharing_restricted:
|
||||
def test_guest_sharing_restricted(self):
|
||||
"""
|
||||
Test when resharingEnabled is False:
|
||||
The check should PASS because guest sharing is restricted.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import (
|
||||
sharepoint_guest_sharing_restricted,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserSharingOnly",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
legacyAuth=True,
|
||||
resharingEnabled=False,
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_guest_sharing_restricted()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].status_extended == (
|
||||
"Guest sharing is restricted; guest users cannot share items they do not own."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserSharingOnly",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "allowList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_guest_sharing_not_restricted(self):
|
||||
"""
|
||||
Test when resharingEnabled is True:
|
||||
The check should FAIL because guest sharing is not restricted.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import (
|
||||
sharepoint_guest_sharing_restricted,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserSharingOnly",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
legacyAuth=True,
|
||||
resharingEnabled=True,
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_guest_sharing_restricted()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].status_extended == (
|
||||
"Guest sharing is not restricted; guest users can share items they do not own."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserSharingOnly",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "allowList",
|
||||
"resharingEnabled": True,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_empty_settings(self):
|
||||
"""
|
||||
Test when sharepoint_client.settings is empty:
|
||||
The check should return an empty list of findings.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
sharepoint_client.settings = {}
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_guest_sharing_restricted.sharepoint_guest_sharing_restricted import (
|
||||
sharepoint_guest_sharing_restricted,
|
||||
)
|
||||
|
||||
check = sharepoint_guest_sharing_restricted()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 0
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
from unittest import mock
|
||||
|
||||
from tests.providers.microsoft365.microsoft365_fixtures import (
|
||||
DOMAIN,
|
||||
set_mocked_microsoft365_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_sharepoint_modern_authentication_required:
|
||||
def test_sharepoint_modern_authentication_disabled(self):
|
||||
"""
|
||||
Test when legacyAuth is False:
|
||||
The check should PASS, as SharePoint does not allow access to apps that don't use modern authentication.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import (
|
||||
sharepoint_modern_authentication_required,
|
||||
)
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import (
|
||||
SharePointSettings,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserAndGuestSharing",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
resharingEnabled=False,
|
||||
legacyAuth=False,
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_modern_authentication_required()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].status_extended == (
|
||||
"Microsoft 365 SharePoint does not allow access to apps that don't use modern authentication."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserAndGuestSharing",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "allowList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": False,
|
||||
}
|
||||
|
||||
def test_sharepoint_modern_authentication_enabled(self):
|
||||
"""
|
||||
Test when legacyAuth is True:
|
||||
The check should FAIL, as SharePoint allows access to apps that don't use modern authentication.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import (
|
||||
sharepoint_modern_authentication_required,
|
||||
)
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import (
|
||||
SharePointSettings,
|
||||
)
|
||||
|
||||
sharepoint_client.settings = SharePointSettings(
|
||||
sharingCapability="ExternalUserAndGuestSharing",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
resharingEnabled=False,
|
||||
legacyAuth=True,
|
||||
)
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
check = sharepoint_modern_authentication_required()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].status_extended == (
|
||||
"Microsoft 365 SharePoint allows access to apps that don't use modern authentication."
|
||||
)
|
||||
assert result[0].resource_id == DOMAIN
|
||||
assert result[0].location == "global"
|
||||
assert result[0].resource_name == "SharePoint Settings"
|
||||
assert result[0].resource == {
|
||||
"sharingCapability": "ExternalUserAndGuestSharing",
|
||||
"sharingAllowedDomainList": ["allowed-domain.com"],
|
||||
"sharingBlockedDomainList": ["blocked-domain.com"],
|
||||
"sharingDomainRestrictionMode": "allowList",
|
||||
"resharingEnabled": False,
|
||||
"legacyAuth": True,
|
||||
}
|
||||
|
||||
def test_sharepoint_empty_settings(self):
|
||||
"""
|
||||
Test when sharepoint_client.settings is empty:
|
||||
The check should return an empty list of findings.
|
||||
"""
|
||||
sharepoint_client = mock.MagicMock
|
||||
sharepoint_client.settings = {}
|
||||
sharepoint_client.tenant_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required.sharepoint_client",
|
||||
new=sharepoint_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_modern_authentication_required.sharepoint_modern_authentication_required import (
|
||||
sharepoint_modern_authentication_required,
|
||||
)
|
||||
|
||||
check = sharepoint_modern_authentication_required()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
@@ -0,0 +1,46 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
from prowler.providers.microsoft365.models import Microsoft365IdentityInfo
|
||||
from prowler.providers.microsoft365.services.sharepoint.sharepoint_service import (
|
||||
SharePoint,
|
||||
SharePointSettings,
|
||||
)
|
||||
from tests.providers.microsoft365.microsoft365_fixtures import (
|
||||
DOMAIN,
|
||||
set_mocked_microsoft365_provider,
|
||||
)
|
||||
|
||||
|
||||
async def mock_sharepoint_get_settings(_):
|
||||
return SharePointSettings(
|
||||
sharingCapability="ExternalUserAndGuestSharing",
|
||||
sharingAllowedDomainList=["allowed-domain.com"],
|
||||
sharingBlockedDomainList=["blocked-domain.com"],
|
||||
sharingDomainRestrictionMode="allowList",
|
||||
resharingEnabled=False,
|
||||
legacyAuth=True,
|
||||
)
|
||||
|
||||
|
||||
@patch(
|
||||
"prowler.providers.microsoft365.services.sharepoint.sharepoint_service.SharePoint._get_settings",
|
||||
new=mock_sharepoint_get_settings,
|
||||
)
|
||||
class Test_SharePoint_Service:
|
||||
def test_get_client(self):
|
||||
sharepoint_client = SharePoint(
|
||||
set_mocked_microsoft365_provider(
|
||||
identity=Microsoft365IdentityInfo(tenant_domain=DOMAIN)
|
||||
)
|
||||
)
|
||||
assert sharepoint_client.client.__class__.__name__ == "GraphServiceClient"
|
||||
|
||||
def test_get_settings(self):
|
||||
sharepoint_client = SharePoint(set_mocked_microsoft365_provider())
|
||||
settings = sharepoint_client.settings
|
||||
assert settings.sharingCapability == "ExternalUserAndGuestSharing"
|
||||
assert settings.sharingAllowedDomainList == ["allowed-domain.com"]
|
||||
assert settings.sharingBlockedDomainList == ["blocked-domain.com"]
|
||||
assert settings.sharingDomainRestrictionMode == "allowList"
|
||||
assert settings.resharingEnabled is False
|
||||
assert settings.legacyAuth is True
|
||||
Reference in New Issue
Block a user