Determining effective permissions

This is something that I've wondered about here and there over the years, but never really had a good answer to. How is one intended to determine effective permissions for the interactive user at runtime?

There is edsaObjectRightsEffective, but that only tells you effective rights at the object-level, not the attribute level. There is edsvaATLinksEffective, which should work, but that means I would have to loop through all of the templates, calculate/expand group membership for each applied item, and accumulate them all into a table to determine effective rights - a very resource-intensive (aka slow) proposition, I'm sure. Active Roles must have already calculated this, but I cannot seem to figure out how to access this. I tried querying nTSecurityDescriptor and edsaActiveDirectoryACEs, but neither of these are accessible to a delegated user.

Obviously both the MMC and Web interface have some kind of mechanism for making this determination (how else would the product know that the description attribute should be rendered read-only because the interactive user does not have write privileges to it, for example), but I'm too dumb to figure it out.

TL;DR: How do you programmatically determine if the interactive user has privileges to modify the description attribute on a user?

Thanks!

Parents
  • Hi Shawn,

    The script published in the following thread is very useful:

    (+) Access Template Link Reporting - Forum - Active Roles Community - One Identity Community

    You can query a specific delegate, and the output will show the specific ACLs granted to this delegate and the target where the delegate has these permissions applied to:

    Jose

  • Thanks, Jose!

    That is useful, but ultimately I was hoping that I could access something that would straight-up tell me what privileges I have without having to calculate the cumulative total of what all of the templates contain.

    The best that I've come up with is to use edsaObjetRightsEffective to calculate object-level rights, then rely on allowedAttributesEffective to tell me what attributes are writable by the current user. Not quite as nice as having something that would explicitly tell you "You have effective Read to this list of attributes, and Write to these", but it seems like the closes I can get.

    EDIT: Seems that I'm having some site difficulty and it's not allowing me to submit a code block; hopefully the code below doesn't get too mangled.

    ---
    $ObjectPath = "EDMS://CN=myObject,OU=SomeOU,DC=domain,DC=com"

    $adObject = [adsi]$ObjectPath
    $adObject.RefreshCache(@("distinguishedName", "edsaObjectRightsEffective", "allowedAttributesEffective"))

    $rightsMap = [ordered]@{
        EDS_RIGHT_DS_CREATE_CHILD   = 1
        EDS_RIGHT_DS_DELETE_CHILD   = 2
        EDS_RIGHT_ACTRL_DS_LIST     = 4
        EDS_RIGHT_DS_SELF           = 8
        EDS_RIGHT_DS_READ_PROP      = 16
        EDS_RIGHT_DS_WRITE_PROP     = 32
        EDS_RIGHT_DS_DELETE_TREE    = 64
        EDS_RIGHT_DS_LIST_OBJECT    = 128
        EDS_RIGHT_DS_CONTROL_ACCESS = 256
        EDS_RIGHT_EDS_COPY          = 512
        EDS_RIGHT_EDS_MOVE          = 2048
        EDS_RIGHT_EDS_MOVE_TO       = 4096
        EDS_RIGHT_DELETE            = 65536
        EDS_RIGHT_READ_CONTROL      = 131072
        EDS_RIGHT_WRITE_DAC         = 262144
        EDS_RIGHT_WRITE_OWNER       = 524288
    }

    $effectiveRightsValue = [int64]$adObject.Properties["edsaObjectRightsEffective"].Value
    $effectiveRightsNames = foreach ($entry in $rightsMap.GetEnumerator()) {
        if (($effectiveRightsValue -band [int64]$entry.Value) -eq [int64]$entry.Value) {
            $entry.Key
        }
    }

    ("adObject: '$($adObject.distinguishedName)'.") | Write-Host
    ("edsaObjectRightsEffective value: $effectiveRightsValue.") | Write-Host
    if ($effectiveRightsNames) {
        $effectiveRightsNames | ForEach-Object {
            ("`t{0}" -f $_) | Write-Host
        }
    }
    else {
        "`t(none recognized)" | Write-Host
    }

    # allowedAttributesEffective (AD): attributes the caller may write on this object.
    # Infer each listed ldapDisplayName as EDS_RIGHT_DS_WRITE_PROP scoped to that property.
    Write-Host ""
    Write-Host "allowedAttributesEffective (inferred EDS_RIGHT_DS_WRITE_PROP per attribute):"
    try {
        $aaeRaw = $adObject.Properties["allowedAttributesEffective"].Value
        $aaeList = @(
            if ($null -eq $aaeRaw) { }
            elseif ($aaeRaw -is [System.Collections.IEnumerable] -and -not ($aaeRaw -is [string])) {
                foreach ($item in $aaeRaw) { [string]$item }
            }
            else {
                [string]$aaeRaw
            }
        ) | Where-Object { $_ -and $_.Length -gt 0 } | Sort-Object -Unique

        if ($aaeList.Count -eq 0) {
            Write-Host "`t(no attributes listed, or attribute unavailable on this binding)"
        }
        else {
            foreach ($attr in $aaeList) {
                Write-Host ("`tEDS_RIGHT_DS_WRITE_PROP -> '{0}'" -f $attr)
            }
            Write-Host ("`t({0} writable attribute(s))" -f $aaeList.Count)
        }
    }
    catch {
        Write-Host ("`t(error reading allowedAttributesEffective: {0})" -f $_.Exception.Message)
    }

    $null = $adObject.Dispose()

