Tag Archives: Active Directory

Active Directory Friday: Find users with password never expires

Having password set to never expires might be something that is not allowed by your IT policy, or perhaps you would like to get some insight about how widespread this setting is in your domain. In order to find accounts the Search-ADAccount cmdlet can be used. In order to find all user accounts that do have the password never expires option enabled the following code can be used:

1
Search-ADAccount -UsersOnly -PasswordNeverExpires

Alternatively the Get-ADObject cmdlet can also be used in combination with an LDAP filter to filter out the user accounts and the password never expires option. To filter out user accounts we should filter the following: ‘(objectCategory=person)(objectClass=user)‘. To search for password never expires the following filter is used: ‘(userAccountControl:1.2.840.113556.1.4.803:=65536)‘. Combined that gives us the following code:

1
Get-ADObject -LDAPFilter "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))"

It is of course also possible to do this using the DirectoryServices.DirectorySearcher. This time we use a slightly different LDAP filter, instead of filtering on ‘(objectCategory=person)(objectClass=user)‘ we filter on ‘(sAMAccountType=805306368)‘ which gives the same output but is a more efficient query. Also we set pagesize to 100 so we ensure that all results are displayed:

1
2
3
4
5
$ADSearcher = New-Object DirectoryServices.DirectorySearcher -Property @{
  Filter = '(&(sAMAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=65536))'
  PageSize = 100
}
$ADSearcher.FindAll()

And that is all that is required in order to find AD users with the password never expires option set, with or without the ActiveDirectory module.

Share

Active Directory Friday: Change a user’s password

It is one of the most common tasks Active Directory administrators face, changing a user’s password or unlocking their account. Today we will discuss how this can be done in Powershell using either the Active Directory module or [adsi] type accelerator for this purpose.

Setting or resetting a password is rather straight forward using the Active Directory cmdlets, simply use Get-ADUser to get the AD user object and pipe it into Set-ADAccountPassword:

1
Get-ADUser jaapbrasser | Set-ADAccountPassword -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "secretpassword01" -Force)

To unlock an account the Unlock-ADAccount cmdlet can be used:

1
Get-ADUser jaapbrasser | Unlock-ADAccount

To both unlock and change the password of a user using the ADSI type accelerator the following code can be used:

1
2
3
4
$User = [adsi]([adsisearcher]'samaccountname=jaapbrasser').findone().path
$User.SetPassword("secretpassword01")
$User.lockoutTime = 0
$User.SetInfo()
Share

Active Directory Friday: Create new OU

PowerShell can be used to create any number of objects in Active Directory. Today I will demonstrate how to create an organizational unit using both the ActiveDirectory module as well as the [adsi] alternative.

Creating an OU using the New-ADOrganizationalUnit is quite straight forward:

1
New-ADOrganizationalUnit -Name Departments -Path "ou=Resources,DC=jaapbrasser,DC=com'

Using the [adsi] accelerator to create an OU requires some additional steps. First the parent object has to be selected, in this example the Resources OU in the jaapbrasser.com domain. The next step is create a new object, an organizationalunit in this case, finally the changes are committed to Active Directory by using the SetInfo() method.

1
2
3
$TargetOU = [adsi]'LDAP://ou=Resources,DC=jaapbrasser,DC=com'
$NewOU = $TargetOU.Create('organizationalUnit','ou=Departments')
$NewOU.SetInfo()

That is all there is to it, creating an Organizational Unit in Active Directory is quite easy, with or without the ActiveDirectory module.

Share

Update to my TechNet scripts

I upload some of my scripts into the TechNet Script Gallery and there are some lively discussions going on in the questions and answers sections of the scripts. I received feedback and based on that I have improved and updated some of my scripts.

