Identifying NTFS Folder Permission Differences

Welcome Forums General PowerShell Q&A Identifying NTFS Folder Permission Differences

This topic contains 7 replies, has 5 voices, and was last updated by

 
Participant
3 years, 5 months ago.

  • Author
    Posts
  • #27314

    Participant
    Points: 0
    Rank: Member

    I've taken on the task of doing folder/file cleanup on our NAS and I've run into a scenario where I'm definitely thinking that Powershell can really help. To note, my PS experience is limited at best. I'm familair with some of the AD/Office 365 cmdlets from my daily tasks but do not have a ton of experience when creating advanced scripts.

    I have a parent folder on our NAS with a large amount of access entries on it. This parent folder has hundreds of subfolders. I'm doing some organization of the access entries, but over the years, inheritance has been broken on several subfolders and ACLs have been changed. I'd like to develop a script (or be pointed towards a good resource) that I can recursively run against my parent folder and get a list of subfolders where the ACL is different than that of the parent folder.

    I'm thinking that I can leverage both the Get-ChildItem and Get-Acl cmdlets to accomplish what I want but I'm having some difficulty in bringing it all together.

    I appreciate any advice that you can share with me or resources that you can point me to.

    Thank you!

  • #27315

    Keymaster
    Points: 1,704
    Helping HandTeam Member
    Rank: Community Hero

    Get-ACL will get you a permission object; I'd get it from the parent and store it in a variable.

    From there, Get-ChildItem can get you the child folders, which can be piped to Get-ACL to get their permission object. I'd probably do that in a loop.

    $parent_acl = get-cal c:\parent
    foreach ($folder in (get-childitem c:\parent -directory -recurse)) {
      $folder_acl = get-acl $folder
      compare-object $parent_acl $folder_acl
    }
    

    That – or something similar – will give you a difference object for each child whose ACL is different from the parent's.

    But... Get-ACL only shows direct ACEs, not inherited ones. So a child folder with no ACEs will show as "different" from the parent, because it's inheriting from the parent, which is in fact what you wanted. So in that case, "different" is good, not bad.

    It might be worth thinking carefully about what, exactly, you want to look at and mitigate, before you go down the path of a lot of coding.

  • #27329

    Participant
    Points: 0
    Rank: Member

    Hey Don ....Nice logic and code. Awesome...
    Just wanted to understand David's requirement here..
    Do you want the script to ask for a path of folder and should match the ACL with its parent folder ?

  • #27346

    Participant
    Points: 0
    Rank: Member

    Thank you, Don. Really like how this came together.

    Deepak...it doesn't necessarily need to prompt for a folder path. I can supply the top level parent directory. I'm just looking for it to recursively move through all of the subfolders and determine the difference between each one of them against what the ACLs on the top level parent folder are.

  • #27366

    Participant
    Points: 0
    Rank: Member

    What about something like this?

    Get-ChildItem C:\folder -Recurse | ForEach-Object {
        try { # Get-Acl throws terminating errors, so wrap it in a try/catch block
            $_ | Get-Acl | 
                where { $_.AreAccessRulesProtected -or ($_.Access | where { $_.IsInherited -eq $false }) } |
                foreach { Convert-Path $_.Path }
        }
        catch {
            Write-Error $_
        }
    }
    

    That should return the path to any files/folders (depends on how you call Get-ChildItem) where DACL inheritance is disabled or a single non-inherited ACE is present. It would be a much prettier command if Get-Acl handled errors properly and you didn't have to put it in that ForEach-Object block...

    With a little tweaking, you could get it to show you the differences instead of just giving you the paths.

  • #27449

    Participant
    Points: 0
    Rank: Member

    Just created below one. The script might not be clean :(..The number of lines in code can be reduced. But I just started with PS.

    The script will check if inheritance is broken in any directories and list the ACL of current and its parent. I am not sure if it helps you.

    I am looking for the suggestions from experienced guys to get this cleaned ...Thanks..

    # Give the path of directory below
    $DirDetails = Get-ChildItem -path C:\Work\Test -Recurse -Attributes Directory
    
    ForEach ($Dir in $DirDetails) {
    $DirFullName = $Dir.FullName
    $DirName = $Dir.Name
    $Acl = Get-Acl $DirFullName
    $AclAccess = $Acl.Access
    $InheritedList = $AclAccess.Isinherited
    [int]$BadFolderCount = "0"
    foreach ($ISInherit in $InheritedList) {
    If ($ISInherit -like "False") {
    $BadFolderCount++
    }
    }
    If ($BadFolderCount -gt "0") {
    Write-Host "Directory Name                      :$DirFullName" -ForegroundColor Red
    Write-Host "Count of Not Inherited ACLs         :$BadFolderCount" -ForegroundColor Red
    Write-Host ""
    Write-Host "ACL of Current Directory            :"
    (Get-Acl $DirFullName).Access | select FileSystemRights , IdentityReference | fl
    Write-Host "ACL of Parent Directory             :"
    (Get-Acl ($DirFullName.TrimEnd($DirName))).Access | select FileSystemRights , IdentityReference | fl
    }
    Else {
    Write-Host "Directory Name                      :$DirFullName" -ForegroundColor Green
    Write-Host "Count of Not Inherited ACLs         :$BadFolderCount" -ForegroundColor Green
    }
    Write-Host ""
    }
    
    
  • #27450

    Participant
    Points: 0
    Rank: Member

    By the way Rohn Edwards , wonderful code.
    PS code should be like this. Short and powerful 🙂

  • #27454

    Participant
    Points: 311
    Helping Hand
    Rank: Contributor

    Try this:

    $DirDetails = Get-ChildItem -path C:\Temp\* -Recurse -Attributes Directory
    
    $Acls = ForEach ($Dir in $DirDetails) {
        Get-Acl $Dir.FullName |
            Select Owner,
                   AccessToString,
                   @{Name="Non-Inherited Perms";Expression={($_.Access | Where{$_.IsInherited -eq $false}) | foreach{"{0}: {1}" -f $_.IdentityReference, $_.FileSystemRights}}},
                   @{Name="Non-Inherited Count";Expression={($_.Access | Where{$_.IsInherited -eq $false}).Count}},
                   @{Name="DirFullName";Expression={$Dir.FullName}},
                   @{Name="DirName";Expression={$Dir.Name}}
    }
    
    $Acls
    

    Your script is using Write-Host, which isn't a good practice to begin with. The Power of Powershell comes from working with objects. In your script, you're just writing information to the prompt, which tells you what is wrong but you have to dig thru output to understand how many directories have non-inherited permissions. If I use the script I posted, I just have to do a simple query to see what folder are not set the way I want:

    $Acls | Where{$_."Non-Inherited Count" -gt 0}
    

    Additionally, if I want to fix them, it's a simple as:

    $Acls | Where{$_."Non-Inherited Count" -gt 0} | foreach{
        Set-ACL $_.DirFullName ...
    }
    

    So, I highly recommend trying to keep your data in an object versus writing it in colors to the screen.

The topic ‘Identifying NTFS Folder Permission Differences’ is closed to new replies.