PowerShell – Editing permissions on a file or folder


I got the following question from a reader the other day:

I’ve been trying to figure out how to change permissions on a folder in PowerShell. I’ve looked at the Get-Acl and Set-Acl, but I can only use them to copy the settings from a pre-existing object. How do I manually configure permissions?

This is actually a quite common question, so I thought I’d write a quick post on the subject.

Get-Acl and Set-Acl

To quote the PowerShell documentation "Get-Acl gets the security descriptor for a resource, such as a file or registry key." while "Set-Acl changes the security descriptor of a specified resource, such as a file or a registry key." In other words; if you want Folder_A to have the exact same permissions as Folder_B, then you simply copy the Access Control List (ACL) of Folder_B and "paste" it onto Folder_A.

$Acl = Get-Acl "C:\Folder_B"
Set-Acl "C:\Folder_A" $Acl

So far, so good.

Changing the ACL

Okay, so you want to change the ACL. Here’s some sample code for how to do that:

New-Item -type directory -path C:\MyFolder
$Acl = Get-Acl "C:\MyFolder"
$Ar = New-Object  system.security.accesscontrol.filesystemaccessrule("username","FullControl","Allow")
$Acl.SetAccessRule($Ar)
Set-Acl "C:\MyFolder" $Acl

So, first we create a new folder. We then copy the ACL of that folder. We then create a new AccessRule that gives "username" full control. We then add this AccessRule to the ACL, and finally we reapply the new, altered ACL to the folder.

If we wanted to we could also have used $Acl.RemoveAccessRule($Ar) or possibly $Acl.RemoveAccessRuleAll() as well.

/ Johan

