When you want to secure a Spring Boot application with e.g. Let’s Encrypt or the OpenShift Service CA, then you will pretty soon figure out that working with PKCS #1 PEM files is a nightmare when it comes to Java. When you Google for PKCS #1 and Java, you will find all kinds of tutorials which suggest to use openssl
and keytool
to create a JKS or PKCS #12 keystore. As Java actually supports pluggable KeyStore implementations, I think there is a better solution for that.
A while back I did work on a PKCS #1 PEM keystore implementation, but at the time, it did only support certificates. Now this problem came back to me, and so it was time for version 2.0.
Spring Boot
Securing a Spring Boot application is rather simple, e.g have a look at this tutorial. All you have to do is to provide a system properties:
server.ssl.enabled=true
server.ssl.key-store=/path/to/server.p12
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=secret
server.ssl.key-alias=server
server.ssl.key-password=secret
But most of the tutorial actually is about converting from PKCS #1 PEM files to PKCS #12. Because all that Java can directly process is PKCS #12 or its own JKS format.
PKCS #1 PEM KeyStore
Now you can drop in the PKCS #1 PEM KeyStore, and directly use those PEM:
server.ssl.enabled=true
server.ssl.key-store=/path/to/keystore.properties
server.ssl.key-store-type=PEMCFG
server.ssl.key-store-password=dummy
server.ssl.key-alias=keycert
And then you create the file keystore.properties
:
alias=keycert
source.cert=/etc/…/fullchain.pem
source.key=/etc/…/privkey.pem
Now you need to make the Java security system aware of the PEMCFG
KeyStore provider. Gladly Java doesn’t easily allow to tamper with the security sub-system. So this needs to be an explicit action. In some way, you have to manually register the provider with Java. With Spring Boot the easiest option is in the main application entry-point:
import de.dentrassi.crypto.pem.PemKeyStoreProvider;
…
public static void main(final String[] args) throws Exception {
Security.addProvider(new PemKeyStoreProvider());
SpringApplication.run(Application.class, args);
}
OpenShift Service CA
This also works with the OpenShift Service CA. Assuming you mapped the TLS secret to /etc/tls
, you could use the following application.yaml
file for Spring Boot:
server:
port: 8443
ssl:
key-store-type: PEMCFG
key-store: classpath:keystore.properties
key-store-password: dummy
key-alias: keycert
security:
require-ssl: true
And the following “keystore.properties” file, which you put in your JAR:
alias=keycert
source.key=/etc/tls/tls.key
source.cert=/etc/tls/tls.crt