2

I'm using spring-boot version 1.5.6.RELEASE. I configured SSL on port 9443 declaratively in application.yml. This is working. I am also using Undertow for this Spring-boot app.

server:
session:
    cookie:
        http-only: true
contextPath: /webapp
port: 9443
ssl:
    key-store: /etc/pki/mycert.jks
    key-store-password: ${SSL_KEYSTORE_PWD}
    keyStoreType: JKS
    keyAlias: alias

I have configured an additional SSL port programmatically. Here is a snippet:

@Configuration
public class UndertowAdditionalSSLConfig
{

@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory()
{
    UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
    factory.addBuilderCustomizers(new UndertowBuilderCustomizer()
    {
        @Override
        public void customize(Undertow.Builder builder)
        {
            try
            {
                builder.addHttpsListener(9444, "0.0.0.0", getSSLContext());
            }
            catch (Exception e)
            {
                log.error(e,"Could not add additional listener for https");
            }
        }

    });
    return factory;
  }
}

The secondary ssl port is used for x509 client authentication for REST calls between servers. I have been unable to figure out how to do the following programmatically for the secondary ssl port:

client-auth=need

The problem I'm having is the client cert does not seem to be sent or it is not being accepted by the server. My thinking is that I'm missing this piece. Thanks for any help.

UPDATE

After some digging into Spring boot source. I found this:

builder.setSocketOption(Options.SSL_CLIENT_AUTH_MODE, SslClientAuthMode.REQUIRED);

I applied the change to my code:

        @Override
        public void customize(Undertow.Builder builder)
        {
            try
            {
                builder.addHttpsListener(8444, "0.0.0.0", getSSLContext());
                builder.setSocketOption(Options.SSL_CLIENT_AUTH_MODE, SslClientAuthMode.REQUIRED);
            }
            catch (Exception e)
            {
                log.error(e,"Could not add additional listener for https");
            }
        }

I thought I had the solution I was looking for, however the change bled through to SSL on port 9443 as well and the app became non-responsive to browser access.

Really, a better question for me to ask is: How can I setup SSL on 2 separate ports and have 1 accept a client cert so that client based authentication can occur.

thanks

Jim Kennedy
  • 782
  • 9
  • 23

2 Answers2

2

Instead of setting the getSslContext in addHttpsListener method of the builder, which customizes the entire sslContext used by all your connectors, you need to set the ssl on particular connector

public Ssl ssl() {
    Ssl ssl = new Ssl();
    ssl.setProtocol("TLS");
    ssl.setClientAuth(Ssl.ClientAuth.valueOf("need".toUpperCase()));
    // Other SSL stuff
    return ssl;
}

// Not sure where this function is for 1.5.6 spring boot, but for 1.5.2 it is a method of the container factory which you need to override
protected void customizeConnector(Connector aConnector) {
    final Ssl theSsl = ssl();
    // .. Other stuff to enable disable based on condition
    // turn on SSL for our connector
    theSsl.setEnabled(true);
    this.setSsl(theSsl);
    this.setPort(myConnector.getPort()); //otherwise customizeConnector will override port
}
Dave
  • 31
  • 3
1

You should set client-auth:want in application.properties file like below:

server:
session:
    cookie:
        http-only: true
contextPath: /webapp
port: 9443
ssl:
    key-store: /etc/pki/mycert.jks
    key-store-password: ${SSL_KEYSTORE_PWD}
    keyStoreType: JKS
    keyAlias: alias
    client-auth: want

and then open another port programmatically like below:

@Configuration
public class UndertowAdditionalSSLConfig
{

@Bean
public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory()
{
    UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
    factory.addBuilderCustomizers(new UndertowBuilderCustomizer()
    {
        @Override
        public void customize(Undertow.Builder builder)
        {
            try
            {
                builder.addListener(new Undertow.ListenerBuilder().setPort(8444)
                    .setType(Undertow.ListenerType.HTTPS)
                    .setSslContext(getSSLContext())
                    .setHost("0.0.0.0")
                    .setOverrideSocketOptions(OptionMap.create(Options.SSL_CLIENT_AUTH_MODE, SslClientAuthMode.REQUIRED)));
            }
            catch (Exception e)
            {
                log.error(e,"Could not add additional listener for https");
            }
        }
    });
    return factory;
  }
}

and if you want to use Java lambda expressions:

@Configuration
public class UndertowAdditionalSSLConfig {

    @Bean
    public UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() {
        UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
        factory.addBuilderCustomizers((UndertowBuilderCustomizer) builder -> {
            try {
                builder.addListener(new Undertow.ListenerBuilder().setPort(8444)
                        .setType(Undertow.ListenerType.HTTPS)
                        .setSslContext(getSSLContext())
                        .setHost("0.0.0.0")
                        .setOverrideSocketOptions(OptionMap.create(Options.SSL_CLIENT_AUTH_MODE, SslClientAuthMode.REQUIRED)));
            } catch (Exception e) {
                log.error(e, "Could not add additional listener for https");
            }
        });
        return factory;
    }
}
Nasir
  • 515
  • 5
  • 17