Continuing the rework of older scripts and snippets to use Microsoft Graph PowerShell SDK wrapper module or the Graph API directly, this article will introduce you with the updated version of the code provided as part of the Bulk enable specific services via the Azure AD PowerShell module article. The scenario we want to address remains the same – you have a list of users for which a given service, say Exchange Online, is toggled off, and you want to quickly enable it across all of them.
I’ve took this opportunity to update the code to a more robust solution, now available as full blown script over at my GitHub repo. The basic building blocks remain the same: we authenticate, get the list of users, gather a list of SKUs and service plans you want to toggle, then iterate over each user’s licenses and toggle the corresponding service plan ON. Because the script uses the Graph API endpoints directly, you will need to have an Azure AD application with the necessary permissions (User.ReadWrite.All for the license adjustment, Organization.Read.All for the list of SKUs) prepared, as well as an appropriate set of credentials in order to obtain a token. The script uses a client secret, which is hardly something you should do in a production scenario, so feel free to replace the whole “get token” part of the script with your preferred method.
Once a token is obtained, the script will proceed to generate a list of users (the “bulk” part). One of the improvements I’ve made to this version is to ensure that we only process licensed users, by leveraging the method outlined here. As this is a server-side filter, it should help speed up the execution of the script in larger environments. Another improvement is made possible thanks to the licenseAssignmentStates property, which allows us to check whether a given license is assigned directly, or via a Group. This in turn allows the script to skip processing any group-based license assignments, and creating havoc in the process. We also fetch the list of SKUs, which allows us to use “friendly” names for the corresponding service plans or licenses.
Apart from the auth details (lines 7-9), you will need to provide a set of service(s) to be enabled. This is done via the $plansToEnable list variable, which you can find on line 52. You can provide one or more service plans here, by either using their GUID value, or the ServicePlanName value. Refer to this article to get the proper details. And if you want to run the script against a subset of the users, or import the list via CSV, update the value of the $users variable (line 29) and comment lines 30-44.
Now that we have the list of users, SKUs and service plans to toggle, we can proceed with the actual task. The bulk of the script is a foreach loop, which iterates over each user entry and each license assigned to the user. If the license is assigned via group, we continue to the next license, or next user. If the license is assigned directly, the list of disabled service plans is updated to remove any entries you specified earlier as part of the $plansToEnable variable. Then, we compare the result with the “original” set of licenses/service plans and if any changes are detected, we proceed with the actual license assignment operation, which is performed via a call to the /assignLicense Graph API endpoint.
And that’s pretty much all there is to it. All your users should now have these service plans toggled ON. Some “quality of life” improvements were added to the script too, such as more robust error handling (exposing the “full” error message), a progress bar to help you track the script execution, simple anti-throttling handling, and a lot of Verbose output, if you want to closely monitor what the script does. And you should definitely do that, as while I’ve tried to test the script in all scenarios I could think of, I’ve likely still missed some. You might consider turning on verbose output and commenting line 99 of the script to prevent any actual changes being made, then examine the output to make sure no unwanted license assignments will happen. After you are satisfied with the results, proceed with the actual execution.
It’s also important to note that the script doesn’t handle any plan dependencies, and will fail if you try to enable a plan that has a dependency on another, currently disabled plan.