This is pretty close to what you're looking for. Source for more details. Access Control Lists with Get-ACL
are not as easy to read as Effective Access on Advanced Security Settings and I don't think there is a way around that. I do think that, once used to it, Get-ACL
gives a lot more details when you know what you're looking for \ filter the ACLs to get what you're looking for.
Code
Function Get-EffectiveAccess {
[CmdletBinding()]
param(
[Parameter(
Mandatory,
ValueFromPipelineByPropertyName
)]
[ValidatePattern(
'(?:(CN=([^,]*)),)?(?:((?:(?:CN|OU)=[^,]+,?)+),)?((?:DC=[^,]+,?)+)$'
)][string]$DistinguishedName,
[switch]$IncludeOrphan
)
begin
{
# requires -Modules ActiveDirectory
$ErrorActionPreference = 'Stop'
$GUIDMap = @{}
$domain = Get-ADRootDSE
$z = '00000000-0000-0000-0000-000000000000'
$hash = @{
SearchBase = $domain.schemaNamingContext
LDAPFilter = '(schemaIDGUID=*)'
Properties = 'name','schemaIDGUID'
ErrorAction = 'SilentlyContinue'
}
$schemaIDs = Get-ADObject @hash
$hash = @{
SearchBase = "CN=Extended-Rights,$($domain.configurationNamingContext)"
LDAPFilter = '(objectClass=controlAccessRight)'
Properties = 'name','rightsGUID'
ErrorAction = 'SilentlyContinue'
}
$extendedRigths = Get-ADObject @hash
foreach($i in $schemaIDs)
{
if(-not $GUIDMap.ContainsKey([System.GUID]$i.schemaIDGUID))
{
$GUIDMap.add([System.GUID]$i.schemaIDGUID,$i.name)
}
}
foreach($i in $extendedRigths)
{
if(-not $GUIDMap.ContainsKey([System.GUID]$i.rightsGUID))
{
$GUIDMap.add([System.GUID]$i.rightsGUID,$i.name)
}
}
}
process
{
$result = [system.collections.generic.list[pscustomobject]]::new()
$object = Get-ADObject $DistinguishedName
$acls = (Get-ACL "AD:$object").Access
foreach($acl in $acls)
{
$objectType = if($acl.ObjectType -eq $z)
{
'All Objects (Full Control)'
}
else
{
$GUIDMap[$acl.ObjectType]
}
$inheritedObjType = if($acl.InheritedObjectType -eq $z)
{
'Applied to Any Inherited Object'
}
else
{
$GUIDMap[$acl.InheritedObjectType]
}
$result.Add(
[PSCustomObject]@{
Name = $object.Name
IdentityReference = $acl.IdentityReference
AccessControlType = $acl.AccessControlType
ActiveDirectoryRights = $acl.ActiveDirectoryRights
ObjectType = $objectType
InheritedObjectType = $inheritedObjType
InheritanceType = $acl.InheritanceType
IsInherited = $acl.IsInherited
})
}
if(-not $IncludeOrphan.IsPresent)
{
$result | Sort-Object IdentityReference |
Where-Object {$_.IdentityReference -notmatch 'S-1-*'}
return
}
return $result | Sort-Object IdentityReference
}
}
Usage
PS \> Get-ADOrganizationalUnit -Filter {Name -eq 'ExampleOU'} | Get-EffectiveAccess | Out-GridView
PS \> Get-EffectiveAccess -DistinguishedName 'OU=ExampleOU,DC=domainName,DC=com' | Out-GridView
PS \> $effectiveAccess = Get-ADGroup exampleGroup | Get-EffectiveAccess -IncludeOrphan
PS \> Get-ADOrganizationalUnit -Filter * | Select -First 10 | Get-EffectiveAccess | Out-GridView
By default, the function will filter all orphaned ACLs. Use the IncludeOrphan
switch to include all IdentityReference that begin with S-1-*
Edit
For reference, this is how Full Control looks like with Get-ACL
Compared with BUILTIN\Administrators which has write permissions on this OU but not Full Control
Get-Acl
should give you that information. Use the grouping operator (..) to expose that code property.(Get-ACL .\).Access
. Can you clarify what you mean by "effective permissions"? – Abraham ZinalaAll Objects (Full Control)
in the ACL you're showing means full control over theActiveDirectoryRights
, it is not the same as Effective Access on Advanced Security Settings. Compare the result of anIdentityReference
the you know has full control with the one you're showing, you'll see the difference. In addition, you're not showing if there is other ACL denyingFull Control
over thatIdentityReference
. As I said in my answer, you need to know how to read the output ofGet-ACL
. – Santiago Squarzon