Using Set-AzureADUser To Update Attributes

Hi all!

I wanted to revisit an older post I made a while ago an improve upon it! You can find that post here

Let me lay out the background to this post in case you didn’t read the original. So I had recently had an opportunity to use PowerShell to update update Azure AD attributes. This involved using the Get-AzureADUser and the Set-AzureADUser commands.

This is very much different from the local AD administration I had done in the past. However, I could still leverage this experience for Azure AD. Thankfully!

PowerShell code illustration from Pexels stock image. For example: Set-AzureADUser

I’d never used the Get-AzureADUser command before!

I’d never used the Get-AzureADUser command before but I’m comfortable with PowerShell. And anyone comfortable with PowerShell knows that there are built in helper commands for every module.

So… my mission was this:

Update Azure AD user attributes so that the Marketing department had new address information

This was the mission at hand, what more do you want??

My first method was a little dirty, I put together a foreach loop and hardcoded the values with no error checking:

$marketingUsers = Get-AzureADUser –Filter "Department eq 'Marketing'"

foreach($user in $marketingUsers){
  Set-AzureADUser –ObjectID $user `
    –StreetAddress '51 River St.' `
    –City 'Ridgefield' `
    –State 'CT' `
    –PostalCode '06877' `
    –Country 'United States'
}

I know! It’s a rough method but I was just testing out the command to see if everything worked as I predicted!

There’s also no host output for each successful change so that’s fun.

What I did next was add a couple of checks to my code:

#Get all marketing users
$marketingUsers = $null
try { 
    $marketingUsers = Get-AzureADUser –Filter "Department eq 'Marketing'" –ErrorAction Stop
}catch{
    #Output the error message if any
    Write-Host "Failed to collect Marketing users!" –ForegroundColor Red
    Write-Host $_.ScriptStackTrace –ForegroundColor Red
}

#Checking if there are no marketing users found
if (!$marketingUsers){
    Write-Host "No Marketing users found"
    return; 
}

#Run through each user and update
foreach($user in $marketingUsers){
    try{ 
        Set-AzureADUser –ObjectID $user `
        –StreetAddress '51 River St.' `
        –City 'Ridgefield' `
        –State 'CT' `
        –PostalCode '06877' `
        –Country 'United States' `
        –ErrorAction Stop
    }catch{
        Write-Host "Failed to update $user" –ForegroundColor Red
        Write-Host $_.ScriptStackTrace
    }
}

After that, it was looking much better and I felt more comfortable actually running the code. We all know what it’s like to run code that’s meant to be a ‘test’ that accidently overwrites everyone’s profile.

Just me? Okay.

What I wanted to do next was to implement a technique called Splatting.

Splatting it a way of putting all the variables or inputs for the script or command into it’s own hash-table so that changes are easier to make further on down the line.

Nothing worse than having a command that takes in a bunch of parameters and you have to scroll across the screen to find the one you’re looking for!

Before I move onto splatting though, now is a good time to test the performance of different loop methods.

I wanted to test if using the -filter parameter was faster than piping items into a Where-Object commandlet. So I used the built in measuring tools within PowerShell:

CommandGet-AzureADUser -ErrorAction Stop | Where-Object {$_.Department -eq ‘Development’}Get-AzureADUser -Filter “Department eq ‘Development’” -ErrorAction Stop
#11311.66696630.8861
#21769.62537973.5126
#32122.87496060.9699
#41963.65125315.6691
#53437.2685783.7616
The table of measured command times

Now that is just crazy to me. Using the built-in -filter parameter is more than twice as slow when compared to piping the results to a completely different command.

Now, lets move back to splatting!

I created the required hash-table to hold the values for the Set-AzureADUser command parameters.

Thankfully, this is very simple and you can see my hash-table below:

#51 River St., Ridgefield, CT 06877
#Randomly generated fake address
#New props in a hashtable for splatting
$newProps = @{
    StreetAddress = '51 River St.'
    City = 'Ridgefield'
    State = 'CT'
    PostalCode = '06877'
    Country = 'United States'
}

This means I can now simplify the Set-AzureADUser command massively by just passing in the hash-table as a single parameter versus specifying them all manually.

Using Set-AzureADUser To Update Attributes

This is what my final code looked like:

#51 River St., Ridgefield, CT 06877
#New props in a hashtable for splatting
$newProps = @{
    StreetAddress = '51 River St.'
    City = 'Ridgefield'
    State = 'CT'
    PostalCode = '06877'
    Country = 'United States'
}

#Get all marketing users
$marketingUsers = $null
try { 
    $marketingUsers = Get-AzureADUser –ErrorAction Stop | `
    Where-Object {$_.Department -eq 'Marketing'} 
}catch{
    #Output the error message if any
    Write-Host "Failed to collect Marketing users!" –ForegroundColor Red
    Write-Host $_.ScriptStackTrace –ForegroundColor Red
}

#Checking if there are no marketing users found
if (!$marketingUsers){
    Write-Host "No Marketing users found"
    return; 
}

#Running through each user
foreach ($user in $marketingUsers){
    try{
        Set-AzureADUser –ObjectId $user $newProps –ErrorAction Stop
    }catch{
        Write-Host "Failed to update $user" –ForegroundColor Red
        Write-Host $_.ScriptStackTrace
    }
}

I hope you enjoyed this little journey I’ve created today. And found the importance of measure commands to find the fastest route to success.

Enjoy! 🎉

Leave a Comment

Your email address will not be published. Required fields are marked *

email popup image
Mark Harwood
NEVER miss a blog post again! Subscribe for email notifications whenever a new post is live!
Subscribe
NEVER miss a blog post again! Subscribe for email notifications whenever a new post is live!
Fill Out This Form, And I Will Be In Touch Shortly
Contact form image
I'll Be In Touch Soon