Office 365: Migrate from Cloud identities to Dirsync

In some scenarios, you may have to transfer the the source of authority for your already cloud-only created user accounts in Office 365. One scenario when this is required, is when changing from cloud only identities to synchronized identities from your local Active Directory. Another scenario is when you migrate your AD users from one domain to another, as described in this post.

To make the transitioning to DirSync as smooth as possible, you have to take a couple of precautions to make sure that existing Office 365 accounts are properly matched with the accounts in your local Active Directory.

This can be done using one of the following two methods:

  • Soft matching of each user. For a soft match to properly work, you need to make sure that the primary email address (both in mail and in proxyaddresses) and userprincipalname in the cloud and in the local Active Directory matches.
  • For the users that are to be matched, construct an ImmutableID for each user in the local AD and synchronize that value to WAAD prior activation and doing the first Directory Synchronization. The ImmutableID is basically a Base64-encoded value of the ObjectGuid attribute.

Solution
To make this transition easier, I have created a script that and copies the required attributes from WAAD to your local Active Directory automatically. The script can use both methods to match the users.

If you run the script without any parameters, the following attributes will be updated for all matching users in your local Active Directory:

  • GivenName
  • sn (SurName)
  • DisplayName
  • mail
  • proxyAddresses

If using the -UpdateImmutableID switch, an ImmutableID will be created for the user and synced back to WAAD. Please note, that process will only work without additional steps if you have not been using DirSync before.

With the -CreateNewUsers switch, you have the possibility to let the script create users that are in WAAD but not in your local AD. The SamAccountname will be “firstname.lastname” and a random password will be generated for the new user.

2014-04-18 20-53-32
2014-04-18 20-56-44
2014-04-18 20-57-41

Note: a pre-requisite for the script to work properly is that you’ve already populated the UserPrincipalName attribute for all users in your local Active directory. Of course this must match with the UPN’s used in Office 365/WAAD.

SyncFrom365toAD.ps1

<#  
.SYNOPSIS 
    Script that synchronizes attributes from users in WAAD to the local active directory.
.PARAMETER UpdateImmutableID 
    Constructs and inserts the ImmutableID attribute in WAAD.
.PARAMETER TargetOU
    OU to create new users in.
.PARAMETER CreateNewUsers
    Creates new users for users that are not matching the WAAD users UPN.
.NOTES 
    Author: Johan Dahlbom 
    Blog: 365lab.net 
    Email: johan[at]dahlbom.eu 
    The script are provided “AS IS” with no guarantees, no warranties, and they confer no rights.     
#>
param(
[parameter(Mandatory=$false)]
[switch]$UpdateImmutableID = $false,
[parameter(Mandatory=$false)]
[switch]$CreateNewUsers = $false,
[parameter(Mandatory=$false)]
[string]$TargetOU = "OU=Users,OU=365Lab,DC=cloud,DC=lab"
)
 
#Load required Modules and Assemblys
Import-Module MSOnline
Import-Module ActiveDirectory
[Reflection.Assembly]::LoadWithPartialName("System.Web") | Out-Null
 
Connect-MsolService
 
$WAADUsers = Get-MsolUser -All | Where-Object {$_.UserPrincipalName -notlike "*.onmicrosoft.com"}
 
