turbot/steampipe-mod-microsoft365-compliance

Control: 5.1.3.1 Ensure a dynamic group for guest users is created

Description

A dynamic group is a dynamic configuration of security group membership for Microsoft Entra ID. Administrators can set rules to populate groups that are created in Entra ID based on user attributes (such as userType, department, or country/region). Members can be automatically added to or removed from a security group based on their attributes.

The recommended state is to create a dynamic group that includes guest accounts.

Remediation

To remediate using the UI:

  1. Navigate to Microsoft Entra admin center https://entra.microsoft.com/.
  2. Click to expand Identity > Groups select All groups.
  3. Select New group and assign the following values:
    • Group type: Security
    • Microsoft Entra roles can be assigned to the group: No
    • Membership type: Dynamic User
  4. Select Add dynamic query.
  5. Above the Rule syntax text box, select Edit.
  6. Place the following expression in the box:
user.userType -eq "Guest"
  1. Select OK and Save

To remediate using PowerShell:

  1. Connect to Microsoft Graph using Connect-MgGraph -Scopes "Group.ReadWrite.All".
  2. In the script below edit DisplayName and MailNickname as needed and run:
$params = @{
DisplayName = "All Guest Users"
Description = "Dynamic group containing all guest users"
MailEnabled = $false
MailNickname = "allguestusers"
SecurityEnabled = $true
GroupTypes = @("DynamicMembership")
MembershipRule = "(user.userType -eq ""Guest"")"
MembershipRuleProcessingState = "On"
}
New-MgGroup @params

Default Value

Undefined

Usage

Run the control in your terminal:

powerpipe control run microsoft365_compliance.control.cis_v500_5_1_3_1

Snapshot and share results via Turbot Pipes:

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

SQL

This control uses a named query:

with tenant_list as (
select
distinct on (tenant_id) tenant_id,
_ctx
from
azuread_user
), dynamic_group_for_guest_user as (
select
count(*) as dynamic_group_for_guest_user_count,
tenant_id
from
azuread_group
where
membership_rule = '(user.userType -eq "guest")'
and group_types @> '[ "DynamicMembership" ]'
group by
tenant_id, _ctx
)
select
t.tenant_id as resource,
case
when dynamic_group_for_guest_user_count > 0 then 'ok'
else 'alarm'
end status,
case
when dynamic_group_for_guest_user_count > 0 then t.tenant_id || ' has dynamic group for guest user.'
else t.tenant_id || ' does not have dynamic group for guest user.'
end reason
, t.tenant_id as tenant_id
from
tenant_list as t
left join dynamic_group_for_guest_user as d on d.tenant_id = t.tenant_id

Tags