turbot/steampipe-mod-microsoft365-compliance

Control: 5.3.3 Ensure 'Access reviews' for privileged roles are configured

Description

Access reviews enable administrators to establish an efficient automated process for reviewing group memberships, access to enterprise applications, and role assignments. These reviews can be scheduled to recur regularly, with flexible options for delegating the task of reviewing membership to different members of the organization.

Ensure Access reviews for high privileged Entra ID roles are done monthly or more frequently. These reviews should include at a minimum the roles listed below:

  • Global Administrator
  • Exchange Administrator
  • SharePoint Administrator
  • Teams Administrator
  • Security Administrator

Note: An access review is created for each role selected after completing the process.

Remediation

To remediate using the UI:

  1. Navigate to Microsoft Entra admin center https://entra.microsoft.com/.
  2. Click to expand Identity Governance and select Privileged Identity Management
  3. Select Microsoft Entra Roles under Manage.
  4. Select Access reviews and click New access review.
    • Provide a name and description.
    • Set Frequency to Monthly or more frequently.
    • Set Duration (in days) to at most 4.
    • Set End to Never.
    • Set Users scope to All users and groups.
    • In Role select these roles: Global Administrator,Exchange Administrator,SharePoint Administrator,Teams Administrator,Security Administrator
    • Set Assignment type to All active and eligible assignments.
    • Set Reviewers member(s) responsible for this type of review, other than self.
  5. Upon completion settings:
    • Set Auto apply results to resource to Enable.
    • Set If reviewers don't respond to No change.
  6. Advanced settings:
    • Set Show recommendations to Enable.
    • Set Require reason on approval to Enable.
    • Set Mail notifications to Enable.
    • Set Reminders to Enable.
  7. Click Start to save the review.

Warning: Care should be taken when configuring the If reviewers don't respond setting for Global Administrator reviews, if misconfigured break-glass accounts could automatically have roles revoked. Additionally, reviewers should be educated on the purpose of break-glass accounts to prevent accidental manual removal of roles.

Default Value

By default access reviews are not configured.

Usage

Run the control in your terminal:

powerpipe control run microsoft365_compliance.control.cis_v500_5_3_3

Snapshot and share results via Turbot Pipes:

powerpipe login
powerpipe control run microsoft365_compliance.control.cis_v500_5_3_3 --share

SQL

This control uses a named query:

with tenant_list as (
select distinct on (tenant_id) tenant_id, _ctx
from azuread_user
),
privileged_roles as (
select
tenant_id,
id,
display_name
from
azuread_directory_role_definition
where
display_name in (
'Global Administrator',
'Exchange Administrator',
'SharePoint Administrator',
'Teams Administrator',
'Security Administrator'
)
),
privileged_role_reviews as (
select
ar.tenant_id,
d.id
from
azuread_access_review_schedule_definition ar,
jsonb_array_elements(ar.scope -> 'resourceScopes') as r
join azuread_directory_role_definition d
on split_part(r ->> 'query', 'roleDefinitions/', 2) = d.id
where
(ar.settings -> 'mailNotificationsEnabled')::bool
and (ar.settings -> 'reminderNotificationsEnabled')::bool
and (ar.settings -> 'justificationRequiredOnApproval')::bool
and ar.settings ->> 'defaultDecision' = 'Deny'
),
role_check as (
select
tenant_id,
array_agg(distinct id)::text[] as roles_reviewed
from
privileged_role_reviews
group by tenant_id
)
select
t.tenant_id as resource,
case
when array(select id from privileged_roles where tenant_id = t.tenant_id)
<@ coalesce(r.roles_reviewed, '{}')
then 'ok'
else 'alarm'
end as status,
case
when array(select id from privileged_roles where tenant_id = t.tenant_id)
<@ coalesce(r.roles_reviewed, '{}')
then t.tenant_id || ' has access reviews configured monthly (or more frequently) for all high-privileged roles (Global Administrator, Exchange Administrator, SharePoint Administrator, Teams Administrator, Security Administrator).'
else t.tenant_id || ' does not have access reviews configured monthly for all high-privileged roles. Missing: '
|| array_to_string(
array(
select pr.display_name
from privileged_roles pr
where pr.tenant_id = t.tenant_id
and pr.id not in (
select unnest(coalesce(r.roles_reviewed, '{}'))
)
), ', '
)
end as reason
, t.tenant_id as tenant_id
from
tenant_list as t
left join role_check as r on r.tenant_id = t.tenant_id;

Tags