Feb 23, 2018 10:47:23 AM
Efficient Digital Certificate Management with APIs


Digital Certificate Provisioning

Consider the following scenario: A dozen employees are joining your development team from another site. They already have workstations, but they don't have the client certificates needed to access your source code repository.

Do you:

  1. Have your sysadmin walk around to each workstation, enroll for a certificate, and install it.
  2. Direct all of the employees to visit the CMS enrollment portal and request a certificate, approve the requests, and direct the employees to install them in the correct place.
  3. Run a 15-line PowerShell script that finds the users' computers, obtains a certificate for each one, and automatically pushes the certificate to the appropriate machine store via the CMS Windows Agent.

In the first two cases, coordination is required between more than a dozen individuals. Not only that, these options do nothing to help with the next dozen employees to come on board. However, with an API-based solution, you can develop an automated, repeatable process in a short, simple PowerShell script. A script that doesn't care whether it's issuing a dozen certificates for new employees or ten thousand certificates for the whole organization. Such a script is shown at the end of this post as "Script 1." Furthermore, if you can launch the script from another part of your onboarding and provisioning process, you now have a zero-touch solution for issuing certificates every time you need them.

Digital Certificate Management

CMS can help with the converse scenario too. Suppose a group of employees is leaving a division. The employees each had personal certificates, as well as certificates on their workstations and other devices, to access a variety of applications specific to the group. You want to immediately revoke all certificates that these employees have access to.

Do you:

  1. Have your sysadmins scan their machines for installed certificates, scan the CAs for certificates issued to them, revoke those, and hope that you found them all.
  2. Use the CMS Management Portal to go through the employees and workstations, search for certificates issued to them or present on their devices and revoke them manually.
  3. Run a 15-line PowerShell script that searches your certificate inventory for all certificates issued to these users or present on their workstation, and automatically revokes them all.

Once again, just a few lines of scripting allows time-sensitive operations to be performed quickly, consistently, and thoroughly, with little regard for how many users and machines are affected, or for when and how often it is executed. An example script for this is provided at the end as well, labeled "Script 2."

This API is in no way limited to workforce changes either. Scenarios where virtual machines are spun up dynamically for software testing or other cases where a sandbox environment is needed can leverage the PowerShell SDK at startup to provision any certificates needed for the applications. Web servers with expiring certificates can, with zero-touch by staff, automatically generate a public/private keypair and use it to request a new certificate with the same content to ensure continued server operation. A migration of certificates from aging cryptographic algorithms (or worse, a compromised CA) to newer and more secure algorithms (such as from SHA-1 to SHA-2) can be easily orchestrated to occur at a large scale.

Secure Application Development with APIs

While the PowerShell SDK can help with many issues encountered in system administration and DevOps scenarios, there are of course scenarios where PowerShell scripting is not the best tool. For software developers looking to add or enhance certificate usage in their application, or for administrators working in an environment where PowerShell is not supported, the CMS Web API can be of significant use. For example, a web application can access all of the same functionality that the PowerShell SDK provides by making AJAX requests from JavaScript. Similarly, software developers writing applications in Java or other popular languages can leverage the same APIs. An application running on Linux can access the APIs through a Python script or any other system capable of generating HTTP requests, so Linux servers with expiring certificates or involved in a SHA-1 to SHA-2 migration can still obtain new certificates with on-device key generation. Likewise, the PowerShell scripts using the SDK from the earlier scenarios could be implemented in any other language by using the Web API instead of the SDK.

Another feature of CMS for which the Web API and PowerShell SDK significantly extends other capabilities is certificate metadata. While a great deal of information can be put into a certificate, there is no way to change this data once the certificate is issued and cryptographically signed. Certificates tagged with metadata can address scenarios where associated data may change over the lifetime of a certificate. This includes information describing the individual or group that owns the certificate, the applications that depend on it, the date on which it should be renewed, future migration plans, or any other content that's either subject to change or not known at issuance time. This metadata tagging system can also be used to dynamically enable and disable access to other applications by location, time of day, or other criteria. A sample python script is provided at the end as "Script 3," that programmatically checks if a certificate (provided in base64 PEM encoding) is enabled. In fact, with our tools like the CMS VerdeTTo Access Valve, you can add these enhanced authentication mechanisms at the server platform level without modification to your backend code. So in the second scenario above, the certificates for the departing employees could be temporarily disabled instead of outright revoked by updating a metadata value. This would mean that, if disabling a certificate turns out to impact other users or systems, that certificate could be temporarily re-enabled on a case-by-case basis until a replacement certificate can be issued. Not only that, but with the "Renew" Web API method or the corresponding PowerShell cmdlet, these certificates can quickly be renewed and automatically installed in all locations where they are still needed. In all of these cases and many others, the CMS Web API provides the easiest way to implement repeatable, reliable processes while saving time and minimizing risk.


