Few days ago someone asked me how to programmatically test whether CA server is online, and which interfaces (both administration — ICertAdmin and/or enrollment — ICertRequest) are available.
At first, I want to mention that you can use the following CMD commands:
certutil –ping
Pings certificate management (ICertAdmin) and enrollment (ICertRequest) interfaces. Optionally you can ping remote CA interfaces: certutil –config CAHostName\CAName –ping
What if you want to do this programmatically? Nice question! Looking to CryptoAPI reference you can find the following methods: ICertAdminD::Ping and ICertRequestD::Ping methods. However, local COM interfaces does not support these methods. Workarounds? PowerShell has workaround! Here is a simple code example, that tests CA and interface availability:
function Test-CAOnline { [CmdletBinding()] param( [Parameter(Position = 0)] [string]$Config, [switch]$ShowUI ) $signature = @" [DllImport("Certadm.dll", CharSet=CharSet.Auto, SetLastError=true)] public static extern bool CertSrvIsServerOnline( string pwszServerName, ref bool pfServerOnline ); "@ Add-Type -MemberDefinition $signature -Namespace CryptoAPI -Name CertAdm $CertConfig = New-Object -ComObject CertificateAuthority.Config if ($Config -ne "" -and !$Config.Contains("\")) { Write-Error -Category InvalidArgument -ErrorId InvalidArgumentException ` -Message "Config string must be passed in 'CAHostName\CAName' form." break } elseif ($Config -eq "" -and !$ShowUI) { try {$Config = $CertConfig.GetConfig(0x3)} catch { Write-Error -Category ObjectNotFound -ErrorId ObjectNotFoundElement ` -Message "Certificate Services are not installed on local computer." break } } elseif ($Config -eq "" -and $ShowUI) { $Config = $CertConfig.GetConfig(0x1) } if ($Config) { [void]($Config -match "(.+)\\(.+)") $Server = $matches[1] $CAName = $matches[2] $ServerStatus = $false $hresult = [CryptoAPI.CertAdm]::CertSrvIsServerOnline($Server,[ref]$ServerStatus) if ($ServerStatus) { $CertAdmin = New-Object -ComObject CertificateAuthority.Admin $CertRequest = New-Object -ComObject CertificateAuthority.Request $CA = New-Object psobject -Property @{ Name = $CAName; ICertAdmin = $true; ICertRequest = $true } try {$retn = $CertAdmin.GetCAProperty($Config,0x6,0,4,0)} catch {$CA.ICertAdmin = $false} try {$retn = $CertRequest.GetCAProperty($Config,0x6,0,4,0)} catch {$CA.ICertRequest = $false} $CA } else { Write-Error -Category ObjectNotFound -ErrorId ObjectNotFoundException ` -Message "Unable to find a Certification Authority server on '$Server'." } } else {return} }
This is more complicated, but more helpful example. If you want to test local CA (when CA server is installed on the same computer), or remote CA server. Remote server can be specified explicitly by using –Config parameter. Remote CA server must be passed in a 'CAHostName\CAName' form. Alternatively you can use –ShowUI parameter to select from Enterprise CA list. In that case you must omit –Config parameter. Here are some useful examples:
[Administrator] Test-CAOnline Name ICertRequest ICertAdmin ---- ------------ ---------- Contoso CA True True [Administrator] Test-CAOnline -Config "dc2\contoso-dc2-ca" Name ICertRequest ICertAdmin ---- ------------ ---------- contoso-dc2-ca True True [Administrator] Test-CAOnline -ShowUI Name ICertRequest ICertAdmin ---- ------------ ---------- contoso-DC2-CA True True [Administrator]
If CA server is unavailable — an error will be thrown.
HTH.
works great however it requires the certification admin role be present on the box for that dll to be present :(
ICertAdmin part requires permissions. From what I know, ICertRequest doesn't require specific permissions to succeed.
Hi, Vadims.
Do you know how to interpret output of certutil -ping command? What does it mean: -> a (10) or -> 32 (50). Where i can read about it?
What is the prefered site (site awareness enabled) for requesting cert from Site5?
DsGetSiteName: PC -> Site5
DsGetSiteName[0]: EntSubca1 -> 0: site1 (2969ms)
DsGetSiteName[1]: subca02 -> 1: site2 (5406ms)
DsGetSiteName[2]: subca03 -> 0: site1 (2781ms)
DsGetSiteName[3]: subca04 -> 2: site3 (3672ms)
DsGetSiteName[4]: subca05 -> 0: site1 (2187ms)
DsGetSiteName[5]: subca06 -> 3: site4 (1594ms)
DsQuerySitesByCost: Site5
DsQuerySitesByCost[0]: site1: a (10)
DsQuerySitesByCost[1]: site2: 32 (50)
DsQuerySitesByCost[2]: site3: 32 (50)
DsQuerySitesByCost[3]: site4: 14 (20)
DsQuerySiteCosts[0.0]: EntSubca1(site1) -> a (10)
DsQuerySiteCosts[1.1]: subca02(site2) -> 32 (50)
DsQuerySiteCosts[2.0]: subca03(site1) -> a (10)
DsQuerySiteCosts[3.2]: subca04(site3) -> 32 (50)
DsQuerySiteCosts[4.0]: subca05(site1) -> a (10)
DsQuerySiteCosts[5.3]: subca06(site4) -> 14 (20)
CertUtil: -ping command completed successfully.
I believe, these numbers are costs to particular AD site. First number is in hex format and decimal equivalent in parenthesis.
Ha, Indeed! Thank you, Vadims. Those hex numbers confused me. And what about, for example DsQuerySiteCosts[5.3], what are those numbers in square brackets?
First index points to a site name, second index points to site cost.
Post your comment:
Comments: