mirror of https://github.com/apache/druid.git
Fix hostname validation not skipping with `druid.client.https.validateHostnames=false` in java 8u275 and later (#11538)
* fix skip hostname validation in java 8u275 and later * add unit test * fix checkstyle
This commit is contained in:
parent
23d7d71ea5
commit
4470ca6a92
|
@ -95,6 +95,15 @@ public class CustomCheckX509TrustManager extends X509ExtendedTrustManager implem
|
|||
SSLParameters params = engine.getSSLParameters();
|
||||
params.setEndpointIdentificationAlgorithm(null);
|
||||
engine.setSSLParameters(params);
|
||||
|
||||
// In Java version 8u275 and later, setting EndpointIdentificationAlgorithm to null will be ignored
|
||||
// and the current value will remains. As a workaround, we can set EndpointIdentificationAlgorithm to an
|
||||
// empty String instead. This will still cause the hostname validation to be skipped.
|
||||
if (engine.getSSLParameters().getEndpointIdentificationAlgorithm() != null) {
|
||||
params = engine.getSSLParameters();
|
||||
params.setEndpointIdentificationAlgorithm("");
|
||||
engine.setSSLParameters(params);
|
||||
}
|
||||
}
|
||||
|
||||
certificateChecker.checkServer(chain, authType, engine, delegate);
|
||||
|
|
|
@ -48,7 +48,10 @@ import org.apache.druid.server.initialization.jetty.JettyServerModule;
|
|||
import org.apache.druid.server.initialization.jetty.ServletFilterHolder;
|
||||
import org.apache.druid.server.security.AuthTestUtils;
|
||||
import org.apache.druid.server.security.AuthorizerMapper;
|
||||
import org.apache.druid.server.security.CustomCheckX509TrustManager;
|
||||
import org.apache.druid.server.security.TLSCertificateChecker;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.jboss.netty.handler.codec.http.HttpMethod;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.Assert;
|
||||
|
@ -56,7 +59,12 @@ import org.junit.Ignore;
|
|||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.X509ExtendedTrustManager;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -72,6 +80,7 @@ import java.nio.charset.Charset;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
@ -507,6 +516,44 @@ public class JettyTest extends BaseJettyTest
|
|||
Assert.assertEquals(0, jsm.getActiveConnections());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustomCheckX509TrustManagerSetEndpointIdentificationAlgorithmToNullWithValidateServerHostnamesSetToFalse() throws Exception
|
||||
{
|
||||
SslContextFactory.Server server = injector.getInstance(SslContextFactory.Server.class);
|
||||
server.setEndpointIdentificationAlgorithm("HTTPS");
|
||||
server.start();
|
||||
SSLEngine sslEngine = server.newSSLEngine();
|
||||
X509ExtendedTrustManager mockX509ExtendedTrustManager = Mockito.mock(X509ExtendedTrustManager.class);
|
||||
TLSCertificateChecker mockTLSCertificateChecker = Mockito.mock(TLSCertificateChecker.class);
|
||||
X509Certificate mockX509Certificate = Mockito.mock(X509Certificate.class);
|
||||
String authType = "testAuthType";
|
||||
X509Certificate[] chain = new X509Certificate[]{mockX509Certificate};
|
||||
|
||||
// The EndpointIdentificationAlgorithm should not be null as we set it to HTTPS earlier
|
||||
Assert.assertNotNull(sslEngine.getSSLParameters().getEndpointIdentificationAlgorithm());
|
||||
|
||||
CustomCheckX509TrustManager customCheckX509TrustManager = new CustomCheckX509TrustManager(
|
||||
mockX509ExtendedTrustManager,
|
||||
mockTLSCertificateChecker,
|
||||
false
|
||||
);
|
||||
|
||||
customCheckX509TrustManager.checkServerTrusted(chain, authType, sslEngine);
|
||||
|
||||
ArgumentCaptor<SSLEngine> captor = ArgumentCaptor.forClass(SSLEngine.class);
|
||||
Mockito.verify(mockTLSCertificateChecker).checkServer(
|
||||
ArgumentMatchers.eq(chain),
|
||||
ArgumentMatchers.eq(authType),
|
||||
captor.capture(),
|
||||
ArgumentMatchers.eq(mockX509ExtendedTrustManager)
|
||||
);
|
||||
SSLEngine transformedSSLEngine = captor.getValue();
|
||||
// The EndpointIdentificationAlgorithm should be null or empty Stringas the CustomCheckX509TrustManager
|
||||
// has validateServerHostnames set to false
|
||||
String endpointIdentificationAlgorithm = transformedSSLEngine.getSSLParameters().getEndpointIdentificationAlgorithm();
|
||||
Assert.assertTrue(endpointIdentificationAlgorithm == null || endpointIdentificationAlgorithm.isEmpty());
|
||||
}
|
||||
|
||||
private void waitForJettyServerModuleActiveConnectionsZero(JettyServerModule jsm) throws InterruptedException
|
||||
{
|
||||
// it can take a bit to close the connection, so maybe sleep for a while and hope it closes
|
||||
|
|
Loading…
Reference in New Issue