spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.17k stars 40.68k forks source link

Let's encrypt integration #6148

Open jnizet opened 8 years ago

jnizet commented 8 years ago

Configuring SSL with Java is a pita, and developers typically don't master the JDK commands used to deal with keystores, etc.

Obtaining an SSL certificate in itself is not a piece of cake either. Let's encrypt allows obtaining and renewing certificates for free, in an automated way. But as far as I know, there is no integration with the Java mechanisms to store keys and certificates.

I personally use an Nginx frontend for my Spring-boot applications, only to make it easier to use SSL (and sometimes virtual hosts, but that's another matter).

I have frankly no idea if my idea is doable, but it would be really cool if we could just, in a Spring boot app, set one or two properties (domain name, contact email), and have Spring request a certificate at startup if it doesn't exist, and configure a scheduled job to renew it.

I think it would be a major selling point for Spring boot if it could have SSL out of the box.

I guess that means Spring would need to talk the ACME protocol with let's encrypt, which must be doable, to write private keys and certificates programmatically to the keystore (not sure if it's doable), and make sure the embedded container uses this new key/certificate without having to restart.

stepio commented 8 years ago

I also use nginx to configure SSL, but I've always considered this a feature, not a bug. Using nginx you can easily tweak your server to prevent common pitfalls, such as enabled SSL3 (which is useful only for a tiny segment of IE6 users), or insecure ciphering algorithms.

So in my opinion such integration would be really good only if spring boot's default SSL configuration would receive A here: https://www.ssllabs.com/ssltest/

If not, I'm not sure that the implementation efforts are worth the result.

mp911de commented 8 years ago

Obtaining and configuring SSL certificates upon startup would be a neat feature. I think it would make sense to support a more generic approach like it's done with Caching. Certificates could be obtained from an SSL certificate provider, depending on SSL certificate provider availability.

An example of an additional SSL certificate provider is Hashicorp Vault. It exposes a PKI backend that could be of interest for users willing to use an own (corporate) root/intermediate CA. Users could request SSL certificates for applications inside their corporate network.

wilkinsona commented 8 years ago

For anyone who wants to be able to do in 1.4, the new SslStoreProvider interface provides the necessary plug point

mp911de commented 8 years ago

FWIW, I implemented SSL-on-startup creation with Vault and Spring Cloud Vault that supplies the keystore using SslStoreProvider as experiment.

Docs: Spring Cloud Vault/PKI Backend Code: spring-cloud-vault-config-ssl Tests: spring-cloud-vault-config-ssl Tests

mp911de commented 8 years ago

A challenge with SSL certificate auto-generation and configuration is key/certificate persistence. You probably don't want to generate a certificate with the same common name/alt names multiple times but rather reuse certificates until they expire. This requires some persistence. When an application starts up with multiple instances, it also requires synchronization amongst all nodes behind the same endpoint.

Obtaining a private key/certificate bundle and writing it into a KeyStore is doable by implementing either DER/ASN.1 decoding or using libraries such as BouncyCastle.

Certificate and Public Key Pinning might play into this as well.

voberle commented 7 years ago

Are there any plans to have Mark's PKI backend support merged into Spring Cloud Vault mainline? Vault PKI backend is very promising, but the lack of Spring Cloud support makes it non trivial to use.

wilkinsona commented 7 years ago

@voberle That's a question for Spring Cloud but this is a Spring Boot issue

suman111 commented 6 years ago

For testing we need a documentation to generate self signed certificate and keystore with tomcat server using keytool (in linux) .

jliuold commented 4 years ago

Hello, what's the result of this issue now. A self signed certificate is enough. Spring Boot can provide a self signed certificate generation tool and selectively integrate it into the HTTP server. Everything is configurable and safe by default. No HTTP is becoming more and more important.

bclozel commented 3 years ago

It seems there are two aspects for this problem here:

  1. creating and installing TLS certificates in a production application, using production domains
  2. helping developers setting up TLS locally for development purposes

TLS certificates with LetsEncrypt

Let's assume that we'd like to use a library like acme4j to generate and install certificates dynamically during application startup. The CLI use case is already well covered by the CertBot client.

Creating a certificate with LetsEncrypt involves the following steps:

There are several challenges with this approach. The KeyPair management is probably the toughest one, as it would require a universal and safe approach for storing KeyPairs and Certificates. Any data loss here is hard to fix since the user account would be inaccessible.

Also, the process depends a lot on the deployment model. If your application is using proxies (with TLS termination) or even just multiple instances, deploying the newly generated cert will lead to distributed systems problems - all while the application is considered "UP" by the platform.

Local TLS development with your browser

Using TLS certificates during local development is really useful when the server is configured with an http/2 connector, or when browser behavior with secured connections is important.

Generating TLS certificates locally can be cumbersome and since they're self-signed, they're not trusted by the usual tools (browser, curl, etc). Tools like mkcert and making this way easier, by setting up a local CA and configuring your system to trust them locally.

There are enhancement opportunities here.

We could create new Spring Boot plugin goals that could call the locally installed mkcert and:

I'm still a bit hesitant about this, because this enhancement would tie Spring Boot to a particular binary tool that the Spring team cannot provide support for directly. This would be also a first, since it would involve Spring Boot with host interactions. Adding a newly trusted certiticate to the host is a significant operation.

With all that in mind, I'm tempted to decline this enhancement — this issue is quite popular so we'll leave it open for the time being to collect feedback.

valb3r commented 3 years ago

I've created a small library that manages the entire LetsEncrypt certificate lifecycle (it is no means to replace this feature but at least something, as I'm tired configuring Traefik sidecars or CRON jobs to manage certificate when we have full-blown application servers in Spring), hope it would help someone: https://github.com/valb3r/letsencrypt-helper

Currently, it works for Embedded-Tomcat on Spring-Boot and allows to obtain and renew LetsEncrypt certificate directly within Java just by adding @Import(TomcatWellKnownLetsEncryptChallengeEndpointConfig.class) into configuration

Its functionality quite straightforward:

deepakkoirala commented 1 year ago

I've created a small library that manages the entire LetsEncrypt certificate lifecycle (it is no means to replace this feature but at least something, as I'm tired configuring Traefik sidecars or CRON jobs to manage certificate when we have full-blown application servers in Spring), hope it would help someone: https://github.com/valb3r/letsencrypt-helper

Currently, it works for Embedded-Tomcat on Spring-Boot and allows to obtain and renew LetsEncrypt certificate directly within Java just by adding @Import(TomcatWellKnownLetsEncryptChallengeEndpointConfig.class) into configuration

Its functionality quite straightforward:

  • On bootstrap, if Keystore defined by server.ssl does not exist, it generates a self-signed domain certificate that is expired and stores it into new Keystore defined by server.ssl, also it generates account key-pair and stores it into same KeyStore
  • There is a watcher thread that checks if the domain certificate is expired or is close to expiry and if so issues a new one from LetsEncrypt and stores new certificate into server.ssl defined KeyStore
  • Certificates are stored in Java KeyStore (preferably PKCS12, but users can define their own type, i.e. BCFKS) so that they are protected
  • No JVM restart is necessary to use renewed certificates as Tomcat has reloadSslHostConfigs feature

works great. really helpful