Updating AzureAD User Attributes

Hi Everyone!

I recently had the opportunity to use PowerShell to update AzureAD user attributes. This is different from what I normally do as we still leverage an on-prem AD setup.

I’d never used the command before but I know PowerShell and I’m fairly confident with the AD PowerShell commands.

The mission at hand was this: Update AzureAD user attributes so that the Marketing department had new address information

The first and rather dirty method I put together as a proof-of-concept is below:

$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 right, it’s ugly. It’s lacking any form of error checking, there’s no host output and it’s hard to read.

What I did next was put my code behind a few checks. You can see the improved code below:

#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
}
}

This was looking much better, it handles error nicely but there is still room for improvement…

I want to implement splatting and also look into ways to speed the script up!

I wanted to take a look into speed first. I know there are subtle different between using the -filter parameter and piping the results into a Where-Object commandlet. Lets run some tests!

I ran the below commands 5 times to get an average using Measure-Command and outputted in total miliseconds:

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

Crazy! Switching from the -filter parameter to using the pipeline more than halved the time it took for the command to run!

Next was to build the hashtable for splatting in the Set-AzureADUser parameters before building the final version. This was simple done by using the below code:

#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 now means I can simplify the Set-AzureADUser command.

You can find the full and finished script below:

#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
}
}

Enjoy!

Migrating an Azure VM to HyperV or VMware

Hi All!

Today, I’ll be showing a brief overview of how I migrated some Azure VMs to an on-premise HyperV and VMware server. This is done in stages and for me, required HyperV as a middle man before moving to VMware.

First, log in to your Azure portal and find the VM that you want to migrate. Open the settings for the VM and go into the ‘Disks’

Click on the blue text that shows the VM disk name. This should open the settings for the VM disk. Head to the ‘Disk Export‘ tab and generate a new URL to download the disk. TIP: download this onto your HyperV server.

Once this has downloaded, we can head to the next step!

The download may leave a file without an extension or with a VHD extension. If needed, add the VHD extension.

We now need to use HyperV to convert the VHD file to a VHDX format. Open HyperV, use the ‘Edit Disk‘ wizard. Find the disk and use the convert option:

Once converted, create a new generation 2 VM with near-enough the same specs as the original Azure VM. Don’t create a disk with this VM. Once the VM has been created, add the new VHDX file to the SCSi controller. Make sure to untick the enable secure boot option in the VM firmware tab:

The VM should now boot as the original Azure VM 🥳

From here it’s easy to get the VM onto VMware. Just use the VMware converter tool on the HyperV box whilst the VM is shutdown or on the VM whilst it’s running (this method is slower).

Hope this helped someone out 🙂