I am combing the Internet and a few StackOverflow questions trying to figure this out. I may not have a better solution, but I think this satisfies the question. According to my research, Powershell Set-Acljust doesn't handle inheritance properly. The key to the code below is two things: an object System.Security.AccessControl.DirectorySecurityand using an alternative method to set the ACL $dir.SetAccessControl(). Children of the target folder (both folders and files) will successfully inherit the permissions attached to your target folder.
Call 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
Functions:
function Set-FolderPermissions {
[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
if ($KeepExisting.IsPresent) {
if ($KeepDefault.IsPresent) {
$acl.Access | ForEach-Object { $tempACL+=$_ }
}
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) {
for ($i=0; $i -lt $acl.Access.Count; $i++) {
if ($aryDefaultACL.Contains($acl.Access[$i].IdentityReference.Value)) { $tempACL+=$acl.Access[$i] }
}
}
}
for ($i=0; $i -lt $AccessRuleList.Count; $i++) { $tempACL+=$AccessRuleList[$i] }
$aclDS=New-Object System.Security.AccessControl.DirectorySecurity -ArgumentList @($Path,[System.Security.AccessControl.AccessControlSections]::None)
$aclDS.RemoveAccessRuleSpecific($aclDS.Access[0])
for ($i=0; $i -lt $tempACL.Count; $i++) {
$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)
}
$aclDS.SetAccessRuleProtection($true,$false)
if ($ResetOwner.IsPresent) {
$acl.SetOwner($owner)
Set-Acl -Path $Path -AclObject $acl
}
$dir=Get-Item -Path $Path
$dir.SetAccessControl($aclDS)
}
}
source
share