Open jnizet opened 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.
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.
For anyone who wants to be able to do in 1.4, the new SslStoreProvider interface provides the necessary plug point
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
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.
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.
@voberle That's a question for Spring Cloud but this is a Spring Boot issue
For testing we need a documentation to generate self signed certificate and keystore with tomcat server using keytool (in linux) .
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.
It seems there are two aspects for this problem here:
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:
/.well-known/acme-challenge/
file over HTTPThere 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.
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.
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:
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 KeyStoreserver.ssl
defined KeyStorereloadSslHostConfigs
featureI'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 configurationIts 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 byserver.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
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.