get NTFS permissions and group Identities with same Permissions

This topic contains 19 replies, has 3 voices, and was last updated by Profile photo of Rohn Edwards Rohn Edwards 10 months, 2 weeks ago.

  • Author
    Posts
  • #34185
    Profile photo of H Man
    H Man
    Participant

    Hello

    So i am auditing ntfs permissions, and I would like to group all the identities that have the same permissions and create a ps object out of it . so for example if "Domain Admins" "Office managers" "JSmith" All have Read/write id like to have them all in the read/write property, read only ... etc

    The properties would be

    Path , Read/write , Read
    \\server\folder1 , "Domain Admins" "Office managers" "JSmith" ; "jdoe"
    heres i swhat I have so far

    $targetServer    = '\\Server01'    #Enter hostname
    $targetDirectory = 'Departments' #Enter directory name
    $target          = Join-Path -ChildPath $targetDirectory -Path $targetServer
    $arrResults      = @() #Initialize array used to store custom object output
    $exportPath      = 'C:\temp\ntfsCheck.csv' #Enter name of the CSV output file
     
    #Query target directory for all 'folders' (excludes files via Where statement)
    Get-ChildItem -Recurse -Path $target | Where { $_.PSIsContainer } |
    forEach {
        $objPath = $_.FullName
        $coLACL  = Get-Acl -Path $objPath
        forEach ( $objACL in $colACL ) {
            forEach ( $accessRight in $objACL.Access ) {
                $objResults = New-Object –TypeName PSObject
                $objResults | Add-Member –MemberType NoteProperty –Name DirectoryPath      –Value $objPath
                $objResults | Add-Member –MemberType NoteProperty –Name Identity           –Value $accessRight.IdentityReference
                $objResults | Add-Member –MemberType NoteProperty –Name SystemRights       –Value $accessRight.FileSystemRights
                $objResults | Add-Member –MemberType NoteProperty –Name SystemRightsType   –Value $accessRight.AccessControlType
                $objResults | Add-Member -MemberType NoteProperty -Name IsInherited        -Value $accessRight.IsInherited
                $objResults | Add-Member -MemberType NoteProperty -Name InheritanceFlags   -Value $accessRight.InheritanceFlags
                $objResults | Add-Member –MemberType NoteProperty –Name RulesProtected     –Value $objACL.AreAccessRulesProtected
                $arrResults += $objResults
            }
        }
    }
    

    Thanks!!

  • #34188
    Profile photo of Bob McCoy
    Bob McCoy
    Participant

    What version of PowerShell are you running?

  • #34193
    Profile photo of H Man
    H Man
    Participant

    Hello Bob

    I am running version 4.0

  • #34194
    Profile photo of Bob McCoy
    Bob McCoy
    Participant

    Please take another look at what you want for output.

    \\server\folder1 , "Domain Admins" "Office managers" "JSmith" ; "jdoe"
    

    This is a little confusing.

    • You have two different delimiters comma and semi-colon. Is that for a reason?
    • Are we to assume that if you have multiple identities (for instance in your Read/Write column) that you want them altogether in the field, separated by spaces?
  • #34196
    Profile photo of Bob McCoy
    Bob McCoy
    Participant

    In the meantime, here is a rework of your code above. It is more efficient to create an object and add all the data at once via a hash. And concatenating to an array is the least efficient thing you can do in PowerShell.

    #requires -version 3
    #https://powershell.org/forums/topic/get-ntfs-permissions-and-group-identities-with-same-permissions/
    
    $targetServer    = '\\myserver'    #Enter hostname
    $targetDirectory = 'myshare'       #Enter share name
    $target          = Join-Path -ChildPath $targetDirectory -Path $targetServer
    $exportPath      = 'C:\ephemeral\ntfsCheck.csv' #Enter name of the CSV output file
     
    #Query target directory for all 'folders' (excludes files via Where statement)
    $results = Get-ChildItem -Recurse -Path $target -Directory | forEach {
        $objPath = $_.FullName
        $coLACL  = Get-Acl -Path $objPath
        forEach ( $objACL in $colACL ) {
            forEach ( $accessRight in $objACL.Access ) {
                [PSCustomObject]@{
                    DirectoryPath = $objPath
                    Identity = $accessRight.IdentityReference
                    SystemRights = $accessRight.FileSystemRights
                    SystemRightsType = $accessRight.AccessControlType
                    IsInherited = $accessRight.IsInherited
                    InheritanceFlags = $accessRight.InheritanceFlags
                    RulesProtected = $objACL.AreAccessRulesProtected
                }
            }
        }
    }
    $results
    
  • #34198
    Profile photo of H Man
    H Man
    Participant

    Hello Bob

    Thank you for getting back , the ; delimiter is an error it should be a comma.

    Yes i want all the identities altogether in the field, separated by spaces

    Here is an example of the final output

    Path Read Write Deny
    DNS01\ Everyone "Administrators, Users"
    DNS02\Backup "Administrators, Contoso\sales, Users" "Administrators, Users"

  • #34200
    Profile photo of Bob McCoy
    Bob McCoy
    Participant

    I'm sorry, but this example makes even less sense. You seem to be missing the path. And SystemRights returns a much different list of rights.

  • #34201
    Profile photo of H Man
    H Man
    Participant

    ok no problem lets disregard the example can we just group them and delimit with a comma?

  • #34202
    Profile photo of Bob McCoy
    Bob McCoy
    Participant

    No. Not until you're very clear on what you want them grouped by. In your latest example you're looking at read and write. However, that's not what is returned from SystemRights. For instance, how do you want to handle Modify, Full Control, Synchronize, ReadAndExecute, etc.?

  • #34205
    Profile photo of H Man
    H Man
    Participant

    Ok i want them grouped by if they have the same permissions they are all part of that group They just have to all Have the identical perms for the folder they are on

  • #34206
    Profile photo of Rohn Edwards
    Rohn Edwards
    Participant

    If I understand you correctly (and let me know if I'm not), you're looking for something like this:

    $targetServer    = '\\Server01'    #Enter hostname
    $targetDirectory = 'Departments' #Enter directory name
    $target          = Join-Path -ChildPath $targetDirectory -Path $targetServer
    $exportPath      = 'D:\temp\ntfsCheck.csv' #Enter name of the CSV output file
    
    
    # Need to keep track of all unique Type/Rights combinations so we can
    # build CSV headers later
    $AllPropertyNames = New-Object System.Collections.Generic.List[string]
    $AllPropertyNames += 'Path' # We know we'll want this in our header
    
    $CollectedData = dir -Path $target -Recurse -Directory | ForEach-Object {
    
        $DACL = $_ | Get-Acl | select -ExpandProperty Access
    
        $ObjectProperties = @{
            Path = $_.FullName
        }
        $DACL | Group AccessControlType, FileSystemRights | ForEach-Object {
            $PropertyName = $_.Name -replace ',\s'  # Get rid of commas and spaces
    
            # Remember to keep track of all property names we've seen
            if (-not $AllPropertyNames.Contains($PropertyName)) {
                $AllPropertyNames += $PropertyName
            }
    
            $ObjectProperties[$PropertyName] = ($_.Group | ForEach-Object {
                $Suffix = if ($_.InheritanceFlags -ne 3 -or $_.PropagationFlags -ne 0) {
                    " (Special)"
                }
                else { "" }
    
                '{0}{1}' -f $_.IdentityReference, $Suffix
             }) -join "`n"
        }
        [PSCustomObject] $ObjectProperties
    
    }
    
    $CollectedData | select $AllPropertyNames | Export-Csv $exportPath -NoTypeInformation
    

    The most imporant part is collecting all of the different headers you need while you're collecting info from each folder, then using that list when exporting your CSV. This causes all of your results to be stored in memory, though, which means it's possible to exhaust all of your memory. If you have enough folders to cause that to happen, then there are some things you might try so that you aren't storing everything in memory (temporarily writing the data to XML might help).

    One thing you didn't mention, but I figured you might find important, is checking the inheritance and propagation flags (the part of the ACE that specifies if it applies to the Folder, Subfolders, and Files). I set this up to add '(Special)' after any principal that has an ACE that doesn't apply to all three of those.

    You can also tweak this to exclude inherited rights (or to even include that info in the CSV header).

    Give it a shot and let me know if you have any questions about it...

  • #34209
    Profile photo of H Man
    H Man
    Participant

    Great! I am going to try it now

  • #34210
    Profile photo of H Man
    H Man
    Participant

    Exactly!! I am going to show my team your code and will let you know but it looks great! Thank you

  • #34211
    Profile photo of H Man
    H Man
    Participant

    How would tweak it to Include inherited rights in the csv header ?

  • #34214
    Profile photo of Rohn Edwards
    Rohn Edwards
    Participant

    I can think of at least three ways to handle inherited rights:

    1. Just get rid of any rights that are inherited. That would give you a CSV that just contains explicit rights.

    2. Add another suffix to the principal, like the '(Special)' one when an ACE is inherited.

    3. Include inheritance status in the headers like you asked. To do that, you could just change the 'group-object' call from

    Group AccessControlType, FileSystemRights
    

    to this

    Group { "{0}{1}{2}" -f $_.AccessControlType, $_.FileSystemRights, "$(if (-not $_.IsInherited) { 'Not'})Inherited" }
    

    You can change the format up if you don't like the order I've put it in...

  • #34218
    Profile photo of H Man
    H Man
    Participant

    awesome thx I learned alot off of this thread

  • #34219
    Profile photo of H Man
    H Man
    Participant

    One other ? We have decided we want to export in tab delimmited and with

    Multiple groups we want to enclose in parenthesis and separated by a comma+space

    e.g. "SomeGroup, Contonso\domain admins" what do you think?

  • #34220
    Profile photo of Rohn Edwards
    Rohn Edwards
    Participant

    Both of those should be simple tweaks.

    To change the principal separator, change where it says -join "`n" to -join ', '

    To change the delimiter in the CSV, add -Delimiter "`t" to Export-CSV.

  • #34221
    Profile photo of H Man
    H Man
    Participant

    cool thx sooo much

  • #34222
    Profile photo of Rohn Edwards
    Rohn Edwards
    Participant

    You're welcome

You must be logged in to reply to this topic.