Category Archives: Migration

Migrating from Lotus Notes to Office 365 – The PowerShell Saga

The last few months have been pretty intense, but we finally finished moving ~18000 mailboxes from Lotus Notes to Office 365. I went to the first startup meeting for the implementation part of the project in late September, and we finished most of the migration this week, which was pretty satisfying to say the least ๐Ÿ™‚

It has been a long journey (done in a short timeframe), and a lot of things needed to be done in order for it to work.

Some of the obstacles we (and probably everyone who does a migration) needed to solve were:

  • Changing UPN’s on all the accounts to the users primary smtp address
  • Establish ADFS and DirSync
  • Changing certificates that were using the current UPN’s and therefor would be rendered invalid.
  • Import the ~8000 accounts that only existed in Domino and not in Active Directory and keep them synced.
  • Sync the other 10000 accounts that existed in both Domino and Active Directory
  • Migrate distribution lists
  • Migrate rooms
  • Migrate shared mailboxes with their access lists
  • Build forms to enable users to do some of the management themselves
  • Make sure mail flow works during the “hybrid” period
  • Migrating mobile device id’s allowed to sync through Active Sync
  • Provisioning of new accounts in Office 365 that work with our current processes
  • Automate all the common tasks (creating mailboxes, shared mailboxes, managing distribution lists, approving devices, managing licenses etc.)
  • And more… ๐Ÿ™‚

Since a lot of people out there are probably doing, or will be doing, the same thing we did, I will try to do a couple of post on how we solved these tasks (at least those related to powershell), share some code and good cmdlets for managing everything from rooms to mobile devices,

Hopefully this will become a good repository for myself and for anyone out there facing the same challenge we did ๐Ÿ™‚

Generating passwords for new user accounts

During our migration to Office 365, we first needed to make sure all the users had an account in Active Directory. In our case, a lot of them didn’t since they only used Notes-applications.

The provisioning/sync of these accounts is for another blog post (or several), but I thought I could share some of the code we use for setting passwords.

First of all, you need something to generate the passwords with. There are a lot of scripts written for this (a good blog post that helped me getting started is this one), but most of them I found are using the same process for creating the passwords.

For example:

Get-Random -Minimum 65 -Maximum 90 | % { [CHAR][BYTE]$_ }

This will generate a random upper case letter between A and Z. If you change the range you can generate any character you want using this method. If you would like some help in finding which character is corresponding to what number you can have a look here.

What most of the scripts I found were lacking was a method of making sure that the passwords generated is actually following the password complexity rules. The passwords generated were random, and of the correct length, but you didn’t know if the different characters required were actually in the password.

So I ended up with doing my own function for this. It’s pretty short so I’ll do a code walkthrough of the important parts in it.

First, we need to specify what characters must be included in the password. I did this by creating four different arrays. You might want to have some control of which special characters are included since some applications (if the password is not for Active Directory accounts) can’t handle some of them. And you might not want your users to have to change their keyboard layout to be able to log in ๐Ÿ™‚

You could do something like this:

# Set which characters should be used
$CapitalLetters=For ($a=65;$a โ€“le 90;$a++) { [char][byte]$a }
$SmallLetters=For ($a=97;$a โ€“le 122;$a++) { [char][byte]$a }
$Numbers=0..9
$SpecialCharacters="!","@","#","%","&","?","+","*","=","ยฃ","\"

$AllCharacters=$CapitalLetters+$SmallLetters+$Numbers+$SpecialCharacters

It is now time to actually build a password. I did this with a loop which will execute until it reaches $PasswordLength, which is a parameter for the function.

It looks like this:

# Loop until we reach the password length
for ($CharNr=$NrOfCharacterTypes;$CharNr -le $PasswordLength;$CharNr++) {

# If this is the first run, we should add one of every character type
if ($CharNr -eq $NrOfCharacterTypes) {
$CharacterString+=($CapitalLetters | Get-Random)
$CharacterString+=($SmallLetters | Get-Random)
$CharacterString+=($Numbers | Get-Random)
$CharacterString+=($SpecialCharacters | Get-Random)
}
# If not, start adding random characters.
else {
$CharacterString+=($AllCharacters | Get-Random)
}
}

