JeffHicks

13   8   7

  • TEC 2010 USA Alumni
  • Watchman
  • Debater
  • Fanboy
  • Helper
  • Instigator
  • Participant

User Passwords 3 Ways


LIKED BY
0
PEOPLE

I’m a big time foodie and watch a lot of food TV. I especially like chefs who take an ingredient and prepare it using different techniques on the same dish, usually in threes, like Pork Belly 3 Ways. Recently I got an email asking for help in getting some password age information from a list of user accounts. I quickly turned him on to doing this with PowerShell and got him started. The solution I gave him, is but one of many possible solutions. So let me prepare for you today, “User Passwords 3 Ways”.

All preparations use a simple text list of SAMAccountnames since that was part of the original request. No matter the preparation I want to see the user’s name, distinguishedname, description, when the password was last set and its age.

First on the plate is an approach using ADSI. This will work with all Windows domains and doesn’t require any other snapins or modules.

  1. <br />
  2. $domain=$env:userdomain<br />
  3. $searcher=New-Object DirectoryServices.DirectorySearcher<br />
  4. $searcher.PageSize=100</p>
  5.  
  6. <p>get-content sams.txt | foreach {
  7. [adsi]$user=&#8220;WinNT://$domain/$_,user&#8221;
  8. [datetime]$pwdLastSet=(get-date).AddSeconds(-$user.passwordage.value)
  9. $pwdAge=(get-date) &#8211; $pwdLastSet
  10. $searcher.Filter=&#8221;(&(objectcategory=person)(objectclass=user)(samaccountname=$($user.name.value)))&#8221;
  11. $ADUser=$searcher.findOne()
  12. $user | Add-Member Noteproperty -Name &#8220;Name&#8221; -value $user.fullname.value -force
  13. $user | Add-Member Noteproperty -Name &#8220;DN&#8221; -value $ADUser.properties.distinguishedname<sup class="footnote"><a href="#fn282584b2a9727e6133">0</a></sup> -force
  14. $user | Add-Member Noteproperty -Name &#8220;Description&#8221; -value $user.description.value -force
  15. $user | Add-Member NoteProperty -Name &#8220;PasswordLastSet&#8221; -value $pwdLastSet -force
  16. $user | Add-Member NoteProperty -Name &#8220;PasswordAge&#8221; -value $pwdAge -force -passthru<br />
  17. } | Sort PasswordAge -descending | Select Name,DN,Description,PasswordLastSet,PasswordAge<br />

This code uses a combination of ADSI techniques as it seemed to offer the fastest results with the least amount of code. The code assumes we are using the current domain, but you could enter any value for the $domain variable. I’m primarily going to use the WinNT provider to get the user account because it is fast and has almost everything I need. The one piece of information I can’t get with this provider is the user’s distinguishedname since that is an LDAP property. No matter. I’ll use a directory searcher object to find the user in Active Directory by their SAMAccountname and retrieve their distinguishedname; hence the creation of the DirectoryServices.DirectorySearcher object.

Each name from the list is piped to ForEach object which uses the ADSI type adapter to get the user object from the domain. The PasswordAge value is the number of seconds since the password was changed so I can use that value to determine the date the password was changed in line 7 and then the age in line 8. The password age will be a timespan object written as a string. Next I define a search filter with the SAMAccountname and get the object using the FindOne() method, since there had better be only one match.

Because the object properties are stored as arrays, I use Add-Member to re-define a few values as well as add the new values for the password age and when it was set. All of that output is sorted by the password age in descending order and then I select the properties I want. Here’s a sample of what you can expect.

  1. <br />
  2. Name : Jeffery Hicks<br />
  3. DN : CN=Jeffery Hicks,OU=IT,OU=Employees,DC=<span class="caps">MYCOMPANY</span>,DC=<span class="caps">LOCAL</span><br />
  4. Description : Company admin<br />
  5. PasswordLastSet : 7/20/2009 9:45:20 AM<br />
  6. PasswordAge : 101.01:42:39</p>
  7.  
  8. <p>Name : Roy Biv<br />
  9. DN : CN=Roy Biv,OU=IT,OU=Employees,DC=<span class="caps">MYCOMPANY</span>,DC=<span class="caps">LOCAL</span><br />
  10. Description : A colorful guy<br />
  11. PasswordLastSet : 8/28/2009 8:27:27 PM<br />
  12. PasswordAge : 61.15:00:32<br />

Next on the plate I retrieved the information using the new Get-ADUser cmdlet that is part of the ActiveDirectory module that ships with Windows Server 2008 R2. Or if you are running the Active Directory Management Gateway Service on a Windows 2003/2008 domain controller you can also use this technique. In either case you should be running this from a Windows 7 client with the Remote Server Administration Tools installed and configured for the Active Directory Services roll.

  1. <br />
  2. import-module ActiveDirectory<br />
  3. get-content sams.txt | get-aduser -server &#8220;mycompany-dc01&#8221; -properties Description,PasswordLastSet | <br />
  4. foreach {
  5. $_ | Add-Member Noteproperty -name &#8220;PasswordAge&#8221; -value ((get-date) &#8211; $_.PasswordLastSet) -passthru -force <br />
  6. } | Sort PasswordAge -descending | <br />
  7. Select Name,DistinguishedName,Description,PasswordLastSet,PasswordAge</p>
  8.  
  9. <p>

This time the names are piped to the Get-ADUser cmdlet. Because I’m piping in a value for the identity I specify a domain controller to search. The cmdlet by default only returns a limited number of properties so I use the -properties parameter to indicate what other information I’m going to need. This object is then piped to ForEach where I add a new property for PasswordAge. The PasswordLast set value is already formatted as a date time object. The rest of the expression is the same as before.

The output will be identical with one minor exception. The password age timespan object will be formatted to show a complete millisecond value whereas when using ADSI this was rounded to 2 places.

Last on the plate is an approach using the Get-QADUser cmdlet from the Quest ActiveRoles snapin. This will work with any domain and any PowerShell client. My code assumes you’ve already loaded the snapin.

  1. <br />
  2. get-content sams.txt | get-qaduser | Sort PasswordAge -desc | Select DN,Name,Description,PasswordLastSet,PasswordAge<br />

As you can see this is the simplest approach since the cmdlet automatically handles alot of the conversions and calculations I had to do previously. Output is nearly identical to Get-ADUser except that the property name is DN instead of DistinguishedName.

With all of these preparations you could easily pipe them further to other cmdlets such as Out-File, Export-CSV, or ConverTo-HTML.

I don’t want you to think that one technique is better than the others. It depends on what you have available to work with. My point was to show you several approaches to solving a task. Bon Appetit!

Note: All of my examples were done from a PowerShell v2.0 session. From this point on all future posts will assume you are running PowerShell v2.0. Microsoft has released versions for just about everything so hopefully there’s no reason you can’t run it on your desktop. I generally don’t need the remoting piece for Active Directory so you don’t necessarily have to install PowerShell v2 on your domain controllers…yet.

Replies

None, yet.

Post a Reply

Click here for help with the editor.



Load a new image
 

You are posting anonymously.
Please enter the five characters
shown to the left:

Save Your Reply