CPS
The CPS API has been around for a long time and is the most common interface customers use to interact with certificates. The API itself, and by extension the PowerShell module, has support for DV, OV and EV certificates, even though the Akamai Terraform provider only supports DV. As such, PowerShell is often considered for interacting with OV or EV certificates, pushing changes to existing enrollments, or for auditing purposes.
Enrollments
In CPS, the most common object you interact with is the enrollment.
Retrieving Enrollments
You can list enrollments like this:
$Enrollments = Get-CPSEnrollmentYou could also use this function to perform certificate auditing. For example, if you wanted to find only those enrollments which are SNI-only, and display just the ID, common name, and network (Standard TLS vs Enhanced TLS), you could do this:
Get-CPSEnrollment | Where-Object { $_.networkConfiguration.sniOnly -eq $true } | Select-Object id, @{Name="CN";Expression={$_.csr.cn}}, @{Name="Network";Expression={$_.networkConfiguration.secureNetwork}}Typically, you would simply want to filter your list of enrollments to find a specific one by its common name, like this:
$Enrollment = Get-CPSEnrollment | Where-Object { $_.csr.cn -eq "www.example.com" }Alternatively, the same command can also be used to retrieve a single enrollment by its ID, if known:
$Enrollment = Get-CPSEnrollment -EnrollmentId 123456
$Enrollment
id : 12345
productionSlots : {30000}
stagingSlots : {30000}
assignedSlots : {30000}
location : /cps/v2/enrollments/12345
ra : lets-encrypt
validationType : dv
certificateType : san
certificateChainType : default
networkConfiguration : @{geography=core; secureNetwork=standard-tls; mustHaveCiphers=ak-akamai-2018q3; preferredCiphers=ak-akamai-2018q3;
fipsMode=False; disallowedTlsVersions=System.Object[]; sniOnly=True; quicEnabled=False; dnsNameSettings=; ocspStapling=on;
clientMutualAuthentication=}
signatureAlgorithm : SHA-256
changeManagement : False
csr : @{cn=www.example.com; c=GB; st=London; l=London; o=Akamai; ou=; sans=System.Object[]; preferredTrustChain=}
org : @{name=Akamai; addressLineOne=7 Air St; addressLineTwo=; city=London; region=London; postalCode=W1B5AD; country=GB;
phone=+44800800800}
orgId :
adminContact : @{firstName=Bob; lastName=Loblaw; phone=+44 203 800 800; email=bob@loblaws.com; addressLineOne=;
addressLineTwo=; city=; country=; organizationName=; postalCode=; region=; title=}
techContact : @{firstName=Tom; lastName=Leighton; phone=+44 203 800 800; email=tomleighton@akamai.com; addressLineOne=; addressLineTwo=;
city=; country=; organizationName=; postalCode=; region=; title=}
thirdParty :
enableMultiStackedCertificates : False
autoRenewalStartTime :
pendingChanges : {@{location=/cps/v2/enrollments/12345/changes/2345678; changeType=renewal; changeId=9144360}}
maxAllowedSanNames : 100
maxAllowedWildcardSanNames : 25The CPS API uses a versioned object model approach, which means that depending on the request headers you send, the object you receive may be different. More details can be found here (opens in a new tab), but when using PowerShell we always default to the latest version, so you shouldn't need to worry about it.
Creating Enrollments
As you can see, there are a lot of settings inside this object, which makes creating enrollments difficult. There are no user-friendly parameters for New-CPSEnrollment, purely because there are too many options and they are too complex, so typically we recommend finding a comparable enrollment (evenb on another account), exporting that either to JSON or a PSCustomObject, editing then pushing to the New endpoint. Like this:
$Enrollment = Get-CPSEnrollment -EnrollmentId 123456
$Enrollment.csr.cn = "new.example.com"
$Enrollment.csr.sans = @("new.example.com")
$Enrollment | New-CPSEnrollment -ContractID 1-2AB34CNote: the above command assumes that only the CSR and SANs would differ between your reference certificate and the new one. This is valid, but somewhat simplified. There are many, many other options you might change.
Updating Enrollments
Similar to how we create enrollments, updating enrollments is a pretty simple matter with PowerShell. You can do this generally either with the returned PSCustomObject, which is best for straightforward changes, or with a JSON file if you need a more wholistic view. Let's say you wanted to add a SAN to an existing enrollment, you could do this:
$Enrollment = Get-CPSEnrollment -EnrollmentId 123456
$Enrollment.csr.sans += "new-san.example.com"
$Enrollment | Set-CPSEnrollmentAlternatively, in JSON:
Get-CPSEnrollment -EnrollmentId 123456 | ConvertTo-Json -Depth 10 | Out-File "Enrollment.json"Then edit the JSON file to add the new SAN, and then push it back:
Set-CPSEnrollment -EnrollmentId 123456 -Body (Get-Content .\Enrollment.json -Raw)When using the pipeline, the
-EnrollmentIDparameter gets its data from the piped object. When using-Body, either with JSON data or PSCustomObject, you must provide it with the-EnrollmentIDparameter.
This command can often fail, specifically if the enrollment has pending changes, which you can see in the enrollment object. If this is the case, and you wish to update the enrollment anyway, you must add the -AllowCancelPendingChanges parameter.
Deleting Enrollments
Deleting an enrollment is a simple matter of using the Remove-CPSEnrollment command, like this:
Remove-CPSEnrollment -EnrollmentId 123456Or, more commonly, you would have retrieved your enrollment first, then piped it to the Remove-CPSEnrollment command, like this:
$Enrollment = Get-CPSEnrollment | Where-Object { $_.csr.cn -eq "www.example.com" }
$Enrollment | Remove-CPSEnrollmentor even
Get-CPSEnrollment | Where-Object { $_.csr.cn -eq "www.example.com" } | Remove-CPSEnrollmentThe above scenario with
-AllowCancelPendingChangesalso applies to deleting enrollments. If you have pending changes, you must use that parameter to delete the enrollment.
Working with changes
There are various CPS states which require interaction. Most common would be retrieving a CSR for a Third Party enrollment, and uploading its reciprocal signed certificate, but there are several others you can see below.
| Change Type | Command |
|---|---|
| Promote a certificate from staging to production when your enrollment has 'Always test on staging' enabled. | Complete-CPSChange |
| Retrieve third party CSR. | Get-CPSCSR |
| Upload third party signed certificate. | Add-CPSThirdPartyCert |
| Retrieve Lets Encrypt challenges for DV enrollments. | Get-CPSLetsEncryptChallenges |
| Instruct CPS that LE challenges are in place. | Confirm-CPSLetsEncryptChallengesCompleted |
| Retrieve pre-verification warning.s | Get-CPSPreVerificationWarnings |
| Acknowledge pre-verification warnings. | Confirm-CPSPreVerificationWarnings |
| Retrieve post-verification warnings. | Get-CPSPostVerificationWarnings |
| Acknowledge post-verification warnings. | Confirm-CPSPostVerificationWarnings |
| Schedule a timed deployment of a change. | Set-CPSDeploymentSchedule |
| Get the schedule for a timed deployment. | Get-CPSDeploymentSchedule |
Most of these changes in some way require a -ChangeID parameter. There is no API endpoint to list active changes, you can instead find them in the pendingChanges property of the enrollment object. You can also retrieve the status of a specific change by its ID, like this:
Get-CPSChangeStatus -EnrollmentId 123456 -ChangeId 2345678As way of an example, let's say you haved created a third party enrollment (we'll skip the creation part for brevity).
First, we retrieve the enrollment and hold it in a variable.
$Enrollment = Get-CPSEnrollment | Where-Object { $_.csr.cn -eq "www.example.com" }Next we need to set it not to proceed to production without approval.
$Enrollment.changeManagement = $true
$Enrollment | Set-CPSEnrollmentThen, we need to retrieve the CSR for the third party CA to sign.
$CSR = Get-CPSCSR -EnrollmentId $Enrollment.id -ChangeId $Enrollment.pendingChanges[0].changeId
$CSR.csrs | Where-Object keyAlgorithm -eq 'RSA' | Select-Object -ExpandProperty csr | Out-File "www.example.com.rsa.csr"
$CSR.csrs | Where-Object keyAlgorithm -eq 'ECDSA' | Select-Object -ExpandProperty csr | Out-File "www.example.com.ecdsa.csr"Next, once you have retrieved the signed certificate from your CA, you would save them into files in your directory. Those files can then be read into strings as part of the Add-CPSThirdPartyCert command, like this:
$Cert = Get-Content .\www.example.com.crt -Raw
$Chain = Get-Content .\www.example.com.chain.crt -Raw
Add-CPSThirdPartyCert -EnrollmentId $Enrollment.id -ChangeId $Enrollment.pendingChanges[0].changeId -Certificate $Cert -TrustChain $ChainThis should kick off the process to get your cert as far as the staging network, as we configured. Then, you would test the cert works as expected, and finally promote it to production, like this:
Complete-CPSChange -EnrollmentId $Enrollment.id -ChangeId $Enrollment.pendingChanges[0].changeId