NIFI-6196: Upgrade Jetty version to 9.4.15.v20190215

Updated NOTICE with current copyright year for Jetty dependencies
Updated Jetty SSLContextFactory usage, invoke setEndpointIdentificationAlgorithm(null) on server SslContextFactory instances
Updated TestInvokeHttpSSL to provide a separate client keystore, rather than reusing the server's keystore
Regenerated nifi-standard-processors keystore and truststore, added client keystore
Updated ITestHandleHttpRequest, TestInvokeHttpSSL, TestInvokeHttpTwoWaySSL, and TestListenHTTP to use a separate client keystore instead of reusing the server's keystore.  Also updated the tests to separately test one-way and two-way SSL

NIFI-6196 - Setting the endpoint identification algorithm to null for sockets to ensure certificates without SANs applied correctly still work. We can change this in a new NiFi release with other potentially breaking changes.

This closes #3426.
This commit is contained in:
Jeff Storck 2019-04-08 20:09:28 -04:00 committed by thenatog
parent cf6f517250
commit 65c41ab917
28 changed files with 212 additions and 52 deletions

View File

@ -591,7 +591,7 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
(ASLv2) Apache Tomcat
The following NOTICE information applies:

View File

@ -173,7 +173,7 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
(ASLv2) Apache Velocity
The following NOTICE information applies:

View File

