HTTPS With Undertow
This guide will help you generate a certificate and configure Undertow to use it for HTTPS.
The project
To go through this guide, you need a Web project based on the Undertow embedded Web server. If you don’t have one, invoke
the SeedStack generator to create a web
project type:
mvn -U org.seedstack:seedstack-maven-plugin:generate
A self-signed certificate
In this section, you are going to start the process by generating a self-signed certificate.
Generate the certificate
We are going to use the Java keytool
program (locate in the JDK bin
folder) to generate a keystore containing a
2048 bits self-signed certificate and its key pair. Go into the project directory and type:
keytool -genkey -alias ssl -keyalg RSA -keysize 2048 -dname "CN=myserver.mycompany.com,OU=IT,O=My company,L=Paris,C=FR,email=contact@email.com" -keystore master.jks -storepass changeMe -keypass changeMe
For good security, use strong and unique passwords for the key store itself and for the key.
Update the the dname
parameter value according to your company and/or personal details.
Configure the keystore and SSL
Now edit the application.yaml
file of your project. Add the following section to configure the master
keystore:
crypto:
keystores:
master:
path: master.jks
password: changeMe
ssl:
keyPassword: changeMe
This declares:
- A keystore named
master
, based on the file we generated before. - The password used by SSL to read the key from the keystore.
In SeedStack, the master
keystore is used by default for various tasks like configuration encryption or SSL.
Enable HTTPS
In the application.yaml
file, add the following section:
web:
server:
https: true
This will enable HTTP on port 8080, HTTPS on port 8443 and will automatically redirect any HTTP access to HTTPS.
Try it!
Launch the Web application:
mvn seedstack:run
And point your browser to https://localhost:8443.
You will see a security warning in your browser because the certificate is self-signed for now. Ignore it at the moment, to display the application homepage.
A trusted certificate
In this section, you are going to ask a trusted «Certificate Authority» (CA) to sign your initial certificate to replace your self-signed one.
Create a CSR
To obtain a trusted certificate, you need to create a «Certificate Signing Request» (CSR):
keytool -certreq -alias ssl -keystore master.jks -file request.csr
This CSR will have to be submitted to the CA of your choice, which will return the signed certificate to you.
Import the CA certificates in the keystore
To be able to import the signed certificate in the keystore, you must first import the CA certificate(s) in the keystore:
keytool -import -trustcacerts -alias root_ca -file root_ca.crt -keystore master.jks -storepass changeMe -keypass changeMe
Depending on how your certificate authority work, you may also have to import one or more intermediate certificates in addition to the root certificate. Just add them to the keystore, each under a unique alias name.
The unbroken chain from the signed server certificate to the CA root certificate must be present and valid in the keystore.
Import the signed certificate
At last, import the signed certificate in the keystore under the same alias as your self-signed certificate to overwrite it:
keytool -import -alias ssl -file signed_cert.cer -keystore master.jks -storepass changeMe -keypass changeMe
Try it!
After deploying the application on an URL matching the CN of your certificate, you can point your browser to the CN. In our (fake) example, it is:
https://myserver.mycompany.com
Mutual authentication
This section deals about establishing a mutual authentication between the server and the clients. It’s useful when you need to guarantee your client identity from their certificate.
Create a truststore to validate client certificates
To be able to validate the chain of trust, you have to import the certification authority (CA) certificate(s) into a truststore:
keytool -import -trustcacerts -alias root_ca -file root_ca.crt -keystore truststore.jks -storepass changeMe -keypass changeMe
Depending on how your certificate authority work, you may also have to import one or more intermediate certificates in addition to the root certificate. Just add them to the truststore, each under a unique alias name.
A client certificate will be validated against the chain of CA certificates present in the truststore.
Some certificates, particularly the CA root, will be the same between the keystore and the truststore. You can choose to merge both stores but it is recommended to keep them separate.
Configure the truststore
Now edit the application.yaml
file of your project. Add the following section to configure the truststore:
crypto:
truststore:
path: truststore.jks
password: changeMe
Configure SSL to require a client certificate
If you want to go beyond HTTPS and require HTTPS clients to send their own certificate, set the following configuration:
crypto:
ssl:
clientAuthMode: REQUIRED
Optional: use the client certificate for authentication
If you want to use the client certificate as the subject identity you will need to have the following dependency in your project:
<dependency>
<groupId>org.seedstack.seed</groupId>
<artifactId>seed-web-security</artifactId>
</dependency>
Show version
dependencies {
compile("org.seedstack.seed:seed-web-security:3.15.1")
}
Then configure the security subsystem to use the certificate for authentication and authorization purposes:
security:
realms: X509CertificateRealm
To extract the certificate from the HTTP request, add the cert
filter on the necessary URL patterns:
security:
web:
urls:
-
pattern: "/**"
filters: cert
You can inject the SecuritySupport
interface to do additional checks
on the subject:
package org.generated.project.interfaces.rest;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.seedstack.seed.security.SecuritySupport;
@Path("hello")
public class HelloResource {
@Inject
private SecuritySupport securitySupport;
@GET
public String hello() {
String id = securitySupport.getIdentityPrincipal().getPrincipal().toString();
return "Hello " + id + "!";
}
}
Troubleshooting
Setting up a working SSL handshake can be tricky, so if you encounter any problem you can switch the Java SSL debugging on with the -Djavax.net.debug=all
system property. Example with the run
goal:
mvn -Djavax.net.debug=all seedstack:run