foreach ($WAADUser in $WAADUsers) {
    $ADuser = Get-ADUser -Filter {UserPrincipalName -eq $WAADUser.UserPrincipalName}
      
    try {
 
        $Mail = $($WAADUser.ProxyAddresses | Where-Object {$_ -cmatch "^SMTP"}).substring(5)
         
        if ($ADuser) {
        #Update AD user with attributes from WAAD
        Set-ADUser -Identity $ADuser `
            -EmailAddress $Mail `
            -GivenName $WAADUser.FirstName `
            -SurName $WAADUser.LastName `
            -DisplayName $WAADUser.DisplayName `
            -Replace @{ProxyAddresses=[string[]]$WAADUser.ProxyAddresses} `
            -ErrorAction Stop -WarningAction Stop
 
        Write-Output "SUCCESS: Updated $($ADuser.userprincipalname) with proper attributes from WAAD"
         
        } else {
 
            if ($CreateNewUsers) {
 
                     #Generate password for the user aduser
                     $NewUserPassword = [System.Web.Security.Membership]::GeneratePassword(13,0)
 
                     #Generate samaccountname "firstname.lastname"
                     $SAM = [Text.Encoding]::ASCII.GetString([Text.Encoding]::GetEncoding("Cyrillic").GetBytes("$($WAADUser.Firstname).$($WAADUser.Lastname)".ToLower()))
                                           
                     New-ADUser -Path $TargetOU `
                        -Name $WAADUser.DisplayName `
                        -UserPrincipalName $WAADUser.UserPrincipalName `
                        -SamAccountName $sam `
                        -Enabled $true `
                        -EmailAddress $Mail `
                        -GivenName $WAADUser.FirstName `
                        -SurName $WAADUser.LastName `
                        -DisplayName $WAADUser.DisplayName `
                        -OtherAttributes @{ProxyAddresses=[string[]]$WAADUser.ProxyAddresses} `
                        -AccountPassword (ConvertTo-SecureString $NewUserPassword -AsPlainText -force) `
                        -ErrorAction Stop -WarningAction Stop
 
                     Write-Output "SUCCESS: Created user $sam with password $NewUserPassword"

            } else {
                    
                     Write-Warning "User $($WAADUser.UserPrincipalName) is not in AD, user might not be synchronized correctly or become a duplicate user.`r`nCreate the user manually or run the script with -CreateNewUsers switch."
            
            }
        }
               
        #If UpdateImmutableID switch has been used, construct and set ImmutableID for the WAAD user.
        if ($UpdateImmutableID) {
            $ADuser = Get-ADUser -Filter {UserPrincipalName -eq $WAADUser.UserPrincipalName}
            if ($ADuser) {
                $ImmutableID = [system.convert]::ToBase64String($ADuser.ObjectGUID.ToByteArray())
                Set-MsolUser -UserPrincipalName $WAADUser.UserPrincipalName -ImmutableId $ImmutableID -ErrorAction Stop -WarningAction Stop
            }
        }
      
   } catch [Microsoft.Online.Administration.Automation.MicrosoftOnlineException] {
             
            Write-Warning "Error when updating ImmutableID $ImmutableID for $Mail`r`n$_"
 
   } catch {
            
            Write-Warning "Error when creating user $Mail`r`n$_"
        
   }
 
}

Good luck running the script and with your Dirsync implementation!

/Johan

Advertisement

9 thoughts on “Office 365: Migrate from Cloud identities to Dirsync

  1. Pingback: Office 365: Migrating DirSync to new AD domain | Tailspintoys – 365lab.net

  2. Joe Whited

    I used your script to complete the final leg of a swing migrate of users from an old SBS server to O365 with a new on-prem 2012 domain.
    But since their UPN had their SAM names in them from the old system, and I wanted the users to have the same SAM name in the new system, I modified the $SAM definition to first copy the UPN to a variable and then split it at the “@”.
    $SAM = $LGN.split(“@”)
    And in the “New-ADUser” section, I changed the sam line to read:
    -SamAccountName $SAM[0]

    Thanks for a great script, and I hope this mod helps anyone who wants the UPN to be the SAM in the target domain.

    Reply
  3. Carlos

    Hi Johan

    Do i need to assign the Immutable ID to the cloud user before using soft match?
    i tought that since the upn and primary mail address matched, it would automatically connect the cloud user with the on-premise user.
    Our scenario is a company that have on-prem users wth mailbox and cloud users that are fully licensed. The cloud users have mail and upn firstname.lastname@contoso.onmicrosoft.com and the on-prem have @contoso.com
    Should soft match work after verifying my domain on the cloud and changing upn for all users?

    Reply
  4. Carlos

    Hi

    i tried to comment put my post is not showing, ill try again
    Do we need to set an immutable id on the cloud user before synchronization?
    i thought that it only required that the upn and primary smtp matched. Since the cloud user dont have any immutableID from the start, i would connect to the on-prem user when synced
    thanks

    Reply
  5. Seth

    I had used the cut over migration. I created 150 user accounts in O365 and copied user’s email data. Then after several months, on-prem exchange was decommissioned. After several more months, managemnt now wants me to implement ADConnect because right now we are creating 2 accounts for each user: I create them in local AD and then i create them in O365 for email. I have gone through AD and matched the upn and email ID for each user to match O365 But i have not started ADConnect yet. I am afraid that it might override the O365 accounts and all mailboxes will be deleted. Please advise.

    Reply
    1. Andreas Lindahl

      When enabling AD Connect no mailboxes will be deleted, even if there is a mismatch. The worst thing that could happend if a UserPrincipalName is mis-spelled is that you will have a duplicate account synced to Azure AD. Are you syncing the same AD domain as when you did the cut over migration? In that case you are less likely to have mismatched UserPrincipalNames.

      Make sure that the proxyAddresses attribute is populated with all existing email addresses and aliases currently in Office 365, and when you have checked that, check it again. 🙂

      I also recommend enabling UPN SoftMatch, https://support.microsoft.com/en-us/help/3164442/how-to-use-upn-matching-for-identity-synchronization-in-office-365,-azure,-or-intune.

      Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s