Managing permissions on files and folders is essential to maintaining data security and access control in a Windows environment. With PowerShell, administrators have powerful tools to manage these permissions efficiently.
Two fundamental cmdlets for working with permissions are Get-ACL and Set-ACL. In this blog post, we’ll explore using these cmdlets to manage NTFS permissions using PowerShell effectively.
Note. The Get-ACL and Set-ACL cmdlets work with the FileSystem and Registry providers, but this article only focuses on the FileSystem examples.
Table of Contents
Understanding Access Control List (ACL) and Access Control Entry (ACE)
Access Control List (ACL)
An ACL, or Access Control List, is a data structure that defines the permissions and security settings associated with a particular object, such as a file, folder, or network resource. It contains a list of Access Control Entries (ACEs), each specifying the access permissions for a specific user, group, or security principal.
An ACL is a collection of rules that dictate who can perform what actions on the object. These actions include reading, writing, modifying, deleting, or executing the object. ACLs enforce security by ensuring that only authorized users or groups can access and manipulate resources.
Access Control Entry (ACE)
An ACE, or Access Control Entry, is a component of an ACL that defines the permissions granted or denied to a specific security principal (user, group, or other entity). An ACE contains the following elements:
- Security Principal: The user or group for whom the permissions are being defined. It can also represent specific types of users, such as anonymous users or built-in system accounts.
- Access Type: This specifies whether the ACE allows or denies the specified permissions. Access types can include “Allow” or “Deny.”
- Access Mask (Rights): The access mask is a set of flags that represent specific permissions or rights. It defines what actions the security principal is allowed or denied on the resource. Examples of access mask flags include read, write, execute, delete, modify, and more.
- Inheritance Flags: Inherited ACEs allow permissions to be propagated from a parent object to its child objects. Inheritance flags indicate whether the ACE should be inherited and how it should be inherited.
- Propagation Flags: These flags control the inheritance of ACEs and how child objects inherit them. They define whether ACEs should be inherited only by immediate children, all descendants, or no descendants.
When a user or group attempts to access a resource, the operating system checks the ACL associated with that resource to determine whether the requested action is allowed or denied based on the ACEs within the ACL.
Understanding Get-ACL and Set-ACL
Get-ACL
The Get-ACL cmdlet retrieves the ACL information for a specified file or folder object. The object can be at a local or network location. The ACL contains a list of ACEs that define the permissions and security principals associated with the object. To use Get-ACL, the syntax is as follows.
Get-ACL -Path C:\Path\To\FileOrFolder
For example, let’s get the ACL of a file and folder on the local machine.
# Folder ACL
$dir_acl = Get-Acl -Path C:\demo\dir1
$dir_acl | Get-Member -MemberType CodeProperty, Property
# File ACL
$file_acl = Get-Acl C:\demo\dir1\dummy_file.txt
$file_acl | Get-Member -MemberType CodeProperty, Property
The folder ACL and file ACL returns these two object classes, respectively.
- [System.Security.AccessControl.DirectorySecurity](https://learn.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.directorysecurity)
- [System.Security.AccessControl.FileSecurity](https://learn.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.filesecurity)
You’ll notice that both ACL objects have identical properties, indicating that they are only different in the item type (directory vs. file.)
Once you have retrieved the object’s ACL, you can view the properties by piping the object to the Format-List cmdlet.
$dir_acl | Format-list
$file_acl | Format-List
For comparison, the ACL object shown in PowerShell and File Explorer is below.
Note. The -536805376 access right is only shown when inheritance is enabled on a directory object.
The brief description of the output is as follows.
- Path = Path to the resource (Provider::Resource Path)
- Owner = Owner of the resource
- Group = Group of the owner
- Access = Access control entries
Set-ACL
The Set-ACL cmdlet allows you to modify permissions on files and folders. It allows adding, modifying, or removing ACEs from an object’s ACL. The basic syntax is:
Set-ACL -Path C:\Path\To\FileOrFolder -AclObject $aclObject
The $aclObject can be copied from another file or folder ACL or created from scratch. The succeeding sections will show more examples of setting ACLs on files and folders.
Managing Permissions with Get-ACL and Set-ACL
Modifying permissions on an object is a common task in file management. Combining Get-ACL and Set-ACL makes a perfect pair when modifying existing permissions.
Suppose you want to replace the owner of a directory and grant “Read” and “Write” permissions to a group.
- Directory object path: C:\demo\dir1
- New owner: THEITBROS\alpha
- Additional group: THEITBROS\CA IT Ops
Related post. iCACLS: List and Manage Folder and File Permissions on Windows.
Changing the Owner
Before modifying permissions, retrieving the current ACL using Get-ACL is a good practice.
$acl = Get-ACL -Path C:\demo\dir1
The current ACL is now stored in the $acl variable. Let’s manipulate this variable to set the new owner and add the access control entry for the group.
To set the owner, call the SetOwner() method.
# Specify the new owner
$newOwner = 'THEITBROS\alpha'
# Set the new owner
$newOwnerId = ([System.Security.Principal.NTAccount]::new($newOwner)).Translate([System.Security.Principal.SecurityIdentifier])
$acl.SetOwner($newOwnerId)
At this point, the Owner has been changed in the ACL object.
Hint. You can also change a file or folder ownership using the takeown.exe command.
Adding Access Control Entry
To add a Read and Write access to the group, we must create the [System.Security.AccessControl.FileSystemAccessRule](https://learn.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.filesystemaccessrule) object.
# specify the new group to add
$addtlGroupIdentity = 'THEITBROS\CA IT Ops'
# define the access rights
$addtlGroupAccessRights = 'Read,Write'
# define the access type "allow/deny"
$addtlGroupAccessType = 'Allow'
$newACE = ([System.Security.AccessControl.FileSystemAccessRule]::New($addtlGroupIdentity, $addtlGroupAccessRights, $addtlGroupAccessType))
Add the new ACE to the ACL object by calling the AddAccessRule() method.
# Set the new ACE
$acl.AddAccessRule($newACE)
# Display the updated ACE
$acl.Access | Format-Table
Finally, let’s modify the ACL of the directory with Set-ACL.
# Update the directory ACL
Set-Acl -Path C:\demo\dir1 -AclObject $acl
# Get the new directory ACL
Get-Acl -Path C:\demo\dir1 | Format-List
The directory ACL has been updated.
Removing Access Control Entry
Suppose the user or group is no longer eligible to access a folder, and you must remove its ACE from that directory’s ACL. Here’s how to do it.
Get the current ACL and list the ACEs.
$acl = Get-ACL -Path C:\demo\dir1
$acl.Access | Format-Table
Note the 0-index-based position of the ACE you want to remove. In this example, the ACE is at index 0.
To remove that access control entry, the command to run is:
# Remove the ACE at position 0
$acl.RemoveAccessRule($acl.Access[0])
# Update the ACL
$acl | Set-Acl -Path C:\demo\dir1
# Confirm the ACE has been removed from the ACL
As you can see, the ACE for ‘THEITBROS\CA IT Ops’ has been removed.
Turning-Off Inheritance Without Breaking Existing Access Rights
Turning off inheritance without breaking existing access rights involves removing inheritance from an object’s ACL while preserving the existing access rights. This can be useful when you want to establish custom permissions for an object without affecting the permissions inherited from its parent. Here’s how you can achieve this using PowerShell.
First, we retrieve the current ACL of the target object.
# Define the path to the file or folder
$objectPath = "C:\demo\dir1"
# Retrieve the current ACL
$acl = Get-ACL -Path $objectPath
# Show the current inheritance status
$acl.AreAccessRulesProtected
In this example, we can confirm that the inheritance is turned on.
To remove the inheritance, we’ll call the SetAccessRuleProtection(bool isProtected, bool preserveInheritance) method. This method requires two arguments:
- isProtected (Boolean) — Sets the inheritance on or off.
- preserveInheritance (Boolean) — Indicates whether existing ACEs will be retained or removed.
# Disable inheritance while preserving existing ACEs
$acl.SetAccessRuleProtection($true, $true) # Disable inheritance, keep existing ACEs
Finally, apply the modified ACL to the object.
# Apply the modified ACL to the object
Set-ACL -Path $objectPath -AclObject $acl
Copying Permissions to Another Object
You can use that object’s ACL as a template if you have a file or folder with the exact permissions needed, including ownership.
For example, to apply the same ACL from the folder C: to C:, here’s how to do it.
First, store the existing ACL from C:\demo\dir1 in a variable using Get-ACL. Then, run Set-ACL to apply the ACL object to the C:\demo\dir2 directory.
$acl = Get-Acl -Path C:\demo\dir1
Set-Acl -Path C:\demo\dir2 -AclObject $acl
Alternatively, you can pipe the Get-ACL result to Set-ACL since the -AclObject parameter accepts pipeline inputs.
Get-Acl -Path C:\demo\dir1 | Set-Acl -Path C:\demo\dir2
No output means the operation was successful.
Caution and Best Practices
When working with permissions, exercise caution to prevent unintentional security vulnerabilities. Here are some best practices:
- Test in a Safe Environment: Before making changes in a production environment, test your PowerShell scripts in a controlled and safe environment to ensure the desired results.
- Document Changes: Maintain clear documentation of the changes you make to permissions, including who made the changes and the reasons behind them.
- Backup: Before modifying permissions, create backups of the current ACL. Exporting the object’s ACL to an XML file is the most convenient way.
- Get-Acl -Path C:\Path\To\FileOrFolder | Export-CliXml -Path C:\Path\To\ACLBackup.xml
- Doing so ensures you can revert in case of unexpected issues.
- Least Privilege: Follow the principle of least privilege, granting only the necessary permissions to users and groups to minimize security risks.
Conclusion
PowerShell provides robust cmdlets like Get-ACL and Set-ACL that effectively empower administrators to manage NTFS permissions on files and folders. By understanding these cmdlets and following best practices, you can maintain a secure and organized environment while ensuring the right users have the appropriate access to your data.
ACLs and ACEs provide the foundation for controlling access to resources in a secure and controlled manner. They allow administrators to define fine-grained permissions for users and groups, ensuring that sensitive data remains protected and authorized users can perform their intended actions.
Remember always to exercise caution when working with permissions.