Skip to content

feat(m365): add Entra Conditional Access group management restriction#11342

Open
SAMurai-16 wants to merge 2 commits into
prowler-cloud:masterfrom
SAMurai-16:feat/entra-ca-groups-management-restricted
Open

feat(m365): add Entra Conditional Access group management restriction#11342
SAMurai-16 wants to merge 2 commits into
prowler-cloud:masterfrom
SAMurai-16:feat/entra-ca-groups-management-restricted

Conversation

@SAMurai-16
Copy link
Copy Markdown

@SAMurai-16 SAMurai-16 commented May 23, 2026

Context

Adds a Microsoft 365 Entra check for Conditional Access policies that reference security groups in includeGroups or excludeGroups.

Groups used by Conditional Access policies are security-sensitive because changing group membership can affect who is included in, or excluded from, access controls. This check helps detect groups that are not protected by Restricted Management Administrative Units or role-assignable group controls.

Fix #11060

Description

This PR adds entra_conditional_access_policy_groups_management_restricted.

The check evaluates enabled and report-only Conditional Access policies, collects referenced group IDs from conditions.users.includeGroups and conditions.users.excludeGroups, and verifies each resolved group has at least one of:

  • isManagementRestricted = true
  • isAssignableToRole = true

The check fails when a referenced group has both values set to false, and reports unresolved group IDs separately as stale Conditional Access references.

Changes included:

  • Extend Microsoft Graph group collection to request isAssignableToRole and isManagementRestricted.
  • Add the new Entra check and metadata.
  • Add tests for protected groups, unprotected groups, no referenced groups, and unresolved group references.

No new provider permissions are required.

Steps to review

  1. Review the group enrichment in prowler/providers/m365/services/entra/entra_service.py.
  2. Review the new check logic under prowler/providers/m365/services/entra/entra_conditional_access_policy_groups_management_restricted/.
  3. Review the new metadata file for severity, remediation, and references.
  4. Run the focused tests:
uv run pytest tests/providers/m365/services/entra/entra_conditional_access_policy_groups_management_restricted/entra_conditional_access_policy_groups_management_restricted_test.py

SDK/CLI

  • Are there new checks included in this PR? Yes
    • If so, do we need to update permissions for the provider? Please review this carefully. No

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@SAMurai-16 SAMurai-16 requested a review from a team as a code owner May 23, 2026 10:16
Copilot AI review requested due to automatic review settings May 23, 2026 10:16
@github-actions github-actions Bot added provider/m365 Issues/PRs related with the M365 provider metadata-review community Opened by the Community labels May 23, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 23, 2026

Conflict Markers Resolved

All conflict markers have been successfully resolved in this pull request.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds a new M365 Entra check to ensure groups referenced by enabled/report-only Conditional Access policies are protected (management-restricted or role-assignable), and extends group collection to fetch the required Graph properties.

Changes:

  • Introduces entra_conditional_access_policy_groups_management_restricted check implementation + metadata.
  • Updates Entra group retrieval to $select role-assignable and management-restricted properties and handle pagination.
  • Adds unit tests covering pass/fail scenarios for protected, unprotected, and unresolved group references.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
prowler/providers/m365/services/entra/entra_service.py Fetches additional group fields (isAssignableToRole, isManagementRestricted) and paginates groups results.
prowler/providers/m365/services/entra/entra_conditional_access_policy_groups_management_restricted/entra_conditional_access_policy_groups_management_restricted.py New check logic to evaluate Conditional Access group references.
prowler/providers/m365/services/entra/entra_conditional_access_policy_groups_management_restricted/entra_conditional_access_policy_groups_management_restricted.metadata.json Metadata for the new check (description, risk, remediation, URLs).
tests/providers/m365/services/entra/entra_conditional_access_policy_groups_management_restricted/entra_conditional_access_policy_groups_management_restricted_test.py New tests for the check behavior.
tests/providers/m365/services/entra/entra_conditional_access_policy_groups_management_restricted/__init__.py Adds package marker for tests directory.
prowler/providers/m365/services/entra/entra_conditional_access_policy_groups_management_restricted/__init__.py Adds package marker for check directory.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +724 to +735
query_parameters = (
GroupsRequestBuilder.GroupsRequestBuilderGetQueryParameters(
select=[
"id",
"displayName",
"groupTypes",
"membershipRule",
"isAssignableToRole",
"isManagementRestricted",
],
)
)
Copy link
Copy Markdown
Author

@SAMurai-16 SAMurai-16 May 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I verified against the installed msgraph-sdk==1.55.0:

module has GroupsRequestBuilderGetQueryParameters: False class has GroupsRequestBuilderGetQueryParameters: True

Comment on lines +106 to +113
def test_no_enabled_or_report_only_policy_references_groups(self):
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_client.audited_domain = DOMAIN
entra_client.groups = []
entra_client.conditional_access_policies = {
"policy-1": _make_policy(state=ConditionalAccessPolicyState.DISABLED)
}
@SAMurai-16 SAMurai-16 requested a review from Copilot May 23, 2026 10:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Comment on lines +107 to +113
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_client.audited_domain = DOMAIN
entra_client.groups = []
entra_client.conditional_access_policies = {
"policy-1": _make_policy(state=ConditionalAccessPolicyState.DISABLED)
}
@@ -0,0 +1 @@

Comment on lines 1639 to +1643
name: str
groupTypes: List[str]
membershipRule: Optional[str]
is_assignable_to_role: bool = False
is_management_restricted: bool = False
Comment on lines +753 to +758
)
or False,
is_management_restricted=getattr(
group, "is_management_restricted", False
)
or False,
@SAMurai-16
Copy link
Copy Markdown
Author

@HugoPBrito Please review and suggest changes if needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community Opened by the Community metadata-review new-check provider/m365 Issues/PRs related with the M365 provider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[New Check]: Conditional Access groups must be protected by RMAU or role-assignable groups

3 participants