Tuesday, 5 March 2019

Security Features for WildFly 17

The development for WildFly 17 has now commenced, here are some of the features we are planning to be looking into developing for WildFly 17.

WFCORE-4360 Support encrypted expression resolution using a CredentialStore

The previous Vault implementation was effectively a repository of encrypted clear text strings that could be referenced using expressions in the management model, the new CredentialStore is a repository of credentials.  WFCORE-4360 is to look into how the CredentialStore could be used to support encrypted values within the overall model.

WFCORE-3947 Support SSL Certificate revocation using OCSP

ELY-1712 Enhanced Audit Logging

As the WildFly Elytron project was integrated with WildFly 11 an initial set of events were made available with a couple of options for logging these events, this feature request is to look into how we can enhance this further.

WFCORE-4361 Enhanced mapping of X509Certificate to the underlying identity.

Presently WildFly Elytron provides a variety of options to configure certificate based authentication, this feature request is to enhance how the certificate is mapped to the underlying identity.

WFLY-11697 Web Services Integration with WildFly Elytron

The WildFly Elytron integration added a new API and configuration file to configure the client side security for outgoing calls, this feature request is to increase the integration for web services clients.

WFCORE-4172 Add support for TLS 1.3

WFCORE-4362 Make the certificate authority used by a certificate-authority-account configurable.

At the moment integration with Lets Encrypt is supported, once the certificate authority account is configurable it will be possible to use this integration with other certificate authorities that implement the ACME protocol.

WFCORE-3832 Support hex encoding in jdbc-realm for elytron.

Using multiple security realms.
WildFly Elytron already supports the use of multiple security realms where a realm can be selected either from the authentication mechanism in use or by some recognisable pattern in the username. 

Where LoginModules were used in the previous PicketBox solution it was possible to stack the LoginModules for a few additional scenarios: -

  • Failover in the event of unavailability.
  • Aggregation of multiple identity stores into one.
    • Allowing identities to be located in different stores.
    • Allowing attributes to be loaded from multiple locations.

Issues will be created as needed to track these different scenarios but the aim is during WildFly 17 to begin to address these as they have been identified as making it difficult to migrate from PicketBox.


Also in preparation to develop WildFly Elytron 1.9 the project has been broken up into smaller modules to allow dependencies to be defined on specific modules without depending on the whole project - WildFly 17 will be switching to use the new modules.

Please keep in mind this blog post is a summary of our general plans and not a guarantee that all will be merged but it should give an indication as to the teams current priorities.  If any of these features are a priority to you please let us know, also let us know if there are missing security features you would like prioritising - we can take this into account for future releases.

Saturday, 19 January 2019

Using WildFly Elytron with the Netty HttpServerCodec

The WildFly Elytron project was developed to meet the needs if the WildFly application server, however the APIs and SPIs within this project also allow us to use the project in other environments.

A couple of previous blogs from Farah Juma and myself have highlighted a couple of these environments already: -
 Using WildFly Elytron with Undertow Standalone
 Securing an embedded Jetty server using Elytron

Also I have previously published a blog describing how to implement a custom HTTP authentication mechanism using the WildFly Elytron SPIs.
WildFly Elytron - Implementing a Custom HTTP Authentication Mechanism

Being able to take a single security project and use it in multiple environments has numerous benefits, some of which are: -

  • Only needing to learn one framework instead of one framework per server type.
  • Portability of custom implementation such as authentication mechanisms or security realms which can be used in all environments.
  • The ability to combine multiple servers into a single process whilst using common security SPIs.
This blog post is to introduce the integration of WildFly Elytron with the Netty HttpServerCodec for HTTP authentication.

It is worth noting this integration is specifically making use of Netty's HttpServerCodec for integration, if an alternative HTTP server was developed on Netty then an alternative integration with WildFly Elytron would also be required.

The project containing the Netty integration code can be found on GitHub at elytron-web-netty

As an integration project this project only exposes once class as public API 'org.wildfly.elytron.web.netty.server.ElytronHandlers'  - the purpose this class is to take configured WildFly Elytron components and use them to insert a set of handlers into a Netty ChannelPipeline, once inserted they will perform authentication kaing use of Wildfly Elytron.

The example project can be found on GitHub at netty-standalone.

After checking out the example project it can be built using maven: -

    mvn clean instal

And then once build can also be executed using maven: -

    mvn exec:exec

Once running you can navigate to http://localhost:7776/ and access the application using the username 'alice' with the password 'alice123+', if successful you should see the following response: -

Current identity 'alice'

Now that the example project is running we can look into the details as to how WildFly Elytron was activated.

Activation

Within Netty a ChannelInitializer is required to add the handlers to the ChannelPipeline, within the example project this is within the class 'org.wildfly.security.examples.TestInitialiser' and is implemented as: -


protected void initChannel(SocketChannel ch) throws Exception {
    ChannelPipeline pipeline = ch.pipeline();
    pipeline.addLast(new HttpServerCodec());
    pipeline.addLast(new HttpServerExpectContinueHandler());
    securityHandler.apply(pipeline);
    pipeline.addLast(new TestContentHandler());
}

The 'securityHandler' within the example block of code is actually an instance of the ElytronHandlers class, it is worth noting that it can be cached and re-used potentially performing many initialisations concurrently.

As the example projects starts up the ElytronHandlers is initialised as follows: -

ElytronHandlers securityHandlers = ElytronHandlers.newInstance()
        .setSecurityDomain(securityDomain)
        .setFactory(createHttpAuthenticationFactory())
        .setMechanismConfigurationSelector(MechanismConfigurationSelector.constantSelector(
                MechanismConfiguration.builder()
                        .addMechanismRealm(MechanismRealmConfiguration.builder().setRealmName("Elytron Realm").build())
                        .build()));

This initialisation takes a pre-configured SecurityDomain and HttpAuthenticationFactory and adds a MechanismConfigurationSelector, these have been covered on prior blogs so I am not going to cover the details of these again here although they can all be seen within the org.wildfly.security.examples.HelloWorld class to see how these are initialised.

One further method not used in this example is: -

public ElytronHandlers setAuthenticationRequired(final Predicate<HttpRequest> authenticationRequired)

This can be used to add a Predicate to decide on a request by request basis if authentication is required after inspecting the HttpRequest.

Outcome

After the initialisation described above the channel end up with the following handlers defined on it's pipeline: -

For a request after being handled by the HttpServerCodec handler it will pass so the ElytronInboundHandler, this is where the authentication by WildFly Elytron takes place and a SecurityIdentity is established.

If authentication fails the request can be turned around at this stage and sent back to the client.

Our next inbound handler is the ElytronRunAsHandler, this handler is responsible for taking any established SecurityIdentity and ensuring it is associated with the current thread.

In this set up we have one outbound handler which is the ElytronOutboundHandler, this handler is called for all messages being sent back to the client is responsible for setting any security related HTTP headers that need to be set on the respone message.


Contribution

The Netty integration project is currently tagged as a Beta as a number of areas still need to be developed, if anyone is interested in contributing their contributions will be welcome.

Completing the implementation of the ElytronHttpExchange class: -
  • Support for all Scope types.
  • Parsing of request parameters.
  • Cookie support.
Request InputStream handling.

Improved response OutputStream handling.

Adding support for authorization, either role based checks or Java permission checks.

Further enhancement of the test cases including adding more mechanisms to be tested.

Outside of the Netty integration there are other projects out there still possible options for integration, some of these are: -
  • Tomcat
  • Pure servlet integration.
  • EE Security integration.

For all integrations some form of common testsuite to verify the full permutation of authentication mechanisms available within WildFly Elytron.