Nathan
Nathan

Reputation: 345

Get names of folders not inheriting permissions

I'm trying to find all folders which do not inherit permissions.

This seems to work, sorta:

DIR "C:\temp" -directory -recurse | GET-ACL | select -ExpandProperty Access | ? -property IsInherited -eq $false

...but it leaves out the actual folder name.

How do I include folder names in the final output? It gets a little tricky for me because I need to filter on a property on an object (Access) within an object (whatever GET-ACL returns).

Any ideas?

Upvotes: 8

Views: 42825

Answers (6)

Daniel
Daniel

Reputation: 1481

I know this is an old question but I was looking for a short and simple solution, so thought I'd post my answer too.

As pointed out by Luca the accepted answer shows all rules which are not inherited, including rules which have been set on directories which actually have inheritance enabled.

The solution which worked for me is the following:

Get-ChildItem C:\PathHere -Directory -Recurse | Get-Acl | where { $_.AreAccessRulesProtected }

This will return output from the Get-Acl command, but if you would prefer output from Get-ChildItem it can be written as follows:

Get-ChildItem C:\PathHere -Directory -Recurse | where { (Get-Acl $_.FullName).AreAccessRulesProtected }

You can also remove -Recurse if you just want top level folders, or replace it with -Depth 2 or -Depth 3 etc. if you only want to check the first few levels.

Upvotes: 0

Nathan
Nathan

Reputation: 345

Scratch that, I'm an idiot.

DIR "C:\temp" -directory -recurse | GET-ACL | where {$_.Access.IsInherited -eq $false}

Upvotes: 13

lightwing
lightwing

Reputation: 162

All answers still seem like a workaround to me. I found this solution to actually answer the question asked (folders only):

$folders = gci -recurse C:\My\Path\Here
foreach ($path in $folders)
{
  if ($path.PSIsContainer -eq $false)
  {
    continue
  }
  if ((get-acl $path.fullname).AreAccessRulesProtected -eq $true)
  {
    $path.fullname
  }
}

For the .AreAccessRulesProtected property of the returned get-acl object:

True = inheritance has been disabled

False = inheritance is still enabled

Source for .AreAccessRulesProtected property: https://petri.com/identify-folders-with-blocked-inheritance-using-powershell

I also confirmed with my own testing that this is the correct property for folder inheritance.

Upvotes: 4

kkuderko
kkuderko

Reputation: 1

Luca's answer gave me false positives for folders with [ in their names. Not sure why.

Adapted Rohn's script to print how many acls are actually not inherited from the parent. If folder has some out of all - it means the inheritance is enabled but some permissions are added manually, if all out of all - it means the inheritance is disabled.

Write-Output "`nNoninheritable permissions:`n"
dir "E:\Projects" -Directory -Recurse | ForEach-Object {
    $Path = $_.FullName
    try {
        $TotalACLs = (Get-Acl $Path | select -ExpandProperty Access).Count
        $InheritedCount = (Get-Acl $Path | select -ExpandProperty Access | where { $_.IsInherited -eq $false } | Add-Member -MemberType NoteProperty -Name Path -Value $Path -PassThru | Select Path).Count
        if ($InheritedCount) {
            Write-Output $InheritedCount" out of "$TotalACLs" in "$Path
        }
    }
    catch {
        Write-Error $_
    }
}

The example result:

Noninheritable permissions:

2 out of 7 in E:\Projects\Active Project

2 out of 8 in E:\Projects\Active Projects\Claire\7. CHRISTMAS\

4 out of 4 in E:\Projects\Active Projects\Closed Projects\Andrea\IT\14.07 Kath - CIMS

Upvotes: 0

Luca Clavarino
Luca Clavarino

Reputation: 434

I think other answers don't really match your request: the commands suggested give you all non-inherited access rule, but also an inheriting folder may have such rules.

I was looking for a better way to achieve your same goal, but at the moment this is the only way I've found:

Get-ChildItem C:\temp -recurse | Select @{Name='Path';Expression={$_.FullName}},@{Name='InheritedCount';Expression={(Get-Acl $_.FullName | Select -ExpandProperty Access | Where { $_.IsInherited }).Count}} | Where { $_.InheritedCount -eq 0 } | Select Path

The concept is: if a folder has at least 1 inherited access rule, then inheritance is enabled, if it has 0 inherited rules, inheritance is disabled.

Upvotes: 3

Rohn Edwards
Rohn Edwards

Reputation: 2659

You can use Add-Member to add the path as a property on each ACE object:

dir c:\temp -Directory -Recurse | ForEach-Object {
    $Path = $_.FullName
    try {
        Get-Acl $Path | 
            select -ExpandProperty Access | 
            where { $_.IsInherited -eq $false } | 
            Add-Member -MemberType NoteProperty -Name Path -Value $Path -PassThru
    }
    catch {
        Write-Error $_
    }
}

I also wrapped Get-Acl in a try block because it throws terminating errors.

Upvotes: 1

Related Questions