62

I am trying to mimic the action of right-clicking on a folder, setting "modify" on a folder, and having the permissions apply to the specific folder and subfolders and files.

I'm mostly there using Powershell, however the inheritance is only being set as "subfolders and files" instead of the whole "this folder, subfolders and files".

Is there some unlisted flag for System.Security.AccessControl.PropagationFlags that will set this properly?

Here's what I'm working with so far.

$Folders = Get-childItem c:\TEMP\
$InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::InheritOnly
$objType = [System.Security.AccessControl.AccessControlType]::Allow 

foreach ($TempFolder in $Folders)
{
echo "Loop Iteration"
$Folder = $TempFolder.FullName

$acl = Get-Acl $Folder
$permission = "domain\user","Modify", $InheritanceFlag, $PropagationFlag, $objType
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission

$acl.SetAccessRule($accessRule)
Set-Acl $Folder $acl
} 
Frank Schwieterman
  • 24,142
  • 15
  • 92
  • 130
Tim AtLee
  • 917
  • 1
  • 10
  • 17

5 Answers5

106

Here's a table to help find the required flags for different permission combinations.

    ╔═════════════╦═════════════╦═══════════════════════════════╦════════════════════════╦══════════════════╦═══════════════════════╦═════════════╦═════════════╗
    ║             ║ folder only ║ folder, sub-folders and files ║ folder and sub-folders ║ folder and files ║ sub-folders and files ║ sub-folders ║    files    ║
    ╠═════════════╬═════════════╬═══════════════════════════════╬════════════════════════╬══════════════════╬═══════════════════════╬═════════════╬═════════════╣
    ║ Propagation ║ none        ║ none                          ║ none                   ║ none             ║ InheritOnly           ║ InheritOnly ║ InheritOnly ║
    ║ Inheritance ║ none        ║ Container|Object              ║ Container              ║ Object           ║ Container|Object      ║ Container   ║ Object      ║
    ╚═════════════╩═════════════╩═══════════════════════════════╩════════════════════════╩══════════════════╩═══════════════════════╩═════════════╩═════════════╝

So, as David said, you'll want

InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit
PropagationFlags.None
marsh-wiggle
  • 2,508
  • 3
  • 35
  • 52
Nick Sarabyn
  • 1,632
  • 2
  • 21
  • 29
44

I think your answer can be found on this page. From the page:

This Folder, Subfolders and Files:

InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit 
PropagationFlags.None
Joey
  • 344,408
  • 85
  • 689
  • 683
David Gladfelter
  • 4,175
  • 2
  • 25
  • 25
17

Here's some succinct Powershell code to apply new permissions to a folder by modifying it's existing ACL (Access Control List).

# Get the ACL for an existing folder
$existingAcl = Get-Acl -Path 'C:\DemoFolder'

# Set the permissions that you want to apply to the folder
$permissions = $env:username, 'Read,Modify', 'ContainerInherit,ObjectInherit', 'None', 'Allow'

# Create a new FileSystemAccessRule object
$rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permissions

# Modify the existing ACL to include the new rule
$existingAcl.SetAccessRule($rule)

# Apply the modified access rule to the folder
$existingAcl | Set-Acl -Path 'C:\DemoFolder'

Each of the values in the $permissions variable list pertain to the parameters of this constructor for the FileSystemAccessRule class.

Courtesy of this page.

Luke
  • 22,826
  • 31
  • 110
  • 193
  • 1
    The key for powershell is to pass the flags as parameters to the constructor for FileSystemAccessRule (i.e. New-Object) as only this answer shows. – bchurchill Sep 29 '20 at 12:28
  • @bchurchill wait, there's a difference between inheritance/propagation at the ACL and ACE level, though. So setting it in the ctor of FileSystemAccessRule affects the ACE, but won't affect the ACL flags. Or what am I missing? – 0xC0000022L Oct 12 '21 at 12:10
  • I think you're right, the answer here just adds a new entry with those flags set, which may work in some cases but not others. – bchurchill Oct 13 '21 at 14:00
12

Just because you're in PowerShell don't forgot about good ol' exes. Sometimes they can provide the easiest solution e.g.:

icacls.exe $folder /grant 'domain\user:(OI)(CI)(M)'
Keith Hill
  • 194,368
  • 42
  • 353
  • 369
  • 2
    Yeah, I almost solved the problems with a DOS batch file and icacls or setacl, but trying to learn powershell.. best way to learn is by solving a problem with it, etc. – Tim AtLee Jul 20 '10 at 16:10
  • 1
    I understand. OTOH I've been using PowerShell for > 5 years now and I don't hesitate to drop back to an EXE if it is significantly easier than the PowerShell equivalent. IOW there's plenty to learn in PowerShell - some more worthwhile than others. :-) – Keith Hill Jul 20 '10 at 18:03
  • The annoying part about icacls appears to be the fact that it uses an older version/dialect of SDDL. – 0xC0000022L Oct 12 '21 at 12:11
9

Here's the MSDN page describing the flags and what is the result of their various combinations.

Flag combinations => Propagation results
=========================================
No Flags => Target folder.
ObjectInherit => Target folder, child object (file), grandchild object (file).
ObjectInherit and NoPropagateInherit => Target folder, child object (file).
ObjectInherit and InheritOnly => Child object (file), grandchild object (file).
ObjectInherit, InheritOnly, and NoPropagateInherit => Child object (file).
ContainerInherit => Target folder, child folder, grandchild folder.
ContainerInherit, and NoPropagateInherit => Target folder, child folder.
ContainerInherit, and InheritOnly => Child folder, grandchild folder.
ContainerInherit, InheritOnly, and NoPropagateInherit => Child folder.
ContainerInherit, and ObjectInherit => Target folder, child folder, child object (file), grandchild folder, grandchild object (file).
ContainerInherit, ObjectInherit, and NoPropagateInherit => Target folder, child folder, child object (file).
ContainerInherit, ObjectInherit, and InheritOnly => Child folder, child object (file), grandchild folder, grandchild object (file).
ContainerInherit, ObjectInherit, NoPropagateInherit, InheritOnly => Child folder, child object (file).

To have it apply the permissions to the directory, as well as all child directories and files recursively, you'll want to use these flags:

InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit 
PropagationFlags.None

So the specific code change you need to make for your example is:

$PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None
deadlydog
  • 22,611
  • 14
  • 112
  • 118