Comments (21)

  1. Ronto says:

    Say… I get the following error when I try your first example to copy folder permissions:

    Set-Acl : The security identifier is not allowed to be the owner of this object

    Any ideas why?

  2. JohanSt says:

    Good question.

    You’re obviously getting this error because you’re trying to change the owner of the object. By default NTFS will only allow you to set the owner of an object to:

    A: Yourself

    B: Administrators-group

    That’s it.

    However, if you’re an administrator or backup operator you can set it to any user, BUT this privilige is disabled by default and must be enabled before you can do so. In case you’re wondering – this is a concious security restriction.

    There are no .NET or PowerShell specific ways of enabling this, but if we leave Microsoft-territory and visit the PowerShell Community Extensions project we find a way…

    I havent used PSCX that much and it’s not a Microsoft product so any questions on them should be directed to http://www.codeplex.com/PowerShellCX rather than here, but here goes:

    Download and install PSCX from http://www.codeplex.com/PowerShellCX

    Set up a wrapper class for TokenPriviliege using the following syntax:

    $oTP = New-Object PSCX.Interop.TokenPriviliege

    Now, grant it to the current process:

    Set-Privilege $oTP

    You should now be able to change the owner of the folder to any user you wish.

    Have fun! / Johan

  3. Tony says:

    I would like to create a powershell script that would scour an OU for any users that are missing a home folder, create the folder on a NAS, apply the appropriate permissions and then set their AD profile to use this new location. Here is what i have so far, any assistance would be very helpfull:

    Get-QADUser -SizeLimit 0 -searchroot ‘ou=***,ou=***,dc=***,dc=***,dc=***’ | `

    where{$_.homedirectory -eq $null} | `

    foreach {

    $NasPath = ‘\NAS’+$_.LogonName

    New-Item -type directory -Path $NasPath

    $Acl = Get-Acl $NasPath

    $Ar = New-Object system.security.accesscontrol.filesystemaccessrule($_.LogonName,"FullControl","Allow")

    $Acl.RemoveAccessRule($Ar)

    Set-Acl $NasPath $Acl

    Set-QADUser $_ -ObjectAttributes @{‘HomeDirectory’= $NasPath; ‘HomeDrive’=’Y’}

    }

    Thanks,

    Tony

  4. ewookie says:

    When trying the sample code, I get the following error message after the last line:

    Set-Acl : The process does not possess the ‘SeSecurityPrivilege’ privilege whic

    h is required for this operation.

    I’m running the script under an account that has full control over the directory where I’m trying to create the new directory…

  5. JohanSt says:

    Are you running the script in Vista with UAC turned on?

    Try running PowerShell with elevated privileges. (Run as administrator)

    / Johan

  6. Nisha says:

    Hi Johan,

    I too got the same error of

    Set-Acl : The security identifier is not allowed to be the owner of this object

    As per your comment above, I tried installing the PSCX from codeplex. I also installed it as a PS Plug-in. When I try,

    $oTP = New-Object PSCX.Interop.TokenPriviliege

    I get the following error:

    New-Object : Cannot find type [PSCX.Interop.TokenPriviliege]: make sure the assembly containing this type is loaded.

    I am running Powershell v 1.0

    Am I missing anything here?

    Thanks,

    Nisha

  7. Dave says:

    I can get most of this to work, except the permissions will not apply.  The user shows up in the ACL of the directory, but no permissions are applied.

  8. Matt says:

    I have this working with the exception of folders that have "[" and "]" in the path.

    Any suggestions?

  9. Cole Cather says:

    Matt can you share your code example.  I too am having issues and would like to see what you are doing.

    Thanks

  10. Brian says:

    Is it possible to do something like:

    $Acl = Get-Acl "D:folder"

    Set-Acl "d:folder_list.txt" $Acl

    I would like to apply the folder permissions to the same folder on a list of servers.

    Thanks!

  11. Dan Stalker says:

    I have a powershell script that I run after I open powershell with "run as administrator" privileges so I truly have administrator rights on the system, using the powershell community extensions:

    add-pssnapin pscx

    $SeRestore = new-object Pscx.Interop.TokenPrivilege "SeRestorePrivilege", $true

    $SeSecurity = new-object Pscx.Interop.TokenPrivilege "SeSecurityPrivilege", $true

    Set-Privilege $SeRestore

    Set-Privilege $SeSecurity

    WIth these privileges you can change security or ownership on any files nad folders

  12. Iain McMullen says:

    This thread is really useful, Thanks so much.

    I am also getting "the security identifier is not allowed to be the owner of this object."

    Now that it is 2013, has anything changed to enable this? Or is it possible to leave the Owner as is and just change the group permissions?

  13. Tobias G says:

    I am having the same problems. I would like to use the PSCX but becaue of our securtiy rules i cannot use "third party" products?

    Any ideas how to fix the issue.

  14. Ben says:

    I have the same issue as Dave. I want to give "Network Service" full access to a directory. I followed the steps as outlined here and I see "Network Service" in the list of users but none of the permissions are applied. This is what I did.. please let me know if you see what is wrong:

    $Acl = Get-Acl $TSPath

    $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Network Service", "FullControl", "Allow")

    $Acl.SetAccessRule($AccessRule)

    Set-Acl $TSPath $Acl

    I also noticed if I added the rule via the GUI and then queried using Get-Acl the user name was "NT AUTHORITYNETWORK SERVICE". However running the same script with that user name has the same result.

  15. AndiMyers says:

    Thanks for this.. been a great help.

    I am now wanting to copy inherited permissions from Parent, Disable Inherit, remove all groups/users with Read Only Permission and add the user.

    I have got all this apart from the removing of Read Only Groups/Users.

    Can you help.. Here is what I have currently:-

    $l_Hdrive = "serverfolder"

    $l_User = "doaminuseraccount"

    $acl = Get-Acl "$l_Hdrive"

    $acl.SetAccessRuleProtection($true, $true)

    $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("$l_User", "Modify", "ContainerInherit,ObjectInherit", "None", "Allow")

    Set-Acl "$l_Hdrive" $Acl

  16. TonyAndersson says:

    I have a question, im trying to set the acl on multiple subolders based on a template

    catalog i made with all the right settings i want for the users.

    then make all subfolder of a specific share get the same ACL.

    the reason i want to do it that way is i manage 9 server shares with about 7000 subfolders

    $acltemplate = Get-Acl  "\servertemplate"

    $rootfolder = Get-ChildItem -Path \serverusershare

    foreach ($userfolder in $rootfolder) { $userfolder.FullName Set-Acl $userfolder.FullName $acltemplate }

  17. nicoh says:

    Nice reading. Here is an article on how to set acl on remote folder (unc path) using powershell : http://www.shellandco.net/set-folders-acl-owner-and-ntfs-rights

  18. Ben says:

    A year later I happen to be having the same issue and I found this thread where I posted a question that was never answered. So after a little more research I found the solution (I had to call the overload that accepts the inheritance and propagation flags):

    $TSPath = "C:tempa"

    $Acl = Get-Acl $TSPath

    $networkService = New-Object System.Security.Principal.SecurityIdentifier([System.Security.Principal.WellKnownSidType]::NetworkServiceSid, $null);

    $rights = [System.Security.AccessControl.FileSystemRights]::FullControl

    $inheritance = [int]([System.Security.AccessControl.InheritanceFlags]::ContainerInherit) + [int]([System.Security.AccessControl.InheritanceFlags]::ObjectInherit)

    $propagation = [System.Security.AccessControl.PropagationFlags]::None

    $accessControl = [System.Security.AccessControl.AccessControlType]::Allow

    $AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($networkService, $rights, $inheritance, $propagation , $accessControl)

    $Acl.SetAccessRule($AccessRule)

    Set-Acl $TSPath $Acl

  19. Senthil says:

    Is it possible to disable delete permission with modify enabled through powershell.

    Rgds

    Senthil.A