mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
feat(entra): add new check entra_policy_restricts_user_consent_for_apps (#7225)
This commit is contained in:
committed by
Pepe Fagoaga
parent
3c9ae06086
commit
dcf53ea357
+1
-1
@@ -7,7 +7,7 @@
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "#microsoft.graph.authorizationPolicy",
|
||||
"ResourceType": "Authorization Policy",
|
||||
"Description": "Require administrators or appropriately delegated users to create new tenants.",
|
||||
"Risk": "It is recommended to only allow an administrator to create new tenants. This prevent users from creating new Azure AD or Azure AD B2C tenants and ensures that only authorized users are able to do so.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/entra/fundamentals/users-default-permissions",
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "microsoft365",
|
||||
"CheckID": "entra_policy_restricts_user_consent_for_apps",
|
||||
"CheckTitle": "Ensure 'User consent for applications' is set to 'Do not allow user consent'",
|
||||
"CheckType": [],
|
||||
"ServiceName": "entra",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "Authorization Policy",
|
||||
"Description": "Require administrators to provide consent for applications before use.",
|
||||
"Risk": "If Microsoft Entra ID is running as an identity provider for third-party applications, permissions and consent should be limited to administrators or pre-approved. Malicious applications may attempt to exfiltrate data or abuse privileged user accounts.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-gb/entra/identity/enterprise-apps/configure-user-consent?pivots=portal",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "1. Navigate to Microsoft Entra admin center (https://entra.microsoft.com/); 2. Click to expand Identity > Applications and select Enterprise applications; 3. Under Security select Consent and permissions > User consent settings; 4. Under User consent for applications select Do not allow user consent; 5. Click the Save option at the top of the window.",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Disable user consent for applications in the Microsoft Entra admin center. This ensures that end users and group owners cannot grant consent to applications, requiring administrator approval for all future consent operations, thereby reducing the risk of unauthorized access to company data.",
|
||||
"Url": "https://learn.microsoft.com/en-gb/entra/identity/enterprise-apps/configure-user-consent?pivots=portal"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Enforcing this setting may create additional requests that administrators need to review."
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
from typing import List
|
||||
|
||||
from prowler.lib.check.models import Check, CheckReportMicrosoft365
|
||||
from prowler.providers.microsoft365.services.entra.entra_client import entra_client
|
||||
|
||||
|
||||
class entra_policy_restricts_user_consent_for_apps(Check):
|
||||
"""Check if the authorization policy restricts users from consenting apps.
|
||||
|
||||
This check verifies whether the default user role permissions in Microsoft Entra
|
||||
prevent users from consenting to apps that access company data on their behalf.
|
||||
If such consent is disabled, the check passes.
|
||||
"""
|
||||
|
||||
def execute(self) -> List[CheckReportMicrosoft365]:
|
||||
"""Execute the check for user consent restrictions.
|
||||
|
||||
Returns:
|
||||
List[CheckReportMicrosoft365]: A list containing the result of the 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",
|
||||
)
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
"Entra allows users to consent apps accessing company data on their behalf."
|
||||
)
|
||||
|
||||
if getattr(auth_policy, "default_user_role_permissions", None) and not any(
|
||||
"ManagePermissionGrantsForSelf" in policy_assigned
|
||||
for policy_assigned in getattr(
|
||||
auth_policy.default_user_role_permissions,
|
||||
"permission_grant_policies_assigned",
|
||||
["ManagePermissionGrantsForSelf.microsoft-user-default-legacy"],
|
||||
)
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = "Entra does not allow users to consent apps accessing company data on their behalf."
|
||||
|
||||
findings.append(report)
|
||||
return findings
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.microsoft365.services.entra.entra_service import (
|
||||
AuthorizationPolicy,
|
||||
DefaultUserRolePermissions,
|
||||
)
|
||||
from tests.providers.microsoft365.microsoft365_fixtures import (
|
||||
set_mocked_microsoft365_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_entra_policy_restricts_user_consent_for_apps:
|
||||
def test_entra_empty_policy(self):
|
||||
"""
|
||||
Test that the check fails when no authorization policy exists.
|
||||
|
||||
This test mocks the 'entra_client.authorization_policy' as an empty dictionary.
|
||||
Expected result: The check returns FAIL with the extended message indicating that
|
||||
Entra allows users to consent apps accessing company data on their behalf.
|
||||
"""
|
||||
entra_client = mock.MagicMock
|
||||
entra_client.authorization_policy = {}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_microsoft365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import (
|
||||
entra_policy_restricts_user_consent_for_apps,
|
||||
)
|
||||
|
||||
check = entra_policy_restricts_user_consent_for_apps()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "Entra allows users to consent apps accessing company data on their behalf."
|
||||
)
|
||||
assert result[0].resource == {}
|
||||
assert result[0].resource_name == "Authorization Policy"
|
||||
assert result[0].resource_id == "authorizationPolicy"
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_entra_policy_allows_user_consent(self):
|
||||
"""
|
||||
Test that the check fails when the authorization policy allows user consent.
|
||||
|
||||
This test mocks the 'entra_client.authorization_policy' with a policy that includes
|
||||
a permission grant policy (e.g., "ManagePermissionGrantsForSelf.microsoft-user-default-legacy")
|
||||
that allows users to consent apps.
|
||||
Expected result: The check returns FAIL with the extended message indicating that
|
||||
Entra allows users to consent apps accessing company data on their behalf.
|
||||
"""
|
||||
id = str(uuid4())
|
||||
entra_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.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import (
|
||||
entra_policy_restricts_user_consent_for_apps,
|
||||
)
|
||||
|
||||
entra_client.authorization_policy = AuthorizationPolicy(
|
||||
id=id,
|
||||
name="Test Policy",
|
||||
description="Test Policy Description",
|
||||
default_user_role_permissions=DefaultUserRolePermissions(
|
||||
permission_grant_policies_assigned=[
|
||||
"ManagePermissionGrantsForSelf.microsoft-user-default-legacy"
|
||||
]
|
||||
),
|
||||
)
|
||||
|
||||
check = entra_policy_restricts_user_consent_for_apps()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "Entra allows users to consent apps accessing company data on their behalf."
|
||||
)
|
||||
assert result[0].resource == entra_client.authorization_policy.dict()
|
||||
assert result[0].resource_name == "Test Policy"
|
||||
assert result[0].resource_id == id
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_entra_policy_restricts_user_consent(self):
|
||||
"""
|
||||
Test that the check passes when the authorization policy restricts user consent.
|
||||
|
||||
This test mocks the 'entra_client.authorization_policy' with a policy that does not include
|
||||
any permission grant policy allowing user consent (i.e., it lacks policies containing
|
||||
"ManagePermissionGrantsForSelf").
|
||||
Expected result: The check returns PASS with the extended message indicating that
|
||||
Entra does not allow users to consent apps accessing company data on their behalf.
|
||||
"""
|
||||
id = str(uuid4())
|
||||
entra_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.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.microsoft365.services.entra.entra_policy_restricts_user_consent_for_apps.entra_policy_restricts_user_consent_for_apps import (
|
||||
entra_policy_restricts_user_consent_for_apps,
|
||||
)
|
||||
|
||||
entra_client.authorization_policy = AuthorizationPolicy(
|
||||
id=id,
|
||||
name="Test Policy",
|
||||
description="Test Policy Description",
|
||||
default_user_role_permissions=DefaultUserRolePermissions(
|
||||
permission_grant_policies_assigned=["SomeOtherPolicy"]
|
||||
),
|
||||
)
|
||||
|
||||
check = entra_policy_restricts_user_consent_for_apps()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "Entra does not allow users to consent apps accessing company data on their behalf."
|
||||
)
|
||||
assert result[0].resource == entra_client.authorization_policy.dict()
|
||||
assert result[0].resource_name == "Test Policy"
|
||||
assert result[0].resource_id == id
|
||||
assert result[0].location == "global"
|
||||
Reference in New Issue
Block a user