No one can deny the superior help of AzureAD and MSOL PowerShell modules and how these two made cloud management straightforward. But the end for these two modules is nearby, and the direction is the Graph API.
Let’s start now and learn the migration steps from the old modules to Graph API.
If you’re new to using graphs, consider checking out the “Connecting and Using Microsoft Graph API Using PowerShell” post. It’s a good starting point for learning how to use this tool.
Table of Contents
- Prerequisites
- Read Your Old Script And Get It Ready
- Importing and connecting to Graph API
- Reading the Graph API Documentation To Find The Replacement Cmdlets
- Finding the Replacement Cmdlets in Microsoft Graph using Get-Comand cmdlet
- Things Are Not Always Straight To The Point
- Checklist to Migrate From MSOnline and AzureAD to Graph API
- Conclusion
Prerequisites
- Microsoft Graph PowerShell Module
- PowerShell 7 or PowerShell 5.1
- VSCode or PowerShell ISE
- Basic knowledge of Graph API and how it works.
Read Your Old Script And Get It Ready
Get your old script, locate and understand the AzureAD and the MSOnline cmdlet functionality. So let’s assume that our script contains some cmdlets such as
Import-AzureAD
Connect-AzureAD
Get-AzureADUser
Get-MsolAccountSku
So, How to start?!
Importing and connecting to Graph API
The module importing process is still similar to importing the AzureAD and MSOnline modules, that is, by using Import-Module
cmdlet
Import-Module Microsoft.Graph
Connecting to Graph API is essential in the script execution by using Connect-MgGraph. But it’s not only using the cmdlet and you are done. Instead, you need to know the connection scope to include. This can be done by using the -Scope parameter.
The Scope is a declaration of which permission the script will use. The scope structure is a Resource.Operation.Constraint.
For example, to read all user data, use User.Read.All, and to write to all user’s data, use User.ReadWrite.All.. But how to find these permissions?
Graph Explorer is a great way to start. Let’s get the required scope to read the user’s profile.
- Open your favorite browser, Edge, Chrome… whatever
- Navigate to Microsoft Graph Explorer
- Click Resource tab
- scroll down and find the User
- expand it and select [GET]User or [POST]User
- Click on Modify Permission,
Select the most relevant permission you need in the connection scope. The permission includes a description of what each one can do.
You can also click on the Code snippets for a PowerShell example with the required cmdlet to run.
Make sure to evaluate all your script and get the required scope for any cmdlet that will use Graph API.
Authentication and Authorization PowerShell and Graph API.
When connecting to Graph API, there are two parts to consider Authentication and Authorization. Starting with the authentication. The authentication support two methods as the following:
- Delegate Authentication: The person who executes the script must authenticate by typing a valid organization username and password. Usually, this type of authentication opens a browser window for the user to authenticate.
- Application Authentication: won’t request the user to type any username or password and won’t open any browser windows. It’s perfect for background processes and automation.
The Azure admin should have previously registered an App in Azure Directory.
Write down the Client Key, Tenant id, and client credentials as these values are needed to connect.
For authorization, if the delegate authentication is used, the user must consent and accept the list of permissions after the user is connected. This will appear straight after the user login.
But if the application authorization is used, there won’t be any message for the user to consent and accept . The registered application is acting on behalf of the users.
Azure admin should assign the registered application the required permission and consent them.
Which one to use?! Whatever you want, make sure always follow the least privileged permission. don’t assign read-write when only read permissions are needed.
Read more about authentication and authorization and how to find the required scope at Connecting and Using Microsoft Graph API Using PowerShell
Ensure that the Graph cmdlet you use in your script supports the used authentication method. Some cmdlet won’t work if application authentication is used like using New-MgChatMessage cmdlet. Such information can only be found on the Microsoft Documentation website.
Reading the Graph API Documentation To Find The Replacement Cmdlets
Microsoft has made a nice map that shows each cmdlet with its replaced cmdlet from the Graph API side. and in most cases, you will find yourself returning to Microsoft Documentation for the Graph cmdlet help. For example, The Get-AzureADUser was replaced by the Get-MgUser.
Check out Find Azure AD and MSOnline cmdlets in Microsoft Graph PowerShell to see the full map. Each cmdlet is linked to its explanation page along with examples.
Finding the Replacement Cmdlets in Microsoft Graph using Get-Comand cmdlet
What about guessing the cmdlet by using Get-Command
cmdlet? Let’s try it. Open PowerShell and type the following.
PS C:\> Get-Command Get*User* | where {$_.Source -like "Microsoft.Graph*"} | Select-Object Name
Name
----
Get-MgUserMember
Get-MgUserMemberByRef
Get-MgUserTransitiveMember
Get-MgUserTransitiveMemberByRef
Get-MgUser
Get-MgUserCreatedObject
Get-MgUserCreatedObjectByRef
Get-MgUserDirectReport
Get-MgUserDirectReportByRef
Get-MgUserExtension
Get-MgUserLicenseDetail.
.
. Output trimmed
This can be a good start to see any cmdlet that might help in doing a similar task of Get-AzureADUser
.
Using Get-Help is another way of knowing what the cmdlet can do, the supported parameters, and each parameter value type. You can use
Get-Help Get-MgUser -Full
for full help. Keep your help files up to date by running Update-Help.
There is a cmdlet named Get-MgUser
. This looks similar to Get-AzureADUser
. So let’s take a closer look. run the following line to see the supported parameters.
PS C:\> (Get-Command Get-Mguser).Parameters
Key Value
--- -----
UserId System.Management.Automation.ParameterMetadata
InputObject System.Management.Automation.ParameterMetadata
ExpandProperty System.Management.Automation.ParameterMetadata
Property System.Management.Automation.ParameterMetadata
Filter System.Management.Automation.ParameterMetadata
Search System.Management.Automation.ParameterMetadata
Skip System.Management.Automation.ParameterMetadata
Sort System.Management.Automation.ParameterMetadata
Top System.Management.Automation.ParameterMetadata
ConsistencyLevel System.Management.Automation.ParameterMetadata
Break System.Management.Automation.ParameterMetadata
HttpPipelineAppend System.Management.Automation.ParameterMetadata
HttpPipelinePrepend System.Management.Automation.ParameterMetadata
Proxy System.Management.Automation.ParameterMetadata
ProxyCredential System.Management.Automation.ParameterMetadata
ProxyUseDefaultCredentials System.Management.Automation.ParameterMetadata
PageSize System.Management.Automation.ParameterMetadata
All System.Management.Automation.ParameterMetadata
CountVariable System.Management.Automation.ParameterMetadata
Verbose System.Management.Automation.ParameterMetadata
Debug System.Management.Automation.ParameterMetadata
ErrorAction System.Management.Automation.ParameterMetadata
There are similar parameters to Get-AzureADUser. Take a look at the table below.
Get-MgUuser | Get-AzureADUser |
UserId | ObjectId |
Filter | Filter |
All | All |
Property | SearchString |
ExpandProperty | Top |
InputObject | |
Break | |
ConsistencyLevel | |
Search |
Why not also check the value type the parameter UserId accept? This helps us know what kind of input should provide to the parameter, whether it is a string, array, hashtable…etc.
(Get-Command Get-MgUser).Parameters.UserID
The UserID in Get-MgUser
is a string, so we are good for now and can proceed with the next step.
We can use the UserID parameter with the Get-MgGraph
cmdlet and pass the user UPN to get user information. But wait, remember to find the required scope.
Using Find-MgGraphCommand To Find The Required Permission Scope.
Use the Find-MgGraphCommand cmdlet to get a list of all the possible permission to execute the Get-MgUser
cmdlet. Read the list to find the most accurate permission that fits your requirement. In this case, it’s User.Read.All.
PS C:\> (Find-MgGraphCommand -Command Get-MgUser -ApiVersion v1.0 ).Permissions | Select-Object Name,Description
Name Description
---- -----------
DeviceManagementApps.Read.All Read Microsoft Intune apps
DeviceManagementApps.ReadWrite.All Read and write Microsoft Intune apps
DeviceManagementManagedDevices.Read.All Read devices Microsoft Intune devices
DeviceManagementManagedDevices.ReadWrite.All Read and write Microsoft Intune devices
DeviceManagementServiceConfig.Read.All Read Microsoft Intune configuration
Directory.Read.All Read directory data
Directory.ReadWrite.All Read and write directory data
User.Read.All Read all users' full profiles
User.ReadBasic.All Read all users' basic profiles
User.ReadWrite.All Read and write all users' full profiles
Some permission might not be needed to execute the cmdlet, such as DeviceManagementApps.Read.All, this is part of the Intune apps. all that you need is the most relative one for your use.
Keep Microsoft Documentation in your bookmark as you need to open it to discover other parameters.
Particse is the key, you will remember all these things by trying.
Let’s try it all. As for now, we found that the scope is User.Read.All
$Scope=@('User.Read.All')
Connect-Graph -Scopes $Scope
Try the Get-MgUser
cmdlet with the UserID UPN, and let see
PS C:\> Get-MgUser -UserId UserTestOne@PowerShellCenter.com
Id DisplayName Mail UserPrincipalName UserType
-- ----------- ---- ----------------- --------
616ed1f3-3210-3210-9acd-9acdd9acd92a User Test One UserTestOne@PowerShellCenter.com UserTestOne@PowerShellCenter.com
Try the -All parameter
PS C:\> Get-MgUser -all
Id DisplayName Mail UserPrincipalName UserType
-- ----------- ---- ----------------- --------
616ed1f3-3210-3210-9acd-9acdd9acd92a User Test One UserTestOne@PowerShellCenter.com UserTestOne@PowerShellCenter.com
c74d2588-4173-4173-aa1a-7c74d257704a User Test Two UserTestTwo@PowerShellCenter.com UserTestTwo@PowerShellCenter.com
All working fine, yes. This is cool and straight to the point.
Things Are Not Always Straight To The Point
Let’s see how to replace Set-MsolUserLicense
from the Microsoft Graph API module.
Start by finding the cmdlet that can relate to Set-MsolUserLicense
, for example, something with Set*UserLicense*. and find the available parameters
#Find the cmdlet
PS C:\> Get-Command Set*UserLicense* | where {$_.Source -like "Microsoft.Graph*"} | Select-Object Name
Name
----
Set-MgUserLicense
#Find the Supported Parameters
PS C:\> (get-command Set-MgUserLicense).Parameters
Key Value
--- -----
UserId System.Management.Automation.ParameterMetadata
InputObject System.Management.Automation.ParameterMetadata
BodyParameter System.Management.Automation.ParameterMetadata
AddLicenses System.Management.Automation.ParameterMetadata
AdditionalProperties System.Management.Automation.ParameterMetadata
RemoveLicenses System.Management.Automation.ParameterMetadata
Break System.Management.Automation.ParameterMetadata
HttpPipelineAppend System.Management.Automation.ParameterMetadata
HttpPipelinePrepend System.Management.Automation.ParameterMetadata
Proxy System.Management.Automation.ParameterMetadat
Get the required permission to run the cmdlet.
PS C:\> (Find-MgGraphCommand -Command Set-MgUserLicense -ApiVersion v1.0).permissions | select Name, Description
Name Description
---- -----------
Directory.ReadWrite.All Read and write directory data
User.ReadWrite.All Read and write all users' full profiles
Comparing the two cmdlets looks good.
Set-MsolUserLicense | Set-MgUserLicense |
ObjectId | UserID |
AddLicenses | AddLicenses |
RemoveLicenses | RemoveLicenses |
Things seems to be correct, so the code should work as expected if the line is written like the following. Yes ?!
Set-MgUserLicense -UserId 'UserTestOne@PowerShellCenter.com' -AddLicenses "PowerShellCenter:SPE_E5"
The answer is No, as mentioned before. you need to check the value type for these parameters. There are two used parameters used in the Set-MsolUserLicense
cmdlet. The UserID, and the AddLicenses.
The parameter type for the UserID is a string, as shown below.
(Get-Command Set-MgUserLicense).Parameters.Userid.ParameterType
But let’s check the AddLicenses parameter type. The Name is IMicrosoftGraphAssignedLicense[], and the BaseType is System.Array.
(Get-Command Set-MgUserLicense).Parameters.AddLicenses.parametertype
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True IMicrosoftGraphAssignedLicense[] System.Array
So now what to do?!! The answer is Microsoft Documentation. We need to know what kind of value we need to provide to this parameter to work.
According to Microsoft, the AddLicenses parameter needs the following
ADDLICENSES : <MicrosoftGraphAssignedLicense[]>:.
Microsoft.com
–[DisabledPlans ]
: A collection of the unique identifiers for plans that have been disabled.
–[SkuId <String>]
: The unique identifier for the SKU.
So, the structure is Set-MgUserLicense -AddLicenses [SkuId=”SKU Identifier”]. This key and value are hashtable and are written between curly brackets. @{Key=Value}
The AddLicenses parameter value should be AddLicenses @{SkuId="06ebc4ee-1bb5-47dd-8120-11324bc54e06"}
A lot of the Graph API cmdlet value type are hashtables. So its -ParameterName @{Key=Value}. Its also possible for the Key value to be an array, such as -ParameterName @{Key=@(Value1,Value2,Value3)}.
Set-MgUserLicense -UserId 'UserTestOne@PowerShellCenter.com' -AddLicenses @{SkuId="06ebc4ee-1bb5-47dd-8120-11324bc54e06"} -RemoveLicenses @()
Also, by reviewing the documentation, you need to provide an additional parameter RemoveLicenses. Running the Set-MgUserLicense
without the -RemoveLicenses
returns the following error.
Set-MgUserLicense_AssignExpanded1: One or more parameters of the function import ‘assignLicense’ are missing from the request payload. The missing parameters are: removeLicenses.
Checklist to Migrate From MSOnline and AzureAD to Graph API
Here is a quick checklist:
- Evaluate your old script, and see where are all the cmdlets related to MSOnline and AzureAD. Take a note.
- Authentication and Permissions
- How the script will be executed using the User context of the application context?
- Think of the required permission to execute the script, and don’t the least privilege concept. Only assign the user/application the required permission.
- Use Graph Explorer and
Find-MgGraphCommand
to find the required scope. - Microsoft Documentation is always a great starting point.
- While evaluating the alternative cmdlet, look at the supported parameter to know how to structure the parameters and the supported value type.
- It’s okay for things not to work from the first time.
- Microsoft Documentation is always a great starting point
- Learn how to use Microsoft Graph Explorer.
Conclusion
There might be some challenges while migrating your script to the Graph API. But once you understand the concept, you find it easy.
Let me know in the comment your method of such migration.