Enabling HTTPS in Undertow

2019-03-09 14:43发布

问题:

We have a working Apache mod_ssl configuration. I want to enable HTTPS support for Undertow, so that it listens for both http and https, thus obviating the need for Apache.

I've looked into Undertow's javadocs. The Undertow.Builder class has two addHttpsListener methods with the following signatures:

   public Builder addHttpsListener(int port, String host, 
       KeyManager[] keyManagers, TrustManager[] trustManagers);
   public Builder addHttpsListener(int port, String host,
       SSLContext sslContext) {

So it seems I can use these when bootstrapping Undertow using the Builder API, e.g.

Undertow server = Undertow.builder()
                    .addHttpsListener(8443, "localhost", sslContext)
                    .build();

I'm not sure though how to create the SSLContext variable, or how to configure KeyManagers and TrustManagers. Having the certificate files that are in use by mod_ssl, how can I proceed then with enabling HTTPS for Undertow?

UPDATE:

Per hwellmann's answer, I've reused SslContextFactory.createSslContext() method. Before that, I had to convert my public/private key pair into PKCS12 format and import that into Java keystore.

Giving the SSL conversion conversion/import commands (taken from here and here) below, hopefully these will be useful to anyone:

# Convert to PKCS12    
$ openssl pkcs12 -export -out output_cert.pfx -inkey input_cert.key -in input_cert.crt -certfile intermediate.crt

# Import into Java keystore
$ keytool -v -importkeystore -srckeystore output_cert.pfx -srcstoretype PKCS12 -destkeystore output_store.jks -deststoretype JKS

回答1:

This is not really Undertow-specific, it's just a question of building an SSL context from a keystore with a certificate.

See SslContextFactory.java for an example used with Undertow.



回答2:

There is an example in Undertow source code on how to create the SslContext: https://github.com/undertow-io/undertow/blob/e8473ec35c420b782e072723d1e6338548def842/examples/src/main/java/io/undertow/examples/http2/Http2Server.java#L76

SSLContext sslContext = createSSLContext(loadKeyStore("server.keystore"), loadKeyStore("server.truststore"));

...

private static SSLContext createSSLContext(final KeyStore keyStore, final KeyStore trustStore) throws Exception {
    KeyManager[] keyManagers;
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyManagerFactory.init(keyStore, password("key"));
    keyManagers = keyManagerFactory.getKeyManagers();

    TrustManager[] trustManagers;
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(trustStore);
    trustManagers = trustManagerFactory.getTrustManagers();

    SSLContext sslContext;
    sslContext = SSLContext.getInstance("TLS");
    sslContext.init(keyManagers, trustManagers, null);

    return sslContext;
}

...

private static KeyStore loadKeyStore(String storeLoc, String storePw) throws Exception {
    InputStream stream = Files.newInputStream(Paths.get(storeLoc));
    if(stream == null) {
        throw new IllegalArgumentException("Could not load keystore");
    }
    try(InputStream is = stream) {
        KeyStore loadedKeystore = KeyStore.getInstance("JKS");
        loadedKeystore.load(is, storePw.toCharArray());
        return loadedKeystore;
    }
}