Automate license removal when users leave a group
Scenario
Cayosoft Administrator supports license management scenarios based on the group membership. This article describes a mover scenario to automatically revoke Microsoft 365 licenses from users who leave an Active Directory (AD) group. The scenario is based on the AD Users | Enforce License rule.
In my hybrid environment, I have an AD group that enforces specific Microsoft 365 licenses for members. I would like Cayosoft Administrator to automatically revoke the licenses from users who leave the group.
IMPORTANT The discovery logic depends on the Active Directory extension settings. If the Active Directory extension settings > Advanced settings > Map cloud users by UPN setting is set to Yes, the rule will map users only using UserPrincipalName. If set to No, the rule will first attempt to find users based on objectID and immutableID attributes, and then fall back to UserPrincipalName. The setting is global; the change will affect all related rules and items in your environment.
Prerequisites
An instance of the AD Users | Enforce License rule.
A distinguished name of the target group that controls the license assignment.
Steps
Using the AD Users | Enforce License rule, you can create a routine check for user membership in a specific group. If not part of the group, a license/license plan is revoked.
Create an instance of the AD Users | Enforce License rule: in the main console view, click New > Rule > Show all templates > AD Users | Enforce License, and click Next. Define rule output, location, etc., and complete the initial setup.
-
In the Query criteria setting, specify the query criteria to limit the scope of AD users by limiting the users to non-members of the target group. Refer to the provided example:
Copy-not (memberOf -eq 'CN=LicensedGroup,OU=Groups,DC=cayo,DC=net') Set the Include licensed users setting to Licensed users only.
-
In the Filter setting, specify the following filter criteria to exclude users based on their objectID, immutableID, and UPN attributes:
Copy{ -not $global:groupMemberCloudIds.Contains([guid]$_.Id) -and ([string]::IsNullOrEmpty($_.onPremisesImmutableId) -or -not $global:groupMemberImmutableIds.Contains($_.onPremisesImmutableId)) -and ([string]::IsNullOrEmpty($_.UserPrincipalName) -or -not $global:groupMemberUpns.Contains($_.UserPrincipalName)) } Optional: Set up the Filter by licenses setting to further limit the scope of affected users.
-
In the Initialization script setting, specify the provided script. The script targets a defined group and verifies the user membership. Replace the distinguished name placeholder
CN=LicensedGroup,OU=Groups,DC=cayo,DC=netwith the target DN:Copy{
if ([Cayo.CALog]::IsEnabled) { CayoWriteLog ("[Initialization script][0]") }
$groupToSearch = "CN=LicensedGroup,OU=Groups,DC=cayo,DC=net"
$correctParams = PMEXTAD_GetADSettingsByDN -ObjectDN $groupToSearch
$global:groupMemberCloudIds = [System.Collections.Generic.HashSet[guid]]::new()
$global:groupMemberImmutableIds = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::Ordinal)
$global:groupMemberUpns = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)
$adUsers = @(Get-ADUser -Filter "memberOf -eq '$groupToSearch'" -Properties 'UserPrincipalName', 'msDS-ExternalDirectoryObjectId', 'mS-DS-ConsistencyGuid' @correctParams)
$withoutAnyId = 0
if($null -ne $adUsers)
{
if($adUsers -isnot [Array]){ $adUsers = @($adUsers) }
foreach ($adUser in $adUsers) {
$cloudId = GetAzureObjectIdForADObject $adUser
if ($null -ne $cloudId) { [void]$global:groupMemberCloudIds.Add($cloudId) }
$immutableId = GetImmunableIdForADObject $adUser
if (-not [string]::IsNullOrWhiteSpace($immutableId)) { [void]$global:groupMemberImmutableIds.Add($immutableId) }
$upn = $adUser.UserPrincipalName
if (-not [string]::IsNullOrWhiteSpace($upn)) { [void]$global:groupMemberUpns.Add($upn) }
$dn = $adUser.DistinguishedName
if ($null -eq $cloudId -and [string]::IsNullOrEmpty($immutableId) -and [string]::IsNullOrEmpty($upn)) {
$withoutAnyId++
if ([Cayo.CALog]::IsEnabled) { CayoWriteLog ("[Initialization script] DistinguishedName: '$($adUser.DistinguishedName)' No cloud id, no ImmutableId, no UPN.") }
}
}
if ([Cayo.CALog]::IsEnabled) { CayoWriteLog ("[Initialization script] adUsers.Count: $($adUsers.Count), groupMemberCloudIds.Count: $($global:groupMemberCloudIds.Count), groupMemberImmutableIds.Count: $($global:groupMemberImmutableIds.Count), groupMemberUpns.Count: $($global:groupMemberUpns.Count), withoutAnyId: $withoutAnyId") }
}
if (0 -eq $global:groupMemberCloudIds.Count -and 0 -eq $global:groupMemberImmutableIds.Count -and 0 -eq $global:groupMemberUpns.Count) {
throw "The group '$groupToSearch' does not contain members"
}
if ([Cayo.CALog]::IsEnabled) { CayoWriteLog ("[Initialization script][1000]") }
} In the Action section, set up the License options setting: pick a specific license plan by clicking Add, and select Unassign to revoke the license/license plan. You can define specific actions for every license/license plan in your Entra domain.
Save changes and click Preview to review the initial query results. Set up the rule schedule and run the rule when ready.
Comments
0 comments
Please sign in to leave a comment.