mirror of https://github.com/apache/nifi.git
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:
parent
cf6f517250
commit
65c41ab917
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue