Changing permissions with powershell doesn't propogate to children
Asked Answered
B

3

8

When I set a new filesystemaccess rule with powershell and set-acl, I set the inheritance flags to propagate to children and leaf objects

$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
    "username","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")))
Set-Acl -path $filename -aclObject $acl

When I look at the permission in explorer.. in the security tab.. advanced.. the propagation is set correctly. But if I look at the children themselves, they do NOT show the new security rule.

If in explorer, I add another rule with a different SID.. and save it (without forcing the option to 'replace all child object permissions...'). Then both the manual, and the powershell rule shows up on the children. Its as if there is some sort of kickstart needed to cause the children to pick up the new propagated rule. What am I missing to make the child objects show the new rule added?

Brooklyn answered 10/6, 2012 at 17:54 Comment(1)
What is $acl ? Are your trying to copy the security descriptor of $filename to $acl ?Tetrahedral
B
7

I have had the same logical problem...

$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"username","FullControl", "ContainerInherit, ObjectInherit", "None", "Allow")))

With that last 'none' you are saying: do not propogate... Change to:

$acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
"username","FullControl", "ContainerInherit, ObjectInherit", "InheritOnly", "Allow")))

and it will propagate your settings. Check out the access rule options here: http://msdn.microsoft.com/en-us/library/ms147785.aspx

These are the propagation flags: http://msdn.microsoft.com/en-us/library/system.security.accesscontrol.propagationflags.aspx

Bouillabaisse answered 25/9, 2012 at 12:19 Comment(0)
A
2

That's very strange. I've got similar code that sets permissions the same way. I've never checked if the children's permissions are getting set or not though. It could just be some weirdness in the Windows Explorer UI. Have you used PowerShell to get the ACLs on one of the children to check if the permissions are or aren't getting applied?

For reference, here's the code I use to grant permissions:

foreach( $permission in $Permissions )
{
    $right = ($permission -as "Security.AccessControl.FileSystemRights")
    if( -not $right )
    {
        throw "Invalid FileSystemRights: $permission.  Must be one of $([Enum]::GetNames("Security.AccessControl.FileSystemRights"))."
    }
    $rights = $rights -bor $right
}

Write-Host "Granting $Identity $Permissions on $Path."
# We don't use Get-Acl because it returns the whole security descriptor, which includes owner information.
# When passed to Set-Acl, this causes intermittent errors.  So, we just grab the ACL portion of the security descriptor.
# See http://www.bilalaslam.com/2010/12/14/powershell-workaround-for-the-security-identifier-is-not-allowed-to-be-the-owner-of-this-object-with-set-acl/
$currentAcl = (Get-Item $Path).GetAccessControl("Access")

$inheritanceFlags = [Security.AccessControl.InheritanceFlags]::None
if( Test-Path $Path -PathType Container )
{
    $inheritanceFlags = ([Security.AccessControl.InheritanceFlags]::ContainerInherit -bor `
                         [Security.AccessControl.InheritanceFlags]::ObjectInherit)
}
$propagationFlags = [Security.AccessControl.PropagationFlags]::None
$accessRule = New-Object "Security.AccessControl.FileSystemAccessRule" $identity,$rights,$inheritanceFlags,$propagationFlags,"Allow"    
$currentAcl.SetAccessRule( $accessRule )
Set-Acl $Path $currentAcl
Assyriology answered 12/6, 2012 at 1:28 Comment(0)
C
1

I have been scouring the internet and several StackOverflow questions trying to puzzle this out. I may not have the best solution, but I think it satisfies the question. According to my research, Powershell's Set-Acl just doesn't handle inheritance properly. The key to the code below is two things: the System.Security.AccessControl.DirectorySecurity object and using the alternative method for setting the ACL $dir.SetAccessControl() The children of the target folder (both folders and files) will successfully inherit the permissions attached to your target folder.

Calling example:

$newACL=@()
$newACL+=New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList @("MyLocalGroup1","ReadAndExecute,Synchronize","ContainerInherit,ObjectInherit","None","Allow")
$newACL+=New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList @("MyLocalGroup2","FullControl","ContainerInherit,ObjectInherit","None","Allow")
Set-FolderPermissions -Path $Path -KeepDefault -ResetOwner -AccessRuleList $newACL

Function:

function Set-FolderPermissions {
  # The whole point of this script is because Set-Acl bungles inheritance
  [CmdletBinding(SupportsShouldProcess=$false)]
  Param ([Parameter(Mandatory=$true, ValueFromPipeline=$false)] [ValidateNotNullOrEmpty()] [string]$Path,
         [Parameter(Mandatory=$false, ValueFromPipeline=$false)] [switch]$KeepExisting,
         [Parameter(Mandatory=$false, ValueFromPipeline=$false)] [switch]$KeepDefault,
         [Parameter(Mandatory=$false, ValueFromPipeline=$false)] [switch]$ResetOwner,
         [Parameter(Mandatory=$true, ValueFromPipeline=$false)] [System.Security.AccessControl.FileSystemAccessRule[]]$AccessRuleList)

  Process {
    $aryDefaultACL="NT AUTHORITY\SYSTEM","CREATOR OWNER","BUILTIN\Administrators"
    $tempACL=@()
    $owner=New-Object System.Security.Principal.NTAccount("BUILTIN","Administrators")
    $acl=Get-Acl -Path $Path

    # Save only needed individual rules.
    if ($KeepExisting.IsPresent) {
      if ($KeepDefault.IsPresent) {
        # Keep everything
        $acl.Access | ForEach-Object { $tempACL+=$_ }
      }
      else {
        # Remove the defaults, keep everything else
        for ($i=0; $i -lt $acl.Access.Count; $i++) { 
         if (!$aryDefaultACL.Contains($acl.Access[$i].IdentityReference.Value)) { $tempACL+=$acl.Access[$i] }
        }
      }
    }
    else {
      if ($KeepDefault.IsPresent) {
        # Keep only the default, drop everything else
        for ($i=0; $i -lt $acl.Access.Count; $i++) { 
         if ($aryDefaultACL.Contains($acl.Access[$i].IdentityReference.Value)) { $tempACL+=$acl.Access[$i] }
        }
      }
      #else { # Do nothing, because $TempACL is already empty. }
    }

    # Add the new rules
    # I could have been modifying $acl this whole time, but it turns out $tempACL=$acl doesn't work so well.
    # As the rules are removed from $acl, they are also removed from $tempACL
    for ($i=0; $i -lt $AccessRuleList.Count; $i++) { $tempACL+=$AccessRuleList[$i] }

    # This is the object that you're looking for...
    $aclDS=New-Object System.Security.AccessControl.DirectorySecurity -ArgumentList @($Path,[System.Security.AccessControl.AccessControlSections]::None)
    # The object, apparently, comes with a bonus rule...
    $aclDS.RemoveAccessRuleSpecific($aclDS.Access[0])
    # Add the rules to our new object
    for ($i=0; $i -lt $tempACL.Count; $i++) {
      # I tried adding the rules directly but they didn't work.  I have to re-create them.
      $tempRule=New-Object System.Security.AccessControl.FileSystemAccessRule -ArgumentList @($tempACL[$i].IdentityReference,$tempACL[$i].FileSystemRights,$tempACL[$i].InheritanceFlags,$tempACL[$i].PropagationFlags,$tempACL[$i].AccessControlType)
      $aclDS.AddAccessRule($tempRule)
    }
    # This has to be done after all the rules are added, otherwise it doesn't work
    $aclDS.SetAccessRuleProtection($true,$false)

    if ($ResetOwner.IsPresent) {
      # Often, the default owner is SYSTEM.  This ownership will prevent you from making any changes.
      # So, we change owner to the local Administrator
      $acl.SetOwner($owner)
      # We have to apply it now because we are applying our ACLs in two stages.  We won't be using Set-Acl again.
      Set-Acl -Path $Path -AclObject $acl
    }

    # Lastly, apply our ACls
    $dir=Get-Item -Path $Path
    $dir.SetAccessControl($aclDS)
  }
}
Catalinacatalo answered 7/6, 2016 at 18:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.