Micronaut-core: Lets Encrypt Integration

Created on 15 Jan 2019  路  10Comments  路  Source: micronaut-projects/micronaut-core

Hi, the SSL documentation mentions Let's Encrypt, but doesn't integrate with the Java ACME client. It'd be good to have this integrated and the certificates auto-generated / renewed (as a background task). Thanks!

awaiting third-party

All 10 comments

I'm considering picking this but wanted to at least write out what Im thinking on how to get there and get some feedback to make sure I'm on the right path.

Changes needed

  1. Setup daily?? background task @Scheduled(fixedRate = "24h"), probably configurable?? to check if the cert is valid. Probably also want this to happen on initial startup (in the background of course to not impact startup time) since if no lets encrypt certificate is there you dont want to wait 24h before the application is using valid ssl setup.
  2. If cert is within a 30 days or less of renewal (maybe configurable renewal time??, default 30days to match certbot renewal time https://certbot.eff.org/docs/using.html#renewing-certificates), use acme4j to do the renewal (https://shredzone.org/maven/acme4j/usage/order.html)
  3. Once we have the cert we will "refresh" the SSLContext for the NettyHttpServer so have it now use the new cert. Also once we have the new cert we will save it to disk. micronaut.ssl.letsEncrypt.certPath

    1. Which means we will need to define a custom SSLContext in this class so that the keystore can be refreshed when we have a new cert. Just like how a custom SSLContext is being done for the self signed certificate path. https://github.com/micronaut-projects/micronaut-core/blob/master/http-server-netty/src/main/java/io/micronaut/http/server/netty/ssl/NettyServerSslBuilder.java#L64

  4. Add a new endpoint so that LetsEncrypt can validate the domain with the path of /.well-known/acme-challenge/{token}. (https://shredzone.org/maven/acme4j/challenge/http-01.html) This would be marked with defaultEnabled=true and defaultSensitive=false since let's encrypt needs to call into it.

Sample Config

Thinking the configuration would live under micronaut.ssl and would probably look something like this.

micronaut:
    ssl:
        enabled: true
        letsEncrypt: 
            enabled: true
            certPath: <location cert should be saved to on disk>
            keyPair: <xxxx>
            renewWithin: 30 //number of days 
            checkFrequency: 24 //hours/cron/etc (whatever @Scheduled allows)
            createNewAccount: true //default false
            accountEmail: [email protected] //only needed for new account creation, default empty
            agreeToTOS: true //only needed for new account creation, thought is its more of an explict thing to make sure you in fact agree, default false
            domains: 
                - <domain name>
                - <domain name>
                - ....
             ips: 
            - <ip>
            - <ip>
            - ...

Code location

Code will probably also get placed under the io.micronaut.ssl package under a letsencrypt package.

Other thoughts on things that could be useful:

  1. /cert/revoke POST endpoint that you could call manually to revoke a certificate and pass a reason (https://shredzone.org/maven/acme4j/usage/certificate.html#Revocation). This would be marked with defaultSensitive=true and defaultEnabled=false
  2. /cert/renew GET endpoint that you could call manually to get a new certificate outside of the background process. This would be marked with defaultSensitive=true and defaultEnabled=false

Any thoughts or suggestions on the above @hc-codersatlas @graemerocher ??

@zendern definitely seems useful. I'm not sure it actually belongs in micronaut-core as a repo, it may make sense to create a project under https://github.com/micronaut-projects/ since it sounds like it may need many third party dependencies. Thoughts?

@graemerocher That makes sense. It definitely needs a third party dependency (acme4j). Once outside of core though I'll have to figure out how to get a new SSLContext into the NettyHttpServer that lives in core. Was going to follow how self signed path works in there but if outside of core that'll change how it's implemented.

@zendern It may be that changes to core are required to implement the feature, but that can be a separate PR

@graemerocher so what's the process for getting a new project in the micronaut-projects family?? I haven't done that before into a project I didn't own.

We create a project and add you as an external contributor. We did that for https://github.com/micronaut-projects/micronaut-graphql which is built by @marceloverdijk

Let us know what you would like to call it

@graemerocher so micronaut-letsencrypt is first thing that comes to mind but honestly none of it should be letencrypt specific. If another vendor has the acme protocol in place it should in theory be pluggable to pull cert by using those acme servers. So maybe micronaut-acme??

1388 More work towards this and for now I have created a repo under my account to start working through the implementation. https://github.com/zendern/micronaut-acme. See PR for status of where that repo is.

@graemerocher are you (or someone else) able to give @zendern some guidance on publishing/appropriate maven coordinates in https://github.com/zendern/micronaut-acme/issues/2#issuecomment-561461688 ?

Was this page helpful?
0 / 5 - 0 ratings