implementation("io.micronaut.acme:micronaut-acme")
Micronaut Acme
Extensions to integrate Micronaut and Acme
Version: 5.2.0
1 Introduction
Micronaut supports ACME via the micronaut-acme
module.
2 Release History
For this project, you can find a list of releases (with release notes) here:  https://github.com/micronaut-projects/micronaut-acme/releases
3 Configuration
Micronaut 1.3.0 or above is required and you must have the micronaut-acme
dependency on your classpath:
<dependency>
<groupId>io.micronaut.acme</groupId>
<artifactId>micronaut-acme</artifactId>
</dependency>
The micronaut-acme
module transitively includes the org.shredzone.acme4j:acme4j-client
and org.shredzone.acme4j:acme4j-utils
dependency.
micronaut:
server:
port : 80 (1)
dual-protocol: true (2)
ssl:
enabled: true (3)
acme:
enabled: true (4)
tos-agree: true (5)
cert-location: /path/to/store/certificates (6)
domains: (7)
- stage.domain.com
- test.domain.com
refresh:
delay: 1m (8)
frequency: 24h (9)
domain-key: | (10)
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAi32GgrNvt5sYonmvFRs1lYMdUTsoFHz33knzsTvBRb+S1JCc
al86zAx3dRdFiLyWw4/lXmS6oS5B/NT1w9R7nW3vd0oi4ump/QjWjOd8SxCBqMcR
....
MIIEowIBAAKCAQEAi32GgrNvt5sYonmvFRs1lYMdUTsoFHz33knzsTvBRb+S1JCc
al86zAx3dRdFiLyWw4/lXmS6oS5B/NT1w9R7nW3vd0oi4ump/QjWjOd8SxCBqMcR
-----END RSA PRIVATE KEY-----
account-key: | (11)
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAi32GgrNvt5sYonmvFRs1lYMdUTsoFHz33knzsTvBRb+S1JCc
al86zAx3dRdFiLyWw4/lXmS6oS5B/NT1w9R7nW3vd0oi4ump/QjWjOd8SxCBqMcR
....
MIIEowIBAAKCAQEAi32GgrNvt5sYonmvFRs1lYMdUTsoFHz33knzsTvBRb+S1JCc
al86zAx3dRdFiLyWw4/lXmS6oS5B/NT1w9R7nW3vd0oi4ump/QjWjOd8SxCBqMcR
-----END RSA PRIVATE KEY-----
acme-server: acme://server.com (12)
order:
pause: 3s (13)
refresh-attempts: 10 (14)
auth:
pause: 1m (15)
refresh-attempts: 10 (16)
renew-within: 30 (17)
challenge-type: tls (18)
timeout: 10s (19)
1 | Set the http port for micronaut. If using http challenge-type this must be set to port 80, unless using a load balancer or some other proxy as Let’s Encrypt for example only sends request to port 80. |
2 | Enables dual port mode that allows for both http and https to be bound. Default is false |
3 | Enables ssl for micronaut. Default is false |
4 | Enables ACME integration for micronaut. Default is false |
5 | Agrees to the Terms of Service of the ACME provider. Default is false |
6 | Location to store the certificate on the server. |
7 | Domain name(s) for the certificate. Can be a 1 or many domains or even a wildcard domain. |
8 | How long to wait until the server starts up the ACME background process. Default is 24 hours |
9 | How often the server will check for a new ACME cert and refresh it if needed. Default is 24 hours |
10 | Private key used to encrypt the certificate. Other options you can use here are classpath:/path/to/key.pem or file:/path/to/key.pem . It is advisable to not check this into source control as this is the secret to handle the domain encryption. |
11 | Private key used to when setting up your account with the ACME provider. Other options you can use here are classpath:/path/to/key.pem or file:/path/to/key.pem . It is advisable to not check this into source control as this is your account identifier. |
12 | Url of the ACME server (ex. acme://letsencrypt.org/staging) |
13 | Time to wait in between polling order status of the ACME server. Default is 3 seconds |
14 | Number of times to poll an order status of the ACME server. Default is 10 |
15 | Time to wait in between polling authorization status of the ACME server. Default is 3 seconds |
16 | Number of times to poll an authorization status of the ACME server. Default is 10 |
17 | Number of days before the process will start to try to refresh the certificate from the ACME provider. Default is 30 days |
18 | The challenge type you would like to use. Default is tls . Possible options : http, tls, dns |
19 | Sets the connection/read timeout when making http calls to the ACME server. Default comes from here https://shredzone.org/maven/acme4j/acme4j-client/apidocs/src-html/org/shredzone/acme4j/connector/NetworkSettings.html#line.61 |
4 Challenge Types
ACME supports 3 different challenge types which will be used to validate that you in fact own the domain before a certificate is issued.
4.1 HTTP-01
Utilizing http
challenge type you will need to do one of the following two things :
-
enable dual protocol support
-
setup redirect from http → https in any load balancer/proxy server you have in front of your application.
The reason for this is that Let’s Encrypt for example will only call out to the http challenge type over http and nothing else but will follow redirects.
acme:
challenge-type: 'http'
micronaut:
server:
dual-protocol: true
4.2 TLS-APLN-01
Utilizing tls
challenge type is the simplest to configure and thus the default because you will only be required
to open up the default secure port for the server to allow the challenge server to validate it.
acme:
challenge-type: 'tls'
4.3 DNS-01
Utilizing dns
challenge type allows validation to be done via entry of a DNS TXT record.
Manual Verification
By default, the application will log out a message that looks as follows.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
CREATE DNS `TXT` ENTRY AS FOLLOWS
_acme-challenge.example.com with value 79ZNJaxlcLYIFootHL6Rrbh2VUCfFGgPeurVyjoRrS8
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Once this is output you will need to log into your DNS provider and create a TXT entry with the following key and value.
-
key:
_acme-challenge.example.com
-
value:
79ZNJaxlcLYIFootHL6Rrbh2VUCfFGgPeurVyjoRrS8
Since this is a manual process you will also want to bump up your acme.auth.pause
duration so that there is enough time between retries
and time take for the manual entry/DNS propagation.
acme:
challenge-type: 'dns'
auth:
# Due to the current manual nature in which the dns validation is performed by default
# we change the amount of time we wait before trying to authorize again to make sure there
# is time for us logging into the dns interface, setting a TXT record and waiting for it
# to propagate.
pause: 2m
Automatic Verification
An implementation of DnsChallengeSolver can be provided to automate the creation and cleanup of the necessary DNS records.
@Singleton
@Replaces(DnsChallengeSolver.class)
class CustomDnsChallengeSolver implements DnsChallengeSolver {
@Override
public void createRecord(String domain, String digest) {
// Create a TXT record for $domain with the key "_acme-challenge" and the value of $digest
}
@Override
public void destroyRecord(String domain) {
// Remove the TXT record for $domain with the key "_acme-challenge" if it exists
}
}
5 CLI
To be able to secure your application using ACME there will be a few setup steps necessary before you can start using the new certificates. Support for ACME and this setup has been baked into micronaut-starter (https://github.com/micronaut-projects/micronaut-starter).
5.1 Usage
To use these functions you must first enable the acme
feature in your app.
For a new app
Either at creation time you will need to select the acme
feature
Using the Micronaut CLI select the acme
feature on creation.
mn create-app --features acme hello-world
Or using Micronaut Launch https://micronaut.io/launch/ simply select acme
feature before downloading your pre-built app.
For an existing app
Use the micronaut cli to do a feature-diff
on an exiting app to show the changes needed
to enable the feature.
ex. CLI Feature Diff
cd <project directory>
mn feature-diff --features acme
Creating keypairs
A utility to help with creating keypairs. This is akin to doing something like so with openssl
$ openssl genrsa -out /tmp/mydomain.com-key.pem 4096
These keypairs will be used for both ACME accounts as well as each domain will also need its own keypair defined.
Usage:
Usage: mn create-key [-fhvVx] [-k=<keyDir>] -n=<keyName> [-s=<keySize>]
Creates an keypair for use with ACME integration
-f, --force Whether to overwrite existing files
-h, --help Show this help message and exit.
-k, --key-dir=<keyDir> Custom location on disk to put the key to be used
with this account.
Default: src/main/resources
-n, --key-name=<keyName> Name of the key to be created
-s, --key-size=<keySize> Size of the key to be generated
Default: 4096
-v, --verbose Create verbose output.
-V, --version Print version information and exit.
-x, --stacktrace Show full stack trace when exceptions occur.
Creating an Account
Creates a new account for a given ACME provider. This command will either create a new account keypair for you or you can pass
the account keypair that you have generated using the mn create-key
or via openssl
or other means in as a parameter.
Certbot or many of the other tools out there can also accomplish this step if you dont want to use this tool.
Usage:
Usage: mn create-acme-account (-u=<serverUrl> | --lets-encrypt-prod | --lets-encrypt-staging)
[-fhvVx] -e=<email> [-k=<keyDir>] -n=<keyName> [-s=<keySize>]
Creates a new account on the given ACME server
-e, --email=<email> Email address to create account with.
-f, --force Whether to overwrite existing files
-h, --help Show this help message and exit.
-k, --key-dir=<keyDir> Custom location on disk to put the key to be used with this
account.
Default: src/main/resources
-n, --key-name=<keyName> Name of the key to be created
-s, --key-size=<keySize> Size of the key to be generated
Default: 4096
-v, --verbose Create verbose output.
-V, --version Print version information and exit.
-x, --stacktrace Show full stack trace when exceptions occur.
ACME server URL
--lets-encrypt-prod Use the Let's Encrypt prod URL.
--lets-encrypt-staging Use the Let's Encrypt staging URL
-u, --url=<serverUrl> URL of ACME server to use
Deactivating an Account
Deactivates a given account based on the account key that was used to create the account.
Usage:
Usage: mn deactivate-acme-account (-u=<serverUrl> | --lets-encrypt-prod |
--lets-encrypt-staging) [-fhvVx] [-k=<keyDir>] [-n=<keyName>]
Deactivates an existing ACME account
-f, --force Whether to overwrite existing files
-h, --help Show this help message and exit.
-k, --key-dir=<keyDir> Directory to find the key to be used for this account.
Default: src/main/resources
-n, --key-name=<keyName> Name of the key to be used
Default: null
-v, --verbose Create verbose output.
-V, --version Print version information and exit.
-x, --stacktrace Show full stack trace when exceptions occur.
ACME server URL
--lets-encrypt-prod Use the Let's Encrypt prod URL.
--lets-encrypt-staging Use the Let's Encrypt staging URL
-u, --url=<serverUrl> URL of ACME server to use
6 Repository
You can find the source code of this project in this repository: