Moving common tasks to the Graph
In the first part of this series, I explained how the Microsoft Graph PowerShell SDK simplifies using the Microsoft Graph API by replacing API calls with more familiar PowerShell cmdlets. I also showed how to install the SDK and connect to run your first cmdlets.
Some of the most common activities admins need to perform involve user and group management. This article goes deeper into using the SDK to perform common day-to-day tasks to manage users and groups through the Graph.
One Place to Manage Microsoft 365 (Kind of…)
One of the biggest benefits of the Microsoft Graph API and the SDK is the ability to manage many aspects of Microsoft 365 from a single place. This might seem like a small thing but when you start automating more complex scenarios, keeping track of the necessary modules is cumbersome, and making sure your environment is prepared takes time. Not to mention keeping all the different modules updated.
One curious outlier is the lack of endpoints to manage Exchange Online. While mailbox data is accessible through the Graph, most Exchange Online management tasks (e.g. Address lists, mail flow rules) still need to be done through the Exchange Online PowerShell module (recently updated to Version 3). Exchange has its own internal APIs that are not yet available through the Graph. This means that managing mailboxes is not something that the SDK supports (or indeed the Graph API).
Using Filtering and Searching
A common scenario for many admins is returning data based on partial information. For example, finding all users within a specific department. The query parameter -filter is used to filter results based on known criteria and supports standard OData filter operators (equals, not equals, less than, etc.) and functions (startswith/endswith). Support for operators varies across the modules and endpoints so it’s worth checking the documentation when planning your scripts.
Filters support conditional operators (and/or) to compile more complex queries. For example, the following command queries users with their department set to “Marketing”:
Get-MgUser -Filter "department eq 'Marketing'"
Then add in startswith to find marketing users who have a display name starting with ‘A’:
Get-MgUser -Filter "(department eq 'Marketing') and (startswith(DisplayName,'A'))"
Finally, we add another filter to exclude the user account with the email address “AllanD@M365x18562375.OnMicrosoft.com”. Note that the notequals (ne) filter is a Graph advanced query, so the consistencylevel (eventual) and countvariable parameters need to be passed:
Get-MgUser -Filter "(department eq 'Marketing') and (startswith(DisplayName,'A')) and (Mail ne 'AllanD@M365x18562375.OnMicrosoft.com')" -ConsistencyLevel eventual -CountVariable count
In Figure 1, we see these filters in action.
![Introduction to the Microsoft Graph PowerShell SDK Part II: Performing Common User and Group Operations](https://s40823.pcdn.co/wp-content/uploads/2022/10/Intro-to-graph-pt.2-figure-1.png)
For multi-valued properties, the filter requires a bit more work with the addition of Lambda Operators. Lambda Operators are used to filter on these properties, for example when filtering for a specific license as explained in this article on how to Use /Any Filters in Microsoft Graph API Queries with PowerShell.
Searching is another method to find data and is useful when you have less specific information. For example, to search for all groups with the word “Sales” in the display name, use the syntax below.
Get-MgGroup -Search "Displayname:Sales" -ConsistencyLevel eventual
Note that when using the Search parameter, the ConsistencyLevel parameter must be set to eventual as this is an advanced query. The CountVariable parameter is not required with search. The search and filter parameters can also be used together to narrow results even further as shown in Figure 2.
![Introduction to the Microsoft Graph PowerShell SDK Part II: Performing Common User and Group Operations](https://s40823.pcdn.co/wp-content/uploads/2022/10/Intro-to-graph-pt.2-figure-2.png)
Filtering and searching with the PowerShell SDK is an easier process than constructing the API call by hand. As with any PowerShell SDK cmdlet, adding the debug parameter shows the URI used to apply the filters (Figure 3).
![Introduction to the Microsoft Graph PowerShell SDK Part II: Performing Common User and Group Operations](https://s40823.pcdn.co/wp-content/uploads/2022/10/Intro-to-graph-pt.2-figure-3.png)
Microsoft Platform Migration Planning and Consolidation
Simplify migration planning, overcome migration challenges, and finish projects faster while minimizing the costs, risks and disruptions to users.
Reporting
The Graph API is a useful tool for reporting on objects in an environment. For example, this article on How to Create a Microsoft 365 Licensing Report Using the Microsoft Graph SDK for PowerShell, shows how with (relative) ease and a small amount of scripting, reports can be built and tailored to exactly what is needed. This can be a great help when the built-in reporting doesn’t give you what you are looking for.
Another common task is reporting on Microsoft 365 Groups. Microsoft 365 Groups are a key component of many workloads and as an admin, it’s not easy to differentiate which Groups are connected to which components. The Group object returned by the Graph API contains a large amount of information to help with this, and by combining this with other cmdlets in the SDK, building these tailored reports is a much easier process.
For example, the below code first returns all Unified Groups in the organization (using filtering on the groupTypes attribute), and then uses the Get-MgGroupDrive cmdlet to fetch the URL of the Groups associated Document Library. This data is stored in the $Report variable along with some other details of the group, ready to be exported as required.
##Return all Unified Groups [array]$Groups = Get-MgGroup -Filter "groupTypes/any(x:x eq 'Unified')" -All ##Create Report Array $Report = @() ##Iterate each Group to retrieve the Drive URL and append to the Report Foreach($Group in $Groups){ $Drive = Get-MgGroupDrive -GroupId $Group.id $DriveDetails = [PSCustomObject]@{ GroupID = $Group.id GroupName = $Group.displayname Email = $Group.mail URL = $Drive.webURL } $Report += $DriveDetails }
This quick report (Output shown in Figure 4) shows how easy it is to retrieve the information you need without much effort.
![Introduction to the Microsoft Graph PowerShell SDK Part II: Performing Common User and Group Operations](https://s40823.pcdn.co/wp-content/uploads/2022/10/Intro-to-graph-pt.2-figure-4.png)
Bulk Management
Locating and reporting on users and groups through the SDK is nice, but a large part of managing a Microsoft 365 environment is updating and creating new objects. Licensing is once again a good example here as outlined in this article on Microsoft 365 License Management for Azure AD Accounts with the Microsoft Graph PowerShell SDK.
Another common use case is the bulk creation of objects, for example, mass user creation. A typical scenario here is provisioning users from a CSV file that is extracted from an HR database. Generally, we provision users and add a license, in this case, we add them to an Azure AD Licensing Group.
Using the CSV file shown in Figure 5, the script below provisions the users, using the format firstname.lastname@domain.com, sets a temporary password, and adds the user to the licensing group:
![Introduction to the Microsoft Graph PowerShell SDK Part II: Performing Common User and Group Operations](https://s40823.pcdn.co/wp-content/uploads/2022/10/Intro-to-graph-pt.2-figure-5.png)
##Retrieve the Licensing Group $LicenseGroup = Get-MgGroup -Filter "Displayname eq 'M365-E3-License'" ##Import the CSV $csv = Import-Csv C:\temp\NewStaff.csv ##Set the Domain Suffix $DomainSuffix = "M365x18562375.onmicrosoft.com" ##Loop through each user foreach($user in $csv){ $PasswordProfile = @{ Password = $user.'Temporary Password' } ##Provision the user $UserObject = New-MgUser -DisplayName "$($user.'first name') $($user.surname)" -PasswordProfile $PasswordProfile -AccountEnabled -MailNickname "$($user.'first name').$($user.surname)" -UserPrincipalName "$($user.'first name').$($user.surname)@$DomainSuffix" ##Add the user to the license group New-MgGroupMember -GroupId $LicenseGroup.id -DirectoryObjectId $UserObject.id }
Summary
In this article, I looked at some common scenarios where the Microsoft Graph PowerShell SDK can help tenant admins automate common processes. There’s nothing terribly new here for anyone who has been using PowerShell to manage their tenant for a while, although there are upsides to having everything available in one module. Adapting code from the other modules should not be too much of a challenge once you have the basics down. In the next part of this series, things get a bit more complicated as we delve into interacting with individual services such as Teams and Exchange and explore some of the interesting advantages of using the Graph.
Cybersecurity Risk Management for Active Directory
Discover how to prevent and recover from AD attacks through these Cybersecurity Risk Management Solutions.
Hi, I know this is an older post. Do the Graph API commands work with Exchange Online distribution groups and mail enabled security groups?
Command run:
new-MgGroupMember -GroupId “objectIDxxx” -DirectoryObjectId objectIDxxx
I receive this error:
“Cannot Update a mail-enabled security groups and or distribution list”
The Real Person!
The Real Person!
THe Graph API deals with Entra ID groups. Mail-enabled distribution groups are basically Exchange Online objects that are synchronized back to Entra ID. Use Exchange Online cmdlets to manage the membership of distribution lists and all is well (including mail-enabled security groups).