I think you’re making the right choice by moving to native PowerShell to manage your permissions. There is a learning curve, but it looks like you’re already most of the way there. Once you understand how .NET/PowerShell treats this stuff, you can create your own tools around it, or at least be able to use other third party tools better.
If I could only give you one suggestion, though, it would be to not use Set-Acl (at least with the file system). There are some very bad bugs over on the Connect site associated with it. Your problems can range from it simply not working sometimes when it should from an un-elevated session, to wiping out your SACLs (the ACL that handles auditing) if you are elevated. Thankfully there’s an easy workaround to using Set-Acl, and that’s the SetAccessControl() .NET method:
$UserName = "UserName"
$UserShareParent = "\\server\shareroot\usershare"
$Acl = Get-Acl $UserShareParent
# If you don't want the parent to inherit permissions, do this:
$Acl.SetAccessRuleProtection($true, $false)
foreach ($CurrentUser in echo Administrators, SYSTEM, $UserName) {
$Acl.AddAccessRule((New-Object System.Security.AccessControl.FileSystemAccessRule(
$CurrentUser,
"FullControl",
"ContainerInherit, ObjectInherit",
"None",
"Allow"
)))
}
(Get-Item $UserShareParent).SetAccessControl($Acl)
You already had that part taken care of, but this does show how to use SetAccessControl() instead of Set-Acl.
If you want to set all of the children to inherit their permissions, that means you want to call Get-Acl on each one and check the ‘AreAccessRulesProtected’ property. If it is true, then the DACL is considered protected and inheritance is disabled. In that case, you’ll need to call the SetAccessRuleProtection() to unprotect them/enable inheritance. You’ll probably also want to make sure that any explicit entries that were added are also removed. Something like this, maybe?
$VerbosePreference = "Continue"
dir $UserShareParent -Recurse | ForEach-Object {
Write-Verbose ("Current FSO: {0}" -f $_.FullName)
$FSO = $_
try {
Write-Verbose " Getting security descriptor"
$Acl = $FSO | Get-Acl
}
catch {
Write-Error ("Error getting security descriptor for '{0}': {1}" -f $FSO.FullName, $_.Exception.Message)
}
if ($Acl.AreAccessRulesProtected) {
Write-Verbose " DACL inheritance is disabled; enabling it now"
$Acl.SetAccessRuleProtection($false, $false)
}
foreach ($Ace in $Acl.GetAccessRules($true, $false, [System.Security.Principal.NTAccount])) {
Write-Verbose (" Removing explicit ACE: {0} {1} {2} (IF: {3}, PF: {4})" -f $Ace.AccessControlType, $Ace.IdentityReference, $Ace.FileSystemRights, $Ace.InheritanceFlags, $Ace.PropagationFlags)
[void] $Acl.RemoveAccessRule($Ace)
}
try {
Write-Verbose " Writing security descriptor"
$FSO.SetAccessControl($Acl)
}
catch {
Write-Error ("Error setting security descriptor for '{0}': {1}" -f $FSO.FullName, $_.Exception.Message)
}
}
Now, that’s looks like a ton of stuff to do for this simple task (because it is). Most of the extra junk is from error handling. Without it, the loop is going to stop at the first error, and you should expect errors when checking an unknown number of files and folders. If you find yourself doing this a lot, you can create your own advanced functions to do this, or you can use other modules (shameless plug: I’ve got one that’s under development available on the TechNet Script repository and GitHub; there’s a demo of it here)
If you can, give the code above a look and let me know if you have any questions.