Exercise - Bulk-provision Relecloud's new-hire users with Microsoft Graph PowerShell

Completed

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.All delegated 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

  1. Open a PowerShell session and connect to Microsoft Graph, requesting only the scope this task needs:

    Connect-MgGraph -Scopes "User.ReadWrite.All"
    
  2. Confirm the connection and the granted scope:

    Get-MgContext | Select-Object Scopes
    
  3. Reflect: User.ReadWrite.All is enough to create and update users. It's not Directory.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

  1. Save your sample new-hire CSV locally (for example, C:\temp\new-hires.csv) with columns DisplayName, UserPrincipalName, and Password.

  2. 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
    }
    
  3. 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

  1. Disconnect and reconnect with only the read scope this verification step needs:

    Disconnect-MgGraph
    Connect-MgGraph -Scopes "User.Read.All"
    
  2. Export the new hires to confirm they exist:

    Get-MgUser -Filter "startsWith(UserPrincipalName, 'newhire')" | Select-Object DisplayName, UserPrincipalName, AccountEnabled
    
  3. Confirm every account from your CSV appears with AccountEnabled: True.

  4. 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.