$CharacterString now contains all the characters we need. But we don’t want the passwords to always have the character types in the same order (first a capital letter, then a small, then a number then a special character, and then random) since that would make the password a lot weaker.

To fix this we turn it into an array and then randomize the order of the characters, and finally send it back to the pipeline.

Like this:

# Create an char array of the characters
$TempPasswordArray=$CharacterString.ToString().ToCharArray()

# Randomize the order of them
$PasswordToReturn=($TempPasswordArray | Get-Random -Count $TempPasswordArray.length) -join ''

# Send it back to the pipeline
Write-Output $PasswordToReturn

This password will always contain all the character types we have specified. And they will always be random.

The complete code (which includes the $NrOfCharacterTypes and some other things), are available here.

Getting pictures converted for ThumbnailPhoto to be used in Lync/Outlook (ConvertTo-ADThumbnail)

There are obviously a lot of things that needs to be migrated when changing mail platform, one of those things that are a “very nice to have” is user pictures/thumbnails which shows up in Outlook, OWA, Lync and so on…

But this can be quite a challenge. The pictures are stored in the “ThumbnailPhoto”-attribute as a byte array, which needs the picture size to be less than 10 kb to work in lync/outlook (actually, the “Active Directory Users & Computers”-snapin wants it under 8 kb to be shown in the attribute editor so this is what we choose).

The pictures from Notes are “user generated”, they can be gif, jpg, png, bmp or something else, and I’m guessing this would be the case for many large organisations out there.

The solution we used was to add a step in our “Notes to Active Directory”-script to check if a picture is available, if it is, it uses a small “advanced function” I wrote to convert the picture to a byte array, and save a copy of the new file on disk, it’s called ConvertTo-ADThumbnail. It also output’s the changes in size if that’s needed.

It looks like this:

PS H:\> ConvertTo-ADThumbnail -PictureFile .\MyPrettyPicture.jpg

OrgFilename : .\MyPrettyPicture.jpg OrgFileSize : 33,748046875 OrgFileWidth : 400 OrgFileHeight : 300 NewFilename : H:\\MyPrettyPicture-ADThumbnail.jpg NewFileSize : 8,9111328125 NewFileWidth : 336 NewFileHeight : 252 ThumbnailByteArray : {255, 216, 255, 224…}

 

To actually write the “ThumbnailByteArray” to the user object you do something like this:


# Set the folder paths
$PictureFilePath = '.\Path\MyPrettyPicture.jpg'
$ADThumbnailPictureFolder = '.\TheFolderISave\ADThumbnails'

# Load the byte array
$UserPicture = [byte[]] $(ConvertTo-ADThumbnail -PictureFile $PictureFilePath -OutputDir $ADThumbnailPictureFolder | select -ExpandProperty ThumbnailByteArray)

# Write it to Active Directory
Set-ADUser -Identity 'MySamAccountName' -Replace @{ thumbnailPhoto = $UserPicture }

The cmdlet handles most picture formats, and shrinks them until they are small enough. You can set the file size, output folder path etc. with parameters.

I have tested the code on 1000+ pictures, so far so good ๐Ÿ™‚

If you missed the link above, the code is available here.

Creating Master Lists for Quests Lotus Notes to Exchange tool

During our migration to Office 365, we ran into an issue with creating Master Lists for the migration tool. The tool just creates one huge file with all of the users in it, but we want to migrate them based on different things like mailbox size, where in the organisation they are and so on.

When we have the users we want to migrate in a list, we need to split that list up for scaleability reasons (multiple migration tool servers), and since the files need to be formatted in a quite specific way, this was becoming a pain…

What better way to fix this problem than with a PowerShell form?

I opened up Sapien PowerShell Studio 2012ย and started working. Here are the results:
CreateMasterLists

Just browse for the master tsv file, the columns found in the file will be automatically populated in the droplist. Choose which one you want to do the matching on (in our case targetaddress, same as e-mail/UPN):

ChoosingKey

 

Select the other settings, should be pretty obvious:

OtherSettings

 

And hit “Build file(s)”, and watch it go:

finding_users

 

If you just want to split the master file, that’s possible aswell, just tick that box and hit the Build-button:

splitting_into_files

 

I hope someone else might have use of this little form!

The code is available hereย and it requires at least PowerShell v3 to run properly.