Get-DsAcl

The goal of this PowerShell function is to create a report of permissions assigned to objects in Active Directory in much the same way as DsRevoke.

The names for extended rights and object types are read from the schema allowing the script to display friendly names.

Properties

Property Description
Name The name of the Object; by default this will be an OU, but I made this configurable (see examples).
DN The DN of the Object; equivalent to Object (DsRevoke)
ObjectClass Object class
SecurityPrincipal The User or Group (or Computer) the Access Control Entry is for; used as the search using DsRevoke
AccessType Allow or Deny; equivalent to ACE Type
Permissions Same as Permissions list in DsRevoke
AppliesTo What the ACE applies to; equivalent to “ACE inherited by all child objects” entry
AppliesToObjectType The object class the ACE applies to; equivalent to “ACE inherited by all child objects of Class …”
AppliesToProperty The specific property or Property Set an ACE applies to, or the Extended Right an ACE grants (if defined)
Inherited True if the Access Control Entry was inherited. Only applies with -Inherited switch.

Usage examples

Standard output (reporting on organizational units in the current domain):

Get-DsAcl

Format Table:

Get-DsAcl | Format-Table

Store in a variable:

ACLs = Get-DsAcl

Export to CSV:

Get-DsAcl | Export-CSV "Rights.csv"

Reporting on User objects:

Get-DsAcl -ObjectType "user"

Reporting on a sub-OU:

Get-DsAcl "OU=Test,DC=domain,DC=com"
# Or
Get-DsAcl -SearchRoot "OU=Test,DC=domain,DC=com"

Reporting on contacts in a sub-OU:

Get-DsAcl "OU=Test,DC=domain,DC=com" -ObjectType "contact"

Using a custom LDAP filter:

Get-DsAcl -LdapFilter "(objectClass=*)"

Including Inherited entries:

Get-DsAcl -LdapFilter "(name=Chris Dent)" -Inherited | Format-Table

Get-DsAcl

Function Get-DSACL {
  # Function to list permissions assigned to objects in Active Directory
  # This function reports on organizationalUnits within the domain by default.

  Param(
    $SearchRoot = ([ADSI]"LDAP://RootDSE").Get("defaultNamingContext"),
    $ObjectType = "organizationalUnit",
    $LdapFilter = "(&(objectClass=$ObjectType)(objectCategory=$ObjectType))",
    [Switch]$Inherited = $False
  )

  # Set the output field separator (default is " ")
  $OFS = "\"

  # Connect to RootDSE
  $RootDSE = [ADSI]"LDAP://RootDSE"
  # Connect to the Schema
  $Schema = [ADSI]"LDAP://$($RootDSE.Get('schemaNamingContext'))"
  # Connect to the Extended Rights container
  $Configuration = $RootDSE.Get("configurationNamingContext")
  $ExtendedRights = [ADSI]"LDAP://CN=Extended-Rights,$Configuration"

  # Find objects based on $SearchRoot and $ObjectType
  $Searcher = New-Object DirectoryServices.DirectorySearcher(`
    [ADSI]"LDAP://$SearchRoot", `
    $LdapFilter)

  $Searcher.FindAll() | %{
    $Object = $_.GetDirectoryEntry()

    # Retrieve all Access Control Entries from the AD Object
    $ACL = $Object.PsBase.ObjectSecurity.GetAccessRules(`
      $True, `
      $Inherited, `
      [Security.Principal.NTAccount])

    # Get interesting values
    $ACL | Select-Object @{n='Name';e={ $Object.Get("name") }}, `
      @{n='DN';e={ $Object.Get("distinguishedName") }}, `
      @{n='ObjectClass';e={ $Object.Class }}, `
      @{n='SecurityPrincipal';e={ $_.IdentityReference.ToString() }}, `
      @{n='AccessType';e={ $_.AccessControlType }}, `
      @{n='Permissions';e={ $_.ActiveDirectoryRights }}, `
      @{n='AppliesTo';e={
        #
        # Change the values for InheritanceType to friendly names
        #
        Switch ($_.InheritanceType) {
          "None"            { "This object only" }
          "Descendents"     { "All child objects" }
          "SelfAndChildren" { "This object and one level Of child objects" }
          "Children"        { "One level of child objects" }
          "All"             { "This object and all child objects" }
        } }}, `
      @{n='AppliesToObjectType';e={
        If ($_.InheritedObjectType.ToString() -NotMatch "0{8}.*") {
          #
          # Search for the Object Type in the Schema
          #
          $LdapFilter = `
            "(SchemaIDGUID=\$($_.InheritedObjectType.ToByteArray() | `
            %{ '{0:X2}' -f $_ }))"
          $Result = (New-Object DirectoryServices.DirectorySearcher(`
            $Schema, $LdapFilter)).FindOne()
          $Result.Properties["ldapdisplayname"]
        } Else { "All" } }}, `
      @{n='AppliesToProperty';e={
        If ($_.ObjectType.ToString() -NotMatch "0{8}.*") {
          #
          # Search for a possible Extended-Right or Property Set
          #
          $LdapFilter = "(rightsGuid=$($_.ObjectType.ToString()))"
          $Result = (New-Object DirectoryServices.DirectorySearcher(`
            $ExtendedRights, $LdapFilter)).FindOne()
          If ($Result) {
            $Result.Properties["displayname"]
          } Else {
            #
            # Search for the attribute name in the Schema
            #
            $LdapFilter = "(SchemaIDGUID=\$($_.ObjectType.ToByteArray() | `
              %{ '{0:X2}' -f $_ }))"
            $Result = (New-Object DirectoryServices.DirectorySearcher(`
              $Schema, $LdapFilter)).FindOne()
            $Result.Properties["ldapdisplayname"]
          }
        } Else { "All" } }}, `
      @{n='Inherited';e={ $_.IsInherited }}
  }
}

Related posts:

  1. Changing the Primary Group with PowerShell Exactly as the title says, an example of how to...
  2. Accept or reject messages from This function reads delivery restrictions from objects in Active Directory....
  3. Building LDAP filters for date based attributes Active Directory contains a number of attributes which hold date...

Related posts brought to you by Yet Another Related Posts Plugin.

Respond to this post