0
votes

I searched and read some topics here but I didn't found what I am looking for.

Basically, I want to check the effective permissions for a specific user for several shares, I want a script such as :

$user = Read-Host "Enter username"
$shares = "\\serverABC\share2","\\serverABC\share1"

foreach ($share in $shares)
{
    Cmdlet-EffectivePermissions $share
}

Output expected :

\\serverABC\share1
Full Control : No
Traverse folder / execute / file : YEs
List folder / read data : No
...

\\serverABC\share2"
Full Control : No
Traverse folder / execute / file : YEs
List folder / read data : No
...

In fact, I want to do in Powershell exactly the same way that effective permissions Tab.

Does it exist a built-in solution (without importing any modules, add-ins, ...) with .NET Method (GetUserEffectivePermissions) or with Get-ACL?

enter image description here

1

1 Answers

3
votes

I'm not aware of a .NET/PowerShell way to do this natively. There is a PowerShell module here that should be able to do what you're looking for, though. After importing that, you should be able to modify your pseudo code to the following:

$user = Read-Host "Enter username"
$shares = "\\serverABC\share2","\\serverABC\share1"

foreach ($share in $shares) {
    Get-EffectiveAccess -Path $share -Principal $user -ListAllRights
}

That returns PS objects instead of simple text. If the format isn't to your liking, you can use some of the utility commands to shape it however you like. Here are two examples of doing that:

First, a simple change to original that doesn't return the exact format you mentioned, but it's pretty close:

foreach ($share in $shares) {
    $share
    Get-EffectiveAccess -Path $share -Principal $user -ListAllRights | ForEach-Object {
        "{0}: {1}" -f $_.Permission, $_.Allowed
    }
    ""
}

Next, a more complicated change that formats the output exactly how you were asking (at least I think):

# Go through each FileSystemRights enum name and add them to a hash table if their value is
# a power of 2. This will also keep track of names that share a value, and later those can
# be combined to provide a friendly permission name
$Ht = @{}
foreach ($Name in [System.Enum]::GetNames([System.Security.AccessControl.FileSystemRights])) {
    $Value = [System.Security.AccessControl.FileSystemRights]::$Name

    if ($Value.value__ -band ($Value.value__ - 1)) {
        # Not a power of 2, so ignore this
        continue
    }

    if (-not $Ht.$Value) {
        $Ht.$Value = @()
    }

    $Ht.$Value += $Name
}

# FullControl isn't a power of 2, but it's useful to test for access, so add it manually
$Ht.([System.Security.AccessControl.FileSystemRights]::FullControl) = "FullControl"

function YesNoTest {
    param(
        [System.Security.AccessControl.FileSystemRights] $EffectiveAccess,
        [System.Security.AccessControl.FileSystemRights] $AccessToTest
    )

    if (($EffectiveAccess -band $AccessToTest) -eq $AccessToTest) {
        "Yes"
    }
    else {
        "No"
    }
}

$shares | Get-EffectiveAccess -Principal $user | ForEach-Object {
    $_.DisplayName

    $EffectiveAccess = $_.EffectiveAccess
    $Ht.GetEnumerator() | sort { $_.Key.value__ } -Descending | ForEach-Object {
        "{0}: {1}" -f ($_.Value -join " / "), (YesNoTest $EffectiveAccess $_.Key)
    }
    ""
}

Note that this won't be completely accurate if you run this against a remote system and the following conditions are met:

  • The security descriptor contains groups that are local to the remote system, i.e., non domain groups
  • The user(s) you're checking is a member of one of the local groups