NTFS folder permissions with PowerShell

***Before we start, I should say that these steps were made on a Windows Server 2008 R2 machine running PowerShell 2.0. I understand there are different switches available to other OSs and PowerShell versions. Changing permissions on the home folders of multiple users is a potential CIM (Career Influencing Move!) and you should only undertake it if you understand fully the steps involved and implications of the change. Testing might be a good idea too.***

You may find yourself in a situation, after a migration of Operating System or filestore, where only the users themselves have ownership and access to their home drives. This makes backups impossible (without taking ownership) and makes the role of support personell difficult if a user wants you to look at some files in their home drive for problem resolution.

The steps included in this article are:

1. Take ownership of the folder.
2. Re-permission the folder so Domain Admins have access.
3. Return permissions to the user.

To save an avalanche of clicks I thought it would be best to script the required steps.

First off you need to make an array of the user folders affected. Get-ADUser or Get-QADUser could do the trick, but would return service accounts and admin accounts that don’t have a Home Drive set. In addition to this, my testing on a reasonably typical home drive (just over 3000 files and 1.2Gb in size) took about 5 minutes to re-permission. If you have 5000 users you might want to set a weekend aside to go through it all! So in this example I will iterate through the folders in the root share. For granularity it might be better to choose a departmental group (you could do $Group = Get-QADGroup “Finance Department” and then iterate through $Group.members).

So to set the array and start to iterate through:

$Folders = \\server\share\
$Folder = Get-ChildItem $Folders
FOREACH ($User in $Folder) {

Next we need to take ownership of the folder. It’s best to do this within the foreach loop and not at the root, as taking ownership will remove the user’s access to the folder (at least it did in my situation, where the user’s ownership of the folder was the only privilege, when I changed the ownership to the admin user the user was stripped of all rights). If you change ownership folder by folder you can have 1 annoyed user at a time, instead of hundreds all at once! Fortunately taking ownership is very simple:

TAKEOWN /F $Folders$User /R /D Y

Next we need to re-permission the folder, you can change permissions in PowerShell with Get-ACL and some logic, but ICACLS (which is built into Windows) will do the job in fewer lines, I always prefer a more direct route to a solution. The ICACLS TechNet page at http://technet.microsoft.com/en-us/library/cc753525.aspx is very similar to the output provided by ICACLS /? and is heavy on information on the available switches, but light on the examples. I found with extensive testing that running

ICACLS '\\server\share\user' /grant '"$Username":(OI)(CI)F' /T

Doesn’t translate well if you try to script it and substitute a variable into the path or user fields. The frustrating error that was repeatedly returned is

No mapping between account names and security IDs was done.

The way to get around this issue is to encase the username you are passing in quotations, then use a “+” to attach to the rest of the string, then wrap the whole lot in brackets, as below:

$FullPath = "$Folder" + "$Username"
ICACLS ("$FullPath") /grant ("$Username" + ':(OI)(CI)F') /T

Then remember to set the owner to Domain Admins:

ICACLS ("$FullPath") /setowner "Domain Admins" /c /t

If you are running Server 2003 SP2 you may need to install a hotfix in order to run setowner as you can get an Access Denied error. See http://support.microsoft.com/kb/947870

Also, depending on your directory structure the user’s folder may be named a variety of ways (ideally consistently!). I have structured the script so that you can replace tha SAMAccountName below with DisplayName or NTAccountName as necessary.

Finally, I have used the Quest AD Management SnapIn for the Get-QADUser to work.

Add-PSSnapin Quest.ActiveRoles.ADManagement
$Folders = "\\server\share\"
$Folder = Get-ChildItem $Folders
FOREACH ($User in $Folder) {
    TAKEOWN /F $Folders$User /R /D Y
    $Username = Get-QADuser $User
    $Username = $Username.SamAccountName
    $FullPath = "$Folders" + "$Username"
    ICACLS ("$FullPath") /grant '"Domain Admins":(OI)(CI)F' /T
    ICACLS ("$FullPath") /grant ("$Username" + ':(OI)(CI)F') /T
    ICACLS ("$FullPath") /setowner "Domain Admins" /c /t
}

nb. setowner may fail if you are running Windows Server 2003. See hotfix here.

Posted in Guides Tagged with: , ,
5 comments on “NTFS folder permissions with PowerShell
  1. Andrew says:

    Can’t you just do this:
    ICACLS $FullPath /grant $Username’:(OI)(CI)(F)’ /T

  2. tomanderson says:

    I couldn’t get it going, spent a very long time fiddling with it.

    If it worked for you I would be keen to know which OS you used.

    Cheers,

    Tom

  3. Joris says:

    Thanks very much for explaining how to use ICACLS in PowerShell.

  4. knych says:

    Hi, Im trying to generate the ACL for multiple path in one report.
    a. an excel or text file contains multiple path
    b. with inputbox- the user would enter the full unc path of the file(excel/ text)
    c. powershell will use: get-content to read and store the contents of the file
    d. then will ask where to save the report
    e. powershell will run the get-acl

    My code looks like this:

    [void][System.Reflection.Assembly]::LoadWithPartialName(‘Microsoft.VisualBasic’)

    $path= [Microsoft.VisualBasic.Interaction]::InputBox(‘Enter the full path of CSV file to be uploaded’)
    $a = Get-Content $path

    $fname= [Microsoft.VisualBasic.Interaction]::InputBox(‘Enter file name of the result’)

    foreach ($folder in $a)
    {
    $acl = get-acl $folder |Format-List
    }

    *******************************
    The thing is I get error message:

    PS C:\> P:\Powershell\Get ACLmulitiple test1.ps1
    get-acl : Attempted to perform an unauthorized operation.
    At P:\Powershell\Get ACLmulitiple test1.ps1:10 char:8
    + $acl = get-acl $folder |Format-List
    + ~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Get-Acl], UnauthorizedAccessException
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetAclCommand

    get-acl : Attempted to perform an unauthorized operation.
    At P:\Powershell\Get ACLmulitiple test1.ps1:10 char:8
    + $acl = get-acl $folder |Format-List
    + ~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Get-Acl], UnauthorizedAccessException
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetAclCommand

    get-acl : Attempted to perform an unauthorized operation.
    At P:\Powershell\Get ACLmulitiple test1.ps1:10 char:8
    + $acl = get-acl $folder |Format-List
    + ~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Get-Acl], UnauthorizedAccessException
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetAclCommand

    • tomanderson says:

      Apologies for the late response.

      Is this related to the original post? It looks like you haven’t defined $folder so the Get-ACL is failing.

      You also need to be running PoSh 3.0 or above to use Get-ACL.

      Thanks,

      Tom

Leave a Reply

Your email address will not be published. Required fields are marked *

*