This blog has moved to http://ThePowerShellGuy.com
Greetings /\/\o\/\/
Script for Adding an Accesrule to a File in MSH using Text parameters.
I started this script after reading this post in the MSH For Fun bl0g
Play with ACL in MSH that lets you set a Owner. that references my bl0g entry
Getting and using a SecurityPrincipal from MSH, but leaves adding a user up to the reader.
As I realized that I did owner setting before,
See
Update-TypeData (Democracy to the types) ,
MSH TakeOwner working And Setting security on a share using WMI.
Replace Security on existing share using MSH ,
Get Binary SID in MSH (Share Security Update)But not setting an ACL on a file, so I started to work on
Monad has a set-ACL CMDlet but, the Set-ACL CMDlet take's a System.Security.AccessControl.ObjectSecurity as input.
so we need contruct this first, we need a couple of .NET objects for this, also there are a couple of methods to set the Security but it's not that difficult as it seems at the start.
b.t.w. it took me a while to post this as I stumbled on a BUG in MSH handling Raw object output in functions and script, see the following NG thread
Get-Acl not returning outputthe $ar.IdentityReference.Translate([System.Security.Principal.securityidentifier]) output caused the get-ACL output to disapear.
This is caused by MSH not handling RAW objectdata right in the middle of a Pipeline.
as This BUG most likely will emain in V1 of MSH, I reccomend reading the tread and not just output Raw data in a Script ore function, always format it.
but to go on with the subject
for this example I make a test.txt file and a User Test to grant access.
Let's look at the ACL of this Testfile :
# Get the ACL
$acl = get-acl test.txt
$acl | GM
# 2 Methods are of interest here :
#SetAccessRule Method System.Void SetAccessRule(FileSystemAccessRule rule)
#SetSecurityDescriptorSddlForm Method System.Void SetSecurityDescriptorSddlForm(String sddlForm)
$acl.GetSecurityDescriptorSddlForm("all")
you see that we can set the AccessRule by use-ing an FileSystemAccessRule or an SDDL string.
the SDDL method just takes a string, you can look up how to create one here
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/security_descriptor_string_format.asp ,
this looks difficult an I will not go into it more in this entry, but this method can be very usefull also, for Example the Security and Configuration Wizard and Secedit INF files also use this format so you can use S&C-Editor to create SDDL strings or copy them from another place.but I will look at the first metod for this post, It takes a FileSystemAccessRule as parameter.
But how to make them, you can use the
MSH Get-MSDN Function for this, or use the following MSH Command :
MSH>[System.Security.AccessControl.FileSystemAccessRule].GetConstructors() | foreach {"$_"}
Void .ctor(System.Security.Principal.IdentityReference, System.Security.AccessControl.FileSystemRights, System.Security.AccessControl.Acces
sControlType)
Void .ctor(System.String, System.Security.AccessControl.FileSystemRights, System.Security.AccessControl.AccessControlType)
Void .ctor(System.Security.Principal.IdentityReference, System.Security.AccessControl.FileSystemRights, System.Security.AccessControl.Inher
itanceFlags, System.Security.AccessControl.PropagationFlags, System.Security.AccessControl.AccessControlType)
Void .ctor(System.String, System.Security.AccessControl.FileSystemRights, System.Security.AccessControl.InheritanceFlags, System.Security.A
ccessControl.PropagationFlags, System.Security.AccessControl.AccessControlType)
This looks a bit strange but Get-Member does not have a way to list the Constructors,
but don't worry the worst part is done.
the constructor we are going to use here is the second one :
Void .ctor(System.String, System.Security.AccessControl.FileSystemRights, System.Security.AccessControl.AccessControlType)it takes a string for the User Parameter so we don't have to make a System.Security.Principal.IdentityReference our self as in the first.
now the second parameter that takes a System.Security.AccessControl.FileSystemRights object as parameter.
this is an enum that looks like this :
MSH>[enum]::GetNames([System.Security.AccessControl.FileSystemRights])
ListDirectory
ReadData
WriteData
CreateFiles
CreateDirectories
AppendData
ReadExtendedAttributes
WriteExtendedAttributes
Traverse
ExecuteFile
DeleteSubdirectoriesAndFiles
ReadAttributes
WriteAttributes
Write
Delete
ReadPermissions
Read
ReadAndExecute
Modify
ChangePermissions
TakeOwnership
Synchronize
FullControl
the last parameter System.Security.AccessControl.AccessControlType has only 2 values "Allow" or "deny"
as we can use just the string representing the Enum value in MSH Most of the times(as long MSH can resolve an unique overload with used parameters)
the result would look like this :
$ar = new System.Security.AccessControl.FileSystemAccessRule("test","FullControl","Allow")
# and now just Add it, and put back the ACL with Set-Acl :
$acl.SetAccessRule($ar)
set-acl $acl
What is that all !, after all that work coming to this ?!?!
Yep ;-)
so the resulting script to add a user acces to a file would be this.
# Add-AclTxt.MSH
# Add's an ACL to a file using text parameters
# Usage Add-Acl "File" "user" "Rights" ("deny")
# /\/\o\/\/ 2006
# http://mow001.blogspot.com
function Add-AclTxt {
Param ($file,$user,
[System.Security.AccessControl.FileSystemRights]$Rights,
[System.Security.AccessControl.AccessControlType]$access = "Allow")
trap{Break}
$ar = new System.Security.AccessControl.FileSystemAccessRule($user,$Rights,$access)
# check if given user is Valid, this will break function if not so.
$Sid = $ar.IdentityReference.Translate([System.Security.Principal.securityidentifier])
$acl = get-acl $file
"Before"
$acl.AccessToString
$acl.SetAccessRule($ar)
set-acl $file $acl
"After"
(get-acl $file).AccessToString
}
you see it's not that difficult adding a simple accessrule in MSH, but the way to it showed that there also a lot more into setting ACL's but after you get used to construct things with .NET objects it's not as hard as it looks, only the way to find .NET-object constuctors in MSH is a bit akward, but you can use reflector or MSDN for that also.
Enjoy,
greetings /\/\o\/\/
Tags : Monad msh