1
votes

I apologize in advance of the long post. I have spent a significant amount of time trying to find an answer or piece together a solution to this problem.

It's a simple request: Add a user/group with 2 sets of permissions to your entire DFS environment applying one set to folders and sub-folders and the other to files only.

Seems easy enough, however in the environment I'm trying to manage we have 1000's of folder paths greater than 260 characters deep and any use of dir -recurse or get-childitem will result in hitting the error "pathtoolong". Every example solution for this problem has used a variation of the above or relies on "get-childitem". This fails for most real world situations as I believe many of us IT admins are faced with long paths due to the nature of DFS use.

The current attempt: Currently I'm using a custom module "NTFSSecurity" which is fantastic to apply NTFS permissions. It works great! It can be found here: https://ntfssecurity.codeplex.com/

A tutorial from here: https://blogs.technet.microsoft.com/fieldcoding/2014/12/05/ntfssecurity-tutorial-1-getting-adding-and-removing-permissions/

The problem found in the above tutorial and every other example I've been able to find, it references commands such as:

dir -Recurse | Get-NTFSAccess -Account $account 

This will fail in the real world of super long file paths.

The "PathTooLong" error workaround:

My workaround current consists of using Robocopy to export the file paths to a text file. I found this as a recommendation from someone dealing with a similar problem. Robocopy will not error on "pathtoolong" issues and is perfect for this exercise. I then try and run commands against the text file containing all of the paths I need to modify.

The command for the Robocopy is this:

robocopy '<insert source path here>' NULL /NJH /E /COPYALL /XF *.* | Out-File -FilePath '<path to fileout.txt>'

This will create a text file while copying only folder structure and permissions. Excellent!

You will then have to clean up the text file from additional characters which I use:

$filepath = '<path>\DFS_Folder_Structure.txt'
$structure = Get-Content $filepath
$structure -replace '     New Dir          0    '| Out-File -FilePath \\<path_you_want_file>\DFS_Folder_Structure2.txt

I also reversed the contents of the text file so it shows the furthest child object (folder) and work down. I thought this might be easier for identifying a parent folder or some other recursive logic which I haven't been able to figure out.

To reverse text from bottom to top use this command here:

$x = Get-Content -Path 'C:\temp_dfs\DFS_Folder_Structure2.txt'; Set-Content -Path 'C:\temp_dfs\Reversed_data.txt' -Value ($x[($x.Length-1)..0])

This script currently only applies to paths with Inheritance off or for childobjects with Inheritance off. This is taken from the NTFSSecurity module command Get-NTFSInheritance which will return results for AccessInheritance and AuditInheritance.Access is if the folder is inheriting from a parent above. Audit is if the folder is passing it down to child objects. There are 4 possibilities:

AccessInheritance True AuditInheritance True

AccessInheritance True AuditInheritance False

AccessInheritance False AuditInheritance True

AccessInheritance False AuditInheritance False

(*Special note: I have seen all 4 show up in the DFS structure I'm dealing with.)

Script to Set Permissions based on file path contained in text file:

#Get File content to evaluate
$path = Get-Content 'C:\temp_dfs\Reversed_data.txt'
$ADaccount = '<insert fully qualified domain\user or group etc.>'

Foreach ($line in $path)
    {
        #Get-NTFSAccess -Path $line -Account $ADaccount | Remove-NTFSAccess
        #This command will find the access of an account and then remove it.
        #It has been omitted but included in case needed later.

    $result = Get-NTFSInheritance -Path $line

    If ($result.AccessInheritanceEnabled -Match "False" -and $result.AuditInheritanceEnabled -match "False") 
    {
        Add-NTFSAccess -Path $line -Account $ADaccount -AccessRights Traverse,ExecuteFile,ListDirectory,ReadData,ReadAttributes,ReadExtendedAttributes,ReadPermissions -AppliesTo ThisFolderAndSubfolders
        Add-NTFSAccess -Path $line -Account $ADaccount -AccessRights ReadAttributes,ReadExtendedAttributes,ReadPermissions -AppliesTo FilesOnly
    }

    If ($result.AccessInheritanceEnabled -Match "False" -and $result.AuditInheritanceEnabled -Match "True")
    {
        Add-NTFSAccess -Path $line -Account $ADaccount -AccessRights Traverse,ExecuteFile,ListDirectory,ReadData,ReadAttributes,ReadExtendedAttributes,ReadPermissions -AppliesTo ThisFolderAndSubfolders
        Add-NTFSAccess -Path $line -Account $ADaccount -AccessRights ReadAttributes,ReadExtendedAttributes,ReadPermissions -AppliesTo FilesOnly 
    }

    If ($result.AccessInheritanceEnabled -Match "True" -and $result.AuditInheritanceEnabled -Match "False")
    {
    continue
    }

    If ($result.AccessInheritanceEnabled -Match "True" -and $result.AuditInheritanceEnabled -Match "True")
    {
    continue 
    }

}

This script will apply permissions for the specified User/Group account and set permissions for Folder and Sub-folders and then add another set of permissions to Files only.

Now this current fix works great except it only touches folders with Inheritance turned off. This means you'd need to run this script and then set permissions on the "main parent folder". This is completely do-able and may be the best method to avoid double entries of permissions and is the current state of my solution.

If you add criteria to the bottom sections where AccessInheritanceEnable = True and Audit = True you will get double entries because you're applying permissions to both the parent --> which pushes its permissions to the child-objects and also explicitly on the child-objects themselves. This is due to the text file contains both parent and child and I haven't figure out a way to address that. This isn't "horrible" but my OCD doesn't like to have double permissions added if it can be avoided.

The real question: What I'd really like to do is somehow identify parent folders, compare them to parents further up the tree and see if it was inheriting permissions and only apply the permission set to the highest parent in a specific chain. My mind wants to explode thinking about how you would compare parents and find the "highest parent".

Again the problem being anytime you want to -recurse the folder structure it will fail due to "pathtoolong" issues so it needs to be contained to logic applied to the text file paths. I've seen a bit mentioned about split-path but I don't really understand how that's applied or how you could compare a path to another path until you identified a parent path.

Thank-you for taking the time to read this long post and question. If you're still awake now, I'm open to any suggestions. lol.

1

1 Answers

0
votes

the NTFSSecurity module is indeed fantastic. I used it to make a script that can export ntfs security of a UNC path and it's subfolders to a readable excel file.

It can be found on: https://github.com/tgoetheyn/Export-NtfsSecurity

I use is frequently and didn't had any problem with long filenames. Hope you like it.

PS: If you add ntfssecurity, don't forget to include the "Synchronize" permission. If not included, strange things can happen.