I have a multi-tenant webservice which I want to use mutual SSL/TLS authentication as well as user authentication. This means that I need to resolve the user and the user's allowed certs, which can only occur after the SSL connection has been established. I will then use PKIXCertPathBuilderResult
to valid the trust chain using the client certs passed in the request.
In Tomcat with the openssl connector, it's possible to use optional_no_ca
mode, which requests a client cert but does not validate it.
With Jetty 9.x, I've tried configuring the following SslContextFactory
options to no avail:
ValidateCerts=false
ValidatePeerCerts=false
TrustAll=true
How can this be achieved in Jetty 9.x?
Edit 2019: The requirement was to demand an SSL certificate from all client devices accessing the system. The validation of the certificate chain and other certificate attributes would then be performed by the application, which also has the ability to lookup missing cert roots from external sources. This is in contrast to the norm - typically, application servers would perform cert-chain validation during the SSL connection setup using a pre-configured static list of known trusted CAs. If trust can not be found, the SSL connection is rejected.
While TrustAll
seems to be the likely solution, it only works if no TrustStore and KeyStore is given. Then you can't connect using a regular client as the server has no certificate to give during the handshake.
To get a sensible trustAll mode, the only options seems to be to extend SslContextFactory
:
package media.alu.jetty;
/**
* SslContextFactoryRelaxed is used to configure SSL connectors
* as well as HttpClient. It holds all SSL parameters and
* creates SSL context based on these parameters to be
* used by the SSL connectors.
*
* TrustAll really means trustAll!
*/
@ManagedObject
public class SslContextFactoryRelaxed extends SslContextFactory
{
private String _keyManagerFactoryAlgorithm = DEFAULT_KEYMANAGERFACTORY_ALGORITHM;
private String _trustManagerFactoryAlgorithm = DEFAULT_TRUSTMANAGERFACTORY_ALGORITHM;
@Override
protected TrustManager[] getTrustManagers(KeyStore trustStore, Collection<? extends CRL> crls) throws Exception
{
TrustManager[] managers = null;
if (trustStore != null)
{
if (isTrustAll()) {
managers = TRUST_ALL_CERTS;
}
// Revocation checking is only supported for PKIX algorithm
else if (isValidatePeerCerts() && "PKIX".equalsIgnoreCase(getTrustManagerFactoryAlgorithm()))
{
PKIXBuilderParameters pbParams = newPKIXBuilderParameters(trustStore, crls);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
trustManagerFactory.init(new CertPathTrustManagerParameters(pbParams));
managers = trustManagerFactory.getTrustManagers();
}
else
{
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(_trustManagerFactoryAlgorithm);
trustManagerFactory.init(trustStore);
managers = trustManagerFactory.getTrustManagers();
}
}
return managers;
}
}
To use:
Edit $jetty.home/etc/jetty-ssl-context.xml
i. Change:
<Configure id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
to:
<Configure id="sslContextFactory" class="media.alu.jetty.SslContextFactoryRelaxed">
ii. Add <Set name="TrustAll">TRUE</Set>
as child of <Configure id="sslContextFactory">