I have been spending a few hours working on a permission configuration issue on remote Windows systems (NT4, 2000 and 2003). The aim of my script was to modify the existing permission on a file on remote systems, as well as setting the ownership for this same file. Obviously I decided to use the cmdlet that Powershell kindly offers (gcm -noun acl), but there are only two:
CommandType Name
----------- ----
Cmdlet Get-Acl
Cmdlet Set-Acl
At first sight I was sure that I was going to have problems with setting file ownership on a remote system because none of these two commands reference it. And I was right. Powershell doesn't allow to change file ownership on a remote file system (as explained here). I even tried to perform this operation with cacls and icacls, but I had no better luck and lot of errors (such as "no SID for trustee" and "Error Bad trustee name/SID no lookup").
As I do most of the times when I want to run something remotely and it doesn't work with native tools/cmdlets, I pulled from my magic hat the old good 'psexec.exe' in conjunction with 'filelacl.exe' (whose project has been recently abandoned by Microsoft, as you can see here, so hurry-up and store a copy of this program in safe place!).
My final script is a combination of pure Powershell cmdlets and freshly-mixed psexec and fileacl statements:
$remotehost = "test_host" $username1 = "my_username" $paswd = "my password" $path = "\\$remotehost\c$\folder\file.txt" $acl = Get-Acl $path #Going to add my username with Full Control $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$username1","FullControl","Allow") $acl.AddAccessRule($rule) #Going to assing readandexecute ot Everyone group $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("everyone","readandexecute","Allow") $acl.AddAccessRule($rule) #Going to remove permissions for the local Administrator group $rule = New-Object System.Security.AccessControl.FileSystemAccessRule("administrators","FullControl","Allow") $acl.RemoveAccessRule($rule) Set-Acl $path $acl #Going to set the remote owner for this file psexec -c -u $username1 -p $paswd \\$remotehost fileacl.exe "$path" /O "$username1" #Let's check everything's been properly set Get-Acl $path | Format-List
I know it doesn't look good but that's the best I could do to solve my issue. It works this way:
- first of all I define a few variables, as the remote host name on which to work
- I retrieve the current ACL of the remote file
- I add two access rule: one for my username and one for the Everyone group
- I also add another access rule to remove the permission for the local admin group
- I apply these access rule with Set-Acl
- I start a psexec session on the remote host and fire fileacl to set the ownership
- I dump the applied permissions with Get-Acl to check everything went well
Possible values for rights that you can assign under System.Security.AccessControl.FileSystemAccessRule are listed below. Just choose the one that applies to your situation:
- AppendData
- ChangePermissions
- CreateDirectories
- CreateFiles
- Delete
- DeleteSubdirectoriesAndFiles
- ExecuteFile
- FullControl
- ListDirectory
- Modify
- Read
- ReadAndExecute
- ReadAttributes
- ReadData
- ReadExtendedAttributes
- ReadPermissions
- Synchronize
- TakeOwnership
- Traverse
- Write
- WriteAttributes
- WriteData
- WriteExtendedAttributes
I hope this simple script will be useful for those who, like me, didn't find a way to write file ownership on remote Master File Tables... be it under Windows NT, Windows 2000 or Windows 2003. Maybe the Scripting Guy can intervene and post a better solution!
$file=' \\System1\test\test.log'
ReplyDelete$acl=get-acl $file
$owner=[System.Security.Principal.NTAccount]'MyDom\user01'
$acl.SetOwner($owner)
set-acl -Path $file -AclObject $acl
Thanks for the code. Anyway it doesn't work on my system, probably because the user I want to declare as owner of the remote file is a remote local user, not a domain user.
ReplyDeleteWhen I run the code:
$full_username = "$remote_hostname" + "\" + "$remote_username"
$owner=[System.Security.Principal.NTAccount]$full_username
$acl.SetOwner($owner)
set-acl -Path $path -AclObject $acl
I get the follwoing translation error:
Exception calling "SetOwner" with "1" argument(s): "Some or all identity references could not be translated."
I am pretty sure the problem is due to the Powershell trying to resolve the SID for $remote_username locally and not remotely. Am I wrong?
Any other suggestion?
Thanks for this post, it helped.
ReplyDelete