Reset password in Active Directory using PowerShell

Page content

I’ve previously written about how to generate a random password and how to output a password in phonetic alphabet. Today I’m going to put those two functions to use in a practical example.

Scenario: Carl is a helpdesk agent and today he is feeling a bit stressed out. There has been an outage on one of the business critical systems and the phones are constantly ringing. One of the calls is a user who forgot his password and Carl quickly asks the usual control questions to make sure that the user is who he claims to be, locates the user account and clicks on reset password. Carl is an experienced agent and is usually very good at quickly making random passwords up but today he just can’t find the inspiration so he quickly enters the password he has heard his colleagues use so many times, Summer15. There is a long queue on the phone line and he simply just don’t have the time to do it right. He also forgot so check that little checkbox that forces the user to change his password on next logon. These do things happen repeatedly once in a while and suddenly there are a whole lot of users using the same password.

Resetting a users password in Active Directory using the Active Directory Users and Computers is quite time consuming. Using Active Directory Administrative Center is a bit faster since it has the Reset Password tile. But both these alternative depends on the technician to make up a password.

Doing the same thing using cmdlets in the Active Directory PowerShell module is a lot of typing and not really a good alternative. Unless you combine all the cmdlets in an advanced function. Let’s start by looking at the process of resetting a password in Active Directory using PowerShell:

  1. First I need to make up a new password and convert it to a secure string.

    $SecPaswd= ConvertTo-SecureString –String ‘Summer2014’ –AsPlainText –Force

  2. Then I reset the password using Set-ADAccountPassword.

    Set-ADAccountPassword -Reset -NewPassword $SecPaswd –Identity john.smith

  3. Now I could check if the account is locked out, but I usually just unlock the account, locked or not.

    Unlock-ADAccount –Identity john.smith

  4. Last I make sure that the user has to change the password on next logon

    Set-ADUser –Identity john.smith –ChangePasswordAtLogon $true

This is a lot to type while having a user waiting in the phone and making up passwords manually is never a good practice. To solve this scenario I wrote the function Reset-SWADPassword that takes four parameters:

  • Identity <String> Takes either account name or distinguished name and is used to identify the account to have its password reset.
  • Length <Int> Defines the number chars in the new password, defaults to 8
  • InputStrings <String[]> An optional list of strings that defines character groups. The generated password will contain at least one char from each string.
  • NoChange Specifies that the user should NOT have to change password on next logon.

The function will make use of two of my previously published functions, New-SWRandomPassword and Get-Phonetic, to generate a new random password and output the password using NATO phonetic spelling to make it easier to read the new password to a user over phone.

Load these three functions on a computer with the Active Directory PowerShell module installed and you can simply reset a users password by running:

Reset-SWADPassword –Identity phil.brath

image

This shows us that Phil now has the password ixi9EG!e

By default, the parameter –InputStrings has the following value:

$InputStrings = @('abcdefghijkmnopqrstuvwxyz', 'ABCEFGHJKLMNPQRSTUVWXYZ', '23456789', '!"#%&')

Meaning that every password will consist of one character from each of the strings. If I find that way too complex I can specify my own inputstrings. However specifying inputstrings every time I want to reset a password is just not going to happen. The solution to this is to set default parameter values in the automatic variable $PSDefaultParameterValues. $PSDefaultParameterValues is a special variable of the type DefaultParameterDictionary which has a hashtable-like structure. To set a default parameter value, I index into the variable like this:

$PSDefaultParameterValues["Reset-SWADPassword:InputStrings"]=@('abcd', 'ABCD', '1234567890')

Now I can run Reset-SWADPassword again without having to specify my custom inputstrings.

image

This time the generated password only contains lowercase a-d, uppercase A-D and numbers 0-9.

To read more about $PSDefaultParameterValues, see the help document about_Parameters_Default_Values

Get-Help about_Parameters_Default_Values

$PSDefaultParameterValues is reset every time I close my PowerShell window. If I want to have this value set every time I open PowerShell I have to put it in my profile. The profile is a script that gets run every time I start PowerShell and I’ve written a post on using PowerShell profiles. Just add the modification of $PSDefaultParameterValues to the appropriate profile script and you’re set!

Here is the function in full:

function Reset-SWADPassword {
<#
.Synopsis
Reset the password for specified user to a random password.
.DESCRIPTION
Uses the functions New-SWRandomPassword and Get-Phonetic to generate a random
password with specified length, reset the specified user's password and display
the new password with phonetic spelling.

Will unlock specified user and unless the parameter -NoChange is specified the user
will have to change its password on next logon.
.EXAMPLE
Example of how to use this cmdlet
.EXAMPLE
Another example of how to use this cmdlet
#>
[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Medium')]
param(
# Identity of user that should have their pasword reset
[Parameter(Mandatory=$true)]
[Alias('DistinguishedName')]
[String]$Identity,

# Length of password that will be generated
[ValidateRange(1,[int]::MaxValue)]
[int]$Length = 8,

# Specifies an array of strings containing charactergroups from which the password will be generated.
# At least one char from each group (string) will be used.
[String[]]$InputStrings = @('abcdefghijkmnopqrstuvwxyz', 'ABCEFGHJKLMNPQRSTUVWXYZ', '23456789', '!"#%&'),

# Specifies that the user will not have to change their password on next logon
[Switch]$NoChange
)
try {
$Password = New-SWRandomPassword -PasswordLength $Length -InputStrings $InputStrings
$SecPaswd = ConvertTo-SecureString -String $Password -AsPlainText -Force
if ($PSCmdlet.ShouldProcess("`n$DistinguishedName",'Reset password')) {
$ADUser = Set-ADAccountPassword -Reset -NewPassword $SecPaswd -Identity $Identity -PassThru -Confirm:$false -WhatIf:$false -ErrorAction Stop
Write-Verbose -Message 'Password reset successfully'
if (-Not $NoChange) {
Set-ADUser -ChangePasswordAtLogon $true -Identity $ADUser -Confirm:$false -WhatIf:$false -ErrorAction Stop
Write-Verbose -Message 'Change password at logon set to True'
}
Unlock-ADAccount -Identity $ADUser -Confirm:$false -WhatIf:$false -ErrorAction Stop
Write-Verbose -Message 'Useraccount unlocked'
Get-Phonetic -Char $Password
}
}
catch {
throw
}
}