This solves a frequent situation: you have an existing Microsoft 365 tenant with users that already are using it, and you want to set-up an Azure AD connect synchronization with an on premise Active directory.
This script will read the AAD user’s attributes, create a local user with matching attributes and set up a mS-DS-ConsistencyGuid attribute that allows Azure AD connect to synchronize the two users.
It is important to note that since we can’t know the AAD user’s password, a new one will need to be set through the script and will replicate to AAD.
<#
.SYNOPSIS
Script synchronizes a remote AzureAd users with a local Activedirectory users that it creates
.DESCRIPTION
This script will get all attributes from office 365 and add them to a locally created user.
It will then generate and add an mS-DS-ConsistencyGuid that will allow AzureADConnect to sync the remote and local user.
User should be created in a non-synced OU and then copied over to a synchronized OU to allow for checks.
.NOTES
A global admin is probably not required but at this stage I'm not sure what permission are actually needed.
.COMPONENT
Requires module AzureAD and MSOnline
.LINK
https://blog.edzilla.info/?p=88
.Parameter usersContainer
OU where the user will be created
.Parameter userUPN
The UPN of the users we want to import
.Parameter userPassword
The password we want to user: password cannot be imported from AAD, so a new one must be set on import.
#>
Param (
[string] $usersContainer = "OU=Isotoit,OU=Building,OU=No-365,OU=Users,OU=XLG,DC=XLG,DC=grp",
[string] $userUPN = "toto@toto.com",
[string] $userPassword = 'Qow65345@@'
)
$UserCredential = Get-Credential
#Install Module
Install-Module -Name AzureAD
Install-Module MSOnline
#Connect to Office 365 Azure AD
Connect-AzureAD -Credential $UserCredential
Connect-MsolService -Credential $UserCredential
#Add UPN suffixes to local ad
$azureDomains = Get-AzureADDomain
$localForest = (get-addomain).Forest
ForEach($domain in $azureDomains)
{
if($domain.Name -notlike "*onmicrosoft.com")
{
Set-ADForest -Identity $localForest -UPNSuffixes @{Add=($domain).Name}
}
}
function convert-guid {
param(
[Parameter(Mandatory=$true)]
[GUID]$guidtoconvert
)
$bytearray = $guidtoconvert.ToByteArray()
$immutableID = [System.Convert]::ToBase64String($bytearray)
$immutableID
}
function Add-LocalADObject
{
ForEach($object in $input)
{
write-host $object.ObjectType $object.DisplayName
if($object.UserPrincipalName -like "*onmicrosoft.com")
{
write-host "Skipping object " $object.DisplayName "because it does not have a custom logon domain"
continue
}
if($object.ObjectType -eq "User")
{
$userName, $upn = $object.UserPrincipalName.split('@')
$upn = "@"+$upn
New-ADUser -SamAccountName $userName -UserPrincipalName $object.UserPrincipalName -Name $object.DisplayName -DisplayName $object.DisplayName -Path $usersContainer -AccountPassword (ConvertTo-SecureString $userPassword -AsPlainText -Force) -Enabled $True -PassThru
$filter = "CN=" + $object.DisplayName
}
$localADObject = Get-ADObject -Filter "UserPrincipalName -eq '$($userUPN)'"
#Update attributes based on Azure contact
if($object.GivenName -ne $null){ Set-ADObject $localADObject -Add @{givenName=$object.GivenName} }
if($object.Surname -ne $null){ Set-ADObject $localADObject -Add @{sn=$object.Surname} }
if($object.Mail -ne $null){ Set-ADObject $localADObject -Add @{mail=$object.Mail} }
if($object.StreetAddress -ne $null){ Set-ADObject $localADObject -Add @{streetAddress=$object.StreetAddress} }
if($object.PostalCode -ne $null){ Set-ADObject $localADObject -Add @{postalCode=$object.PostalCode} }
if($object.City -ne $null){ Set-ADObject $localADObject -Add @{l=$object.City} }
if($object.State -ne $null){ Set-ADObject $localADObject -Add @{st=$object.State} }
if($object.PhysicalDeliveryOfficeName -ne $null){ Set-ADObject $localADObject -Add @{physicalDeliveryOfficeName=$object.PhysicalDeliveryOfficeName} }
if($object.TelephoneNumber -ne $null){ Set-ADObject $localADObject -Add @{telephoneNumber=$object.TelephoneNumber} }
if($object.FacsimilieTelephoneNumber -ne $null){ Set-ADObject $localADObject -Add @{facsimileTelephoneNumber=$object.FacsimilieTelephoneNumber} }
if($object.Mobile -ne $null){ Set-ADObject $localADObject -Add @{mobile=$object.Mobile} }
if($object.JobTitle -ne $null){ Set-ADObject $localADObject -Add @{title=$object.JobTitle} }
if($object.Department -ne $null){ Set-ADObject $localADObject -Add @{department=$object.Department} }
if($object.CompanyName -ne $null){ Set-ADObject $localADObject -Add @{company=$object.CompanyName} }
if($object.Country -ne $null){ Set-ADObject $localADObject -Add @{c="BE"} }
if($object.MailNickName -ne $null){ Set-ADObject $localADObject -Add @{MailNickName=$object.MailNickName} }
if($object.PreferredLanguage -ne $null){ Set-ADObject $localADObject -Add @{PreferredLanguage=$object.PreferredLanguage} }
Set-ADObject $localADObject -Add @{msExchPoliciesExcluded="{26491cfc-9e50-4857-861b-0cb8df22b5d7}"}
#get proxy addresses
if($object.ProxyAddresses -ne $null)
{
ForEach($proxyAddress in $object.ProxyAddresses)
{
Set-ADObject -identity $localADObject -Add @{ProxyAddresses=$proxyAddress}
}
}
}
}
#Add users to local AD
if (!(Get-ADUser -Filter "userPrincipalName -like '$userUPN'"))
{
Get-AzureADUser -ObjectId $userUPN | Add-LocalADObject
}
$user = Get-ADUser -Filter "userPrincipalName -like '$userUPN'"
$immutableID = convert-guid -guidtoconvert $user.objectguid
Set-MsolUser -UserPrincipalName $userUPN -ImmutableId $immutableID
$decodedII = [system.convert]::frombase64string($ImmutableId)
$decode = [GUID]$decodedii
$ImmutableId = $decode
$user | Set-ADUser -Replace @{'mS-DS-ConsistencyGuid'=$($ImmutableId)}
Disconnect-AzureAD