@ -868,6 +868,11 @@ public class JettyServer implements NiFiServer, ExtensionUiLoader {
}
protected static void configureSslContextFactory(SslContextFactory contextFactory, NiFiProperties props) {
// Need to set SslContextFactory's endpointIdentificationAlgorithm to null; this is a server,
// not a client. Server does not need to perform hostname verification on the client.
// Previous to Jetty 9.4.15.v20190215, this defaulted to null, and now defaults to "HTTPS".
contextFactory.setEndpointIdentificationAlgorithm(null);
// require client auth when not supporting login, Kerberos service, or anonymous access
if (props.isClientAuthRequiredForRestApi()) {
contextFactory.setNeedClientAuth(true);

View File

@ -78,6 +78,11 @@ public class NiFiTestServer {
private void createSecureConnector() {
org.eclipse.jetty.util.ssl.SslContextFactory contextFactory = new org.eclipse.jetty.util.ssl.SslContextFactory();
// Need to set SslContextFactory's endpointIdentificationAlgorithm to null; this is a server,
// not a client. Server does not need to perform hostname verification on the client.
// Previous to Jetty 9.4.15.v20190215, this defaulted to null, and now defaults to "HTTPS".
contextFactory.setEndpointIdentificationAlgorithm(null);
// require client auth when not supporting login or anonymous access
if (StringUtils.isBlank(properties.getProperty(NiFiProperties.SECURITY_USER_LOGIN_IDENTITY_PROVIDER))) {
contextFactory.setNeedClientAuth(true);

View File

@ -231,7 +231,7 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
(ASLv2) Apache log4j
The following NOTICE information applies:

View File

@ -237,7 +237,7 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
(ASLv2) Apache log4j
The following NOTICE information applies:

View File

@ -171,7 +171,7 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
(ASLv2) Apache log4j
The following NOTICE information applies:

View File

@ -13,7 +13,7 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
************************
Common Development and Distribution License 1.1

View File

@ -275,7 +275,7 @@ Apache Software License v2
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
(ASLv2) Apache Kafka
The following NOTICE information applies:

View File

@ -506,6 +506,11 @@ public class HandleHttpRequest extends AbstractProcessor {
sslFactory.setProtocol(sslService.getSslAlgorithm());
// Need to set SslContextFactory's endpointIdentificationAlgorithm to null; this is a server,
// not a client. Server does not need to perform hostname verification on the client.
// Previous to Jetty 9.4.15.v20190215, this defaulted to null.
sslFactory.setEndpointIdentificationAlgorithm(null);
if (sslService.isKeyStoreConfigured()) {
sslFactory.setKeyStorePath(sslService.getKeyStoreFile());
sslFactory.setKeyStorePassword(sslService.getKeyStorePassword());

View File

@ -246,6 +246,11 @@ public class ListenHTTP extends AbstractSessionFactoryProcessor {
final SslContextFactory contextFactory = new SslContextFactory();
contextFactory.setNeedClientAuth(needClientAuth);
// Need to set SslContextFactory's endpointIdentificationAlgorithm to null; this is a server,
// not a client. Server does not need to perform hostname verification on the client.
// Previous to Jetty 9.4.15.v20190215, this defaulted to null, and now defaults to "HTTPS".
contextFactory.setEndpointIdentificationAlgorithm(null);
if (needClientAuth) {
contextFactory.setTrustStorePath(sslContextService.getTrustStoreFile());
contextFactory.setTrustStoreType(sslContextService.getTrustStoreType());

View File

@ -30,6 +30,7 @@ import org.apache.nifi.controller.AbstractControllerService;
import org.apache.nifi.http.HttpContextMap;
import org.apache.nifi.processors.standard.util.HTTPUtils;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.nifi.ssl.StandardRestrictedSSLContextService;
import org.apache.nifi.ssl.StandardSSLContextService;
@ -72,7 +73,7 @@ public class ITestHandleHttpRequest {
return props;
}
private static Map<String, String> getKeystoreProperties() {
private static Map<String, String> getServerKeystoreProperties() {
final Map<String, String> properties = new HashMap<>();
properties.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/keystore.jks");
properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), "passwordpassword");
@ -80,7 +81,15 @@ public class ITestHandleHttpRequest {
return properties;
}
private static SSLContext useSSLContextService(final TestRunner controller, final Map<String, String> sslProperties) {
private static Map<String, String> getClientKeystoreProperties() {
final Map<String, String> properties = new HashMap<>();
properties.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/client-keystore.p12");
properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), "passwordpassword");
properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), "PKCS12");
return properties;
}
private static SSLContext useSSLContextService(final TestRunner controller, final Map<String, String> sslProperties, SSLContextService.ClientAuth clientAuth) {
final SSLContextService service = new StandardRestrictedSSLContextService();
try {
controller.addControllerService("ssl-service", service, sslProperties);
@ -91,7 +100,7 @@ public class ITestHandleHttpRequest {
}
controller.setProperty(HandleHttpRequest.SSL_CONTEXT, "ssl-service");
return service.createSSLContext(SSLContextService.ClientAuth.WANT);
return service.createSSLContext(clientAuth);
}
@Test(timeout=30000)
@ -427,6 +436,15 @@ public class ITestHandleHttpRequest {
@Test
public void testSecure() throws InitializationException {
secureTest(false);
}
@Test
public void testSecureTwoWaySsl() throws InitializationException {
secureTest(true);
}
private void secureTest(boolean twoWaySsl) throws InitializationException {
final TestRunner runner = TestRunners.newTestRunner(HandleHttpRequest.class);
runner.setProperty(HandleHttpRequest.PORT, "0");
@ -435,10 +453,10 @@ public class ITestHandleHttpRequest {
runner.enableControllerService(contextMap);
runner.setProperty(HandleHttpRequest.HTTP_CONTEXT_MAP, "http-context-map");
final Map<String, String> sslProperties = getKeystoreProperties();
final Map<String, String> sslProperties = getServerKeystoreProperties();
sslProperties.putAll(getTruststoreProperties());
sslProperties.put(StandardSSLContextService.SSL_ALGORITHM.getName(), "TLSv1.2");
final SSLContext sslContext = useSSLContextService(runner, sslProperties);
useSSLContextService(runner, sslProperties, twoWaySsl ? SSLContextService.ClientAuth.WANT : SSLContextService.ClientAuth.NONE);
// trigger processor to stop but not shutdown.
runner.run(1, false);
@ -451,7 +469,27 @@ public class ITestHandleHttpRequest {
final HttpsURLConnection connection = (HttpsURLConnection) new URL("https://localhost:"
+ port + "/my/path?query=true&value1=value1&value2=&value3&value4=apple=orange").openConnection();
connection.setSSLSocketFactory(sslContext.getSocketFactory());
if (twoWaySsl) {
// use a client certificate, do not reuse the server's keystore
SSLContext clientSslContext = SslContextFactory.createSslContext(
getClientKeystoreProperties().get(StandardSSLContextService.KEYSTORE.getName()),
getClientKeystoreProperties().get(StandardSSLContextService.KEYSTORE_PASSWORD.getName()).toCharArray(),
"JKS",
getTruststoreProperties().get(StandardSSLContextService.TRUSTSTORE.getName()),
getTruststoreProperties().get(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName()).toCharArray(),
"JKS",
null,
"TLSv1.2");
connection.setSSLSocketFactory(clientSslContext.getSocketFactory());
} else {
// with one-way SSL, the client still needs a truststore
SSLContext clientSslContext = SslContextFactory.createTrustSslContext(
getTruststoreProperties().get(StandardSSLContextService.TRUSTSTORE.getName()),
getTruststoreProperties().get(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName()).toCharArray(),
"JKS",
"TLSv1.2");
connection.setSSLSocketFactory(clientSslContext.getSocketFactory());
}
connection.setDoOutput(false);
connection.setRequestMethod("GET");
connection.setRequestProperty("header1", "value1");

View File

@ -49,7 +49,7 @@ public class TestInvokeHttpSSL extends TestInvokeHttpCommon {
// create the SSL properties, which basically store keystore / trustore information
// this is used by the StandardSSLContextService and the Jetty Server
serverSslProperties = createServerSslProperties(false);
sslProperties = createSslProperties(false);
sslProperties = createClientSslProperties(false);
// create a Jetty server on a random port
server = createServer();
@ -103,24 +103,24 @@ public class TestInvokeHttpSSL extends TestInvokeHttpCommon {
map.put(TestServer.NEED_CLIENT_AUTH, Boolean.toString(false));
}
// keystore is always required for the server SSL properties
map.putAll(getKeystoreProperties());
map.putAll(getServerKeystoreProperties());
return map;
}
static Map<String, String> createSslProperties(boolean clientAuth) {
static Map<String, String> createClientSslProperties(boolean clientAuth) {
final Map<String, String> map = new HashMap<>();
// if requesting client auth then we must provide a keystore
if (clientAuth) {
map.putAll(getKeystoreProperties());
map.putAll(getClientKeystoreProperties());
}
// truststore is always required for the client SSL properties
map.putAll(getTruststoreProperties());
return map;
}
private static Map<String, String> getKeystoreProperties() {
private static Map<String, String> getServerKeystoreProperties() {
final Map<String, String> map = new HashMap<>();
map.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/keystore.jks");
map.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), "passwordpassword");
@ -128,6 +128,14 @@ public class TestInvokeHttpSSL extends TestInvokeHttpCommon {
return map;
}
private static Map<String, String> getClientKeystoreProperties() {
final Map<String, String> map = new HashMap<>();
map.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/client-keystore.p12");
map.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), "passwordpassword");
map.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), "PKCS12");
return map;
}
private static Map<String, String> getTruststoreProperties() {
final Map<String, String> map = new HashMap<>();
map.put(StandardSSLContextService.TRUSTSTORE.getName(), "src/test/resources/truststore.jks");

View File

@ -36,7 +36,7 @@ public class TestInvokeHttpTwoWaySSL extends TestInvokeHttpSSL {
// create the SSL properties, which basically store keystore / trustore information
// this is used by the StandardSSLContextService and the Jetty Server
serverSslProperties = createServerSslProperties(true);
sslProperties = createSslProperties(true);
sslProperties = createClientSslProperties(true);
// create a Jetty server on a random port
server = createServer();

View File

@ -20,6 +20,7 @@ import org.apache.nifi.processor.ProcessContext;
import org.apache.nifi.processor.ProcessSessionFactory;
import org.apache.nifi.remote.io.socket.NetworkUtils;
import org.apache.nifi.reporting.InitializationException;
import org.apache.nifi.security.util.SslContextFactory;
import org.apache.nifi.ssl.StandardRestrictedSSLContextService;
import org.apache.nifi.ssl.SSLContextService;
import org.apache.nifi.ssl.StandardSSLContextService;
@ -98,7 +99,7 @@ public class TestListenHTTP {
runner.setProperty(ListenHTTP.PORT, Integer.toString(availablePort));
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_BASE_PATH);
testPOSTRequestsReceived(HttpServletResponse.SC_OK);
testPOSTRequestsReceived(HttpServletResponse.SC_OK, false, false);
}
@Test
@ -107,7 +108,7 @@ public class TestListenHTTP {
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_BASE_PATH);
runner.setProperty(ListenHTTP.RETURN_CODE, Integer.toString(HttpServletResponse.SC_NO_CONTENT));
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT);
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT, false, false);
}
@Test
@ -116,7 +117,7 @@ public class TestListenHTTP {
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_SERVER_BASEPATH_EL);
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_OK);
testPOSTRequestsReceived(HttpServletResponse.SC_OK, false, false);
}
@Test
@ -126,12 +127,12 @@ public class TestListenHTTP {
runner.setProperty(ListenHTTP.RETURN_CODE, Integer.toString(HttpServletResponse.SC_NO_CONTENT));
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT);
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT, false, false);
}
@Test
public void testSecurePOSTRequestsReceivedWithoutEL() throws Exception {
SSLContextService sslContextService = configureProcessorSslContextService();
SSLContextService sslContextService = configureProcessorSslContextService(false);
runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
runner.enableControllerService(sslContextService);
@ -139,12 +140,12 @@ public class TestListenHTTP {
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_BASE_PATH);
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_OK);
testPOSTRequestsReceived(HttpServletResponse.SC_OK, true, false);
}
@Test
public void testSecurePOSTRequestsReturnCodeReceivedWithoutEL() throws Exception {
SSLContextService sslContextService = configureProcessorSslContextService();
SSLContextService sslContextService = configureProcessorSslContextService(false);
runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
runner.enableControllerService(sslContextService);
@ -153,12 +154,12 @@ public class TestListenHTTP {
runner.setProperty(ListenHTTP.RETURN_CODE, Integer.toString(HttpServletResponse.SC_NO_CONTENT));
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT);
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT, true, false);
}
@Test
public void testSecurePOSTRequestsReceivedWithEL() throws Exception {
SSLContextService sslContextService = configureProcessorSslContextService();
SSLContextService sslContextService = configureProcessorSslContextService(false);
runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
runner.enableControllerService(sslContextService);
@ -166,12 +167,12 @@ public class TestListenHTTP {
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_SERVER_BASEPATH_EL);
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_OK);
testPOSTRequestsReceived(HttpServletResponse.SC_OK, true, false);
}
@Test
public void testSecurePOSTRequestsReturnCodeReceivedWithEL() throws Exception {
SSLContextService sslContextService = configureProcessorSslContextService();
SSLContextService sslContextService = configureProcessorSslContextService(false);
runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
runner.enableControllerService(sslContextService);
@ -180,7 +181,61 @@ public class TestListenHTTP {
runner.setProperty(ListenHTTP.RETURN_CODE, Integer.toString(HttpServletResponse.SC_NO_CONTENT));
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT);
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT, true, false);
}
@Test
public void testSecureTwoWaySslPOSTRequestsReceivedWithoutEL() throws Exception {
SSLContextService sslContextService = configureProcessorSslContextService(true);
runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
runner.enableControllerService(sslContextService);
runner.setProperty(ListenHTTP.PORT, Integer.toString(availablePort));
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_BASE_PATH);
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_OK, true, true);
}
@Test
public void testSecureTwoWaySslPOSTRequestsReturnCodeReceivedWithoutEL() throws Exception {
SSLContextService sslContextService = configureProcessorSslContextService(true);
runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
runner.enableControllerService(sslContextService);
runner.setProperty(ListenHTTP.PORT, Integer.toString(availablePort));
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_BASE_PATH);
runner.setProperty(ListenHTTP.RETURN_CODE, Integer.toString(HttpServletResponse.SC_NO_CONTENT));
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT, true, true);
}
@Test
public void testSecureTwoWaySslPOSTRequestsReceivedWithEL() throws Exception {
SSLContextService sslContextService = configureProcessorSslContextService(true);
runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
runner.enableControllerService(sslContextService);
runner.setProperty(ListenHTTP.PORT, HTTP_SERVER_PORT_EL);
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_SERVER_BASEPATH_EL);
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_OK, true, true);
}
@Test
public void testSecureTwoWaySslPOSTRequestsReturnCodeReceivedWithEL() throws Exception {
SSLContextService sslContextService = configureProcessorSslContextService(true);
runner.setProperty(sslContextService, StandardRestrictedSSLContextService.RESTRICTED_SSL_ALGORITHM, "TLSv1.2");
runner.enableControllerService(sslContextService);
runner.setProperty(ListenHTTP.PORT, Integer.toString(availablePort));
runner.setProperty(ListenHTTP.BASE_PATH, HTTP_BASE_PATH);
runner.setProperty(ListenHTTP.RETURN_CODE, Integer.toString(HttpServletResponse.SC_NO_CONTENT));
runner.assertValid();
testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT, true, true);
}
@Test
@ -194,19 +249,35 @@ public class TestListenHTTP {
runner.assertNotValid();
}
private int executePOST(String message) throws Exception {
final SSLContextService sslContextService = runner.getControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, SSLContextService.class);
final boolean secure = (sslContextService != null);
private int executePOST(String message, boolean secure, boolean twoWaySsl) throws Exception {
String endpointUrl = buildUrl(secure);
final URL url = new URL(endpointUrl);
HttpURLConnection connection;
if (secure) {
final HttpsURLConnection sslCon = (HttpsURLConnection) url.openConnection();
final SSLContext sslContext = sslContextService.createSSLContext(SSLContextService.ClientAuth.WANT);
sslCon.setSSLSocketFactory(sslContext.getSocketFactory());
if (twoWaySsl) {
// use a client certificate, do not reuse the server's keystore
SSLContext clientSslContext = SslContextFactory.createSslContext(
"src/test/resources/client-keystore.p12",
"passwordpassword".toCharArray(),
"PKCS12",
"src/test/resources/truststore.jks",
"passwordpassword".toCharArray(),
"JKS",
null,
"TLSv1.2");
sslCon.setSSLSocketFactory(clientSslContext.getSocketFactory());
} else {
// with one-way SSL, the client still needs a truststore
SSLContext clientSslContext = SslContextFactory.createTrustSslContext(
"src/test/resources/truststore.jks",
"passwordpassword".toCharArray(),
"JKS",
"TLSv1.2");
sslCon.setSSLSocketFactory(clientSslContext.getSocketFactory());
}
connection = sslCon;
} else {
connection = (HttpURLConnection) url.openConnection();
}
@ -227,14 +298,14 @@ public class TestListenHTTP {
return String.format("%s://localhost:%s/%s", secure ? "https" : "http" , availablePort, HTTP_BASE_PATH);
}
private void testPOSTRequestsReceived(int returnCode) throws Exception {
private void testPOSTRequestsReceived(int returnCode, boolean secure, boolean twoWaySsl) throws Exception {
final List<String> messages = new ArrayList<>();
messages.add("payload 1");
messages.add("");
messages.add(null);
messages.add("payload 2");
startWebServerAndSendMessages(messages, returnCode);
startWebServerAndSendMessages(messages, returnCode, secure, twoWaySsl);
List<MockFlowFile> mockFlowFiles = runner.getFlowFilesForRelationship(RELATIONSHIP_SUCCESS);
@ -265,13 +336,13 @@ public class TestListenHTTP {
runner.assertTransferCount(ListenHTTP.RELATIONSHIP_SUCCESS, numberOfExpectedFlowFiles);
}
private void startWebServerAndSendMessages(final List<String> messages, int returnCode)
private void startWebServerAndSendMessages(final List<String> messages, int returnCode, boolean secure, boolean twoWaySsl)
throws Exception {
Runnable sendMessagestoWebServer = () -> {
try {
for (final String message : messages) {
if (executePOST(message) != returnCode) {
if (executePOST(message, secure, twoWaySsl) != returnCode) {
fail("HTTP POST failed.");
}
}
@ -284,12 +355,14 @@ public class TestListenHTTP {
startWebServerAndSendRequests(sendMessagestoWebServer, messages.size(), returnCode);
}
private SSLContextService configureProcessorSslContextService() throws InitializationException {
private SSLContextService configureProcessorSslContextService(boolean twoWaySsl) throws InitializationException {
final SSLContextService sslContextService = new StandardRestrictedSSLContextService();
runner.addControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, sslContextService);
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, "src/test/resources/truststore.jks");
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, "passwordpassword");
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, "JKS");
if (twoWaySsl) {
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, "src/test/resources/truststore.jks");
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, "passwordpassword");
runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, "JKS");
}
runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, "src/test/resources/keystore.jks");
runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, "passwordpassword");
runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, "JKS");

