Wednesday, 24 February 2016

WildFly Elytron - SSL Configuration

One of the features being delivered by the upcoming WildFly Elytron integration within WildFly is the ability to provide SSL definitions centrally and then reference these definitions from elsewhere in the configuration.  This blog post demonstrates how to centrally configure SSL resources and subsequently use them to enable SSL both for web applications deployed to Undertow and for management of the server.  This blog post will also demonstrate how the same approach can be taken in domain mode to enable SSL to manage the server.

Environment

As WildFly 10 has been prepared for release the WildFly Elytron development has continued in parallel, to run the examples described here build the following three tags in order: -

https://github.com/wildfly-security-incubator/wildfly/tree/10.0.0.Final-Elytron1

The resulting server is the equivalent of a little before the WildFly 10 release but with the addition of the integration with WildFly Elytron.

After the WildFly build you will find a usable distribution in: -
 'wildfly/dist/target/wildfly-10.0.0.Final-Elytron1'.

Configuring SSL

For this example I am using a JKS KeyStore which contains a single entry which contains a private key and self signed certificate, certificate authority signed certificates would also be usable here.

To start up the application server with the WildFly Elytron subsystem included in the default configuration use the following command: -

bin/standalone.sh -c standalone-elytron.xml

Next start up the CLI and connect to the running server.

The approach taken with the WildFly Elytron subsystem is that different components required for security are defined independently of each other and then are assembled together for the final solution - this approach is taken to make it a lot easier to integrate custom implementations of the different components and to even allow other subsystems to advertise their own implementations within the application server so they can be used either with or in place of the Elytron implementations.

Within the CLI we next need to define three new resources within the Elytron subsystem: -
  1. KeyStore
  2. KeyManager(s)
  3. Server SSL Context
A new KeyStore can be added with the following command: -

./subsystem=elytron/keystore=server:add(type=jks, 
    path=/home/darranl/server.keystore, 
    password=keystore_password)

The arguments to this command should be fairly self explanatory.

The KeyManagers resource is then added with: -

./subsystem=elytron/key-managers=server:add(algorithm=SunX509, 
    keystore=server, 
    password=keystore_password)

In this command the 'keystore' argument is a reference to the KeyStore defined in the first command.

Then the Server SSL Context is defined: -

./subsystem=elytron/server-ssl-context=server:add(
    key-managers=server, 
    protocols=[TLSv1_2])

The 'key-managers' argument is a reference back to the KeyManagers resource defined in the previous command.

The server-ssl-context resource is where all policy information related to SSL will be defined, in this example however as this is a bare minimum definition we just reference the previously defined key-managers and specify that the protocol should be TLS 1.2.

Enable SSL With Undertow

Now that the resources are defined the next step is to enable the use of this resource within Undertow so the following command adds a https-listener referencing the previously defined server-ssl-context: -

./subsystem=undertow/server=default-server/
    https-listener=https:add(
        ssl-context=server, 
        socket-binding=https)

It should now be possible to connect a web browser to port 8443 and the previously defined SSL configuration within the Elytron subsystem will be used.

Enable SSL for Management over HTTP

Within the CLI with a couple more commands the same SSL resources can be used to enable SSL for access to the HTTP management interface: -

./core-service=management/management-interface=http-interface:
    write-attribute(
        name=ssl-context, 
        value=server)

The first command adds a reference to the previously defined server-ssl-context.

./core-service=management/management-interface=http-interface:
    write-attribute(
        name=secure-socket-binding, 
        value=management-https)

This second command then just enables HTTPS access on port 9993.

This last command will also require you to execute :reload for the changes to take effect.

Now you can connect to https://localhost:9993 and this will also be using the same previously defined SSL resources.

Enable SSL for Management over HTTP - Domain Mode

For this next step we now need to shut down the standalone server and start up domain mode with the host controller configured to enable Elytron.

bin/domain.sh --host-config=host-elytron.xml

When running within domain mode the host controller process can now contain it's own subsystems, first we need to repeat the three commands to add SSL resources but this time to the host controllers own Elytron subsystem.


./host=master//subsystem=elytron/keystore=server:
    add(
        type=jks, 
        path=/home/darranl/server.keystore, 
        password=keystore_password)

./host=master/subsystem=elytron/key-managers=server:
    add(
        algorithm=SunX509, 
        keystore=server, 
        password=keystore_password)

./host=master//subsystem=elytron/server-ssl-context=server:
    add(
        key-managers=server, 
        protocols=[TLSv1_2])

The only difference to the previous commands is in each of these the address has been prefixed with 'host=master' - this is so that the Elytron subsystem definition specific to the host controller is configured - apart from that it is exactly the same subsystem.

As before apart from a difference in address this SSL definition can be referenced in the same way: -

./host=master/core-service=management/
    management-interface=http-interface:
        write-attribute(
            name=ssl-context, 
            value=server)

How the port is specified in domain mode is slightly different so this is specified with: -

./host=master/core-service=management/
    management-interface=http-interface:
        write-attribute(
            name=secure-port, 
            value=9993)

The host controller can then be restarted with: -

./host=master:reload

At this point connections to https://localhost:9993 will be using this SSL definition.

Summary

The end result of this development will mean that administrators can learn how to define and tweak SSL policies all within the context of Elytron and the Elytron subsystem and then these policies can be applied across the application server where subsystems reference these resources - the aim being so that administrators do not need to learn how to configure SSL within each subsystem independently.

Advanced Configuration.

This blog post has focussed on the minimal steps required to get SSL enabled, I will follow up with some additional blog posts to cover the following features.

  • Alias Filtering
  • Cipher Suite Selection
  • Client Cert Authentication
  • Inspecting the KeyStore contents using the management model.
  • Inspecting (and invalidating) active sessions from the configured SSL resources.

3 comments:

  1. Thanks for this nice blog. Please let us know how these SSL components will relate to other EAP subsystems, i.e. CXF or Wildfly-Camel.
    Thanks!

    ReplyDelete
  2. Working through the other subsystems is one of our next tasks, we will be dependent on the various libraries and projects that are integrated with the application server and their integration APIs will need to support being passed pre-configured Objects e.g. KeyStore, SSLContext but the intention is everything will be able to depend on the standard types and benefit from a centralised configuration.

    In addition to this we will also be working on default SSLContext registration so for components / libraries / subsystems that make use of the JVM wide default SSLContext we will have one registered to be used.

    ReplyDelete
  3. Just note: "keystore_password" in key-manager definition is password of private key, not password of keystore ;)

    ReplyDelete