I recently did an Active Directory migration and one of the requirements was that the passwords are complex and random.
Ok… So the first thing i did was googled “Powershell Generate Random Password” because imitation is the sincerest form of flattery… 😉 Ah a hit!
Function random-password ($length = 8) { $punc = 46..46 $digits = 48..57 $letters = 65..90 + 97..122 # Thanks to # https://blogs.technet.com/b/heyscriptingguy/archive/2012/01/07/use-pow $password = get-random -count $length ` -input ($punc + $digits + $letters) | % -begin { $aa = $null } ` -process {$aa += [char]$_} ` -end {$aa} return $password }
Script is pretty straightforward the function random-password will generate a password of said length. Nice!
Ok so far so good. I also needed to set the complex password as the user’s Default password when logging in the first time. I just smiled and asked are you certain you want to do that? (I’ll explain later…)
Quick sidestep: The function is great at generating random passwords! I did noticed however when setting the new password I got an error at times (randomly… go figure…)
Turns out it wasn’t an error, was just that the password wasn’t totally compliant.
Then I remembered complex passwords have some requirements. So I fired up GMPC just to see what they were again…
Complexity Password Dictates that it must:
Contain characters from three of the following four categories:
1: English uppercase characters (A through Z)
2: English lowercase characters (a through z)
3: Base 10 digits (0 through 9)
4: Non-alphabetic characters (for example, !, $, #, %)
Aaaah… So that’s why it failed randomly! Some of the passwords only had two out of the four categories. Ok so I just need to make sure the password contains at least three of the four characters.
Ok I knew then and there I had to do something with regular expressions. I’ll admit regular expressions isn’t my forte. Lucky for me I have an “ Arco” :-). Arco is a colleague of mine that is the personification of the UberGeek. His idea of “fun” is reprogramming HP SmartArray controllers. He can also program in assembly… Oh and he’s a whizz at regular expressions!!!
Ok truth be told I did try figuring it out for like 3 minutes then I went straight to Arco! Don’t judge me…
Turns out that google is truly your friend! (Yeah… I know… in hindsight…) So Arco sent me this link:
http://stackoverflow.com/questions/5142103/regex-for-password-strength
Hey, why reinvent the wheel eh?
function random-password { param( $length = 8 ) $punc = 46..46 $digits = 48..57 $lowercase = 97..122 $uppercase = 65..90 $symbols = 35..37 # Thanks to # https://blogs.technet.com/b/heyscriptingguy/archive/2012/01/07/use-pow do { $password = get-random -count ($length) ` -input ($punc +$digits+$uppercase+$symbols+$lowercase) | % -begin { $aa = $null } ` -process {$aa += [char]$_} ` -end {$aa} } until( $password -match "^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{$length}$") return $password }
So I tweaked the regular expression string to have at least a character from uppercase, lowercase and numbers. symbols are just a bonus. If it meets the requirements, then return it.
The main part of the script looks like this:
foreach ($user in $csvUsers) { $newUserPassWord = random-password -length $PasswordLength $objRandomPW = new-object psobject -Property @{ SamAccountName = $user.SamAccountName Name = $user.Name Password = $newUserPassWord } $arrExportRandomPW += $objRandomPW } $arrExportRandomPW | out-gridview
I edited it somewhat, but you get the general idea. Remember csv is my friend!
Ok, I did what was asked. Password random? Check! Complex and compliant? Check!
But…
Now I want to get into something different…
As scripters we’re eager to script! If I have to repeat anything twice I’m already thinking how should I script this.
Password are sacred. So the first thing that popped into my head is how are we going to distribute these passwords without compromising them? If I export them to a csv file and they fall into the wrong hands then what?
“We’ll email them their passwords…” Ok… Problem was that we’re also migrating their mail system to Exchange… So yeah… there’s that…
“We’ll generate Word documents containing their password…” Still tricky but ok. Whose generating the word document, I asked with a smirk on my face? “We’ll take care that…” Nice!
BTW if you’re gonna print passwords please use courier font! There’s is nothing more frustrating than trying to figure out if it’s the letter I (Irwin) or l (live) , case in point Il.
“I could also save the password encrypted in csv file, but then you’d need the key to decrypt” Hmmm… is it worth the hassle? Who’ll do the decrypting? If the key and code falls into the wrong hands then we’re back at square one!
I’ve been in a situation where I needed to report asap which accounts were enabled and didn’t log in yet. Someone got fired (Name wasn’t disclosed) and they needed to take some legal actions. So in this case having a default generic password was kinda of a big issue… At times like that adsi filter is your friend!
Here’s my take on it all. I’d like to hear from you what your thought are about this.
The safest bet is this to:
- Enable accounts JIT (Just in time). Yes it might get a little busy at the beginning but you won’t have any rogue accounts activated.
- Use a generic password agreed upon. The key is not to enable the account too soon or a colleague may be able to log in with mal intent. Using a generic password just helps with the logistics. I’ve seen first hand what happens when complex passwords aren’t typed in correct, accounts get locked out etc etc… It’s a lot easier to enable JIT, use the time for AD to sync to explain the user about his new configuration.
- Make sure the user is required to change password at logon. Just make sure to set the password ahead of time. Depending on your group policy setting you might have to wait a day.
Ok, I think that covers that. It wasn’t my intention to go on and on. Scripting is awesome but.. “With scripting comes responsibility…” Make sure your scripts do no harm as far as it’s up to you.
Hope it’s worth something to you…
Ttyl,
Urv