Showcasing my ‘ImmutableID Swiss Army knife’.  A tool that takes hours of Active Directory  Sync prep work and put it into a few click with worries about sync issues of loss of data. Even though script is currently design to work with AADConnect everything except the -ForceSync switch will work with DirSync and AADSync.

20160317 - AADConnect Automation

Script Output

Download Script Here

Syntax:

.\SyncMasterPlan.ps1 -O365Domain <Domianname> -O365Connect -PrepAD -ForceSync

Example:

.\SyncMasterPlan.ps1 -O365Domain o365c.cu.cc -O365Connect -PrepAD -ForceSync

 

The script covers;

  • Updating UserPrincipalName (UPN) and ProxyAddesses of local Active Directory user to match cloud users
  • Add users to be sync to ‘Office 365 Users’ OU
  • Get and update Local Active Directory users’ ImmutableID to the cloud users
  • Then Initiate a sync

Prerequisite

  • Needs to be run on a server that has AADConnect and can access Active Directory and Office 356
  • AD, ADSync and MSOline modules must be installed on that the server
  • Must have a valid Office 365 Global Admin Account

Script in Action

 

Script Breakdown 

#AADConnect Sync Prep Automation
#Hannel Hazeley
#hhazeley@outlook.com
#Version 5.0

 Param(
 [Parameter(Mandatory=$true)]
 $O365Domain,
 [switch]$O365Connect,
 [switch]$PrepAD,
 [switch]$ForceSync
 )

$ErrorActionPreference = "SilentlyContinue"

$timecode = Get-Date -Format 'yyyyMMddHHmmss'
$file = ".\$timecode`_ImmutableID_Update.log"
Start-Transcript -Path $file

Function logline
{
Write-Output " " | Out-File -FilePath $file -Append -NoClobber -Encoding default
}

Function CreateOU
{
$OU = Get-ADOrganizationalUnit -Filter {name -eq "Office 365 Users"}
If ($OU.DistinguishedName -eq $null)
{
Write-Host -ForegroundColor Green "OU not in AD..... Creating Office 365 Users OU......"
Write-Output "OU not in AD..... Creating Office 365 Users OU......" | Out-File -FilePath $file -Append -NoClobber -Encoding default
logline
New-ADOrganizationalUnit -Description "Contians Office 365 users to be synced" -DisplayName "Office 365 Users" -Name "Office 365 Users" -ProtectedFromAccidentalDeletion $true
$OU = Get-ADOrganizationalUnit -Filter {name -eq "Office 365 Users"}
}
Else
{
Write-Host -ForegroundColor Green "OU '"$OU.name"' already in AD......"
}
Write-Host -ForegroundColor Green "Moving Users into the "$OU.name" OU......"
$Users | Move-ADObject -TargetPath $OU.DistinguishedName
Write-Host

}

Function PrepAD
{
$Users = Get-ADGroupMember -Identity office365users
Write-Host
logline
Write-Host -ForegroundColor Green "Updating UserPrincipalName and ProxyAddresses......" 
Write-Output "Updating UserPrincipalName and ProxyAddresses......" | Out-File -FilePath $file -Append -NoClobber -Encoding default
Write-Host
Foreach ($user in $users) 
{
$UserPrincipalName = (Get-ADUser -Identity $user).SamAccountName+"@"+$O365Domain
Set-ADUser -Identity $user.SamAccountName -UserPrincipalName $UserPrincipalName
$smtp = (Get-ADUser -Identity $user.SamAccountName -Properties proxyaddresses).proxyaddresses -replace ("SMTP:","smtp:")
Set-ADUser -Identity $user.SamAccountName -Replace @{Proxyaddresses=$smtp}
Set-ADUser -Identity $user.SamAccountName -Remove @{Proxyaddresses="smtp:"+$UserPrincipalName}
Set-ADUser -Identity $user.SamAccountName -Add @{Proxyaddresses="SMTP:"+$UserPrincipalName}
Write-Host -ForegroundColor Green "UserPrincipalName and ProxyAddresses for "$user.Name" has been updated......"
}
$Users | % {Get-ADUser -Identity $_ -Properties * | FL DisplayName,SamAccountName,UserPrincipalName,Proxyaddresses}
Write-Host
Write-Host
CreateOU
}

