问题
I want to check whether a given user has access to a given folder - by checking if they have "Modify" access assigned to them.
I thought that the PS for that would be:
(Get-Acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} |?{$_.filesystemrights.value -contains "Modify"}
But the final part of that isn't working - I get back no result. But I know that they have Modify access - if I put in:
(Get-Acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} | select -ExpandProperty filesystemrights
then I get back:
Modify, Synchronize
ReadAndExecute, Synchronize
Is this because the FileSystemRights property is an enumeration? And if so, how do I test against it?
回答1:
It's a type problem. (Get-Acl .\myfolder).Access[].FileSystemRights
is of type System.Security.AccessControl.FileSystemRights
. It's not really displaying a string. To make it a string, just use the ToString()
method:
(Get-Acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} |?{$_.filesystemrights.ToString() -contains "Modify"}
Or you can use the bitwise comparison method. However, it's very easy to confuse when you want to use this:
($_.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Modify) -eq [System.Security.AccessControl.FileSystemRights]::Modify
With when you want to use this:
($_.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Modify) -eq $_.FileSystemRights
They have very different meanings. For example, if you have Full Control, the former test is still true. Is that what you want? Or do you want to know when the FileSystemRights
are literally just Modify
?
Also, [System.Security.AccessControl.FileSystemRights]
is an incomplete enumeration. In my environment, I found 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's interesting to compare the output of these:
[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 GENERIC
rights are not enumerated in the .Net class, but you will see that numeric value if you enumerate enough files.
Good luck!
回答2:
Got it:
(get-acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} | ?{($_.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Modify) -eq [System.Security.AccessControl.FileSystemRights]::Modify}
It's both a bitwise comparison - and therefore you need to use "-band".
But "-band" will return true if any of the same bits are set in both enumerations. And as even "Read" has several bits set (it's 100000000010001001) - some of which will match with "Modify", you need to also compare the result with "Modify" to make sure that the result is actually the same.
(Thanks to the comments below for getting me pointed in the right direction.)
回答3:
Updated new version.
Clarified version from Arco's comment.
With this version we're checking if the Modify bit is set.
(Get-Acl .\myfolder).Access | ?{$_.IdentityReference -eq "BUILTIN\Users"} |?{ $_.FileSystemRights -band [Security.AccessControl.FileSystemRights]::Modify}
The value__ property is the numeric bit set version.
来源:https://stackoverflow.com/questions/27529174/how-can-i-compare-against-filesystemrights-using-powershell