Share this post: |
Hey, Scripting Guy! I am trying to get a handle around the security of a folder on my computer. I need to be able to figure out a way to determine who has access and what those access rights are. I guess I could use the Icacls utility, but I prefer to use something that is native to Windows PowerShell so that I can work with the objects that are returned and not have to waste a bunch of time parsing text.
— BH
Hello BH,
Microsoft Scripting Guy Ed Wilson here. If you have friended me on Facebook, you know that today is my birthday. I am at the point where having a birthday is not necessarily a cause for celebration—the Scripting Wife has not made me a cake and ice cream or invited my friends over for a party. At least not in the last couple of years. But still, I would rather have a birthday than not have a birthday so I am in a good mood. In addition, with the Scripting Wife, one never knows what she may have up her sleeve for the occasion.
Back to your question. If you do not want to use the Icacls utility because it is not native to Windows PowerShell, the best tool to use to work with security on a folder is the Windows PowerShell Get-Acl cmdlet. When you use the Get-Acl cmdlet and give it the path to a folder, it returns an instance of the System.Security.AccessControl.DirectorySecurity object, which is documented on MSDN and is used to represent the access control and the audit security for a directory. It specifies the access rights for a directory and how access attempts are audited. The class represents each of the access and audit rights as a set of rules. The access rules are presented as instances of the System.Security.AccessControl.FileSystemAccessRule object and the audit rules are presented as instances of the System.Security.AccessControl.FileSystemAuditRule class.
To retrieve the DirectorySecurity object using the Get-Acl cmdlet, you specify the path to the folder via the path parameter. This is seen here:
PS C:\> Get-Acl -Path C:\fso
Directory: C:\
Path Owner Access
—- —– ——
fso BUILTIN\Administrators NWTRADERS\Administrato…
PS C:\>
You can see from the output that the Owner property is returned. The Access property is truncated and does not display all of the users who have access to the folder. You might decide to pipe the results to the Select-Object cmdlet and choose the Access property. When you use this technique, as seen here, the Access control information is still truncated:
PS C:\> Get-Acl -Path C:\fso | select-object access
Access
——
{System.Security.AccessControl.FileSystemAccessRule, System.Security.AccessC…
PS C:\>
If you pipe the result of the Select-Object cmdlet to the Format-List cmdlet and choose all of the properties, you will finally be able to see all of the information returned from the Access property. As seen here, however, the results are not what might be expected:
PS C:\> Get-Acl -Path C:\fso | select-object access | Format-List *
Access : {System.Security.AccessControl.FileSystemAccessRule, System.Security.A
ccessControl.FileSystemAccessRule, System.Security.AccessControl.FileS
ystemAccessRule, System.Security.AccessControl.FileSystemAccessRule…
}
PS C:\>
To retrieve a list of the users who have access to the folder, you need to use the accessToString property because the access rights to the folder is stored as a series of FileSystemAccessRules. After you have piped the results to the Format-List cmdlet, you no longer have a DirectorySecurity object. You have a formatted textual representation of the underlying object. This is seen here:
PS C:\> Get-Acl -Path C:\fso | Format-List AccessToString
AccessToString : NWTRADERS\Administrator Allow FullControl
BUILTIN\Administrators Allow FullControl
BUILTIN\Administrators Allow 268435456
NT AUTHORITY\SYSTEM Allow FullControl
NT AUTHORITY\SYSTEM Allow 268435456
BUILTIN\Users Allow ReadAndExecute, Synchronize
NT AUTHORITY\Authenticated Users Allow Modify, Synchronize
NT AUTHORITY\Authenticated Users Allow -536805376
If you wish to write to a text file the list of people who have access to the folder, the above formatted list is quite acceptable. To write the users who have access to a text file, you can use the Out-File cmdlet as seen here:
PS C:\> Get-Acl -Path C:\fso | Format-List accessToString |
Out-File -FilePath c:\fso\fsoAcl.txt -Append
PS C:\>
When the above command is run, the following text file is seen:
If you prefer to work with the folder in a more direct manner, you can use the Get-Acl cmdlet to retrieve the DirectorySecurity object, and you can store it in a variable. This is seen here:
PS C:\> $acl = Get-Acl -Path C:\fso
PS C:\> $acl
Directory: C:\
Path Owner Access
—- —– ——
fso BUILTIN\Administrators NWTRADERS\Administrato…
PS C:\>
After you have the DirectorySecurity object stored in a variable, you can work directly with the underlying objects. This is shown here:
PS C:\> $acl = Get-Acl -Path C:\fso
PS C:\> $acl
Directory: C:\
Path Owner Access
—- —– ——
fso BUILTIN\Administrators NWTRADERS\Administrato…
To examine the methods and properties that are available from the object we have stored in the $acl variable, we use the Get-Member cmdlet. This is seen here:
PS C:\> $acl | Get-Member
TypeName: System.Security.AccessControl.DirectorySecurity
Name MemberType Definition
—- ———- ———-
Access CodeProperty System.Security.AccessControl…
Group CodeProperty System.String Group{get=GetGr…
Owner CodeProperty System.String Owner{get=GetOw…
Path CodeProperty System.String Path{get=GetPath;}
Sddl CodeProperty System.String Sddl{get=GetSddl;}
AccessRuleFactory Method System.Security.AccessControl…
AddAccessRule Method System.Void AddAccessRule(Sys…
AddAuditRule Method System.Void AddAuditRule(Syst…
AuditRuleFactory Method System.Security.AccessControl…
Equals Method bool Equals(System.Object obj)
GetAccessRules Method System.Security.AccessControl…
GetAuditRules Method System.Security.AccessControl…
GetGroup Method System.Security.Principal.Ide…
GetHashCode Method int GetHashCode()
GetOwner Method System.Security.Principal.Ide…
GetSecurityDescriptorBinaryForm Method byte[] GetSecurityDescriptorB…
GetSecurityDescriptorSddlForm Method string GetSecurityDescriptorS…
GetType Method type GetType()
ModifyAccessRule Method bool ModifyAccessRule(System….
ModifyAuditRule Method bool ModifyAuditRule(System.S…
PurgeAccessRules Method System.Void PurgeAccessRules(…
PurgeAuditRules Method System.Void PurgeAuditRules(S…
RemoveAccessRule Method bool RemoveAccessRule(System….
RemoveAccessRuleAll Method System.Void RemoveAccessRuleA…
RemoveAccessRuleSpecific Method System.Void RemoveAccessRuleS…
RemoveAuditRule Method bool RemoveAuditRule(System.S…
RemoveAuditRuleAll Method System.Void RemoveAuditRuleAl…
RemoveAuditRuleSpecific Method System.Void RemoveAuditRuleSp…
ResetAccessRule Method System.Void ResetAccessRule(S…
SetAccessRule Method System.Void SetAccessRule(Sys…
SetAccessRuleProtection Method System.Void SetAccessRuleProt…
SetAuditRule Method System.Void SetAuditRule(Syst…
SetAuditRuleProtection Method System.Void SetAuditRuleProte…
SetGroup Method System.Void SetGroup(System.S…
SetOwner Method System.Void SetOwner(System.S…
SetSecurityDescriptorBinaryForm Method System.Void SetSecurityDescri…
SetSecurityDescriptorSddlForm Method System.Void SetSecurityDescri…
ToString Method string ToString()
PSChildName NoteProperty System.String PSChildName=fso
PSDrive NoteProperty System.Management.Automation….
PSParentPath NoteProperty System.String PSParentPath=Mi…
PSPath NoteProperty System.String PSPath=Microsof…
PSProvider NoteProperty System.Management.Automation….
AccessRightType Property System.Type AccessRightType {…
AccessRuleType Property System.Type AccessRuleType {g…
AreAccessRulesCanonical Property System.Boolean AreAccessRules…
AreAccessRulesProtected Property System.Boolean AreAccessRules…
AreAuditRulesCanonical Property System.Boolean AreAuditRulesC…
AreAuditRulesProtected Property System.Boolean AreAuditRulesP…
AuditRuleType Property System.Type AuditRuleType {get;}
AccessToString ScriptProperty System.Object AccessToString …
AuditToString ScriptProperty System.Object AuditToString {…
The Access property is a codeproperty. This means it was added by the Windows PowerShell team. To see what you can do with the Access property, pipe it to the Get-Member cmdlet. This is seen here:
PS C:\> $acl.Access | Get-Member
TypeName: System.Security.AccessControl.FileSystemAccessRule
Name MemberType Definition
—- ———- ———-
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
AccessControlType Property System.Security.AccessControl.AccessControlType…
FileSystemRights Property System.Security.AccessControl.FileSystemRights …
IdentityReference Property System.Security.Principal.IdentityReference Ide…
InheritanceFlags Property System.Security.AccessControl.InheritanceFlags …
IsInherited Property System.Boolean IsInherited {get;}
PropagationFlags Property System.Security.AccessControl.PropagationFlags …
PS C:\>
The Access property returns an instance of the System.Security.AccessControl.FileSystemAccessRule .NET Framework class. When you look at the Access property, it displays the following information:
PS C:\> $acl.Access
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : NWTRADERS\Administrator
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : 268435456
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : 268435456
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
FileSystemRights : ReadAndExecute, Synchronize
AccessControlType : Allow
IdentityReference : BUILTIN\Users
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
FileSystemRights : Modify, Synchronize
AccessControlType : Allow
IdentityReference : NT AUTHORITY\Authenticated Users
IsInherited : True
InheritanceFlags : None
PropagationFlags : None
FileSystemRights : -536805376
AccessControlType : Allow
IdentityReference : NT AUTHORITY\Authenticated Users
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : InheritOnly
Because the System.Security.AccessControl.FileSystemAuditRule class is returned as a collection, you can index directly into it. This is seen here:
PS C:\> $acl.Access[0]
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : NWTRADERS\Administrator
IsInherited : False
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
The IdentityReference property returns an instance of System.Security.Principal.NTAccount .NET Framework class. The members of this object are seen here:
PS C:\> $acl.Access[0].identityReference | Get-Member
TypeName: System.Security.Principal.NTAccount
Name MemberType Definition
—- ———- ———-
Equals Method bool Equals(System.Object o)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
IsValidTargetType Method bool IsValidTargetType(type targetType)
ToString Method string ToString()
Translate Method System.Security.Principal.IdentityReference Tra…
Value Property System.String Value {get;}
The IdentityReference property points to a specific user account. You can use that property to return a list of all the users who have access to a folder. When you query the Value property, it returns a string. This is seen here:
PS C:\> $acl.Access | ForEach-Object { $_.identityReference.value }
NWTRADERS\Administrator
BUILTIN\Administrators
BUILTIN\Administrators
NT AUTHORITY\SYSTEM
NT AUTHORITY\SYSTEM
BUILTIN\Users
NT AUTHORITY\Authenticated Users
NT AUTHORITY\Authenticated Users
PS C:\>
If you wanted to search the list of users for a specific user who has rights, you could pipe the results to the Where-Object. This is seen here:
PS C:\> $acl.Access | ForEach-Object { $_.identityReference.value |
Where-Object { $_ -eq ‘nwtraders\administrator’ } }
NWTRADERS\Administrator
PS C:\>
Well, BH, this brings us to the end of another Hey, Scripting Guy! post. We hope we have inspired you to fire up Windows PowerShell and start playing around with the Get-Acl cmdlet.
If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson and Craig Liebendorfer, Scripting Guys
0 comments