View File

@ -97,6 +97,11 @@ public class TestServer {
ssl.setNeedClientAuth(Boolean.parseBoolean(clientAuth));
}
// Need to set SslContextFactory's endpointIdentificationAlgorithm to null; this is a server,
// not a client. Server does not need to perform hostname verification on the client.
// Previous to Jetty 9.4.15.v20190215, this defaulted to null, and now defaults to "HTTPS".
ssl.setEndpointIdentificationAlgorithm(null);
// build the connector
final ServerConnector https = new ServerConnector(jetty, ssl);

View File

@ -312,5 +312,5 @@ Apache Software License v2
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.

View File

@ -26,7 +26,7 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
(ASLv2) Jackson JSON processor
The following NOTICE information applies:

View File

@ -66,12 +66,18 @@ public abstract class AbstractJettyWebSocketService extends AbstractWebSocketSer
}
protected SslContextFactory createSslFactory(final SSLContextService sslService, final boolean needClientAuth, final boolean wantClientAuth) {
protected SslContextFactory createSslFactory(final SSLContextService sslService, final boolean needClientAuth, final boolean wantClientAuth, final String endpointIdentificationAlgorithm) {
final SslContextFactory sslFactory = new SslContextFactory();
sslFactory.setNeedClientAuth(needClientAuth);
sslFactory.setWantClientAuth(wantClientAuth);
// Need to set SslContextFactory's endpointIdentificationAlgorithm.
// For clients, hostname verification should be enabled.
// For servers, hostname verification should be disabled.
// Previous to Jetty 9.4.15.v20190215, this defaulted to null, and now defaults to "HTTPS".
sslFactory.setEndpointIdentificationAlgorithm(endpointIdentificationAlgorithm);
if (sslService.isKeyStoreConfigured()) {
sslFactory.setKeyStorePath(sslService.getKeyStoreFile());
sslFactory.setKeyStorePassword(sslService.getKeyStorePassword());

View File

@ -171,7 +171,7 @@ public class JettyWebSocketClient extends AbstractJettyWebSocketService implemen
final SSLContextService sslService = context.getProperty(SSL_CONTEXT).asControllerService(SSLContextService.class);
SslContextFactory sslContextFactory = null;
if (sslService != null) {
sslContextFactory = createSslFactory(sslService, false, false);
sslContextFactory = createSslFactory(sslService, false, false, null);
}
client = new WebSocketClient(sslContextFactory);

View File

@ -356,7 +356,7 @@ public class JettyWebSocketServer extends AbstractJettyWebSocketService implemen
want = false;
}
final SslContextFactory sslFactory = (sslService == null) ? null : createSslFactory(sslService, need, want);
final SslContextFactory sslFactory = (sslService == null) ? null : createSslFactory(sslService, need, want, null);
return sslFactory;
}

View File

@ -157,6 +157,11 @@ public class WebSocketServerExample {
sslContextFactory.setKeyStorePassword("passwordpassword");
sslContextFactory.setKeyStoreType("JKS");
// Need to set SslContextFactory's endpointIdentificationAlgorithm to null; this is a server,
// not a client. Server does not need to perform hostname verification on the client.
// Previous to Jetty 9.4.15.v20190215, this defaulted to null, and now defaults to "HTTPS".
sslContextFactory.setEndpointIdentificationAlgorithm(null);
final HttpConfiguration https = new HttpConfiguration();
https.addCustomizer(new SecureRequestCustomizer());
sslConnector = new ServerConnector(server,

View File

@ -94,7 +94,7 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Jetty
The following NOTICE information applies:
Jetty Web Container
Copyright 1995-2017 Mort Bay Consulting Pty Ltd.
Copyright 1995-2019 Mort Bay Consulting Pty Ltd.
(ASLv2) Groovy (org.codehaus.groovy:groovy-all:jar:2.4.5 - http://www.groovy-lang.org)
The following NOTICE information applies:

View File

@ -67,6 +67,11 @@ public class TlsCertificateAuthorityService {
sslContextFactory.setKeyStore(keyStore);
sslContextFactory.setKeyManagerPassword(keyPassword);
// Need to set SslContextFactory's endpointIdentificationAlgorithm to null; this is a server,
// not a client. Server does not need to perform hostname verification on the client.
// Previous to Jetty 9.4.15.v20190215, this defaulted to null, and now defaults to "HTTPS".
sslContextFactory.setEndpointIdentificationAlgorithm(null);
HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.addCustomizer(new SecureRequestCustomizer());

View File

@ -94,7 +94,7 @@
<inceptionYear>2014</inceptionYear>
<org.slf4j.version>1.7.26</org.slf4j.version>
<ranger.version>1.0.0</ranger.version>
<jetty.version>9.4.11.v20180605</jetty.version>
<jetty.version>9.4.15.v20190215</jetty.version>
<jackson.version>2.9.8</jackson.version>
<nifi.registry.version>0.3.0</nifi.registry.version>
</properties>