How can I compare to FileSystemRights using Powershell?
I want to check if a given user has access to a given folder by checking to see if they have Edit access assigned to them.
I thought the PS for this would be:
(Get-Acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} |?{$_.filesystemrights.value -contains "Modify"}
But the last part of it doesn't work - I get no result. But I know they have Modify access - if I added:
(Get-Acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} | select -ExpandProperty filesystemrights
then I will return:
Modify, Synchronize ReadAndExecute, Synchronize
Is it because the FileSystemRights property is an enumeration? And if so, how should I try it out?
source to share
This is a type problem. (Get-Acl .\myfolder).Access[].FileSystemRights
has a type System.Security.AccessControl.FileSystemRights
. It doesn't show the line. To make it a string, just use the method ToString()
:
(Get-Acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} |?{$_.filesystemrights.ToString() -contains "Modify"}
Or you can use the bitwise comparison method. However, it is very easy to get confused when you want to use this:
($_.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Modify) -eq [System.Security.AccessControl.FileSystemRights]::Modify
If you want to use this:
($_.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Modify) -eq $_.FileSystemRights
They have very different meanings. For example, if you have complete control, the previous test is still valid. Is this what you want? Or do you want to know when FileSystemRights
literally simple Modify
?
It is also [System.Security.AccessControl.FileSystemRights]
an incomplete listing. In my environment, I found that I needed this table:
+-------------+------------------------------+------------------------------+
| Value | Name | Alias |
+-------------+------------------------------+------------------------------+
| -2147483648 | GENERIC_READ | GENERIC_READ |
| 1 | ReadData | ListDirectory |
| 1 | ReadData | ReadData |
| 2 | CreateFiles | CreateFiles |
| 2 | CreateFiles | WriteData |
| 4 | AppendData | AppendData |
| 4 | AppendData | CreateDirectories |
| 8 | ReadExtendedAttributes | ReadExtendedAttributes |
| 16 | WriteExtendedAttributes | WriteExtendedAttributes |
| 32 | ExecuteFile | ExecuteFile |
| 32 | ExecuteFile | Traverse |
| 64 | DeleteSubdirectoriesAndFiles | DeleteSubdirectoriesAndFiles |
| 128 | ReadAttributes | ReadAttributes |
| 256 | WriteAttributes | WriteAttributes |
| 278 | Write | Write |
| 65536 | Delete | Delete |
| 131072 | ReadPermissions | ReadPermissions |
| 131209 | Read | Read |
| 131241 | ReadAndExecute | ReadAndExecute |
| 197055 | Modify | Modify |
| 262144 | ChangePermissions | ChangePermissions |
| 524288 | TakeOwnership | TakeOwnership |
| 1048576 | Synchronize | Synchronize |
| 2032127 | FullControl | FullControl |
| 268435456 | GENERIC_ALL | GENERIC_ALL |
| 536870912 | GENERIC_EXECUTE | GENERIC_EXECUTE |
| 1073741824 | GENERIC_WRITE | GENERIC_WRITE |
+-------------+------------------------------+------------------------------+
It is interesting to compare the result:
[System.Enum]::GetNames([System.Security.AccessControl.FileSystemRights]);
[System.Enum]::GetNames([System.Security.AccessControl.FileSystemRights]) | % { "$($_.ToString())`t`t$([System.Security.AccessControl.FileSystemRights]$_.ToString())`t`t$(([System.Security.AccessControl.FileSystemRights]$_).value__)";}
[System.Enum]::GetValues([System.Security.AccessControl.FileSystemRights]) | % { "$($_.ToString())`t`t$(($_).value__)";}
The permissions are GENERIC
not listed in the .Net class, but you will see this numeric value if you list enough files.
Good luck!
source to share
Got this:
(get-acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} | ?{($_.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Modify) -eq [System.Security.AccessControl.FileSystemRights]::Modify}
It's also a bitwise comparison - and that's why you need to use "-band".
But "-band" will return true if any of the same bits are set in both enumerations. And since even Read has several bits (100000000010001001), some of which will correspond to Modify, you also need to compare the result with Modify to make sure the result is actually the same.
(Thanks for the comments below to get me pointed in the right direction.)
source to share
New version updated.
Adjusted version from Arco's comment.
In this version, we check if the modification bit is set.
(Get-Acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} |?{ $_.FileSystemRights -band [Security.AccessControl.FileSystemRights]::Modify}
Value__ is the numeric bit version.
source to share