Let’s Encrypt ACME with Alibaba Cloud API Gateway and CDN — Part 3

By John Hanley, Alibaba Cloud Tech Share Author. Tech Share is Alibaba Cloud’s incentive program to encourage the sharing of technical knowledge and best practices within the cloud community.

In this multipart article, we will discuss about SSL certificates in detail to remove any doubts on this topic. We will learn how to use the Let’s Encrypt ACME version 2 API using Python to develop software that can create, install, renew and revoke SSL certificates for Alibaba Cloud. Although we have used Alibaba Cloud products for the tutorial, the same principles apply to any computing service that supports X.509 SSL certificates.

In Part 2, we talked about creating your Account Key, Certificate Key and Certificate Signing Request (CSR).

In this section, we will explain about ACME endpoints, getting the ACME directory, creating an ACME account, and retrieving your ACME account information.

Let’s Encrypt API Endpoints

Let’s Encrypt ACME supports two modes by using different endpoints. A production mode that will issue real certificates and is rate limited, and a staging mode for testing that issues test certificates. The production endpoint limits the number of requests that you can make per day. While developing and software for Let’s Encrypt make sure that you are using the staging endpoint otherwise you will reach your API limit and need to wait until the next day to resume testing.

Staging Endpoint: https://acme-staging-v02.api.letsencrypt.org/directory

Production Endpoint: https://acme-v02.api.letsencrypt.org/directory

ACME Directory

The first API call should be to get the ACME directory. The directory is a list of URLs that you call for various commands. The response from get directory is a JSON structure that looks like this:

The first line should be ignored. ACME generates a random key and value to dissuade developers from hard coding JSON expectations into their code.

Let’s look at each of the returned data parts:

This URL is used to change the public key associated with the account. This is used to recover from a key compromise.

An array of hostnames which the ACME server recognizes as referring to itself for the purposes of CAA record validation. We do not use these records in the example code.

A URL identifying the current terms of service. Take the time to read the referenced document on the Terms of Service at https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. In the example code, we set the fields accepting the Terms of Service by default.

A URL locating a website providing more information about the ACME server. We do not use this record in the example code. You can learn more about it here https://letsencrypt.org/docs/staging-environment/

This is an important API and should be the second call that you make to the ACME API. A nonce is a unique random value that protects against replay attacks. Each API call (except for directory) requires a unique nonce value.

This endpoint is used to create a new account.

This endpoint is used to request this issuance of an SSL certificate.

This endpoint is used to revoke an existing certificate that was issued by the same account.

Example Code to Get the ACME Directory

This is the simplest ACME API example in the examples package. This example just calls the ACME main endpoint. The returned data is a JSON structure that defines the API endpoints as described above. Review the output from this program and become familiar with the various URLs as they will be used in most of the following examples.

Source: get_directory.py

Example Code to Create a New Account

The next step is to create a new account on the ACME server. This uses the account.key that we created in Part 2. The ACME server does not track information such as company name in the account database; only a contact email address is needed for notifications.

In this example, change the EmailAddress parameter to be your email address. The example shows how to include more than one email address. The ACME server does not require that you include and email address as this is optional. The ACME server does not verify the email address.

Let’s review a couple of key points about the code.

1. Get the ACME directory

2. Get the “newAccount” URL

3. Request a nonce for the first ACME API call
After the first ACME API call, a new nonce in returned in the header “Replay-Nonce” after each ACME API call.

4. Assemble the HTML headers
The important item is: Content-Type: application/jose+json

5. Assemble the HTML body with the ACME API parameters
Creating the HTTP body will be covered in detail in the Part 4.

6. Assemble the HTML body “jose” data structure
Notice how everything is base64 encoded.

7. Finally, call the ACME API
This is done with an HTTP POST with a JSON body.

8. After the ACME API two items are returned in the HTTP response headers
Location is the URL for your account.

Replay-Nonce is the “nonce” value for the next ACME API call.

Most ACME API calls require the HTTP headers include:

Source: new_account.py

Example Code to Get Account Information

Now that we have created an account using our account.key, let’s communicate with the ACME server to see what information is stored on the server. This example introduces a configuration file “acme.ini” to contain the configuration parameters instead of hard coding them into the source code.

Modify acme.ini to include your specific information such as email address.

Source: acme.ini

Source: get_acount_info.py


In Part 4, we will go deeper into the ACME API and learn how to construct each part of the JSON body, sign the payload and process the results.



Follow me to keep abreast with the latest technology news, industry insights, and developer trends.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store