Link to home
Start Free TrialLog in
Avatar of MarkJenks
MarkJenksFlag for United States of America

asked on

Setting permissions on a entire folder tree w/ exceptions.

I don't have time to try and figure this out and want to learn powershell, but haven't had the chance yet.

I need to change the permissions on an entire folder structure, but it has a special need.

Folder starts at D:\HRDept

I need to reset all permissions, inherit for HRDept-Users Modify and HRDept-Payroll-Usersl list folders.  This is to remove old user permissions that should no longer be there.

But there are folders inside of D:\HRDept that are called "Payroll", where HR-Dept-Payroll needs Modify access.  So, when it comes across those folders, it needs to turn off inherit, copy the rules, and add a single new rule.

Added  bonus is to be able to run it on a individual folder for the GUI when they create a new user account.
                                                                       
Thanks in advance!
Avatar of egrylls
egrylls

I would use RichCopy.  Copy the Payroll folder with perms to perhaps the root of the drive.  Make sure the permissions copied over acurately.

Then, reset the permissions at the root level of the folder as you described and tell it to reset permissions on all of the child objects right through explorer.  Once the permissions reset is complete, use RichCopy to copy the folder with the permissions back into place and add your permissions to the destination folder.
Avatar of MarkJenks

ASKER

Maybe I didn't explain it well enough.

D:\HRDept\Employeename\
And then folders inside of them for Payroll, Documents, etc, etc.

So, there are 1000's of folders, one for each Employee, and inside of those are the Payroll folders.
Avatar of Chris Dent

Copy the ACL from where? The parent? Or a generic ACL you've set up?

Chris
Basicly I want to reset the permissions for the entire tree to HRDept-Users Modify and HRDept-Payroll-Usersl list folders.   Turning on inherit for the entire tree.

Then I need something to go through the structure (recursive) and if the name of the folder is "Payroll", I need to turn off inherit and add the HRDept-Payroll-Users for Modify on all files in those folders.
ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I'm missing a closing quote in this section:

# Create the new access rule - notes below.
  $AccessRule = New-Object `
    Security.AccessControl.FileSystemAccessRule(`
      "YourDomain\HRDept-Payroll-Users", `
      @("Modify", "Synchronize"), `
      @("ObjectInherit", "ContainerInherit"), `
      "None",
      "Allow")

Sorry about that.

Chris
Wow, pretty much exactly what I was looking for with a good description to what it is doing.   I didn't even know about the -Filter option.  Takes me one step further into understanding it and writing my own.

"Note, this snippet does not removed access control entries. Do you need to to remove the access control entries defined on the folder so only inherited access applies?"

The ACL's that have been applied to here are pretty hosed up after years of changes and them not using groups, but adding users all over the place.   I would like to RESET the entire tree and start over.

I know I can do the reset from the GUI, but it's nice to understand how to do it from PS also.

This code above will do wonders for me and anyone that needs to do what I am doing.  

I'll have to wait until the morning to give it a try, but it looks like you got it.

A little modification to flush out existing rules, this is done in the first piece, at the same time as inheritance is enabled down the tree.

At the moment this part is limited to Folders because of the Where-Object filtering applied at the beginning. If you want it to apply to files as well as folders simply remove Where-Object (?{ $_.PsIsContainer }).

Chris
# Get all items beneath D:\HRDept. Apply a filter with 
# Where-Object (?) to return folders only
Get-ChildItem "D:\HRDept" -Recurse | ?{ $_.PsIsContainer } | %{

  # Get the access control list for this folder
  $ACL = Get-ACL $_.FullName

  # If the folder does not inherit
  If ($ACL.AreAccessRulesProtected -eq $True)
  {
    # Turn off AccessRuleProtection, or enable Inheritance.
    $ACL.SetAccessRuleProtection($False, $False)
  }

  # Find Access Control Entries which are applied explicitly
  $ACL.Access | ?{ $_.IsInherited -eq $False } | %{
    # Remove the rule from $ACL
    $ACL.RemoveAccessRule($_)
  }

  # Apply the modified ACL
  Set-ACL $_.FullName -AclObject $ACL
}

Open in new window


Hmm I just had a thought.

MoW wrote a simple function a long time ago that'll let you export the permissions assigned to an entire directory structure to a CSV file (leverages the SDDL format for security descriptors).

Using the script would give you a way back if you need to undo a change like this for all or part of the directory structure.

http://mow001.blogspot.com/2006/05/powershell-import-and-export.html

We could re-write it to make it a little prettier if we needed to, but it should work quite nicely as it stands :)

Chris
At C:\powershell\grant-payroll.ps1:23 char:10
+   Set-ACL <<<<  $_.FullName -AclObject $ACL
    + CategoryInfo          : InvalidOperation: (D:\Departments\...Barbara\Pay
   roll:String) [Set-Acl], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.Power
   Shell.Commands.SetAclCommand

Set-Acl : The security identifier is not allowed to be the owner of this object
Okay, after messing around with this, I have an idea what is going on.

Why does set-acl want to set the owner to myself?  I want to leave the owner as "HRDept-Users".

I changed the owner via the GUI to myself for the entire tree, and now it works.

-Mark

I've seen this before.

Set-ACL cannot do anything clever or particularly useful with the owner. If the current owner is considered invalid then it will fail to set the ACL entirely. Unfortunately forcefully changing the owner requires far more rights than PS has or can be given.

In these cases I tend to recommend calling TakeOwn to fix the owner, the continuing with the job the script is trying to do.

But you've changed the owner already so it's no longer an issue?

Chris
Correct, I force changed the owner from the GUI.

I talked to a friend of mine and he was wondering if it was because I was using 1.0 and not 2.0.

I'll goof around today and see if 2.0 does anything different.

Thanks for your help.   Not only did you help me solve what I needed quick, but now I understand more about PS than I did a few days ago.

-Mark