Summary: Microsoft guest blogger and PFE, Ian Farr, talks about using Windows PowerShell to get account lockout and password policies.
Microsoft Scripting Guy, Ed Wilson, is here. Welcome back guest blogger, Ian Farr. Ian is a Microsoft PFE in the UK.
Recently, I was asked how to retrieve a domain’s Account Lockout Policy and Password Policy with Windows PowerShell. Both are stored as attributes on each domain’s Domain Naming Context. In fact, when you update these policies with the Group Policy Management Console, it is the role of the domain’s PDC emulator to write the changes to the header of the domain naming context.
This function reads policy information from a domain header: Get-ADDomainAccountPolicies.
Account Lockout Policy
Here’s how to get the Account Lockout Policy settings. First, connect to the RootDSE of a domain controller:
$RootDSE = Get-ADRootDSE -Server $Domain
Use Get-ADObject to retrieve properties from the domain naming context (defaultNamingContext):
$AccountPolicy = Get-ADObject $RootDSE.defaultNamingContext -Property lockoutDuration, lockoutObservationWindow, lockoutThreshold
Next, produce a customized output representing the policy.
$AccountPolicy | Select @{n="PolicyType";e={"Account Lockout"}},`
DistinguishedName,`
@{n="lockoutDuration";e={"$($_.lockoutDuration / -600000000) minutes"}},`
@{n="lockoutObservationWindow";e={"$($_.lockoutObservationWindow / -600000000) minutes"}},`
lockoutThreshold | Format-List
Select-Object displays some standard properties: DistinguishedName and LockoutThreshold. It also displays some custom properties constructed with the aid of two hash tables. Let’s look at the format of the lockout duration value:
@{n="lockoutDuration";e={"$($_.lockoutDuration / -600000000) minutes"}}
- @{} denotes the hash table, which contains one or more key-value pairs
- n is the name of the property to be stored, and its value is lockoutDuration
- e is the expression that Windows PowerShell evaluates, and that value is…
What’s the expression doing? The LockoutDuration property of the current object $_ is a negative 64-bit time value interval expressed in nanoseconds. This is divided by -600000000 to give a positive value in minutes. This calculation is performed as part of a subexpression, which is recognized by this notation: ‘$( )’. The code in brackets is calculated first. The returned value is then added to a string where minutes is appended and stored as the value associated with e.
We now have a hash table with two elements, n and e, that Select-Object recognizes and formats into a display property to the console screen. The previous process also applies to the LockoutObservationWindow value.
Here’s some sample output:
Password Policy
Again, use Get-ADObject to retrieve properties from the domain naming context:
$PasswordPolicy = Get-ADObject $RootDSE.defaultNamingContext -Property minPwdAge, maxPwdAge, minPwdLength, pwdHistoryLength, pwdProperties
Next, produce a customized output that represents the policy:
$PasswordPolicy | Select @{n="PolicyType";e={"Password"}},`
DistinguishedName,`
@{n="minPwdAge";e={"$($_.minPwdAge / -864000000000) days"}},`
@{n="maxPwdAge";e={"$($_.maxPwdAge / -864000000000) days"}},`
minPwdLength,`
pwdHistoryLength,`
@{n="pwdProperties";e={Switch ($_.pwdProperties) {
0 {"Passwords can be simple and the administrator account cannot be locked out"}
1 {"Passwords must be complex and the administrator account cannot be locked out"}
8 {"Passwords can be simple, and the administrator account can be locked out"}
9 {"Passwords must be complex, and the administrator account can be locked out"}
Default {$_.pwdProperties}}}}
We’re doing similar stuff here with the hash tables, except that we calculate days, not minutes, from the negative nanosecond value.
For the last value returned, we’re taking $_.pwdProperties and attempting to match it to a known value by using a Switch statement. For example, if $_.pwdPropeties is 8, then the value associated with e will be "Passwords can be simple, and the administrator account can be locked out."
Here is a sample output:
Not the prettiest function, but certainly effective!
You can download the entire function from the Script Center Repository: Get-ADDomainAccountPolicies Function.
~Ian
Thank you, Ian, for once again sharing your time and knowledge.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
Thanks for sharing this.
NB: I noticed one slight ommision; you specify the domain when getting the rootdse, but not when fetching the required information from AD; so if you’re running the script on a different domain to the rootDSE’s domain, you’ll get a “cannot find an object with identity…” error
Fix is to replace:
$AccountPolicy = Get-ADObject $RootDSE.defaultNamingContext -Property lockoutDuration, lockoutObservationWindow, lockoutThreshold
with:
$AccountPolicy = Get-ADObject $RootDSE.defaultNamingContext -Property lockoutDuration, lockoutObservationWindow, lockoutThreshold -Server $Domain