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
 
          
 
