So we have all been there, or atleast most everyone who has a SMB customer has been there. They have a shared network drive where all of their employees can access their files. However instead of having the folder permissions setup with groups, making the management immensely easier, the permissions are setup on the individual level. So when a new employee is hired, instead of just adding them to a couple of AD groups, you are piece-mealing their permissions together by having to manually touch 30+ folders to make sure the employee gets their requested access.
Well, after having done this one too many times, I wrote a script.
Function Copy-FolderPermission{ param([Parameter(Mandatory=$true)][string]$refid, [Parameter(Mandatory=$true)][string]$newuser, [Parameter(Mandatory=$true)][string]$location) $permprop=@("Folder","User","Access", "Permissions") $collection=@() [array]$permarray $folders=get-childitem $location |Where {$_.psIsContainer -eq $true} #This Function collects the permissions for a specific user Function get-craccess{ param($user) FOREACH ($folder in $folders){ $acl = get-acl $folder.fullname $perms=$acl.access|?{$_.identityreference -like "*$user*"} FOREACH($perm in $perms){ $permarray= "" |select-object -property $permprop $permarray.Folder=$folder.fullname $permarray.user=$user $permarray.access=$perm.AccessControlType [string]$per=$perm.filesystemrights $permarray.Permissions= "$per" $permarray } }} FOREACH ($folder in $folders){ #Delete Any Current Access the NewUser Might have $acl = get-acl $folder.fullname # $account=new-object system.security.principal.ntaccount("$newuser") # $acl.purgeaccessrules($newuser) # set-acl -aclobject $acl -path $folder.fullname $access=(get-acl $folder.fullname).access IF(($acl.access|?{$_.identityreference -like "*$newuser*"}) -ne $null) { Write-Verbose "Deleting Existing permission of $newuser on $($folder.fullname)" $deleteexisting=$acl.access |?{$_.identityreference -like "*$newuser*"}|%{$_.identityreference}|Get-Unique $acl.purgeaccessrules($deleteexisting) $acl|set-acl } } $collection+=get-craccess -user $refid #Takes access from the $refid and uses it to produce the proper access for the new user FOREACH($item in $collection) { [string]$permissions=$item.permissions $local=$item.folder $accesstype=$item.access $colRights = [System.Security.AccessControl.FileSystemRights] "$permissions" $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit $PropagationFlag = [System.Security.AccessControl.PropagationFlags]::None $objType =[System.Security.AccessControl.AccessControlType]::$accesstype $objUser = New-Object System.Security.Principal.NTAccount("$newuser") $objACE = New-Object System.Security.AccessControl.FileSystemAccessRule ($objUser, $colRights, $InheritanceFlag, $PropagationFlag, $objType) $objACL = Get-ACL $local $objACL.AddAccessRule($objACE) Set-ACL $local $objACL } $collection+=get-craccess -user $newuser $collection }
So lets do an example!
Let’s Say a user “Langer” already has access to a group of folders, and we want to copy those permissions to another user “Atwell”
So what we see here, are the permissions that Langer has on the folders that are contained within C:\Power\Test. Immediately following that are the permissions that Atwell are given on these same folders…Cool Huh?
Let’s look at the actual permissions in windows.
Look at that exactly the same.
At this point I should mention that these user accounts were not created to have any similarity to anyone living or dead, they are just random letters I put together to create a name. They don’t represent anyone.
Ok, for the next example let’s say we have started liking Atwell less and he shouldn’t have as much permissions as he currently does. Maybe he posted one too many #scottlowefacts, or maybe he upsets you because has red hair, or maybe he just doesn’t have a soul. Regardless he needs to be given less permissions than what he currently has. Again, these usernames are not suppose to represent anyone…they are just a random collection of letters.
Fortunately, we already have someone that doesn’t have very many permissions…Coen. So we are now going to give Atwell the same permissions as Coen.
Sweet, now Atwell has less permissions as he should.
A couple things to note, on Folders 1 and 2, Atwell’s permissions were erased and then recreated because Coen had permissions on those folders. Since Coen did not have permissions Folder 3, it made no change to Atwells permissions that were there.
Hope this helps
[wpfilebase tag=file id=3 /]
References:
#http://technet.microsoft.com/en-us/library/ff730951.aspx
#http://stackoverflow.com/questions/3282656/setting-inheritance-and-propagation-flags-with-set-acl-and-powershell
#http://developers.de/blogs/damir_dobric/archive/2007/06/18/directory-security-and-access-rules.aspx
#http://social.technet.microsoft.com/Forums/en-US/winserverpowershell/thread/4e6d0554-1b76-4219-84de-52d86dad6d4b/
9 Comments
Scott · July 15, 2012 at 8:57 pm
When I try to run the script, I’m getting the error AuthorizationManager check failed.
At line:1 char:31
I’ve restarted WMI, saved it as UTF-8, set the Execution Policy to Unrestricted, and nothing. =(
C-Rad · July 27, 2012 at 2:41 pm
Hey Scott!! Thanks for the comment, and sorry it has taken me a while to get back to you… Line 1 Char31 looks like the end of the naming of the function…I would make sure you aren’t missing either of the { } for the Function name. Also authorizationmanager would also make me think that maybe you need to run the script as an admin or double check your own permissions on the folders you are trying to edit. Hope this helps. Let me know!
Andrew · August 22, 2012 at 3:18 pm
Awesome script. Any way to analyze and set them recursively? I tried adding -Recurse to the $folder=get-childitem line and it doesn’t handle the permission copying correctly. It is giving the new user the permissions on everything recursively.
C-Rad · August 26, 2012 at 11:55 am
Andrew, this is a great questions. Honestly, I am not sure. I feel pretty confident there is a way to make it work, but I haven’t messed with that too much as of yet… I will have to get back to you on that one.
belgiandude · January 8, 2020 at 8:42 am
Hello C-RAD have you found a way to set recursivity ?
belgiandude · January 8, 2020 at 9:46 am
hey guys just to do the trick :
$Shareroot = “C:\rootfolder”
$refid = “Domain\user1″
$newuser =”Domain\user2”
Get-ChildItem -Path $Shareroot -Directory -Recurse | Foreach-Object{
Copy-FolderPermission -refid $refid -newuser $newuser -location $_.FullName
}
Set-Acl : The security identifier is not allowed to be the owner of this object
copy-folderPermission:74: 1
i suppose it’s due to the admin account not being owner of the folder ?
as per the set-acl limitations ?
Andrew · August 23, 2012 at 12:03 pm
Just found SetACL: http://helgeklein.com/
It isn’t powershell, but it is powerful!
Lewis · June 18, 2013 at 10:14 am
I am trying to write a basic powershell script that allows me to DENY user/group access to a given folder. Full Control = DENY (not “allow”). But the only references I can find anywhere, deal with granting, not denying rights. Is there no easy way to do this in PS?
C-Rad · July 16, 2013 at 2:43 pm
The easiest way I can think of to do it, would be just to have a sample Full Control Deny person, and then just pull the Flags you need from it to use elsewhere.