Closed mikaves closed 2 years ago
There is already a field called clientCertificateChain
that is available in callbacks (method / closure OR class). Currently there is not support for assertion on client certificate chain but it would be fairly simple to create a closure callback that did this, for example:
mockServerClient
.when(
request()
.withPath("/some_path")
)
.respond(
httpRequest -> {
if (httpRequest.isSecure()) {
assertThat(httpRequest.getClientCertificateChain().size(), equalTo(2));
assertThat(httpRequest.getClientCertificateChain().get(0).getSubjectDistinguishedName(), equalTo("C=UK, ST=England, L=London, O=MockServer, CN=localhost"));
assertThat(httpRequest.getClientCertificateChain().get(1).getSubjectDistinguishedName(), equalTo("C=UK, ST=England, L=London, O=MockServer, CN=www.mockserver.com"));
}
return response()
.withBody("some_response");
}
);
I'm not sure I full understand you first point. As I understand you want MockServer to configure the tlsMutualAuthenticationCertificateChain
for client connections even when tlsMutualAuthenticationRequired
is false so that clients that want to present their certificate can choose the correct certificate to present? If so I can change the logic as follows:
from:
final SslContextBuilder sslContextBuilder = SslContextBuilder
.forServer(
keyAndCertificateFactory.privateKey(),
keyAndCertificateFactory.certificateChain()
)
.protocols(TLS_PROTOCOLS)
// .sslProvider(SslProvider.JDK)
.clientAuth(configuration.tlsMutualAuthenticationRequired() ? ClientAuth.REQUIRE : ClientAuth.OPTIONAL);
if (configuration.tlsMutualAuthenticationRequired()) {
sslContextBuilder.trustManager(trustCertificateChain(configuration.tlsMutualAuthenticationCertificateChain()));
} else {
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
}
to:
final SslContextBuilder sslContextBuilder = SslContextBuilder
.forServer(
keyAndCertificateFactory.privateKey(),
keyAndCertificateFactory.certificateChain()
)
.protocols(TLS_PROTOCOLS)
// .sslProvider(SslProvider.JDK)
.clientAuth(configuration.tlsMutualAuthenticationRequired() ? ClientAuth.REQUIRE : ClientAuth.OPTIONAL);
X509Certificate[] trustCertificateChain = trustCertificateChain(configuration.tlsMutualAuthenticationCertificateChain())
if (trustCertificateChain != null && trustCertificateChain.length > 0) {
sslContextBuilder.trustManager(trustCertificateChain);
} else {
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
}
This way the tlsMutualAuthenticationCertificateChain
will be used if it is configured even if tlsMutualAuthenticationRequired
is false.
Does that cover both your points?
It looks like we cannot use optional client certificate authentication. Setting the tlsMutualAuthenticationCertificateChain has effect only if tlsMutualAuthenticationRequired is true which makes the client certificate authentication mandatory.
If tlsMutualAuthenticationRequired is false client certificate authentication is made optional but we cannot then specify the acceptable client certificate list and mockserver sends empty list to client in tls handshake. Client cannot pick any suitable client certificate from the key store as it does not know which CAs server accepts.
Naturally this also raises the need to be able to verify that client provided client certificate in the case it should have been provided. Also it would be good to be able to assert which certificate was used as one could have application which has multiple key stores and one would need to assert that key was picked up from correct key store.