Function O365Connect { Function RollBack { Write-Host
Write-Host -ForegroundColor Red "Cannot connect to Office 365 No or Invalid Office 365 Credential supplied"
Write-Host
logline
Write-Output "Cannot connect to Office 365 No or Invalid Office 365 Credential supplied" | Out-File -FilePath $file -Append -NoClobber -Encoding default
logline
Stop-Transcript
Break } Write-Host
Write-Host
#Connect to MSOL Environment
Write-Host -ForegroundColor Yellow "Connecting to Office 365........"
Write-Output "Connecting to Office 365........" | Out-File -FilePath $file -Append -NoClobber -Encoding default
logline

$cred = Get-Credential -Message "Please enter a Global Admin credential for your Office 365 Environment."
if ($Cred -eq $null)
{
Rollback
}
Connect-MsolService -Credential $cred -ErrorAction SilentlyContinue -ErrorVariable ConnectError
if ($ConnectError -ne $null)
{
Rollback
}
}
 Function UpdateMSOL { #Convert GUID to ImmutableID $ImmutableID = [System.Convert]::ToBase64String($GUID.tobytearray())
 #Update ImmuteableID to Office 365 Set-MSOLuser -UserPrincipalName $upn -ImmutableID $immutableID Write-Host -ForegroundColor Green "ImmutableID for $upn updated to $immutableID in Office 365" Write-Output "ImmutableID for $upn updated to $immutableID in Office 365" | Out-File -FilePath $file -Append -NoClobber -Encoding default }

#Get and Validate user's GUID
If ($PrepAD.IsPresent) {PrepAD}
If ($O365Connect.IsPresent) {O365Connect}
$OU = Get-ADOrganizationalUnit -Filter {name -eq "Office 365 Users"}
$upns = (Get-MsolUser | ?{$_.Userprincipalname -like "*@$O365Domain"}).Userprincipalname | sort Userprincipalname
Foreach ($upn in $upns)
{
$GUID = (Get-ADUser -SearchBase $ou.DistinguishedName -Filter {UserPrincipalName -eq $upn}).ObjectGUID
if ($GUID -eq $null)
{
Write-Host -ForegroundColor Red "User with UPN ($upn) is not in the 'Office 365 Users' OU in AD"
Write-Output "User with UPN ($upn) is not in the 'Office 365 Users' OU in AD" | Out-File -FilePath $file -Append -NoClobber -Encoding default
}
Else
{
UpdateMSOL
$SyncNeeded = $true
}
}

 If ($SyncNeeded -eq $true -and $ForceSync.IsPresent) 
{
Write-Host
Write-Host -ForegroundColor Green "A delta sync has been initiated"
logline
Write-Output "A delta sync has been initiated" | Out-File -FilePath $file -Append -NoClobber -Encoding default
logline
Start-ADSyncSyncCycle -PolicyType Delta
Write-Host
Stop-Transcript
}
ELSEIf ($SyncNeeded -ne $true -and $ForceSync.IsPresent) 
{
Write-Host
Write-Host -ForegroundColor Green "Nothing change no force sync needed."
logline
Write-Output "Nothing change no force sync needed." | Out-File -FilePath $file -Append -NoClobber -Encoding default
logline
Write-Host
Stop-Transcript
}
Else 
{
Write-Host
Write-Host -ForegroundColor Green "Please wait 2 sync cyles for all changes to replicate."
logline
Write-Output "Please wait 2 sync cyles for all changes to replicate." | Out-File -FilePath $file -Append -NoClobber -Encoding default
logline
Write-Host
Stop-Transcript
}