In this post, we will discuss about modifying folder NTFS permissions without GUI on a Windows platform. Modifying NTFS permissions for a small environment by manual GUI means is understandable, but it can get really hectic and time consuming for a large environment. Now lets have a look at the following Powershell Script that is a step in the direction of automating this task.
$CSVFile = "C:\log.csv" $machines = get-content "C:\servers.txt" foreach ($machine in $machines) { <# get all network path names of shared folders from another text file, then process through each path recursively sample path file: \\$machine\Users \\$machine\Departments Instead of inputting text file, we can also use: $paths = gi "H:\Users\*","H:\Departments\*" #> $paths = (get-content "C:\paths.txt").replace('$machine', $machine) foreach ($path in $paths) { <# -----part-1 (disable inheriance)----- To change access of an object on folder which has been inherited from parent folder, we need to disable the inheritance first. So, traverse one level down in each path, then check there only for folders, then disable inheritance at that level. #> get-childitem -Path $path\* | ? { $_.PsIsContainer } | % { <# We could have also used $acl = Get-Item $_ | get-acl But this would not work in cases where the account who is launching the script is not an owner of the folder whose permissions are being changed. So we need to tell powershell to only look for 'Access' by using a piped code structure. #> $acl = (Get-Item $_).GetAccessControl('Access') <# first arguement ($true) will disable inheritance and second arguement ($false) will remove all ACEs inherited from parent folder. #> $acl.SetAccessRuleProtection($true, $false) Set-Acl -path $path -aclObject $acl | Out-Null <# ----part-2 changing premissions of an account--- To avoid the problem of ownership, here also we first try to tell powershell that we are only interested in accesses of each acl and not anything extra, by using a loop structure. #> $acl2 = Get-Acl -path $path $accesses = $acl2.Access # get ace from each acl recursively foreach ($access in $accesses) { $ids = $access.IdentityReference.Value foreach ($id in $ids) { if ($id -eq "$machine\User") { <# when conditions true, remove all permissions for the mentioned account only #> $acl2.RemoveAccessRule($access) | Out-Null } } <# provide Read and Execute permission at parent or root folders level to the same account #> Set-Acl -path $path -aclObject $acl2 | Out-Null $permission = $name,'ReadandExecute','ContainerInherit,ObjectInherit','None','Allow' $aclrule = New-Object system.security.accesscontrol.filesystemaccessrule -ArgumentList $permission $acl.SetAccessRule($aclrule) Set-Acl -path $path -aclObject $acl2 | Out-Null $OutInfo = $machine+","+$path+","+$aclrule.IdentityReference+","+$aclrule.FileSystemRights Write-Host $OutInfo Add-Content -Value $OutInfo -Path $CSVFile } } }
Here Inheritance flag is set for both container and object whereas Propogation flag is none.
Following is a table which will help in setting propogation and inheritance flags.
╔═════════════╦═════════════╦═══════════════════════════════╦════════════════════════╦══════════════════╦═══════════════════════╦═════════════╦═════════════╗ ║ ║ folder only ║ folder, sub-folders and files ║ folder and sub-folders ║ folder and files ║ sub-folders and files ║ sub-folders ║ files ║ ╠═════════════╬═════════════╬═══════════════════════════════╬════════════════════════╬══════════════════╬═══════════════════════╬═════════════╬═════════════╣ ║ Propagation ║ none ║ none ║ none ║ none ║ InheritOnly ║ InheritOnly ║ InheritOnly ║ ║ Inheritance ║ none ║ Container|Object ║ Container ║ Object ║ Container|Object ║ Container ║ Object ║ ╚═════════════╩═════════════╩═══════════════════════════════╩════════════════════════╩══════════════════╩═══════════════════════╩═════════════╩═════════════╝
We can speed up things by employing psexec utility for above PowerShell script as discussed in my previous posts. For some reason get-acl and set-acl fail to function for folders on which the current user is not an owner of. Set-acl tries to change the owner of folder which is certainly not the intention in most cases.
For further reading, refer to this technet link: Windows PowerShell Tip of the Week where [System.Security.AccessControl.FileSystemRights] (a .NET Framework file system enumeration) and security descriptors are discussed in greater detail.
There is another approach to above scenario, which makes use of a powershell module “NTFSsecurity” File System Security PowerShell Module 4.2.3 by Raimund Andree. We can achieve the desired effect by proceeding as follows.
<#First we need to import the module "NTFSSecurity" If we want the module to be used by all users on the system, then it should be #placed under the path: C:\Program Files(x86)\WindowsPowerShell\Modules\NTFSSecurity #> Import-Module C:\Program Files (x86)\WindowsPowerShell\Modules\NTFSSecurity <#This will list out all the commands which are available in this module#> Get-Command -Module ntfssecurity <#This will disable inheritance at only one level below the root "test" folder. Remove the \* from path, if inheritance is to be disabled at all levels inside.#> get-item "\\server1\test\*" | Disable-NTFSAccessInheritance <#Now we first get the access of the account whose access we want to change, then we remove its access from the folder. Now we add the desired access of the same account to the folder.This is particularly useful when we want to remove the special permissions provided to any account, which may present a security risk.#> Get-Item -Path "\\server1\test" |Get-NTFSAccess -Account Users | Remove-NTFSAccess Add-NTFSAccess -Path "\\server1\test" -Account Users -AccessRights ReadAndExecute -AppliesTo ThisFolderAndSubfoldersOneLevel
Before proceeding with the solutions presented in this post, do take a full backup of ACls of the folder in question using icacls command. This technet blog How to Back Up and Restore NTFS and Share Permissions provides all the details required for performing a quick backup and restore of ACLs.
By wracking mind with these and many other solutions sometimes we feel like that sticking to basics does the job best. A simple command line approach is both faster and accurate in a mass folder structure. We can use icacls to do the same stuff what we discussed so far by putting far lesser effort. For this purpose I a sharing this link iCACLS.exe (2003 sp2, Vista+), which has got all the applications of this command covered.