20 November 2012

I need to vent a little before I get into the code.  Had a frustrating one today!  All because of unclear documentation in MSDN’s published library of their .NET classes. I guess it’s true what they say, that sometimes you should listen to what isn’t said.

I had to build a work-around to a problem with an MSI from a certain cardiovascular imaging software.  It seems the MSI wants to strip the permissions for the local “Users” group off of the C:\ProgramData folder.  Not cool!  At first the vendor tried to brush it under the rug and gave me a few lines about the development process, blah, blah (develoment?!  you’re just fixing the installer!) and then said it could take 10-12 weeks (which is further out than our very-rushed go-live) and if I could just work around it.  Did I mention this isn’t a lesson in customer service skills?

So anyway, I sat down to figure out how I was going to do it.  I’ve lost a lot of my VB skill because I haven’t used it in over 6 months and I’ve been learning a lot of Powershell.  I love Powershell and I’ve already written code to modify permissions (on a file on XP) so I figured this would be easy.  The one good thing I had going is the issue is only affecting Windows 7 so running the Powershell script locally isn’t a problem (we never pushed PS out to our XP devices).  What I thought would be a 5 minute mod of my existing code turned out to be about 30-40 minutes.

It seems just supplying the user/group (IdentityReference),  read/write/etc (FileSystemRights), and Allow/Deny (AccessControlType) were enough… but not really.   Mine was set to:

 

$Ar = New-Object  system.security.accesscontrol.filesystemaccessrule("Users","ReadAndExecute","Allow")

When setting just those three properties the permissions got applied but if you right-clicked on the folder and viewed the Security tab of the folders properties you saw a blank list of rights for that user/group.  All except for “Special Permissions” at the bottom.  If you went into advanced and dug a little deeper you could see that the Traverse folder/ execute file, List folder/read data, Read attributes, and Read extended attributes were all selected.  Read permissions was not.  Kind of a problem.  Below is what that looked like.

The other problem is it says “Apply to:  Subfolders and files only”.  With the changes not applying to the root folder I actually made the changes on, and not having proper read permissions, I have a funky looking ACL.  The odd thing is that the permissions I was wanting to apply worked.  Someone who fell into the “Users” group was able to read and execute like I wanted.  But, it’s technically broken so it needed to be fixed.

So I called up the MSDN library to find out what else I might need.  This post is already longer than it needs to be so it will suffice to say that I fiddled around with the InheritanceFlags Enumeration and PropagationFlags Enumeration parameters for quite a while.  I assumed the the FileSystemRights could be comma-separated since there were many options and you could have multiple.  I tried that and it worked, I got the “Read Permissions” checkbox back on the advanced properties view.   Still, the ACL was blank on the Security tab (with the exception of Special Permissions).  that took setting the Inheritance and Propagation flags correctly.  Both of these flags apply ONLY to the child object.  They do not affect whether the folder you are making changes to will inherit from it’s parent.  Inherit determinse whether the child object(s) inherit from the folder you are making changes on and propagate is what it pushes them down to.  Propagate is dependent on Inherit.

Ok, finish this up already.  Since I needed to put permisions back to default so that All Users/Public can appropriately access that folder I needed both file and folders to inherit.  And the kicker (reading what isn’t said…) is that the Propagation flags have to be set to None.  Why?  Because it doesn’t mean it wont propagate, it means it’s going to use the default value for propagation, which is:  This folder, subfolders, and files!  But the documentation does not say that anywhere!  It finally dawned on me that, that is what it would do.  So, my final code for adding “Users” to the ACL for the C:\ProgramData folder with Read and execute, List folder contents, and Read permissions is:

 

$Acl = Get-Acl C:\ProgramData
$Ar = New-Object  system.security.accesscontrol.filesystemaccessrule("Users","ReadAndExecute,Read","ObjectInherit,ContainerInherit","None","Allow")
$Acl.SetAccessRule($Ar)
Set-Acl C:\ProgramData $Acl

Line 1 I’m getting the ACL of the object I want to modify
Line 2 I’m creating a new access rule and setting all of the parameters.  The local Users group, the TWO FileSystemRights, the Inheritance Flags (so that folders and files inherit), the Propagation flag (none means use default), and finally that I”m Allowing access and not Denying.
Line 3 I’m taking that access rule and adding it to the ACL object I created from the folder
Line 4 I’m actually setting the new ACL [in stone]

Yes, all that for 4 lines of code.

“Special” thanks to the MSDN library:  http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.filesystemaccessrule.aspx


4 Responses to “Powershell: Modifying Permissions; Child-Objects”

  • Austin
    April 9th, 2014 at 5:00 am     

    Great post!!
    Thanks so much!
    I’ve been fighting with this for hours!

  • thegeek
    April 9th, 2014 at 7:35 am     

    You’re welcome!

  • Chuck
    August 29th, 2014 at 6:48 am     

    Hi,
    I need to modify about 2000 Home directories.
    How can I modify this script so that I can use an import csv for the users and directories?
    For example, \\\\server\\share\\user will be a variable as will the domain\\username for the filesystemaccessrule

  • thegeek
    August 29th, 2014 at 7:30 am     

    Should be able to do something like this:

    $list = import-csv “file path”

    ForEach($item in $list) {
    $Acl = Get-Acl $item.filepath
    $Ar = New-Object system.security.accesscontrol.filesystemaccessrule($item.user,”ReadAndExecute,Read”,”ObjectInherit,ContainerInherit”,”None”,”Allow”)
    $Acl.SetAccessRule($Ar)
    Set-Acl C:\ProgramData $Acl
    }

    The first line of your CSV should be the headers. That’s what I’m using in the code, so, for example the headers would be User and FilePath. Those become properties for each item (row) in the CSV and that is how you call them. Then, later in the code I changed “user” from my original script to be $item.user so it would be giving permission to the actual user…. or modify that to be giving access to whichever group or username you are wanting to add. After that is the type of permissions you want to add.

You must be logged in to post a comment.

Links

RSS 2.0 Feed

Support

Brave Rewards
This site supports Brave Rewards. Please consider tipping or adding it to your monthly contributions if you find anything helpful!

For other ways: Support

Support this blog! If you have found it helpfu you can send me crypto. Any amount is appreciated!
ETH: 0xBEaF72807Cb5f4a8CCE23A5E7949041f62e8F8f0 | BTC: 3HTK5VJWr3vnftxbrcWAszLkRTrx9s5KzZ | SHIB: 0xdb209f96dD1BdcC12f03FdDfFAD0602276fb29BE
Brave Users you can send me BAT using the browser.