In this post, I am going to share 3 scripts. One sets the owner for folders and files recursively and other two sets ntfs permissions for files and folders recursively. I believe it is crucial to understand what ACL related objects and flags are and what they mean when we are working with the ACL. So, you can easily modify the script according to your needs.
Before we can set an object’s ACL we need to build one. The easiest way to do that is to save the current ACL in a variable and then modify it.
$acl = Get-Acl .\Directory\
Another option would be to create a completely new, and empty, ACL object like this:
$acl = New-Object System.Security.AccessControl.DirectorySecurity
Inheritance Flag:
When creating access rules we will want to specify inheritance flags also. When doing so we have four options. You will most likely want to set both the ContainerInheritance and the ObjectInheritance flags. This indicates that we want our permission to be propagated to all child directories and files.
Inheritance Flag Meaning
ContainerInherit Propagate to child containers (directories).
None Do not propagate this permission to any child containers or objects.
ObjectInherit Propagate to child objects (files).
Propogation Flag:
We can also set Propagation Flags. The default Windows behavior is None. Setting this flag to InheritOnly will cause the access rule to only apply to child objects of the container.
Propagation Flag Meaning
InheritOnly Specifies that the ACE is propagated only to child objects. This includes both container and leaf child objects.
None Specifies that no inheritance flags are set.
NoPropagateInherit Specifies that the ACE is not propagated to child objects.
SetAccessRule() vs AddAccessRule()
The first method is SetAccessRule(). When using SetAccessRule() our new rule will overwrite any existing rule of the same type (Allow or Deny) for that security principal (user or group) regardless of the existing permissions. If a user has Modify permission and a new rule is created using SetAccessRule() specifying Read permission that user will now only have Read permission. This method essentially removes any existing access an replaces that access with the specified rule.
The second method is AddAccessRule(). This method will add this access rule to the ACL. Here if a user has Modify permission and we use AddAccessRule() to create a new rule with Read permission the user will still have Modify permissions. This can be dangerous from a security perspective if we think we intend to limit a user’s access, but mistakenly use the AddAccessRule() method.
Access Rule Applies To |
Inheritance Flags |
Propagation Flags |
Subfolders and Files only |
ContainerInherit,ObjectInherit |
InheritOnly |
This Folder, Subfolders and Files |
ContainerInherit,ObjectInherit |
None |
This Folder, Subfolders and Files |
ContainerInherit,ObjectInherit |
NoPropagateInherit |
This folder and Subfolders |
ContainerInherit |
None |
Subfolders only |
ContainerInherit |
InheritOnly |
This Folder and Files |
ObjectInherit |
None |
This Folder and Files |
ObjectInherit |
NoPropagateInherit |
This Folder only |
None |
None |
If you dont have read permission on the folders and files., you can not run the Powershell scripts to change their owner or ntfs permissions. However you can use psexec to run powershell or powershell ISE as SYSTEM. That way, even if you dont have read permission you can run your script as SYSTEM and modify owner or ntfs permissions.
You can download PSEXEC from the link below:
https://docs.microsoft.com/en-us/sysinternals/downloads/psexec
Extract psexec to C drive. Change directory to C and run the command below.
psexec.exe -i -s powershell_ise.exe
Script1: Changing The Owner Recursively For Files and Folders (make sure you change the user anything you want. For local admin group you should type “Administrators”).
#This part sets owner of parent folder
$acl = Get-Acl \\file-server\D$\YourSharedFolder
$owner = New-Object System.Security.Principal.NTAccount("Administrators")
$acl.SetOwner($owner)
Set-Acl \\file-server\D$\YourSharedFolder $acl
Write-Host "Owner Set -" $acl.Path
#This part sets owner of subfolders and files
Get-ChildItem -LiteralPath \\file-server\D$\YourSharedFolder -Force -Recurse -ErrorAction SilentlyContinue | Get-Acl |
ForEach-Object {
$_.SetOwner($owner)
Set-Acl -Path $_.PSPath $_
Write-Host "Owner Set -" $_.Path
}
Script2: Adding Users to NTFS permissions (You can use this if you are completely sure that inheritance is enabled on all folders and subfolders ). In the script I am using the first for loop to add multiple users. If you need to add only 1 user, just remove the for loop and type domain\username instead of ${user}.
#This Works but if inheritance enabled in all subfolders and files, but not applied on inheritance disabled folders
$users = 'Yourdomain\user1', 'Yourdomain\user2', 'Yourdomain\user3', 'Yourdomain\user4, 'Administrators'
foreach ($user in $users)
{
$acl = Get-Acl \\file-server\D$\YourSharedFolder
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule (${user}, 'FullControl', "ContainerInherit, ObjectInherit", "None", 'Allow')
$acl.SetAccessRule($rule)
Set-Acl \\file-server\D$\YourSharedFolder $acl
}
Script3: Adding Users to NTFS permissions even if Inheritance is disabled in some folders: I created this script for folders in which inheritance is disabled The main difference is if/else block. I had to use it because you can not apply inheritance or propogation flag on files. So I had to check if the object is a Directory or not. Based on the if/else statement returned value, I use different flags for $rule.
#This Works Perfect, even if Inheritance is disabled on Subfolders and files
$users = 'yourdomain\user1', 'yourdomain\user2', 'yourdomain\user3', 'yourdomain\user4', 'Administrators'
#This part sets ACL for top folder and the folders and files for which inheritance is Enabled
foreach ($user in $users)
{
$acl = Get-Acl \\file-server\YourFolder
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule (${user}, 'FullControl', 'ContainerInherit, ObjectInherit', 'None', 'Allow')
$acl.AddAccessRule($rule)
Set-Acl \\file-server\YourFolder $acl
}
#I run this part for the all child folders and files. Therefore inheritance disabled folders and files are included here
$folder = Get-ChildItem -Path \\file-server\YourFolder -recurse
foreach ($user in $users)
{
ForEach ($fl in $folder)
{
#echo $fl
#echo $fl.PSPath
if((Get-Item $fl.PSPath) -is [System.IO.DirectoryInfo])
{Write-Host $fl " is a Folder, ACL is set for: "$user
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule (${user}, 'FullControl', 'ContainerInherit, ObjectInherit', 'None', 'Allow')
$objACL = Get-ACL $fl.PSPath
$objACL.AddAccessRule($rule)
Set-ACL $fl.PSPath $objACL
}
else
{Write-Host $fl " is a File, ACL is set for: "$user
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule (${user}, 'FullControl', 'Allow')
$objACL = Get-ACL $fl.PSPath
$objACL.AddAccessRule($rule)
Set-ACL $fl.PSPath $objACL
}
}
}
Thanks for reading. I hope that you found this post helpful.