-
Notifications
You must be signed in to change notification settings - Fork 22
Open
Labels
Description
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)
}
}