Reply
  • Thanks, Jose!

    That is useful, but ultimately I was hoping that I could access something that would straight-up tell me what privileges I have without having to calculate the cumulative total of what all of the templates contain.

    The best that I've come up with is to use edsaObjetRightsEffective to calculate object-level rights, then rely on allowedAttributesEffective to tell me what attributes are writable by the current user. Not quite as nice as having something that would explicitly tell you "You have effective Read to this list of attributes, and Write to these", but it seems like the closes I can get.

    EDIT: Seems that I'm having some site difficulty and it's not allowing me to submit a code block; hopefully the code below doesn't get too mangled.

    ---
    $ObjectPath = "EDMS://CN=myObject,OU=SomeOU,DC=domain,DC=com"

    $adObject = [adsi]$ObjectPath
    $adObject.RefreshCache(@("distinguishedName", "edsaObjectRightsEffective", "allowedAttributesEffective"))

    $rightsMap = [ordered]@{
        EDS_RIGHT_DS_CREATE_CHILD   = 1
        EDS_RIGHT_DS_DELETE_CHILD   = 2
        EDS_RIGHT_ACTRL_DS_LIST     = 4
        EDS_RIGHT_DS_SELF           = 8
        EDS_RIGHT_DS_READ_PROP      = 16
        EDS_RIGHT_DS_WRITE_PROP     = 32
        EDS_RIGHT_DS_DELETE_TREE    = 64
        EDS_RIGHT_DS_LIST_OBJECT    = 128
        EDS_RIGHT_DS_CONTROL_ACCESS = 256
        EDS_RIGHT_EDS_COPY          = 512
        EDS_RIGHT_EDS_MOVE          = 2048
        EDS_RIGHT_EDS_MOVE_TO       = 4096
        EDS_RIGHT_DELETE            = 65536
        EDS_RIGHT_READ_CONTROL      = 131072
        EDS_RIGHT_WRITE_DAC         = 262144
        EDS_RIGHT_WRITE_OWNER       = 524288
    }

    $effectiveRightsValue = [int64]$adObject.Properties["edsaObjectRightsEffective"].Value
    $effectiveRightsNames = foreach ($entry in $rightsMap.GetEnumerator()) {
        if (($effectiveRightsValue -band [int64]$entry.Value) -eq [int64]$entry.Value) {
            $entry.Key
        }
    }

    ("adObject: '$($adObject.distinguishedName)'.") | Write-Host
    ("edsaObjectRightsEffective value: $effectiveRightsValue.") | Write-Host
    if ($effectiveRightsNames) {
        $effectiveRightsNames | ForEach-Object {
            ("`t{0}" -f $_) | Write-Host
        }
    }
    else {
        "`t(none recognized)" | Write-Host
    }

    # allowedAttributesEffective (AD): attributes the caller may write on this object.
    # Infer each listed ldapDisplayName as EDS_RIGHT_DS_WRITE_PROP scoped to that property.
    Write-Host ""
    Write-Host "allowedAttributesEffective (inferred EDS_RIGHT_DS_WRITE_PROP per attribute):"
    try {
        $aaeRaw = $adObject.Properties["allowedAttributesEffective"].Value
        $aaeList = @(
            if ($null -eq $aaeRaw) { }
            elseif ($aaeRaw -is [System.Collections.IEnumerable] -and -not ($aaeRaw -is [string])) {
                foreach ($item in $aaeRaw) { [string]$item }
            }
            else {
                [string]$aaeRaw
            }
        ) | Where-Object { $_ -and $_.Length -gt 0 } | Sort-Object -Unique

        if ($aaeList.Count -eq 0) {
            Write-Host "`t(no attributes listed, or attribute unavailable on this binding)"
        }
        else {
            foreach ($attr in $aaeList) {
                Write-Host ("`tEDS_RIGHT_DS_WRITE_PROP -> '{0}'" -f $attr)
            }
            Write-Host ("`t({0} writable attribute(s))" -f $aaeList.Count)
        }
    }
    catch {
        Write-Host ("`t(error reading allowedAttributesEffective: {0})" -f $_.Exception.Message)
    }

    $null = $adObject.Dispose()

Children
No Data