Active Directory is Microsoft’s LDAP (Local Directory Access Protocol) implementation. Active Directory provides user authentication and authorization services on a Microsoft Network, and is generally the hub security activities on a Windows network.

Retrieving Recursive Group Memberships with PowerShell

This is a problem that has plagued me for a long time. I’ve seen solutions implemented in VBScript, and I’ve seen PowerShell solutions that relied on third-party tools to get the job done.  Well I’ve finally implemented a solution to finding all of an account’s group memberships with PowerShell.

The following script provides a function I call Get-ADPrincipalGroupMembershipRecursive, which I named after the built-in function ADPrincipalGroupMembership.  The function is called by passing the distinguished name of the account.  It will determine all of the group’s memberships using the memberOf attribute, then recursively check those groups, their subgroups, etc. until a comprehensive list of the account’s memberships has been built.

<# .SYNOPSIS Gets all the Active Directory groups that have a specified user, computer, group, or service account. .DESCRIPTION Gets all the Active Directory groups that have a specified user, computer, group, or service account. Unlike the built-in Get-ADPrincipalGroupMembership cmtlet, the function I've provided below will perform a recursive search that will return all of the groups that the account is a member of through membership inheritance. This function required the Active Directory module and thus must be run on a domain controller or workstation with Remote Server Administration Tools. .PARAMETER dsn The distinguished name (dsn) of the user, computer, group, or service account. .PARAMETER groups An array of ADObject instances for each group in which the user, computer, group, or service account is a member. This parameter can be ignored and in fact should never be specified by the caller. The groups parameter is used internally to track groups that have already been added to the list during recursive function calls. .NOTES Author : Brian Reich <breich@reich-consulting.net .LINK http://www.reich-consulting.net #> function Get-ADPrincipalGroupMembershipRecursive( ) { Param( [string] $dsn, [array]$groups = @() ) # Get an ADObject for the account and retrieve memberOf attribute. $obj = Get-ADObject $dsn -Properties memberOf # Iterate through each of the groups in the memberOf attribute. foreach( $groupDsn in $obj.memberOf ) { # Get an ADObject for the current group. $tmpGrp = Get-ADObject $groupDsn -Properties memberOf # Check if the group is already in $groups. if( ($groups | where { $_.DistinguishedName -eq $groupDsn }).Count -eq 0 ) { $groups += $tmpGrp # Go a little deeper by searching this group for more groups. $groups = Get-ADPrincipalGroupMembershipRecursive $groupDsn $groups } } return $groups } # Simple Example of how to use the function $username = Read-Host -Prompt "Enter a username" $groups = Get-ADPrincipalGroupMembershipRecursive (Get-ADUser $username).DistinguishedName $groups | Sort-Object -Property name | Format-Table

The Following Domain Controller Could Not Be Contacted

Whiles studying for my Microsoft certification exams I ran into the following error.  When I used the Active Directory Users and Computers snap-in and attempted to connect to another domain controller I received the error “The following Domain Controller could not be contacted: server01.contoso.com. A local error has occurred.

The first step in my troubleshooting steps was to visit Event View and see if I could find any events related to the problem.  I noted several Security-Kerberos and Time-Service events around the time I experienced the error.

“The kerberos client received a KRB_AP_ERROR_TKT_NYV error from the server server01$. This indicates that the ticket used against that server is not yet valid (in relationship to that server time). Contact your system administrator to make sure the client and server times are in sync, and that the KDC in realm CONTOSO.COM is in sync with the KDC in the client realm.”

If your next step after reading that error is not to glance down at your system time, your troubleshooting skills leave much to be desired! Apparently when I setup my second server I couldn’t be bothered to change the time zone or the date. After updating the system date and time to the same time as my other domain controller, I was able to connect successfully.

Undeleting Deleted Items in Active Directory

Friday afternoon I received a call from a coworker who was getting an Access Denied error when she would try to print to a particular network printer.  Sure enough upon inspection of the printer’s ACL I found that one of our organization’s most important Security Groups had been deleted (how that happened is another story).

Because ACLs in AD environments are based on the SID, or Security Identifier, of an object rather than it’s name, you can’t just create a new object with the same name and expect things to work. They won’t. So how do you recover the original object?

Microsoft did not see fit to give Active Directory a Recycle Bin, but they did build in a feature called the Tombstone Lifetime. When an Active Directory object is deleted the object is actually moved to a hidden container called deleted objects and it stays there for the number of days specified by the tombstone lifetime.

Using the LDAP client built into Windows Server you can restore an object that is stuck in limbo between being deleted and wiped out permanantly when it’s tombstone lifetime expires. The video below illustrates how to do it far better than I ever could.

One final note: restoring a deleted object will not restore all of it’s properties. For example when restoring a Group object the group’s membership is lost. The important part is that the object is restored with the same SID, so after you manually restore it’s members existing Access Control Lists will function as expected.

[youtube_sc url=http://www.youtube.com/watch?v=0KffgbO6CTQ width=580 rel=0 fs=1]