Obtaining and managing certificates from Let’s Encrypt using the WildFly CLI
It is possible to obtain and manage certificates from the Let’s Encrypt certificate authority using the WildFly CLI. In particular, it is possible to get a certificate from Let’s Encrypt, revoke it if necessary, and check if it’s due for renewal. This blog post is going to give an overview of these new operations.
- Obtaining a certificate from Let’s Encrypt
- Revoking a certificate from Let’s Encrypt
- Checking if a certificate is due for renewal
- Using a CLI script to automate certificate renewal
- Updating the contact URLs associated with your Let’s Encrypt account
- Changing your Let’s Encrypt account key
- Deactivating your Let’s Encrypt account
- Summary
Obtaining a certificate from Let’s Encrypt
First, make sure your WildFly server instance is publicly accessible using the domain name(s) you will be obtaining a certificate for from Let’s Encrypt. For example, if you are requesting a certificate for the domain name "www.example.org", then "www.example.org" needs to be publicly accessible. This is because Let’s Encrypt will attempt to access this URL when attempting to validate that you really do own this domain name. WildFly itself will handle proving that you really do own this domain name.
There are a couple ways to obtain a certificate from Let’s Encrypt using WildFly CLI commands.
Using the security
command
The simplest way to obtain and make use of a certificate from Let’s Encrypt is by using one of the security
wrapper commands as follows:
security enable-ssl-http-server --interactive --lets-encrypt
security enable-ssl-management --interactive --lets-encrypt
These commands allow you to easily enable either one-way or two-way SSL for applications or management interfaces, respectively, using a certificate that will be obtained automatically from Let’s Encrypt.
Let’s take a look at the security enable-ssl-http-server --interactive --lets-encrypt
command:
[standalone@localhost:9990 /] security enable-ssl-http-server --interactive --lets-encrypt
Please provide required pieces of information to enable SSL:
Let's Encrypt account key-store:
File name (default accounts.keystore.jks):
Password (blank generated):
Let's Encrypt certificate authority account:
Account name (default CertAuthorityAccount):
Contact email(s) [admin@example.com,info@example.com]:
Password (blank generated):
Alias (blank generated):
Certificate authority URL (default https://acme-v02.api.letsencrypt.org/directory):
Let's Encrypt TOS (https://community.letsencrypt.org/tos)
Do you agree to Let's Encrypt terms of service? y/n:y
Certificate info:
Key-store file name (default default-server.keystore):
Password (blank generated):
Your domain name(s) (must be accessible by the Let's Encrypt server at 80 & 443 ports) [example.com,second.example.com]: www.example.org
Alias (blank generated):
Enable SSL Mutual Authentication y/n (blank n):
Let's Encrypt options:
account key store name: account-key-store-b1f62709-d679-4e19-acf4-f5d286d481b8
password: OAaMa6aI
account keystore file accounts.keystore.jks will be generated in server configuration directory.
Let's Encrypt certificate authority account name: CertAuthorityAccount
contact urls: []
password: lSgY0ZoS
alias: account-key-store-alias-b1f62709-d679-4e19-acf4-f5d286d481b8
certificate authority URL: https://acme-v02.api.letsencrypt.org/directory
You provided agreement to Let's Encrypt terms of service.
SSL options:
key store file: default-server.keystore
domain name: [www.mydomainname.com]
password: iuApeaDH
validity: 90
alias: alias-b1f62709-d679-4e19-acf4-f5d286d481b8
Certificate will be obtained from Let's Encrypt server and will be valid for 90 days.
Server keystore file will be generated in server configuration directory.
Do you confirm y/n :y
As we can see from the output, this command will first prompt you to specify the information needed to configure your Let’s Encrypt account. It will then ask for information related to the certificate that you would like to obtain from Let’s Encrypt. This command will then automatically create your Let’s Encrypt account (if it doesn’t already exist), it will obtain a certificate from Let’s Encrypt using the domain name that you specified, and it will configure one-way SSL using this certificate.
Using Elytron subsystem commands
It is also possible to obtain a certificate from Let’s Encrypt using Elytron subsystem commands directly.
Prerequisite configuration
First, configure a key-store
in the Elytron subsystem that will be used to hold your server certificates.
Note that the path to the keystore file doesn’t need to exist yet.
/subsystem=elytron/key-store=serverKS:add(path=server.keystore.jks, relative-to=jboss.server.config.dir, credential-reference={clear-text=secret}, type=JKS)
Show me the commands first
Obtaining certificates from Let’s Encrypt using Elytron subsystem commands requires a couple one-time configuration steps. These commands are shown below. We’re going to go through each of these commands in more detail in the following sections.
### One-time configuration
# Configure a Let’s Encrypt account
/subsystem=elytron/key-store=accountsKS:add(path=accounts.keystore.jks,relative-to=jboss.server.config.dir,credential-reference={clear-text=secret},type=JKS)
/subsystem=elytron/certificate-authority-account=myLetsEncryptAccount:add(alias=letsEncrypt,key-store=accountsKS,contact-urls=[mailto:admin@admin.org])
### Now you’re ready to start obtaining and managing certificates
# Obtain a certificate from Let’s Encrypt
/subsystem=elytron/key-store=serverKS:obtain-certificate(alias=server,domain-names=[www.example.org],certificate-authority-account=myLetsEncryptAccount,agree-to-terms-of-service)
# Revoke a certificate that was issued by Let’s Encrypt
/subsystem=elytron/key-store=serverKS:revoke-certificate(alias=server,reason=keyCompromise,certificate-authority-account=myLetsEncryptAccount)
# Check if a certificate is due for renewal in less than 30 days
/subsystem=elytron/key-store=serverKS:should-renew-certificate(alias=server)
Configuring a Let’s Encrypt account
Before obtaining your first certificate from Let’s Encrypt, a Let’s Encrypt account needs to be configured.
First, configure a key-store
in the Elytron subsystem that will be used to hold your Let’s Encrypt account key.
The path to the keystore file doesn’t need to exist yet.
/subsystem=elytron/key-store=accountsKS:add(path=accounts.keystore.jks,relative-to=jboss.server.config.dir,credential-reference={clear-text=secret},type=JKS)
Now we can configure a Let’s Encrypt account that we will reference when obtaining certificates:
/subsystem=elytron/certificate-authority-account=myLetsEncryptAccount:add(alias=letsEncrypt,key-store=accountsKS,contact-urls=[mailto:admin@admin.org])
The above command results in the following configuration in the Elytron subsystem:
<subsystem xmlns="urn:wildfly:elytron:4.0" final-providers="combined-providers" disallowed-providers="OracleUcrypto">
...
<tls>
...
<certificate-authority-accounts>
<certificate-authority-account name="myLetsEncryptAccount" contact-urls="mailto:admin@admin.org">
<account-key key-store="accountsKS" alias="letsEncrypt"/>
</certificate-authority-account>
</certificate-authority-accounts>
...
</tls>
...
</subsystem>
Notice that a certificate-authority-account
has the following attributes and element:
-
name
- The name of the certificate authority account. -
contact-urls
- An optional list of contact URLs that Let’s Encrypt can use to notify you about any issues with your account. -
account-key
- Information about the account key that will be used when communicating with Let’s Encrypt. -
key-store
- A reference to the Elytronkey-store
that will hold your Let’s Encrypt account key. -
alias
- The alias in the referencedkey-store
that will contain your Let’s Encrypt account key.
Obtaining a certificate from Let’s Encrypt
To obtain a certificate from Let’s Encrypt, the key-store
obtain-certificate
command can be used. Its syntax is as follows:
obtain-certificate --alias= --domain-names= --certificate-authority-account= [--agree-to-terms-of-service=<true,false>] [--staging=<true,false>] [--algorithm=] [--key-size=] [--credential-reference=]
Let’s take a closer look at the obtain-certificate
operation’s parameters:
-
alias
- The alias in the key-store that will be used to store the certificate obtained from Let’s Encrypt. -
domain-names
- The list of domain names to request a certificate for. -
certificate-authority-account
- A reference to the certificate authority account information that should be used to obtain the certificate. -
agree-to-terms-of-service
- Whether or not you agree to Let’s Encrypt’s terms of service (this only needs to be specified the first time you obtain a certificate from Let’s Encrypt with yourcertificate-authority-account
). -
staging
- Optional. Indicates whether or not Let’s Encrypt’s staging environment should be used to obtain the certificate. The default value is false. This should only be set to true for testing purposes. This should never be set to true in a production environment. -
algorithm
- Optional. Indicates the key algorithm that should be used (RSA or EC). The default value is RSA. -
key-size
- Optional. Indicates the key size that should be used. The default value is 2048. -
credential-reference
- Optional. Thecredential-reference
that should be used to protect the generated private key. The default value is thekey-store
password.
The obtain-certificate
command will use the referenced certificate-authority-account
to create an account with
Let’s Encrypt if one does not already exist. It will then request a certificate from Let’s Encrypt for the specified domain-names
.
In particular, the obtain-certificate
operation will prove ownership of the requested domain names, generate a key pair,
generate a certificate signing request (CSR) using the generated key pair and the requested domain names, and submit this
CSR to Let’s Encrypt. If successful, the obtain-certificate
operation will retrieve the resulting
certificate chain from Let’s Encrypt and store it along with the generated PrivateKey under the given alias in the key-store
.
These changes will also be persisted to the file that backs the key-store
.
For example, to request a certificate from Let’s Encrypt for the domain name "www.example.org" using the "myLetsEncryptAccount"
certificate-authority-account
, the following command could be used. The resulting certificate will be stored in the file that backs
the "serverKS" key-store
under the alias "server".
/subsystem=elytron/key-store=serverKS:obtain-certificate(alias=server,domain-names=[www.example.org],certificate-authority-account=myLetsEncryptAccount,agree-to-terms-of-service)
You can now check the alias names in the key-store
and confirm the new alias, "server", is listed:
/subsystem=elytron/key-store=serverKS:read-aliases()
{
"outcome" => "success",
"result" => ["server"]
}
To make use of this server certificate that’s been issued by Let’s Encrypt for one-way or two-way SSL, this server key-store
can be used to create a key-manager
in the Elytron subsystem and an ssl-context
that references this key-manager
can
then be created. More details about setting up one-way and two-way SSL can be found in the Elytron documentation.
Now that we’ve seen the two main ways that certificates can be obtained from Let’s Encrypt using WildFly CLI commands, the next sections will describe how to manage these certificates.
Revoking a certificate from Let’s Encrypt
If you need to revoke a certificate that was issued by Let’s Encrypt, the revoke-certificate
command can be used:
/subsystem=elytron/key-store=serverKS:revoke-certificate(alias=server,reason=keyCompromise,certificate-authority-account=myLetsEncryptAccount)
In the above example, alias identifies the certificate that should be revoked. The certificate-authority-account
is a
reference to the certificate authority account information that should be used to revoke the certificate. The reason is
optional and indicates the reason for revocation. If provided, it must be a valid revocation string.
Once the certificate has been successfully revoked, it will be deleted from the key-store
. This change will also be
persisted to the file that backs the key-store
.
Checking if a certificate is due for renewal
The should-renew-certificate
command can be used to check if a certificate is due for renewal. It returns true if the
certificate expires in less than the given number of days and false otherwise. Its output also indicates the number of
days to expiry. In the following example, should-renew-certificate checks if the certificate stored under the alias
"server" expires in less than 15 days.
/subsystem=elytron/key-store=serverKS:should-renew-certificate(alias=server,expiration=15)
{
"outcome" => "success",
"result" => {
"should-renew-certificate" => false,
"days-to-expiry" => 89L
}
}
If the expiration parameter is not provided, it will default to 30 days, i.e., should-renew-certificate
will return
true if the certificate expires in less than 30 days and false otherwise.
Using a CLI script to automate certificate renewal
Certificates issued by Let’s Encrypt are valid for 90 days. Let’s Encrypt recommends renewing certificates every 60 days. You can automate renewal by first creating a CLI script that checks if a certificate is due for renewal and if so, uses the obtain-certificate command to renew it. You could then create a cron job that runs say, twice daily, and executes the CLI script. A simple example of such a CLI script can be found below:
if (result.should-renew-certificate == true) of /subsystem=elytron/key-store=serverKS:should-renew-certificate(alias=server)
# certificate is due for renewal in less than 30 days, obtain a new certificate to replace the existing one in the key-store
/subsystem=elytron/key-store=serverKS:obtain-certificate(alias=server,domain-names=[www.example.org],certificate-authority-account=myLetsEncryptAccount,agree-to-terms-of-service)
# re-initialize your key-manager to ensure your new certificate will be used without needing to restart the server
/subsystem=elytron/key-manager=httpsKM:init()
end-if
Notice that in the above script, after renewing the certificate, we can simply execute the key-manager init command in order to ensure that the new certificate will be used by the key-manager from now on without needing to restart WildFly.
Updating the contact URLs associated with your Let’s Encrypt account
To update the contact URLs that are associated with your Let’s Encrypt, the following commands can be used:
/subsystem=elytron/certificate-authority-account=myLetsEncryptAccount:write-attribute(name=contact-urls,value=[mailto:newadmin@admin.org])
reload
/subsystem=elytron/certificate-authority-account=myLetsEncryptAccount:update-account()
Changing your Let’s Encrypt account key
If you ever want to change the key that is associated with your Let’s Encrypt account (e.g., in the event of a key
compromise), the change-account-key
command can be used:
/subsystem=elytron/certificate-authority-account=myLetsEncryptAccount:change-account-key()