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.