Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature request] Implement way to manage certificate managers/enrolment agents rights #12

Open
jalliot opened this issue Feb 5, 2018 · 0 comments

Comments

@jalliot
Copy link

jalliot commented Feb 5, 2018

See blog post https://www.sysadmins.lv/blog-en/how-to-read-adcs-enrollment-agentcertificate-manager-rights-in-powershell.aspx

This would be good to have this officially implemented in pkix.net/PSPKI module and thus be able to read but also write certificate managers and enrolment agents rights.

One step further would be to implement a method actually checking the current user's permissions (based on its current security token) for a given template.
I did write such a method some time ago, using a slightly modified version of your Get-OfficerRights function from the blog post. It is quite ugly but if it may help you some bit, here it is:

# We don't use the simpler $CertificationAuthority.GetMyRoles() either because it
# does not check "deny only" SIDs and does not test certificate mnagers restrictions
function Test-CertificateManager {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('CA')]
        [PKI.CertificateServices.CertificateAuthority] $CertificationAuthority,

        [PKI.CertificateTemplates.CertificateTemplate] $Template
    )

    # Get current user's identities
    $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $allowedSids = @($currentUser.UserClaims |
        Where-Object Type -in ([System.Security.Claims.ClaimTypes]::PrimaryGroupSid,
                               [System.Security.Claims.ClaimTypes]::PrimarySid,
                               [System.Security.Claims.ClaimTypes]::GroupSid,
                               [System.Security.Claims.ClaimTypes]::Sid) |
        ForEach-Object { $_.Value })
    $deniedSids = $allowedSids + @($currentUser.UserClaims |
        Where-Object Type -in ([System.Security.Claims.ClaimTypes]::DenyOnlyPrimaryGroupSid,
                               [System.Security.Claims.ClaimTypes]::DenyOnlyPrimarySid,
                               [System.Security.Claims.ClaimTypes]::DenyOnlySid) |
        ForEach-Object { $_.Value })

    $denied = $false
    $allowed = $false
    (Get-CASecurityDescriptor -CertificationAuthority $CertificationAuthority).Access |
        Where-Object {
            $_.CertificationAuthorityRights -band [PKI.Security.AccessControl.CertificationAuthorityRights]::ManageCertificates
        } |
        ForEach-Object {
            $sid = $_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value
            if ($_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Deny -and $sid -in $deniedSids) {
                $denied = $true
            } elseif ($_.AccessControlType -eq [System.Security.AccessControl.AccessControlType]::Allow -and $sid -in $allowedSids) {
                $allowed = $true
            }
        }

    $isOfficer = -not $denied -and $allowed
    if (-not $Template -or -not $isOfficer) {
        return $isOfficer
    }

    # Test certificate managers restrictions
    $CertAdmin = New-Object -ComObject CertificateAuthority.Admin
    try {
        $aclBytes = $CertAdmin.GetConfigEntry($CertificationAuthority.ConfigString, [String]::Empty, 'OfficerRights')
        $denied = $false
        $allowed = $false
        Convert-OfficerRights $aclBytes |
            Where-Object { [String]::IsNullOrEmpty($_.Template) -or $_.Template.Value -eq $Template.OID.Value } |
            Where-Object {
                $ret = $false
                $toBeTestedSids = if ($_.AceType -eq [System.Security.AccessControl.AceQualifier]::AccessDenied) { $deniedSids } else { $allowedSids }
                $_.Securables | ForEach-Object { $ret = $ret -or $_ -in $toBeTestedSids }
                $ret
            } |
            ForEach-Object {
                if ($_.AceType -eq [System.Security.AccessControl.AceQualifier]::AccessDenied -and $_.Officer -in $deniedSids) {
                    $denied = $true
                } elseif ($_.AceType -eq [System.Security.AccessControl.AceQualifier]::AccessAllowed -and $_.Officer -in $allowedSids) {
                    $allowed = $true
                }
            }

        return -not $denied -and $allowed

    } catch {
        # There is no restriction applied so return previous result
        return $isOfficer
    } finally {
        [void] [Runtime.InteropServices.Marshal]::ReleaseComObject($CertAdmin)
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants