Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(m365): add sharepoint service with 4 checks #7057

Merged
merged 59 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
210207a
feat(microsoft365): Add new provider microsoft 365 to prowler main
MarioRgzLpz Nov 20, 2024
9bb4329
feat(microsoft365): Add microsoft365 CheckReport model
MarioRgzLpz Nov 20, 2024
9a9cc9a
feat(microsoft365): Add microsoft365 to provider and summary table
MarioRgzLpz Nov 20, 2024
a27029c
feat(microsoft365): Add microsoft365 as a new provider. Add a service…
MarioRgzLpz Nov 20, 2024
ad1518f
feat(microsoft365): Fix some things so the output is correctly generated
MarioRgzLpz Nov 26, 2024
4bd81de
feat(microsoft365): Rename users service to admincenter and add some …
MarioRgzLpz Nov 26, 2024
4564f0d
feat(admincenter): Finish checks and service, add metadata but still …
MarioRgzLpz Nov 26, 2024
eb4e41b
fix(microsoft365): Adding verify connection to m365 provider, current…
MarioRgzLpz Nov 27, 2024
8860895
feat(admincenter): Delete one attribute from the user that was not go…
MarioRgzLpz Nov 28, 2024
13f6139
feat(tests): Add service and checks tests working properly, provider …
MarioRgzLpz Nov 28, 2024
a18b79a
feat(tests): Fix some microsoft tests, still not working
MarioRgzLpz Dec 2, 2024
68e29b6
feat(microsoft365): Fix exceptions, make some changes in provider to …
MarioRgzLpz Dec 2, 2024
ac80388
feat(microsoft365): Finish provider and mutelist tests
MarioRgzLpz Dec 3, 2024
1dccb40
feat(microsoft365): Finish provider with test connection, finish exce…
MarioRgzLpz Dec 3, 2024
de10410
feat(microsoft365): Change service to save only one client as multite…
MarioRgzLpz Dec 4, 2024
6a8c43f
feat(microsoft365): Adjust tests to service changes
MarioRgzLpz Dec 4, 2024
5a88a60
feat(microsoft365): Fill compliance with the done checks and put manu…
MarioRgzLpz Dec 4, 2024
ff81f4d
fix(admincenter): Fix metadata service in the checks so scan by servi…
MarioRgzLpz Dec 18, 2024
b366afe
fix: Delete categories in the check metadata
MarioRgzLpz Dec 19, 2024
8f7ac79
Merge branch 'master' into PRWLR-5291-microsoft-365-mvp-development
danibarranqueroo Jan 10, 2025
04964d2
fix(m365): fix provider test
danibarranqueroo Jan 16, 2025
fc64e50
chore(m365): fix regions test
danibarranqueroo Jan 16, 2025
72b8da1
fix(m365): modify regions file name
danibarranqueroo Jan 16, 2025
e5ca040
feat: mutelist tested and mutelist example added
HugoPBrito Jan 17, 2025
ff10832
chore: enhanced exepction management
HugoPBrito Jan 20, 2025
90e665e
chore: add m365 to help
MrCloudSec Jan 21, 2025
ec31c0b
chore: revision and add compliance
MrCloudSec Jan 21, 2025
a2a5691
chore: improve check
MrCloudSec Jan 21, 2025
19b93e0
feat(sharepoint): add first version of new service for m365
danibarranqueroo Jan 22, 2025
93be3e1
feat: add new authentication flow
HugoPBrito Jan 22, 2025
2522de8
feat: added cli and browser auth methods
HugoPBrito Jan 22, 2025
a7dff9c
feat: improve error logs and add auth tests
HugoPBrito Jan 23, 2025
325b26c
chore: change args names
MrCloudSec Jan 23, 2025
c926937
chore: revision
MrCloudSec Jan 23, 2025
4d4a19a
chore: revision
MrCloudSec Jan 23, 2025
02a270c
chore: revision
MrCloudSec Jan 23, 2025
4aaf459
chore: revision
MrCloudSec Jan 23, 2025
979ad41
feat: add tenant id to cli auth identity
HugoPBrito Jan 23, 2025
41e48de
fix: test connection
HugoPBrito Jan 23, 2025
270e89f
feat: enhance logic and add m365 static credentials
HugoPBrito Jan 24, 2025
d63cf78
Merge branch 'master' into PRWLR-5291-microsoft-365-mvp-development
HugoPBrito Jan 24, 2025
3120e66
feat: add resource metadata
HugoPBrito Jan 24, 2025
8250087
Merge branch 'PRWLR-5291-microsoft-365-mvp-development' into PRWLR-60…
danibarranqueroo Jan 24, 2025
f5bd486
merge branch master into 'PRWLR-6061-create-sharepoint-service'
danibarranqueroo Jan 27, 2025
3815b02
feat(sharepoint): add service test and modify service
danibarranqueroo Jan 27, 2025
74851ec
feat(sharepoint): add new check for modern authentication with unit t…
danibarranqueroo Feb 13, 2025
10431eb
feat(sharepoint): add check and unit tests to ensure external sharing…
danibarranqueroo Feb 14, 2025
a7bdbda
feat(sharepoint): add new check for manage domains through lists
danibarranqueroo Feb 17, 2025
439c95c
feat(sharepoint): add new check for restricting guest sharing
danibarranqueroo Feb 19, 2025
0038e81
chore(sharepoint): remove from the service useless api call
danibarranqueroo Feb 19, 2025
85611e4
Merge branch 'master' into PRWLR-6061-create-sharepoint-service
danibarranqueroo Feb 26, 2025
9be9c3c
chore(sharepoint): refactor external sharing managed check
danibarranqueroo Feb 26, 2025
0d3f681
chore(sharepoint): refactor external sharing restricted check
danibarranqueroo Feb 26, 2025
b2656fa
chore(sharepoint): refactor guest sharing restricted check
danibarranqueroo Feb 27, 2025
44b796e
chore(sharepoint): refactor modern authentication check
danibarranqueroo Feb 27, 2025
18895d5
chore(sharepoint): refactor service test
danibarranqueroo Feb 27, 2025
171bd4d
Merge branch 'master' into PRWLR-6061-create-sharepoint-service
danibarranqueroo Feb 27, 2025
ad2aa6a
chore: revision
MrCloudSec Feb 27, 2025
76ae9b1
chore(sharepoint): change legacy auth parameter name
danibarranqueroo Feb 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@ def execute(self) -> List[CheckReportMicrosoft365]:
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(
Expand All @@ -48,10 +49,7 @@ def execute(self) -> List[CheckReportMicrosoft365]:
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
Empty file.
Original file line number Diff line number Diff line change
@@ -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())
Original file line number Diff line number Diff line change
@@ -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": ""
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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": ""
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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": ""
}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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": ""
}
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading