Automate Certificate Renewal
On this page
This article will describe how the Curity Identity Server fits into industry-standard patterns for automatically issuing and renewing HTTPS certificates. Many companies already use these patterns for their own APIs.
Assume that services are already running at a cloud provider of your choice, using virtual machines or containers. Let's Encrypt offers free options and comes with a great opportunity for automation. In most — if not all — cases, automation should be the default way for issuing and managing certificates. This also applies to the HTTPS certificates of the Curity Identity Server.
Assume that the nodes are deployed in the cloud just as other services are. The admin service is accessible over
https://admin.example.com, and the runtime nodes serve requests on
https://login.example.com. The certificates protecting those endpoints should automatically be renewed using the Certbot client. However, it is not enough to only create the new certificate automatically. Deploy the certificates in an automated manner as well. Consider running the
---deploy-hook for deploying a new certificate at the Curity Identity Server similar to the following command:
certbot renew --deploy-hook /path/to/deploy-certificate-idsvr-script
The Curity Identity Server has two interfaces that are suitable for automation: CLI and RESTCONF API. This tutorial shows how to use either of these interfaces for updating the certificates and keys configured in the Curity Identity Server without restart or downtime. It provides insight into the configuration of certificates and explains how to update an HTTPS certificate and corresponding key via the CLI or RESTCONF API. Other keys and certificates can be updated accordingly.
HTTPS and the Server SSL Keystore
Before getting to the actual commands, have a look at the background of configuring SSL server certificates. The Curity Identity Server is always assigned a service role as part of the startup. This role defines which port to use, which endpoints to expose, and which client certificates to trust, among other details. The service role is also where HTTPS for the endpoints is configured (except for the admin service, which has its own configuration). The
<ssl-server-keystore> attribute refers to an identifier of a certificate and its corresponding private key.
The following example uses a key with the identifier
default-admin-ssl-key for setting up HTTPS for all the instances with the
default service role assigned.
The actual data of the HTTPS certificate and corresponding private key resides at a different section of the configuration. All keys, certificates, and trust stores lie under
facilities/crypto. The server's private keys and related certificates that may be used for SSL/TLS sessions are placed under
facilities/crypto/ssl/server-keystore as shown in the following example. Note that the value of the keystore in the snippet is truncated for display purposes.
Familiarize yourself with the identifier of the certificate that should be renewed and its path in the configuration. If a new certificate with a unique identifier is added, it will not be active until it is also referenced, for example, by a service role. However, if an existing certificate is replaced with a new one and the identifier remains the same, then no further configuration is required. The certificate is loaded as soon as the changes are committed and the transaction is closed.
Knowing the configuration details helps to understand the commands listed in the instructions provided by this tutorial. The knowledge is especially helpful if the steps provided by this tutorial should be adapted for other certificates.
This tutorial assumes that the file called
privkey.pem contains the private key, and the file
cert.pem contains the SSL certificate. Both are encoded in PEM format and may result from running the Certbot client as part of the integration with Let's Encrypt. Here you can learn how to update a certificate at the Curity Identity Server using the CLI or RESTCONF API.
Use full-chain certificates if applicable
If your tool creates a full-chain certificate as well a single certificate, use the full-chain version. For example,
certbot might create a
fullchain1.pem. If you use the
getssl tool, it might create a
fullchain.crt file. These files should be then used instead of a
cert.pem file. Substitute the filename accordingly or update any commands or scripts in this tutorial to use the full-chain file.
Update via the CLI
The CLI is the appropriate choice for automation if the script calling it runs on the same server as the admin-service. There are two strategies to update a certificate and key through the CLI:
- Direct import of a base64-encoded keystore
- Import of an embedded keystore through an XML configuration file
The CLI cannot import PEM files directly but requires the key and certificate to be placed in a PKCS12 or JKS file format. To work with the private key and certificate mentioned above, convert them to a PKCS12 keystore and encode it with base64 using the following commands.
openssl pkcs12 -export -name "default-admin-ssl-key" -in cert.pem -inkey privkey.pem -out updated-keystore.p12openssl base64 -in updated-keystore.p12 -out updated-keystore.p12-b64
Enter the password for the private key and choose a password for the PKCS12 keystore. Remove any line breaks so that the keystore is represented as a "one-liner". Use the
tr tool for that purpose and copy the output.
tr -d '\n' < updated-keystore.p12-b64
Access the CLI by running
idsh. Within the CLI, run a system-level request to update the certificate for
default-admin-ssl-key. The changes are automatically committed.
idshrequest facilities crypto add-ssl-server-keystore id `default-admin-ssl-key`
The CLI will prompt for the missing parameters. Paste the keystore that you copied, and enter the password for the keystore. The certificate is now successfully updated. However, user input was required. To fully automate the process of renewing an existing certificate, study the following script:
# The id of the certificate to updateCERTIFICATENAME="default-admin-ssl-key"# Files to load the SSL certificate and corresponding private key fromCERTFILE=cert.pemKEYFILE=privkey.pem# The password which the private key is protected withKEYPWD="mySecretKey"# A random string to protect the temporary keystore withKEYSTOREPWD=$(< /dev/urandom LC_ALL=C tr -dc [:alnum:] | head -c20; echo;)# Prepare the certificate and key and convert them into a supported format# 1. Create a temporary PKCS12 keystore from the certificate and file# 2. Base64 encode the keystore# 3. Remove any line breaksKEYSTORE_B64=$(openssl pkcs12 -export -name $CERTIFICATENAME -in $CERTFILE -inkey $KEYFILE -passin pass:$KEYPWD -passout pass:$KEYSTOREPWD | openssl base64 | tr -d '\n')# Update the certificate identified by CERTIFICATENAME using request actionidsh <<< "request facilities crypto add-ssl-server-keystore id $CERTIFICATENAME password $KEYSTOREPWD keystore $KEYSTORE_B64"# Changes are committed at once
status true indicates that everything went fine.
When the key and certificate are already stored in a PKSC12 keystore, you can skip the conversion from one key format to another. There is no need for a temporary keystore and password. However, the CLI still requires the input keystore to be a single-line base64-encoded string.
Import Through a Configuration File
The method described here includes an XML configuration file with an embedded keystore containing the updated private key and certificate. Start with preparing the configuration file for the new keystore where
$KEY is the unprotected private key in
$CERT the contents of
$CERTIFICATENAME the identifier of the keystore.
<config xmlns="http://tail-f.com/ns/config/1.0"><facilities xmlns="https://curity.se/ns/conf/base"><crypto><ssl><server-keystore><id>$CERTIFICATENAME</id><keystore>$KEY$CERT</keystore></server-keystore></ssl></crypto></facilities></config>
Encrypted Private Key
The XML cannot be imported if the private key is encrypted because there is no support for providing the password to decrypt it. Make sure that the key is in plaintext.
Merge the configuration file into the existing configuration.
idsh <<< "configureload merge /tmp/updateSslServerCert.xmlset environments environment services service-role default ssl-server-keystore default-admin-ssl-keycommit"
A complete script that creates a temporary XML file and imports it via the CLI may look like the following.
# The service role to update the HTTPS certificate forSERVICE_ROLE="default"# The id of the certificate to updateCERTIFICATENAME="default-admin-ssl-key"# The names of the key and certificate filesKEY_FILE="privkey.pem"CERT_FILE="cert.pem"# Create a temporary file for the configurationXMLFILE=$(mktemp -u /tmp/conf-XXXXXX)PKCS8_KEY_FILE=$(mktemp -u /tmp/key-XXXXXX)# Make sure to delete the temporary file when the script exitstrap "rm -f $XMLFILE $PKCS8_KEY_FILE" EXITif grep -q 'BEGIN RSA PRIVATE KEY' "$KEY_FILE"; then# Convert the PKCS#1 file to PKCS#8openssl pkcs8 -in "$KEY_FILE" -topk8 -out "$PKCS8_KEY_FILE" -nocryptKEY_FILE=$PKCS8_KEY_FILEfi# Read the private key and certificateKEY=$(cat $KEY_FILE)CERT=$(cat $CERT_FILE)# Create the configuration data to update the certificate# Read all characters until EOF is received and redirect the output to the temporary XML fileBITS=$(openssl rsa -in $KEY_FILE -text -noout | grep "Private-Key" | sed 's/Private-Key: (\([[:digit:]][[:digit:]]*\) bit)/\1/'if [ $BITS -ne "2048" ]; thenSIZE="<size>$BITS</size>"ficat <<EOF > $XMLFILE<config xmlns="http://tail-f.com/ns/config/1.0"><facilities xmlns="https://curity.se/ns/conf/base"><crypto><ssl><server-keystore><id>$CERTIFICATENAME</id><keystore>$KEY$CERT</keystore>$SIZE</server-keystore></ssl></crypto></facilities></config>EOF# Enter configuration mode in CLI, merge the XML configuration into the existing one, update the reference and commit the changes.idsh <<< "configureload merge $XMLFILEset environments environment services service-role $SERVICE_ROLE ssl-server-keystore $CERTIFICATENAMEcommit comment \"change certificate for $SERVICE_ROLE to $CERTIFICATENAME\""
This method supports the import of a PEM-encoded key and certificate. It is a convenient method for the example used throughout this tutorial because there is no conversion to other key formats required. However, the private key is in plaintext, which may raise security concerns. It is essential to restrict access to sensitive files like the private key
key.pem and XML configuration file. Make sure to permanently remove or destroy any sensitive data when not needed anymore.
Cluster-Mode and Reverse Proxy
Protecting the runtime nodes of the Curity Identity Server via a load balancer or reverse proxy is recommended. As a result, the certificate that the clients are facing is presented by the reverse proxy, and thus it is there the certificate is renewed. However, mutual TLS authentication and certificate-bound tokens do not work with SSL termination. In that case, the load balancer must just pass through the traffic, and the runtime nodes must decrypt the transport message. Consequently, the runtime nodes must be configured with a valid SSL certificate.
The best approach to renew SSL certificates at the runtime nodes of the Curity Identity Server is to make use of the admin node. If you use
LetsEncrypt for your certificates, you may run a cronjob on the admin node checking for expiration and renewing the SSL certificate automatically via
certbot. The scripts provided in this tutorial can then be used in conjunction with the cronjob to configure the renewed certificates through the admin service. The runtime nodes will then receive the update from the admin node.
If you operate a cluster of stand-alone runtime nodes without an admin node, you will have to update each node individually. The best option is to prepare an updated configuration with the new certificate, for example, by updating one of the nodes and exporting its configuration. Then run an ordinary upgrade procedure where one node after the other is replaced with a new node containing the new configuration and certificate.
In previous years, managing certificates and dealing with expiry has been difficult and could involve manual user actions. The Curity Identity Server is designed to use industry-standard cloud-native patterns for certificate management, which require only simple code. This enables certificates to be managed seamlessly over time, without any issues or downtime for end-users.
Join our Newsletter
Get the latest on identity management, API Security and authentication straight to your inbox.
Start Free Trial
Try the Curity Identity Server for Free. Get up and running in 10 minutes.Start Free Trial