The first script I would like to highlight is the Get-RemoteProgram script that has been built as a replacement for the Win32_Product WMI class. The Win32_Product class is useful but there are some downsides to this, have a look at this article for more information. This prompted me to write an alternative function for this purpose. This function generates a list by querying the registry and returning the installed programs of a local or remote computer. In the latest version of this script. There was an issue with some scenarios when running this script on a 32 bit machine which have been resolved in the latest version.

.EXAMPLE 
Get-RemoteProgram -ComputerName Server01 -Property DisplayVersion,VersionMajor 
 
Description: 
Will gather the list of programs from Server01 and attempts to retrieve the displayversion and versionmajor subkeys from the registry for each installed program 
 
.EXAMPLE 
'server01','server02' | Get-RemoteProgram -Property Uninstallstring 
 
Description 
Will retrieve the installed programs on server01/02 that are passed on to the function through the pipeline and also retrieves the uninstall string for each program

The second script that received an update is the Get-ScheduledTask the status of the tasks was listed in integers instead of ‘Running’,’Disabled’ or ‘Ready’. This has been updated and there were also scenarios in which the script would list the same task twice which has also been patched.

.EXAMPLE 
.\Get-ScheduledTask.ps1 -Computername mycomputer1

Description 
----------- 
This command query mycomputer1 and display a formatted list of all scheduled tasks on  that computer

Another script that I have updated is the Get-OrphanHomeFolder, this script takes a folder path as input and checks if the the folder has a corresponding samaccountname in Active Directory and if that is the case if the account is enabled or disabled. A request came in to also display the enabled users in order to get a full overview. Because of this I added the DisplayAll parameter to the script.

.PARAMETER DisplayAll 
This switch parameters will force the script to also display enabled active directory  accounts, can be used in combination with -FolderSize parameter. 

.EXAMPLE    
.\Get-OrphanHomeFolder.ps1 -HomeFolderPath \\Server01\Home -FolderSize -DisplayAll 
 
Description: 
Will list all the folders in the \\Server01\Home path. For each of these folders it    will query AD using the foldername, regardless of the AD results folder size will be returned 

The last script I updated is the Compare-ADuserAddGroupGUI this script compares the group membership between two users. The goal of this script is to grant the destination user all the missing memberships when compared to the source user. Any missing memberships will be added by this script and and any additional memberships will be removed. The ComputerName parameter has been added to this script in order to specify which domain controller will be queried for the comparison.

.EXAMPLE 
.\Compare-ADuserAddGroupGUI.ps1 testuserabc123 testuserabc456

Description 
----------- 
This command will add&remove from groups testuserabc456 to match groups that testuserabc123 is a member of the user is prompted by user interface to confirm these changes.

.EXAMPLE 
 .\Compare-ADuserAddGroupGUI.ps1

Description 
----------- 
Will use GUI to prompt for confirmation 

For a complete list of all my script feel free to browse to my submissions in the TechNet Script Gallery.

TechNet Script Gallery
My entries in TechNet Script Gallery
Get-RemoteProgram Get-ScheduledTask
Get-OrphanHomeFolder Compare-ADuserAddGroupGUI
Share

Active Directory Friday: Determine tombstone lifetime

In Active Directory objects are tomb stoned after a deletion occurs. This is allow replication to occur between domain controllers before an object is deleted from the Active Directory data store. The default value depends on the server when the forest was initially created, Microsoft recommends that this is set at 180 days.

The tombstone lifetime is set at the forest level and can be viewed by running the following code:

1
([adsi]"LDAP://CN=Directory Service,CN=Windows NT,CN=Services,$(([adsi](“LDAP://RootDSE”)).configurationNamingContext)").tombstoneLifetime

Alternatively this can also be retrieved by using the Get-ADObject cmdlet:

1
2
3
4
5
6
$HashSplat = @{
    Identity = 'CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=jaapbrasser,DC=com'
    Partition = 'CN=Configuration,DC=jaapbrasser,DC=com'
    Properties = 'tombstoneLifetime'
}
Get-ADObject @HashSplat | Select-Object -Property tombstoneLifetime
Share