Script 1: PowerShell for automatic certificate enrollment and installation to target users' machines.

Param ([pscredential]$cred, [string]$UsersFile, [string]$APISecret) 
# CMS client general configuration
$APIApp = New-CMSEnrollmentContext -Key "607616a3fc0b7c749d27" - Secret $APISecret
# List the accounts of users who need certificates
$Users = Get-Content -Path ]$UsersFile 
# Get the list of machines in the environment
$Computers = Get-ADComputer -Filter {(enabled -eq "true")} 
$Computers = $Computers | Select-Object -ExpandProperty DnsHostName 
# Find the computers used by the employees who need certificates
ForEach($Computer in $Computers){
$Profiles = Get-WmiObject -Class Win32_UserProfile -Computer $Computer
ForEach($Profile in $Profiles){
$profileSID = New-Object System.Security.Principal.SecurityIdentifier($Profile.sid)
$username = $profileSID.Translate([System.Security.Principal.NTAccount]).value
if($Users.Contains($username)){  # This is a machine that needs a new cert
# Define a certificate store
$store = Add-CMSCertificateStore -ClientMachine $Computer -CertificateStoreType 
"IIS Personal" -StorePath "IIS Personal" -Password (ConvertTo-SecureString 
"password" -AsPlainText -force) -AgentName Dev1.dev.cms -CMSUri 
http://localhost/CMSAPI -Credential $cred
# Request a certificate as a PFX
$pfx = New-CMSPfxEnrollment -ApiEnrollmentContext $APIApp -TemplateName 
"UserServer" -PfxPassword $password -SubjectName "CN=$username" -CMSUri 
http://localhost/CMSAPI -Credential $cred
# Schedule the new PFX to be added to the new store.
Add-CMSCertificateStoreCert -CertificateStore $store -PFX $pfx.Pkcs12Blob 
-PfxPassword $password -HasEntryPassword $FALSE -Overwrite $TRUE 
-Alias "sourceControlCert" -CMSUri http://localhost/CMSAPI -Credential $cred



Script 2: PowerShell for automatic certificate revocation for target users and their machines. 

Param ([pscredential]$cred, [string]$UsersFile, [string]$MachinesFile) 
# List the accounts of users with certificates to be revoked
$Users = Get-Content -Path $UsersFile
# Find certificates issued to any of these users and revoke them
ForEach($User in $Users){
$certs = Search-CMSCertificate -Query ("CN -contains ""$User""") -CMSUri 
http://localhost/CMSAPI -Credential $cred
ForEach($cert in $certs){
Revoke-CMSCertificate -Info $cert -Comment "Cessation of operation" -Reason 5 
# Get the list of machines (by hostname) used by these employees
$Machines = Get-Content -Path $MachinesFile 
# Find certificates present on any of these machines and revoke them
ForEach($Machine in $Machines){
$stores = Show-CMSCertificateStores -CMSUri http://localhost/CMSAPI -Credential $cred 
| Where-Object {$_.ClientMachine -eq $Machine}
ForEach($store in $stores){
$inventory = Get-CMSCertificateStoreInventory -CertificateStore $store -CMSUri 
http://localhost/CMSAPI -Credential $cred
$certIds = $inventory | Select-Object -ExpandProperty Certificates 
| Select-Object -ExpandProperty CertificateId
Foreach ($certId in $certIds){
Revoke-CMSCertificate -CMSID $certId -Comment "Cessation of operation" 
-Reason 5 -CMSUri http://localhost/CMSAPI -Credential $cred



Script 3: Python using the CMS Web API to determine, based on a metadata value, if a cert is enabled.

import base64       # For encoding credentials
import json         # For decoding http response
import urllib2      # For http request
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
# Sends an HTTP request and returns the response
def getResponse(endpoint, data, credentials):
request = urllib2.Request(endpoint)
request.add_header("Authorization","Basic " + base64.b64encode(credentials))
return urllib2.urlopen(request).read()
# Returns whether or not the certificate is enabled via CMS Web API.
# Uses the certificate thumbprint to identify the cert to the metadata API.
def checkAccessEnabled(PEM_cert, credentials):
certificate = x509.load_pem_x509_certificate(PEM_cert, default_backend())
thumbprint = certificate.fingerprint(hashes.SHA1()).encode("hex")
endpoint = "http://localhost/CMSAPI/Metadata/2/Compare"
data = '{"Key" : "Thumbprint", "Thumbprint" : "'+thumbprint+'","metadatalist" : {"isEnabled" : "True"}}'
return json.loads(getResponse(endpoint, data, credentials))


For more on how to operationalize certificate management with efficiency, download the PKI Automation for the Future white paper:

Download White Paper