Tag Archives: LDAP query

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

Active Directory Friday: Search for computers accounts

I have decided to reintroduce Active Directory Friday on my blog, so today is the start of the new series of articles on Friday. The format remains the same as the previous posts. Usually the examples will be written by using .Net objects or the [adsi] and [adsisearcher] accelerators, although occasionally examples using the Active Directory cmdlets will be posted. My preference for avoiding the cmdlets is mostly compatibility, usually there is only a select number of systems that has access to the Active Directory module, so it pays off to know the native method as well.

Today we will take a look at how to find computer objects in Active Directory using the DirectoryServices.DirectorySearcher object. In order to search for computer objects the following properties of this object will be set:

  • Filter – This contains the LDAP filter used to select only the computer objects by specifying the objectcategory
  • PageSize – This allows for paging to occur, by specifying the pagesize more than 1000 results can be returned
1
2
3
4
5
$Searcher = New-Object DirectoryServices.DirectorySearcher -Property @{
    Filter = '(objectCategory=computer)'
    PageSize = 500
}
$Searcher.FindAll()

To search in a specific organizational unit the SearchRoot property can be used, only computer objects in the Servers OU will be returned by this search:

1
2
3
4
5
6
7
$Searcher = New-Object DirectoryServices.DirectorySearcher -Property @{
    Filter = '(objectCategory=computer)'
    PageSize = 500
    SearchRoot = 'LDAP://OU=Servers,DC=jaapbrasser,DC=com'
    SearchScope = 'Subtree'
}
$Searcher.FindAll()

The SearchScope property has been set to Subtree, which means that the OU will be recursively searched through and all child-ous will be included in the search. There are a total of three options available for the SearchRoot property:

  • Base – Only returns a single objects
  • OneLevel – Only searches the current container, will not recursively search
  • Subtree – Searches recursively through all child containers
Share

Active Directory Friday: List password information for Domain Administrators

In today’s Active Directory Friday we touch the subject of security of Domain Administrator accounts. Although this should not be overlooked it is not uncommon for passwords to be unchanged for a long period of time.

To find the members of the Domain Admins group we can use following LDAP Filter:

1
"(memberof=CN=Domain Admins,CN=Users,DC=jaapbrasser,DC=com)"

Then for each account found a PowerShell Custom Object is created with the following three properties:

  • Samaccountname
  • PasswordAge
  • Account Enabled

So combing all these statements the complete code is as follows:

1
2
3
4
5
6
7
8
9
10
11
$Searcher = New-Object DirectoryServices.DirectorySearcher -Property @{
    Filter = "(memberof=CN=Domain Admins,CN=Users,DC=jaapbrasser,DC=com)"
    PageSize = 500
}
$Searcher.FindAll() | ForEach-Object {
    New-Object -TypeName PSCustomObject -Property @{
        samaccountname = $_.Properties.samaccountname -join ''
        pwdlastset = [datetime]::FromFileTime([int64]($_.Properties.pwdlastset -join ''))
        enabled = -not [boolean]([int64]($_.properties.useraccountcontrol -join '') -band 2)
    }
}
Share

Active Directory Friday: Get DistinguishedName of current domain

To determine the DistinguishedName of the current domain the [adsi] accelerator can be utilized. The following piece of code can be used to retrieve the DN of the current domain:

1
2
New-Object -TypeName System.DirectoryServices.DirectoryEntry |
Select -ExpandProperty distinguishedName

Alternatively the [adsi] accelerator can be utilized for this purpose, as this requires less code and it is easier to remember:

1
([adsi]'').distinguishedName

The value returned by this line of code a System.DirectoryServices.PropertyValueCollection instead of a string object. To unwrap this code can be used:

1
([adsi]'').distinguishedName[0]

Now the object returned is a string and the methods and properties of a string object are available, so it is possible to manipulate the output for example by doing a text replace:

1
([adsi]'').distinguishedName[0].replace('com','jaap')

Note that in PowerShell v3 and up it is not required to unwrap the array, as the Member Enumeration feature of PowerShell will ensure that the methods and properties of underlying objects in an array are available. As demonstrated in the following line of code:

1
([adsi]'').distinguishedName.replace('com','jaap')
Share

Active Directory Friday: Query Group Policy Objects in Active Directory

For the second Active Directory Friday we have Group Policies on our radar. To query for Group Policy objects the following LDAP filter can be used:

1
'(objectClass=groupPolicyContainer)'

To get the full list of Group Policy objects the adsisearcher accelerator should be used in combination with the LDAP filter. This will return all group policy objects:

1
([adsisearcher]'(objectClass=groupPolicyContainer)').FindAll()

To generate a short report with relevant information about the following code can be used:

1
2
3
4
5
6
7
8
9
10
11
12
$GPOSearcher = New-Object DirectoryServices.DirectorySearcher -Property @{
    Filter = '(objectClass=groupPolicyContainer)'
    PageSize = 100
}
$GPOSearcher.FindAll() | ForEach-Object {
    New-Object -TypeName PSCustomObject -Property @{
        'DisplayName' = $_.properties.displayname -join ''
        'CommonName' = $_.properties.cn -join ''
        'FilePath' = $_.properties.gpcfilesyspath -join ''
        'DistinguishedName' = $_.properties.distinguishedname -join ''
    } | Select-Object -Property DisplayName,CommonName,FilePath,DistinguishedName
}

This will display a list of all Group Policy Objects and display the following properties:

  • DisplayName
  • CommonName
  • FilePath
  • DistinguishedName

The full script is also available in the TechNet Script Gallery: http://gallery.technet.microsoft.com/Get-GroupPolicyObject-05aaef2d

Share

Active Directory Friday: Find user accounts that have not changed password in 90 days

Today I am starting a new section my blog. Each friday I will post an example of a task I have performed in Active Directory using PowerShell. For this I will usually not use any of the Active Directory Cmdlets, so there is no dependancy on any modules to be present on a system in order to execute these queries. If you have any suggestions for a task or query that could be discussed, please drop me a line in the comments and I will consider it for next week. Today I will start with a query that gathers the samaccountname, pwdlastset and if an account is currently enabled or disabled. Note that the commands in this article only query Active Directory so no changes to objects will be made. First we will create a variable, $PwdDate, that contains the filetime of a date ninety days ago:

1
$PwdDate = (Get-Date).AddDays(-90).ToFileTime()

Then an DirectoryServices.DirectorySearcher object will be created with the LDAP Query to locate only user accounts that have their passwords last set on a date 90 or more days ago:

1
2
3
4
$Searcher = New-Object DirectoryServices.DirectorySearcher -Property @{
    Filter = "(&(objectclass=user)(objectcategory=person)(pwdlastset<=$PwdDate))"
    PageSize = 500
}

ForEach user account found we output its samaccountname, pwdlastset and enabled or disabled state of the account:

1
2
3
4
5
6
7
$Searcher.FindAll() | ForEach-Object {
    New-Object -TypeName PSCustomObject -Property @{
        samaccountname = $_.Properties.samaccountname -join ''
        pwdlastset = [datetime]::FromFileTime([int64]($_.Properties.pwdlastset -join ''))
        enabled = -not [boolean]([int64]($_.properties.useraccountcontrol -join '') -band 2)
    }
}

Note that the -join ” operator this is used to unwrap the properties, which are by default provided as System.DirectoryServices.ResultPropertyValueCollection objects. Alternatively the array indexing notation [0] could be used, this has the downside that when a property is empty it will cause the script to display errors. The full code used in this example is available here in the TechNet Script Repository: http://gallery.technet.microsoft.com/scriptcenter/Query-for-AD-Users-that-b87acf2f

Share

AD queries and the Active Directory Recycle Bin

Lately I have been playing around with the AD Recycle Bin on Windows Server 2012. It is a  useful feature that was introduced in Server 2008 R2 and has been improved in Server 2012. New features include:

  • AD Object restore from GUI
  • Password restore
  • Restore of a entire OU
To enable this feature using PowerShell the following line of code should be executed:
Enable-ADOptionalFeature -Identity 'Recycle Bin Feature' `
-Scope 'ForestOrConfigurationSet' -Target 'dmn.com' -Confirm:$false

Note that this feature can never be disabled after it has been enabled. To test its functionality we will create a user:

New-ADUser -SamAccountName Jaap -Name Jaap -Enabled:$true `
-AccountPassword (ConvertTo-SecureString -AsPlainText '$ecret01' -Force)
This command creates a new account named Jaap with $ecret01 as the password. To be able to set a password this string is first converted into a SecureString. To verify that this account was created we can query it using Get-ADobject:
Get-ADobject -Filter 'samaccountname -eq "jaap"'
An alternative, and my personal preference is to utilize [adsisearcher] to query for AD object. It has the advantage that it is available natively in PowerShell, in any version. Here is the syntax to query for the account that was just created:
([adsisearcher]'(samaccountname=jaap)').findone()
We have now established that the account can be found and, so let’s remove the account so it moves to the Active Directory Recycle Bin:
Remove-ADUser jaap
So now we can try the same query again:
Get-ADobject -Filter 'samaccountname -eq "jaap"'
([adsisearcher]'(samaccountname=jaap)').findone()
Get-ADobject will return an error and [adsisearcher] will not return any results. This is because the user account is Tombstoned and placed in the Deleted objects container. To get the desired results, the -IncludeDeletedObjects switch should be used:
Get-ADobject -Filter 'samaccountname -eq "jaap"' -IncludeDeletedObjects
For [adsisearcher] a slightly different approach should be used, the following query will retrieve the deleted user account:
$Searcher = [adsisearcher]'(samaccountname=jaap)'
$Searcher.Tombstone = $true
$Searcher.FindOne()

And that how to query accounts have been deleted and stored in the AD Recycle Bin.

Share