SSL.com’s SWS API – Introduction

Managing large numbers of certificates can be quite a hassle. Randomly-occurring incidents, such as the recent industry-wide serial number entropy issue, may require administrators to manually revoke and reissue hundreds of certificates at once. Our own support agents and administrators have also experienced this in the past, a fact which motivated SSL.com to implement a more practical solution: the SSL.com Web Services (SWS) API.

The SWS API can be used to automate various certificate-related operations, such as issuing certificates, re-keying and reprocessing orders, managing user access, and so on via any programming or scripting language. To get pregenerated API cURL commands for an individual order, try appending “/developer” at the end of that certificate order page (ie https://www.ssl.com/certificate_orders/co-1234xyz/developer).

To introduce some of the API’s features, this tutorial will walk you through the issuance of a domain-validated (DV) web server certificate. In the process we will touch on many useful topics, such as accessing the API, creating a CSR, and preparing your server for domain control validation. What’s more, we will see how we can revoke certificates in bulk via the API, which is especially useful in cases of security incidents.

The Sandbox

Any kind of automation requires extensive testing prior to launching in a production system, especially when there’s money involved. For this reason, SSL.com has implemented and maintains the Sandbox. The Sandbox is a development clone of our production API. It contains all the functionality of the original, but is not connected to the production database. This means that you can create new users and experiment freely without fear of messing something up and getting charged for a mistake.

When you are satisfied that your automation is functioning properly in the Sandbox, you can then move your code to production and be certain that your scripts will not fail.

NOTE: This article has been developed for the Sandbox, and you can experiment with any of the API calls contained in this document.

The production API can be found in the following URL:

https://sws.sslpki.com/

To perform API calls to the Sandbox, you only need to change the domain name as is shown in the following snippet:

https://sws-test.sslpki.com/

Prepare the Environment

Before you start playing around with the API, you must first prepare a working environment. The tools we will be using throughout this tutorial are a Linux terminal and your trusty text editor.

NOTE: These instructions have been written for the vanilla Ubuntu Linux distribution, which is a typical development environment that one might encounter in the real world. Having said that, the scripts provided in this document also work on Windows via Cygwin.

The first thing you are going to need is a directory for all the necessary files. For utility’s sake, we will refer to this directory as sslcom_api_test/ or “the working directory”. To create and enter the directory, please issue the following commands into the terminal.

$ mkdir ~/sslcom_api_test 
$ cd ~/sslcom_api_test

Next, you must download SSL.com’s intermediate certificates bundle, which is an archive file containing all the necessary certificate files to securely access the API. That way, any data you exchange with the API server will be encrypted and you can rest assured that any sensitive information, such as the API keys, will be protected from eavesdropping.

Download the ZIP archive from the link above and unzip it to the working directory. (Make sure that you change ~/Downloads to the directory where you saved the ZIP file, if needed). The certificate file we will be using throughout this article is SSL_COM_RSA_SSL_SUBCA.crt.

NOTE: On Windows, you will have to locate the ZIP archive, double-click it, and extract the files in the working directory.
$ unzip ~/Downloads/SSLcom_DV_CA_Zip.zip -d .
Archive:  ./SSLcom_DV_CA_Zip.zip
 extracting: ./SSL_COM_RSA_SSL_SUBCA.crt 
 extracting: ./SSL_COM_ROOT_CERTIFICATION_AUTHORITY_RSA.crt
 extracting: ./CERTUM_TRUSTED_NETWORK_CA.crt

We will be using cURL, a typical Linux network tool, for all API calls in this tutorial. cURL can perform any HTTP operation and is installed by default in most Linux distributions. What’s more, cURL can be easily installed on Windows via the binary executables provided in the cURL project page, or by selecting it in the Cygwin installer. However, please note that since the API is based on open formats you may use almost any other such network tool or programming language to access it.

Moreover, we are going to be using OpenSSL to prepare our certificate order. OpenSSL is an open-source tool kit that can perform almost any cryptographic operation you might find a need for. This tool is also included in the Cygwin package list, hence you can either select it for installation while setting up your Cygwin instance, or install it manually via the binary files provided in the project’s homepage.

Finally, you will need two API keys in order to work with the Sandbox, which are associated with your user account. If you don’t already have an account in the Sandbox, please register via the Sandbox’s log-in page or using this link. The process is identical to creating a normal SSL.com customer account. If you already have an account in the Sandbox, you may safely skip this step.

 

Access the API

Our SWS API is based on HTTP (the protocol browsers use), and all data are exchanged in the JSON format.

The majority of API calls will require you to include an account_key and a secret_key parameter for authorization purposes. You can always find your account’s credentials in the Sandbox’s Dashboard page, though in this case we are going to retrieve them via the API.

The command listed in the next snippet of code will log you into the portal and retrieve your account’s information including these API keys. If you are copying and pasting the command in a terminal window, please make sure that you replace USERNAME and PASSWORD with your account’s credentials.

$ curl -L --cacert SSL_COM_RSA_SSL_SUBCA.crt --request GET --data-urlencode 'password=PASSWORD' \
       'https://sws-test.sslpki.com/user/USERNAME' 

{
    "login": "JDemo",
    "email": "jdemo@mailinator.com",
    "account_number": "abc-1ec6012",
    "account_key": "4497618e5c98",
    "secret_key": "FY+s9/ghUrv7SQ==",
    "status": "enabled",
    "user_url": "https://sws-test.sslpki.com/users/1322857",
    "available_funds": "$0.00"
}

Although cURL’s syntax is quite straightforward, let’s get you more familiar with it by looking into the previous call in detail.

  • -L instructs cURL to follow all HTTP redirects. You should include this option in all calls to avoid any issues.
  • --cacert SSL_COM_RSA_SSL_SUBCA.crt instructs cURL to validate the API server’s certificate, with the certificate we downloaded in the bundle. This will allow cURL to encrypt all data sent to the server.
  • --request GET instructs cURL to perform an HTTP GET request. Some calls only accept HTTP POST or PUT requests. This option is the way to handle such requests.
  • --data-urlencode prepares the account’s password to be transmitted to the server. GET requests can include parameters in the URL, while PUT and POST requests only include parameters in the body. Since the password will be passed via the URL, we must encode it to escape any symbols (e.g. / , ? or # ) that might confuse the server. This process is called URL encoding.
NOTE: The backslash (\) at the end of the first line forces Linux terminal to ignore a new-line character and continue parsing characters in the next line as part of the original command. We will be using this syntax to split long commands into multiple lines, in an attempt to make them more presentable.

The result of the API call is a JSON object containing account information, including the account_key and secret_key, required in subsequent API calls.

Issue a server certificate

After having prepared the working environment and gotten hold of the API keys you are now ready to start playing around with the API. As an example, we will request the issuance of a Basic SSL certificate for an imaginary web server named example.ssl.com. Regardless of whether you use the API or the customer portal, the issuance of a certificate requires certain steps to be followed.

These steps include generating a private and public key pair, creating a certificate signing request (CSR), creating a certificate order,  and performing the domain control validation.

Generate the CSR

There are several methods to create a CSR, however since we are already using the terminal, let’s look at how to create a CSR with OpenSSL. If you already have a CSR you can use for this purpose, you may skip this step.

A CSR is a base64 encoded file that contains most of the information that will be included in the final certificate file. Among its most important contents are the public key and the domain name of the server the certificate will be issued for.

That means we are going to need a public key pair before issuing a CSR. The following command will create a new PEM file in the working directory, named example.ssl.com.key, containing the two keys.

$ openssl genrsa -out example.ssl.com.key 2048

Generating RSA private key, 2048 bit long modulus
...................+++
..............................................................+++
e is 65537 (0x010001)

Using the key pair, OpenSSL can now generate a CSR for you. To accomplish this, please use the command shown in the following code snippet.

$ openssl req -new -key example.ssl.com.key -out example.ssl.com.csr

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:Texas
Locality Name (eg, city) []:Houston
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example
Organizational Unit Name (eg, section) []:Example Department
Common Name (e.g. server FQDN or YOUR name) []:example.ssl.com
Email Address []:admin@example.ssl.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

OpenSSL will ask you about your basic contact information and the Common Name of the certificate. For SSL certificates, the Common Name is the server’s domain name (in this case example.ssl.com). Running the command above will create a file, named example.ssl.com.csr, in the current directory containing the base64 encoded CSR.

$ cat example.ssl.com.csr 

-----BEGIN CERTIFICATE REQUEST-----
MIIC5DCCAcwCAQAwgZ4xCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G
A1UEBwwHSG91c3RvbjEQMA4GA1UECgwHRXhhbXBsZTEbMBkGA1UECwwSRXhhbXBs
ZSBEZXBhcnRtZW50MRgwFgYDVQQDDA9leGFtcGxlLnNzbC5jb20xJDAiBgkqhkiG
9w0BCQEWFWFkbWluQGV4YW1wbGUuc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAN7XMG7+zhaGfimdD1F0P3xxUS8dC6knKId3ONEt14Wa5E62
ZIUkyNgQC7gd3Be31jBhcuzJKn8UbTcWnPXd3OCbznbkqXtnljiF3yN9cRnj2f7y
89Hfmje8C07xe6AsoUMSTYzwsoo3zai1bxOUhy+uDU8FzxcSHunepdx/naHXY1Md
waQwzBCp668hFeIOslEjkTCNle3HK1LrgjZCIg0tyHBuZTNuUcQOyXrrDSrtOxx8
dqOD7sYqJie2xiCC9kkpNGYYTEuCuVKidgiC3e/DuLUNbhoUMfSENv64TGA7lRIj
nEBrrEm6FOSgPEGgEsM78cexVaqNCavNXNy49ysCAwEAAaAAMA0GCSqGSIb3DQEB
CwUAA4IBAQAV1Ac9nYH64BrB4OHlOYPkZbK6qCKfipTg7s4Xdcc3TponjTnMJyaQ
NNh0koCUOFJaYPjWIk/YkCeGNv/fbce+sddNbh0jtcVTPw8EFvs53IaUAE99zDvn
577Azj+OXfmaLQXjK15BtnT5hbmRKsrpPxnAdk4NOohM7QKWNEdBrcfTuH1q3WpD
6jSD35FlIFUfMgNi34mxF4vYamGrWgdURIb7DCk2h7B2LQK+vRNx1uPm9FVSeYZc
tHZWTiw2xEExw2Qco6lqXYl8t0Eo07gYl4gAEx9bibvVqYMo3Zss1mRg6+WEB8Xs
G+Hn1TG3XIaIbmvlpRNma/l766KZwLXG
-----END CERTIFICATE REQUEST-----

Create the certificate order

Having obtained the CSR, you are now ready to create a certificate order via the API. The first API call we looked at was a GET request, while this one is a POST. POST requests must include all parameters in their bodies as JSON objects. Consequently, you need to format the certificate order’s parameters in JSON. A JSON configuration for this example can be found in the following snippet.

{
 "account_key": "4497618e5c98", 
 "secret_key": "FY+s9/ghUrv7SQ==", 
 "product": "106", 
 "period": "365", 
 "server_software": "15", 
 "organization_name": "Example", 
 "street_address_1": "Example st", 
 "locality_name": "Houston", 
 "state_or_province_name": "Texas", 
 "postal_code": "77777", 
 "country_name": "US", 
 "duns_number": "1234567", 
 "company_number": "Example number", 
 "registered_country_name": "US",
 "unique_value": "1ed1c72baf",
 "csr":"-----BEGIN CERTIFICATE REQUEST-----MIIDIjCCAgwaRlkPnuD ... 0QQ3JKQqJbii3760Rgon8hZmbkiE=-----END CERTIFICATE REQUEST-----"
}

We have already seen the API keys before. However, to order certificates we also have to include additional parameters such as the product ID and the validity period. You can find a list of product IDs in the SWS API documentation. In this example, the order is made for a basic SSL certificate with a validity period of 1 year. The next group of parameters store contact information about the registrant (that’s you). The unique_value parameter (optional), contains an alphanumeric string that ensures the uniqueness of the request. If you do not supply a unique value, one will be generated for you (SSL.com uses a random 10-digit hexadecimal number for this purpose). Specifying a unique value in this way is useful if you want to generate DCV files or CNAME entries outside of SSL.com’s user portal. Finally, the csr parameter must contain a valid base64-encoded CSR, like the one we saved in example.ssl.com.csr.

Replace the parameters with the values of your own contact details and CSR, and save this JSON configuration in a file named example.ssl.com.json.

NOTE: Please make sure you have removed all new-line characters from the CSR before adding it to the command. New-lines are used to instruct the terminal to process the text entered until the new-line character. Leaving the characters in might make your cURL commands fail.

With everything set up, you are now ready to create your order. cURL accepts the JSON parameters either as an inline string, or via a filename. Due to the first option being too verbose, let’s pass the filename instead.

Please take note of the --data-binary cURL switch, which instructs cURL to include the file’s contents in the body of the POST request.

$ curl -L --cacert SSL_COM_RSA_SSL_SUBCA.crt --request POST --header "Content-Type: application/json" \
       --data-binary "@example.ssl.com.json" 'https://sws-test.sslpki.com/certificates' 

{
    "ref": "co-ac1ecm200",
    "registrant": {
        "organization": "Example",
        "organization_unit": null,
        "street_address_1": "Example st",
        "street_address_2": null,
        "street_address_3": null,
        "locality": "Houston",
        "state_or_province": "Texas",
        "post_office_box": null,
        "postal_code": "77777",
        "country": "US",
        "email": null
    },
    "order_status": "validation required",
    "validations": null,
    "order_amount": "$49.00",
    "certificate_url": "https://sandbox.ssl.com/team/abc-1ec6012/certificate_orders/co-ac1ecm200",
    "receipt_url": "https://sandbox.ssl.com/team/abc-1ec6012/orders/fe3b-1ecm201",
    "smart_seal_url": "https://sandbox.ssl.com/team/abc-1ec6012/certificate_orders/co-ac1ecm200/site_seal",
    "validation_url": "https://sandbox.ssl.com/team/abc-1ec6012/certificate_orders/co-ac1ecm200/validation",
    "external_order_number": null,
    "certificates": null
}

The result of the operation is another JSON object which contains the details of the newly-created certificate order. We can see its order_status, and its reference number in the ref parameter which is used to reference this order in all subsequent API calls. Moreover, the output contains various URLs, such as the certificate_url, which points to the order’s details in the portal and the validation_url, which points to the validation page of the order.

Finally, certificates will contain all the certificates associated with the order. Since the order has not been validated yet, no certificates have been created.

Domain control validation

As stated in the certificate order’s order_status of validation required, you need to perform the validation prior to having a certificate issued.

Publicly-trusted CAs (such as SSL.com) are required to verify that the certificate purchaser indeed controls the server the certificate will be issued for before issuing them any certificates. This can be accomplished through multiple methods, and you can view all of the available validation methods for a specific order via this next API call.

Please make sure you replace the reference number co-ac1ecm200 in the URL with your order’s reference number, which was generated in the previous API call.

$ curl --cacert SSL_COM_RSA_SSL_SUBCA.crt --request GET \
       --data-urlencode 'secret_key=FY+s9/ghUrv7SQ==' --data-urlencode 'account_key=4497618e5c98' \
       'https://sws-test.sslpki.com/certificate/co-ac1ecm200/validations/methods'

{
    "instructions": "https://www.ssl.com/faqs/ssl-dv-validation-requirements/",
    "md5_hash": "29BD4C00B65613CCEC04C19C0050D931",
    "sha2_hash": "BF340FDFD9C43D45B8310FC4A400E4D4B61CAF8D2002BAAF0945252E35F9D751",
    "dns_sha2_hash": "BF340FDFD9C43D45B8310FC4A400E4D4.B61CAF8D2002BAAF0945252E35F9D751.167c8a5c49",
    "dcv_methods": {
        "example.ssl.com": {
            "email_addresses": [
                "admin@ssl.com",
                "administrator@ssl.com",
                "webmaster@ssl.com",
                "hostmaster@ssl.com",
                "postmaster@ssl.com",
                "admin@example.ssl.com",
                "administrator@example.ssl.com",
                "webmaster@example.ssl.com",
                "hostmaster@example.ssl.com",
                "postmaster@example.ssl.com"
            ],
            "http_csr_hash": {
                "http": "http://example.ssl.com/.well-known/pki-validation/29BD4C00B65613CCEC04C19C0050D931.txt",
                "allow_https": "true",
                "contents": "BF340FDFD9C43D45B8310FC4A400E4D4B61CAF8D2002BAAF0945252E35F9D751\nssl.com\n167c8a5c49"
            },
            "cname_csr_hash": {
               "cname": "_29BD4C00B65613CCEC04C19C0050D931.example.ssl.com. CNAME ff8716e0fd.ssl.com.",
               "name": "_29BD4C00B65613CCEC04C19C0050D931.example.ssl.com",
               "value": "BF340FDFD9C43D45B8310FC4A400E4D4.B61CAF8D2002BAAF0945252E35F9D751.ff8716e0fd.ssl.com."
            }
        }
    },
    "ca_tag": "ssl.com"
}

The returned output will include all of the information you need to perform domain control validation. For example, if you want to use the http_csr_hash validation method, you must create a file in the server this certificate will be issued for, named .well_known/pki-validation/29BD4C00B65613CCEC04C19C0050D931.txt. The file should exactly contain the value of the contents parameter.

Afterwards, you can visit the validation_url found in the previous call that created the order and proceed with the validation as you would normally do with an order you have created via your customer portal. (You can always visit the Validations page and find the URL for the specific order).

After a successful domain control validation occurs, the certificate will be issued and you will be able to download it.

Retrieve the certificate

You can find your certificate in the web portal or retrieve it via the API. For our purposes we will use the API. As seen in the previous section, when creating a new certificate order, the response contains a reference number. This number can be used to retrieve the order’s details including the actual certificate data.

$ curl --request GET -L --cacert SSL_COM_RSA_SSL_SUBCA.crt  \
       --data-urlencode 'secret_key=FY+s9/ghUrv7SQ==' --data-urlencode 'account_key=4497618e5c98' \
       'https://sws-test.sslpki.com/certificate/co-ac1ecm200?response_type=individually&response_encoding=base64'

{
    "description": "1 Year Basic SSL",
    "product": "106",
    "product_name": "basicssl",
    "order_status": "issued",
    "order_date": "2019-05-02T10:08:48.000-05:00",
    "registrant": {
        "organization": "Example",
        "organization_unit": null,
        "street_address_1": "Example st",
        "street_address_2": null,
        "street_address_3": null,
        "locality": "Houston",
        "state_or_province": "Texas",
        "post_office_box": null,
        "postal_code": "77777",
        "country": "US",
        "email": null
    },
    "certificates": "\nMIIE1TCCA72gAwIBAgIRANsjhF+t ... 4CAw5Egg73IgIHggE1QEZiYQRu+0wDQY\n",
    "common_name": "example.ssl.com",
    "domains_qty_purchased": "1",
    "wildcard_qty_purchased": "0",
    "subject_alternative_names": [
        "example.ssl.com",
        "www.example.ssl.com"
    ],
    "validations": null,
    "effective_date": "2019-05-03T11:22:37.000-05:00",
    "expiration_date": "2020-05-02T11:22:37.000-05:00",
    "algorithm": "SHA256",
    "external_order_number": null,
    "domains": null,
    "site_seal_code": null,
    "subscriber_agreement": null,
    "server_software": 15,
    "contacts": [ { ... }, { ... }]
}

Since the API is meant to be used programmatically, you must parse the JSON response in order to isolate the certificate and save it into a file. JSON parsing is beyond the scope of this article; however, it is a simple task that can be easily implemented in most modern scripting or programming languages.

Search certificate orders

If you don’t have the reference number at hand, you may issue an API call to retrieve all your account’s certificate orders. This call allows you to filter the orders, as well as which information will be shown.

$ curl  --cacert SSL_COM_RSA_SSL_SUBCA.crt --request GET \
        --data-urlencode 'secret_key=FY+s9/ghUrv7SQ==' --data-urlencode 'account_key=4497618e5c98' \
        'https://sws-test.sslpki.com/certificates?fields=domains,ref,order_status' 

[    
    {
        "ref": "co-ac1ecm200",
        "order_status": "issued",
        "domains": [
            "example.ssl.com"
        ]
    },
    {
        "ref": "co-581eclsap",
        "order_status": "validating, please wait",
        "domains": [
            "example.ssl.com"
        ]
    },
    {
        "ref": "co-6f1ecm1of",
        "order_status": "waiting on contacts information from customer",
        "domains": [
            "test.ssl.com"
        ]
    }
}

The fields URL parameter allows you to control which certificate details will be shown in the output. You can additionally paginate via the per_page and page request parameters. To limit the number of certificates based on their issuance dates you may use start and end parameters. Finally, you can filter and search the orders using criteria such as product ID, expiration date, or any other field contained in the certificate. For more information take a look at SSL.com’s API documentation.

Revoke the certificate

The final feature we are going to look at in this guide is bulk certificate revocation. Certificates can protect you as long as only you (or people you trust) hold the private key associated with them. In case a private key gets compromised, or any information on the certificate needs to be changed, then the certificate must be immediately revoked and a new one should be issued.

In cases where the private key is suspected to be stolen, it is imperative that client software (such as browsers or operating systems) stop accepting it as valid as soon as possible. For this reason, we strongly recommend that you implement an automated system of revoking, reissuing, retrieving and installing certificates on your servers.

SSL.com’s SWS API allows you to programmatically revoke one, more or all the certificates under any of your certificate orders. The following API call will revoke all certificates under certificate order co-ac1ecm200:

curl --cacert SSL_COM_RSA_SSL_SUBCA.crt --request DELETE --header "Content-Type: application/json" \
     --data-binary '{"account_key":"4497618e5c98","secret_key":"FY+s9/ghUrv7SQ==","reason":"stolen"}' \
     'https://sws.sslpki.com/certificate/co-ac1ecm200'

{
  "status":"revoked"
}

This cURL command issues a DELETE HTTP request (instead of a GET or POST like previous commands) and provides the JSON configuration inline. It is also valid to create a file with the JSON contents and pass it to cURL via filename in the same manner as the command that issued the certificate order.

You may specify whatever reason you wish in the reason parameter, and may optionally include a list of certificate serial numbers in the JSON to only revoke the certificates matching those serials. If no serial numbers are included, then all certificates belonging to the specified certificate order will be revoked.

For more information on this API call, please take a look at our API documentation.

Conclusion

This article describes a straightforward process to issue and revoke a DV server certificate, as a simplistic example of the operations you can perform via SSL.com’s SWS API. We at SSL.com encourage the use of automation where possible because it removes the hassle of manually performing the same repetitive tasks, and more importantly allows for faster response times in cases of emergency (see the serial number entropy issue).

Please feel free to experiment with our Sandbox and SWS API, and don’t hesitate to contact our support agents if you encounter any issues.


We are always happy to answer our customers’ questions. Drop us an email at support@ssl.com (or contact us via the in-page chat) with any questions or issues about our API, and an expert will be there to help you.