Table of Contents
Overview
In a hybrid environment, you can have multiple unified endpoint management solutions in your environment, and choosing the right one to package the application can be confusing. Some endpoint management solutions include Intune, MECM, Citrix and Jamf Pro to name a few. Depending on requests or scope, one might be better than another for a period of time. But with cloud based UEMs, new features are constantly becoming generally available thus incentivizing application packages in the cloud. As companies move towards a cloud-only environment, the applications are expected to be moved to the cloud as well.
MECM Device Collection to Entra User Group
The issue at hand was an application being deployed to a device collection in MECM (formerly SCCM). With single sign on and user-based licensing, it can be easier to assign apps to users rather than devices. Here are the prerequisites for the script to work.
Prerequisite Steps
- Package the Application in Intune
- Create an Entra group to add users (Using PowerShell or the Portal)
- Export a CSV file of workstations using CMPivot or directly from the device collection
- Install and Import ConfigurationManager
- Install and Import Microsoft.Graph.Beta.Groups
- Install and Import Microsoft.Graph.Beta.Users
- Microsoft Graph command-line interface configured with Group.ReadWrite.All and User.Read Graph permissions (or create a new Enterprise Application and user the App ID)
Script to Assign the Primary User of a CM Device to an Entra Group
We want to get the primary user assigned to the device in MECM, then use that value and add the user to the Entra group.
Script Parameters
We declare our parameters to use in the script and import the necessary modules. We also connect to Graph using Connect-MGGraph
cmdlet and import our CSV file.
param ( [String] $groupName, [String] $siteCode, [String] $managementPointServer ) Import-module ConfigurationManager Import-Module Microsoft.Graph.Beta.Groups Import-Module Microsoft.Graph.Beta.Users Connect-MgGraph -Scopes 'Group.ReadWrite.All', 'User.Read' $workstations = Import-Csv -path "Workstations.csv"
Parameter Name | Description |
$groupName | Name of the Entra Group to assign the users |
$siteCode | Alphanumeric identifier assigned to each Configuration Manager site |
$managementPointServer | The Main Point site server in your MECM environment |
Connect to Configuration Manager Site
There are numerous blog posts and resources online with similar functions, I referenced and slightly modified the function from an SCCMPowerShell post.
function Connect-CMSite { if($null -eq (Get-Module ConfigurationManager)) { Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" } if($null -eq (Get-PSDrive -Name $siteCode -PSProvider CMSite -ErrorAction SilentlyContinue)) { New-PSDrive -Name $siteCode -PSProvider CMSite -Root $managementPointServer } Set-Location "$($siteCode):\" }
The
$ENV:SMS_ADMIN_UI_PATH
should be an environmental variable on the server hosting the site system. This variable points to the location of the Configuration Manager console installation files, including the ConfigurationManager.psd1 module manifest file.Use Microsoft Graph to Get Group Object and its Members
We get the group object and use its Id. Each member is a IMicrosoftGraphUser object so we can retrieve all attributes such as UserPrincipalName. Open the link to view all available properties on the object. We also call the Connect-CMSite
function we declared to connect to our site.
$entraGroup = Get-MgBetaGroup -Filter "DisplayName eq '$groupName'" $entraGroupMembers = Get-MgBetaGroupMember -GroupId $entraGroup.Id Connect-CMSite
Logic to Add Users to Entra Group with Graph
We loop through our array of workstation created by importing the CSV file. We use the Get-CMUserDeviceAffinity to retrieve the primary user of the device, and then use some string manipulation to parse it as a valid userPrincipalName.
The output of the property UniqueUserName
is like this: DOMAIN\SamAccountName
So, we split the string to retrieve the SamAccountName and add the domain DNS root. We get the array of IMicrosoftGraphUser objects returned by Get-MgBetaGroupMember
. Just a note you have to expand with AdditionalProperty to access the IMicrosoftGraphuser object. I also put some conditional logic using simple regex to exclude any accounts you don’t want to add. You can certainly modify the regex as you please. We then use Get-MgBetaUser
to get the IMicrosoftGraphuser object, and we use the Id property to pass it into New-MgBetaGroupMember
. You can wrap it in a try catch and use appropriate error handling. When the loop finishes, we set the path back to the location of the script.
foreach($workstation in $workstations){ $userAffinity = Get-CMUserDeviceAffinity -DeviceName $workstation $upn = if($null -ne $userAffinity.UniqueUserName){"$($userAffinity.UniqueUserName.split("\")[1])@$((Get-ADDomain).DNSRoot)"} else {Continue} if(($entraGroupMembers.AdditionalProperties.userPrincipalName) -notcontains $upn){ # Write-Output $upn if($upn -notmatch '^excludedUser'){ $entraUser = Get-MgBetaUser -Filter "UserPrincipalName eq '$upn'" Write-Host "Adding $($entraUser.UserPrincipalName) to $groupName" -ForegroundColor Green New-MgBetaGroupMember -GroupId $entraGroup.Id -DirectoryObjectId $entraUser.Id } } } Set-Location $PSScriptRoot
Calling the Script
addUserFromCMDevice.ps1 ` -groupName "Entra Group Name" ` -siteCode "SITE" ` -managementPointServer "mpsiteserver.dnssuffix.com"
Completed Script
param ( [String] $groupName, [String] $siteCode, [String] $managementPointServer ) Import-module ConfigurationManager Import-Module Microsoft.Graph.Beta.Groups Import-Module Microsoft.Graph.Beta.Users Connect-MgGraph -Scopes 'Group.ReadWrite.All', 'User.Read' $workstations = Import-Csv -path "Workstations.csv" function Connect-CMSite { if($null -eq (Get-Module ConfigurationManager)) { Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" } if($null -eq (Get-PSDrive -Name $siteCode -PSProvider CMSite -ErrorAction SilentlyContinue)) { New-PSDrive -Name $siteCode -PSProvider CMSite -Root $managementPointServer } Set-Location "$($siteCode):\" } $entraGroup = Get-MgBetaGroup -Filter "DisplayName eq '$groupName'" $entraGroupMembers = Get-MgBetaGroupMember -GroupId $entraGroup.Id Connect-CMSite foreach($workstation in $workstations){ $userAffinity = Get-CMUserDeviceAffinity -DeviceName $workstation $upn = if($null -ne $userAffinity.UniqueUserName){"$($userAffinity.UniqueUserName.split("\")[1])@$((Get-ADDomain).DNSRoot)"} else {Continue} if(($entraGroupMembers.AdditionalProperties.userPrincipalName) -notcontains $upn){ if($upn -notmatch '^excludedUser'){ $entraUser = Get-MgBetaUser -Filter "UserPrincipalName eq '$upn'" Write-Host "Adding $($entraUser.UserPrincipalName) to $groupName" -ForegroundColor Green New-MgBetaGroupMember -GroupId $entraGroup.Id -DirectoryObjectId $entraUser.Id } } } Set-Location $PSScriptRoot
Conclusion
In summary, this script automates the process of adding users to a specified group in Entra based on workstation usage. It imports workstation data, connects to the Configuration Manager site, retrieves group information, and iterates through workstations to determine user affinity. If a user is not already a member of the Entra group and is not excluded, the script adds them to the group. Finally, it ensures the script returns to its original location upon completion. if you have any suggestions drop a comment or Contact me.
Now loading...