# Setting Folder ACL

This topic contains 24 replies, has 4 voices, and was last updated by  Charlie Spencer 1 year, 6 months ago.

• Author
Posts
• #32933

Participant

Hi All,

I'm trying to set ACL permissions on a folder. The goal is to set a ACE on the folder with a user in AD to have modify rights. Cant seem to ge thtis done. Below you find a snipping from the script.

setup directories
New-Item -Path \\ec-data\ecdata\documents -Name $initials -ItemType directory set acl$homepath="\\ec-data\ecdata\documents\$initials"$acl=get-acl $homepath$permission="ecp\$username","modify","allow"$accessrule=new-object System.Security.AccessControl.FileSystemAccessRule $permission$acl.SetAccessRule($accessrule)$acl | set-acl $homepath new-item -path \\ec-redir\pst$ -name $username -ItemType directory • #32934 Don Jones Keymaster I think this is the third ACL post today ;). The usual recommendation is, "Get-ACL and Set-ACL are a pain in the butt. Consider using icacls.exe instead." I know that seems like "cheating," but it isn't. There's a good reason PowerShell runs external command-line utilities – sometimes, they're the best tool for the job. If you are for some reason dead-set on using Set-ACL, you'll need to do more than post your script, though. What's it do? Any errors? Does absolutely nothing happen? Does Get-ACL return something different from the GUI? But... I'd use the command-line utility. • #44946 Charlie Spencer Participant I don't already know icacls.exe. Am I better off trying to learn how to massage ACLs with PS, or taking the detour in my PS exploration and learning icacls.exe instead? Which will be faster? Will learning icacls give me a better understanding of what is being done in this command? $accessrule=new-object System.Security.AccessControl.FileSystemAccessRule $permission Thanks! • #32958 Raymond Slieff Participant My experience shows you have to use the right set of parameters for FileSystemAccessRule. Another thing to be aware of is if you are creating the account in the same script you may have to delay it, or get the GUID of the account at creation (PassThru) and apply with that. The particular constructor I've had to follow is this one : FileSystemAccessRule Constructor (IdentityReference,FileSystemRights,InheritanceFlags,PropagationFlags,AccessControlType) Here are some snippets of the script I created at work that is used to make new shared folders. $Internal_ACL = Get-Acl -Path $Internal #region Disable Inheritance, remove previous ACLs$Internal_ACL.SetAccessRuleProtection($true,$false) | Out-Null
$Internal_ACL.Access | ForEach-Object {$Internal_ACL.RemoveAccessRule($_) | Out-Null } #endregion Disable Inheritance, remove previous ACLs #region Create ACLs # Domain Admins$Rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("Domain Admins", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")
$Internal_ACL.AddAccessRule($Rule) | Out-Null
# Group rights
$Rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule($Department.Group, "DeleteSubdirectoriesAndFiles, Modify", "ContainerInherit, ObjectInherit", "InheritOnly", "Allow")
$Internal_ACL.AddAccessRule($Rule) | Out-Null
$Rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule($Department.Group, "DeleteSubdirectoriesAndFiles, Write, ReadAndExecute", "None", "None", "Allow")
$Internal_ACL.AddAccessRule($Rule) | Out-Null

# Internal Group rights
$Rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule($Department.GroupInR, "ReadAndExecute", "ContainerInherit, ObjectInherit", "None", "Allow")
$Internal_ACL.AddAccessRule($Rule) | Out-Null
#endregion Create ACLs

#region Set ACLs
Set-Acl -Path $Internal -AclObject$Internal_ACL -ErrorVariable ACLError -ErrorAction 'SilentlyContinue' | Out-Null
if ($ACLError) { Write-Output -InputObject "An error was caught attempting to apply security rights, ntyou may have to take ownership of the '$ParentPath\$Internal' folder" Write-Verbose -Message "$ACLError"
$ACLError =$false
} # if ACLError
#endregion Set ACLs
• #44949

Don Jones
Keymaster

I'd learn Icacls. But no, it won't help with that command. That command is basically low level .NET programming. Icacls doesn't use that. And yes, it's faster. It's probably easier. And it isn't a detour; you can run it in PowerShell. The Set-Acl stuff would also, by that definition, be a detour, because it's going to be low-level .NET programming, not cmdlets.

• #44951

Raymond Slieff
Participant

That script line just creates the rule, and matters a lot on what is in that $permission variable. The link my previous post is probably your best information for what those settings are and how to configure them for what you need. As for details about that particular line, it's creating a variable called$accessrule, which is a System.Security.AccessControl.FileSystemAccessRule .NET object type, the properties you feed it are what define the created object. You typically collect these in a different object with the .AddAccessRule method of an ACL Object.

