Exercise - Bulk-provision Relecloud's new-hire users with Microsoft Graph PowerShell
Relecloud's new overseas office opens in two weeks, and its new hires need to be provisioned in bulk before then. You've just learned the CSV + New-MgUser pattern and the least-privileged scope rule—now apply both yourself.
Important
Prerequisites for this exercise:
- The Microsoft Graph PowerShell SDK installed (
Install-Module Microsoft.Graph). - Permission to connect with the
User.ReadWrite.Alldelegated scope (a User Administrator or Global Administrator account). - A sample CSV of new-hire records with columns for display name, user principal name, and initial password. You can create one yourself if your lab doesn't provide it.
If you don't have a spare tenant to bulk-create test accounts in, complete Task 1 up to the connection step and read through the rest to see the cmdlet pattern.
Task 1: Connect with the least-privileged scope
Open a PowerShell session and connect to Microsoft Graph, requesting only the scope this task needs:
Connect-MgGraph -Scopes "User.ReadWrite.All"Confirm the connection and the granted scope:
Get-MgContext | Select-Object ScopesReflect:
User.ReadWrite.Allis enough to create and update users. It's notDirectory.ReadWrite.All, which would also let this session touch groups, administrative units, and directory settings this task doesn't need.
Task 2: Bulk-create users from the CSV
Save your sample new-hire CSV locally (for example,
C:\temp\new-hires.csv) with columnsDisplayName,UserPrincipalName, andPassword.Import the CSV and create each user:
$newHires = Import-Csv -Path "C:\temp\new-hires.csv" foreach ($hire in $newHires) { $passwordProfile = @{ Password = $hire.Password ForceChangePasswordNextSignIn = $true } New-MgUser -DisplayName $hire.DisplayName ` -UserPrincipalName $hire.UserPrincipalName ` -MailNickname ($hire.UserPrincipalName -split "@")[0] ` -AccountEnabled ` -PasswordProfile $passwordProfile }Watch for errors as the loop runs—a duplicate UPN or a password that doesn't meet the tenant's complexity policy will fail that iteration without stopping the rest.
Task 3: Verify the created accounts with a read-only export
Disconnect and reconnect with only the read scope this verification step needs:
Disconnect-MgGraph Connect-MgGraph -Scopes "User.Read.All"Export the new hires to confirm they exist:
Get-MgUser -Filter "startsWith(UserPrincipalName, 'newhire')" | Select-Object DisplayName, UserPrincipalName, AccountEnabledConfirm every account from your CSV appears with
AccountEnabled: True.Reflect: this verification session only ever held
User.Read.All—read-only, and scoped to users. You didn't need write access to confirm the write operation worked, so you didn't request it.
You've now bulk-provisioned Relecloud's overseas new hires with the least-privileged scope for each step, and verified the result with an equally scoped read-only session—the exact pattern you'll reuse for the next office opening.