Learning either is useful, I've been trying to stick with powershell for as much as I can but I recently just hit a task where I had to break out icalcs for something powershell just could not properly push through, and gave almost no error about. So learn both, and then learn to start with the powershell part and just have icacls as a backup in the same script, that would be a great lesson.

If you have more specific questions about that object type or the properties it sets, I can attempt to answer them to the best of my knowledge.

• #44953

Charlie Spencer
Participant

Gentlemen, thanks for the quick responses!

I'll take a look at icacls. Y'all scared me off with talk of 'low-level .NET objects'. I understood the creation of the $permission variable in the earlier statement. I understood the '$accessrule=' was creating another variable and was using the $permission variable, but the whole 'new-object System.Security.AccessControl.FileSystemAccessRule' threw me for a loop. Don, FYI, 'PS in a Month of Lunches' arrived today. The preface and '1.2 Is this book for you?' are very encouraging. You and Jeff are correct in the preface; the other books I've looked at assumed previous scripting experience. • #44964 Charlie Spencer Participant Okay, let me know if this icacls question is considered outside the scope of this forum and I'll take it elsewhere. On the other hand, since y'all did bring it up... I'm not getting the results I expect from either of these commands. As I understand, either of these should remove 'Domain Users' from the ACL of the specified folder. PS C:\> icacls \\domain.com\users\last6fm /remove 'domain.com\Domain Users' processed file: \\domain.com\users\last6fm Successfully processed 1 files; Failed processing 0 files and PS C:\> icacls \\domain.com\users\last6fm /remove:g 'domain.com\Domain Users' processed file: \\domain.com\users\last6fm Successfully processed 1 files; Failed processing 0 files When I look in the GUI, Domain Users is still in the ACL with 'Read & Execute', 'List Folder Contents', and Read, the permissions it had before I ran either command. The output seems to indicate my commands are valid, so apparently the syntax isn't correct for what I want to accomplish. Thanks for any suggestions, including that I take this elsewhere. • #44977 Don Jones Keymaster Are those permissions inheriting from somewhere else? Icacls only modifies the direct ACL; it doesn't (and can't) remove any permissions inheriting from above, unless you use it to disable inheritance. • #44989 Charlie Spencer Participant Yes, they are inherited! Setting the ACL is a step in the series of actions I take when I create a new user account. I'm used to doing it all from the GUI, and disabling the inheritance has become another automatic 'point and click' action to me. I don't consciously think about it any more (or most of the other steps). I'll dig up handling inheritance at the command line. Thanks. • #45016 Charlie Spencer Participant I licked the inheritance problem (icacls parameter /inheritance:d, if anyone is interested in the future). Also for anyone else's future benefit, I ran into an issue using a variable with icacls. The first command works successfully, but it's just to test my syntax. The second replaces the coded username with a variable holding the same username string. I tried enclosing the entire domain.com\$Name in single quotes, double quotes, percent signs, double and single, etc. Enclosing only the variable but NOT the domain turned out to be the solution.

PS C:\Windows\system32> icacls \\domain.com\users\$Name /grant domain.com\last6fm:m processed file: \\domain.com\users\last6fm Successfully processed 1 files; Failed processing 0 files PS C:\Windows\system32> icacls \\domain.com\users\$Name /grant "domain.com\$Name":m icacls : Invalid parameter "/grant" At line:1 char:1 + icacls \\domain.com\users\$Name /grant "domain.com\$Name":m + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (Invalid parameter "/grant":String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError PS C:\Windows\system32> icacls \\domain.com\users\$Name /grant domain.com\"$Name":m processed file: \\mu3srvfsbbg1.mu3.global.sys\users\last6fm Successfully processed 1 files; Failed processing 0 files I've got to figure out more effective search terms to use when Googling. I'm getting too many results that relate to other scripting tools. • This reply was modified 1 year, 6 months ago by Charlie Spencer. Reason: Clarity • #45019 Charlie Spencer Participant Well, I thought it did what I want but it doesn't. It handles the variable okay, but I'm still not getting the permissions I want. I thought :M would apply the same permissions as checking Modify in the GUI, but it doesn't. The account is added to the ACL but the permissions are applied as 'Special'. I also can't get the command to accept the (OI) and (CI) inheritance parameters for subordinate files and folders. PS C:\Windows\system32> icacls \\domain.com\users\$Name /t /grant last6fm:(OI)(CI)M
OI : The term 'OI' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and try again.
At line:1 char:69
+ icacls \\mu3srvfsbbg1.mu3.global.sys\users\$Name /t /grant last6fm:(OI)(CI)M + ~~ + CategoryInfo : ObjectNotFound: (OI:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException EDIT – the above command does work correctly from a command prompt. It looks like my inability to use the inheritance parameter is why the rights are showing up as Special. • This reply was modified 1 year, 6 months ago by Charlie Spencer. Reason: Additional Information • #45024 Don Jones Keymaster The error indicates that PowerShell is trying to parse the command, rather than sending it as-is to Cmd.exe. That's not unusual. See http://edgylogic.com/blog/powershell-and-external-commands-done-right/ for background (especially the v3 section), but you probably want to run... &"icacls.exe" --% ...everything...else...  The –% will tell PowerShell to knock it off with the remainder of the command, and just pass it along as-is. • #45032 Charlie Spencer Participant Yeah, that works as long as everything is hard-coded. I want to replace the specified username 'last6fm' with a variable$Name. As I suspected and my tests showed, the variable value doesn't getting passed along to icacls.

This is what frustrates me more than anything else. I suspect I have the logic down, it's the syntax that drives me nuts, especially trying to make external, non-cmdlet pieces fit together.

• #45034

Don Jones
Keymaster

Check out that article. You'll have to start getting fancy with double quotes, and seeing if you can get the right combination to get it parsed and passed.

• #45036

Charlie Spencer
Participant

I started with the article, but I can't find any use of both –% and a variable.

Also, if you need to reference PowerShell variables, you can't use this trick either. Read on.

but darned if I've found it yet. I'll keep digging. Thanks.

• #45040

Raymond Slieff
Participant

Could you give an example of what you want the file rights to be, along with it's inheritance and propagation rights?

OI is probably causing "special" permissions because it's for sub folders and files only, instead of this folder and decedents.
CI is asking to inherit any propagated rights from above, so this could be tweaking what the final right set it as well.

I typically end up giving the folder itself some kind of special rights, to stop users from being able to move or modify it directly, while still having control of all the items within it properly.

• #45050

Charlie Spencer
Participant

Sure. I want to give the user the same rights he would get if I used the GUI and clicked the Allow:Modify box. That results in the following boxes getting checked: Modify, Read & Execute, List folder contents, Read, and Write.

This command does exactly what I want, once Don pointed out the & and –% requirements.

PS I:\> &icacls --% e:\users\last6fm /grant domain.com\last6fm:(oi)(ci)m

But I want to replace last6fm with a variable $Name. The exact rights aren't the issue; I don't have any problems from a command prompt. It's getting PS to hand off all the parameters to icacls. I'd find something to copy and paste and just move on, but it looks like there's something important I need to learn from this about using resources external to PS. There's got to be some logic here somewhere, but most of what I've found makes it look like trial and error. Thanks. • #45060 Raymond Slieff Participant ok, what about this. &icacls e:\users\$($Name) /grant domain.com\$($Name):"(oi)(ci)m" • #45064 Charlie Spencer Participant That works. Can you tell me how? What's with $($Name) and :"(oi)(ci)m" ? • #45066 Raymond Slieff Participant I just kept working on the paring until it did what I wanted it to do. the whole$($variable) is just a way to force it to expand it before it executes the line. Putting the parentheses in quotes let them pass through as proper string, without powershell mucking with them. I'm actually a little surprised it let the colon go in there without being in quotes but it just got stranger the more I played with it. You might find that in a script it parses slightly different and might need more tweaking, I've had occasional issues like that. • #45068 Charlie Spencer Participant For whatever reason, the first$($Name) in the filename isn't necessary, just the second one in the username. That apparent inconsistency mystifies the living crud out of me. And this was easier than Get-ACL / Set-ACL? Gods. I'm going to lunch before I get any more discouraged. Thanks to all. • #45072 Don Jones Keymaster Honestly, anything involving ACLs is a shit-show. And Microsoft knows it. That's why there's such a press for role-based authorization (e.g., DAC), and to move away from ACLs over time. Maintaining ACLs is impossible. • #45092 Raymond Slieff Participant Totally agree with Don, ACL management is a cluster. Just for reference the powershell ACL method would be more like : $TargetPath = "e:\users\$Name"$FolderACL = Get-Acl -Path $TargetPath$ACLRule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule("domain.com\$($Name)", "Modify", "ContainerInherit, ObjectInherit", "None", "Allow")
$FolderACL.AddAccessRule($ACLRule)
Set-Acl -Path $TargetPath -AclObject$FolderACL

Now that you have a better understanding of the icacls, you should see the main similarities, just in this one you are also explicitly listing propagation type, and if it is an Allow or Deny ACL type.

• #45140

Charlie Spencer
Participant

Okay, now everything looks better after a chicken salsa wrap and house-made chips. Glad to hear the issues aren't just with this newbie.

It could be worse for me. I long ago mandated that there would only be two global groups in an ACL – one for read, one for write. If a user wants something else in a subfolder, we'll create a new top-level directory. At least I don't have to deal with those nested nightmares.

Thanks. I'll take a break from attempting a real-world application and dive into Don's chapter on the Help system.

You must be logged in to reply to this topic.