From 11e9ff377333784974fa55f41483c4281d80da50 Mon Sep 17 00:00:00 2001 From: exceptionfactory Date: Wed, 27 Jan 2021 16:13:39 -0600 Subject: [PATCH] NIFI-8178 This closes #4787. Replaced StandardSSLContextService in unit tests with SslContextUtils - Removed references to StandardSSLContextService from nifi-standard-processors - Removed TestGetHTTPGroovy and TestPostHTTPGroovy since these are testing deprecated processors - Optimized HandleHttpRequest, GetHTTP, PostHTTP to use SSLContextService.createContext() NIFI-8178 Changed TestGetHTTP to ITGetHTTP since GetHTTP is deprecated NIFI-8178 Changed TestPostHTTP to ITPostHTTP since PostHTTP is deprecated Signed-off-by: Joe Witt --- .../nifi/security/util/TlsConfiguration.java | 3 +- .../nifi/processors/standard/GetHTTP.java | 40 +- .../standard/HandleHttpRequest.java | 20 +- .../standard/HandleHttpResponse.java | 2 +- .../nifi/processors/standard/ListenFTP.java | 2 +- .../nifi/processors/standard/PostHTTP.java | 46 +- .../standard/TestGetHTTPGroovy.groovy | 488 ------------------ .../standard/TestPostHTTPGroovy.groovy | 443 ---------------- .../{TestGetHTTP.java => ITGetHTTP.java} | 232 +++++---- .../standard/ITListenAndPutSyslog.java | 42 +- .../{TestPostHTTP.java => ITPostHTTP.java} | 282 +++++----- .../standard/ITestHandleHttpRequest.java | 90 +--- .../processors/standard/TestInvokeHTTP.java | 48 +- .../processors/standard/TestListenHTTP.java | 27 +- .../processors/standard/TestListenRELP.java | 37 +- .../processors/standard/TestListenTCP.java | 109 ++-- .../standard/TestListenTCPRecord.java | 94 ++-- .../nifi/web/util/ssl/SslContextUtils.java | 75 +++ 18 files changed, 502 insertions(+), 1578 deletions(-) delete mode 100644 nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/groovy/org/apache/nifi/processors/standard/TestGetHTTPGroovy.groovy delete mode 100644 nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/groovy/org/apache/nifi/processors/standard/TestPostHTTPGroovy.groovy rename nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/{TestGetHTTP.java => ITGetHTTP.java} (78%) rename nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/{TestPostHTTP.java => ITPostHTTP.java} (64%) create mode 100644 nifi-nar-bundles/nifi-standard-bundle/nifi-standard-web-test-utils/src/main/java/org/apache/nifi/web/util/ssl/SslContextUtils.java diff --git a/nifi-commons/nifi-security-utils-api/src/main/java/org/apache/nifi/security/util/TlsConfiguration.java b/nifi-commons/nifi-security-utils-api/src/main/java/org/apache/nifi/security/util/TlsConfiguration.java index 94a90d2837..cd4d3a5c15 100644 --- a/nifi-commons/nifi-security-utils-api/src/main/java/org/apache/nifi/security/util/TlsConfiguration.java +++ b/nifi-commons/nifi-security-utils-api/src/main/java/org/apache/nifi/security/util/TlsConfiguration.java @@ -30,9 +30,10 @@ public interface TlsConfiguration { String TLS_1_0_PROTOCOL = "TLSv1"; String TLS_1_1_PROTOCOL = "TLSv1.1"; + String TLS_1_2_PROTOCOL = "TLSv1.2"; String[] LEGACY_TLS_PROTOCOL_VERSIONS = new String[]{TLS_1_0_PROTOCOL, TLS_1_1_PROTOCOL}; - String JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION = "TLSv1.2"; + String JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION = TLS_1_2_PROTOCOL; String JAVA_11_MAX_SUPPORTED_TLS_PROTOCOL_VERSION = "TLSv1.3"; String[] JAVA_8_SUPPORTED_TLS_PROTOCOL_VERSIONS = new String[]{JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION}; String[] JAVA_11_SUPPORTED_TLS_PROTOCOL_VERSIONS = new String[]{JAVA_11_MAX_SUPPORTED_TLS_PROTOCOL_VERSION, JAVA_8_MAX_SUPPORTED_TLS_PROTOCOL_VERSION}; diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetHTTP.java index a130449037..c772ae72ad 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetHTTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/GetHTTP.java @@ -31,12 +31,10 @@ import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.BasicHttpClientConnectionManager; -import org.apache.http.ssl.SSLContextBuilder; import org.apache.nifi.annotation.behavior.DynamicProperties; import org.apache.nifi.annotation.behavior.DynamicProperty; import org.apache.nifi.annotation.behavior.InputRequirement; @@ -70,24 +68,14 @@ import org.apache.nifi.processor.Relationship; import org.apache.nifi.processor.exception.ProcessException; import org.apache.nifi.processor.util.StandardValidators; import org.apache.nifi.processors.standard.util.HTTPUtils; -import org.apache.nifi.security.util.KeyStoreUtils; import org.apache.nifi.ssl.SSLContextService; import org.apache.nifi.util.StopWatch; import org.apache.nifi.util.Tuple; import javax.net.ssl.SSLContext; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -326,32 +314,6 @@ public class GetHTTP extends AbstractSessionFactoryProcessor { .build(); } - private SSLContext createSSLContext(final SSLContextService service) - throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException { - - final SSLContextBuilder sslContextBuilder = new SSLContextBuilder(); - - if (StringUtils.isNotBlank(service.getTrustStoreFile())) { - final KeyStore truststore = KeyStoreUtils.getKeyStore(service.getTrustStoreType()); - try (final InputStream in = new FileInputStream(new File(service.getTrustStoreFile()))) { - truststore.load(in, service.getTrustStorePassword().toCharArray()); - } - sslContextBuilder.loadTrustMaterial(truststore, new TrustSelfSignedStrategy()); - } - - if (StringUtils.isNotBlank(service.getKeyStoreFile())) { - final KeyStore keystore = KeyStoreUtils.getKeyStore(service.getKeyStoreType()); - try (final InputStream in = new FileInputStream(new File(service.getKeyStoreFile()))) { - keystore.load(in, service.getKeyStorePassword().toCharArray()); - } - sslContextBuilder.loadKeyMaterial(keystore, service.getKeyStorePassword().toCharArray()); - } - - sslContextBuilder.useProtocol(service.getSslAlgorithm()); - - return sslContextBuilder.build(); - } - @Override public void onTrigger(final ProcessContext context, final ProcessSessionFactory sessionFactory) throws ProcessException { final ComponentLog logger = getLogger(); @@ -384,7 +346,7 @@ public class GetHTTP extends AbstractSessionFactoryProcessor { } else { final SSLContext sslContext; try { - sslContext = createSSLContext(sslContextService); + sslContext = sslContextService.createContext(); } catch (final Exception e) { throw new ProcessException(e); } diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpRequest.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpRequest.java index ad9d95d9d6..b9a26f8421 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpRequest.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpRequest.java @@ -60,6 +60,7 @@ import com.google.common.base.Optional; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; +import javax.net.ssl.SSLContext; import javax.servlet.AsyncContext; import javax.servlet.DispatcherType; import javax.servlet.MultipartConfigElement; @@ -544,25 +545,14 @@ public class HandleHttpRequest extends AbstractProcessor { return containerQueue.size(); } - private SslContextFactory createSslFactory(final SSLContextService sslService, final boolean needClientAuth, final boolean wantClientAuth) { - final SslContextFactory sslFactory = new SslContextFactory.Server(); + private SslContextFactory createSslFactory(final SSLContextService sslContextService, final boolean needClientAuth, final boolean wantClientAuth) { + final SslContextFactory.Server sslFactory = new SslContextFactory.Server(); sslFactory.setNeedClientAuth(needClientAuth); sslFactory.setWantClientAuth(wantClientAuth); - sslFactory.setProtocol(sslService.getSslAlgorithm()); - - if (sslService.isKeyStoreConfigured()) { - sslFactory.setKeyStorePath(sslService.getKeyStoreFile()); - sslFactory.setKeyStorePassword(sslService.getKeyStorePassword()); - sslFactory.setKeyStoreType(sslService.getKeyStoreType()); - } - - if (sslService.isTrustStoreConfigured()) { - sslFactory.setTrustStorePath(sslService.getTrustStoreFile()); - sslFactory.setTrustStorePassword(sslService.getTrustStorePassword()); - sslFactory.setTrustStoreType(sslService.getTrustStoreType()); - } + final SSLContext sslContext = sslContextService.createContext(); + sslFactory.setSslContext(sslContext); return sslFactory; } diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpResponse.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpResponse.java index a0d3f4f6b1..46622515c3 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpResponse.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/HandleHttpResponse.java @@ -62,7 +62,7 @@ import org.apache.nifi.util.StopWatch; @ReadsAttribute(attribute = HTTPUtils.HTTP_LOCAL_NAME, description = "IP address/hostname of the server. Used for provenance event."), @ReadsAttribute(attribute = HTTPUtils.HTTP_PORT, description = "Listening port of the server. Used for provenance event."), @ReadsAttribute(attribute = HTTPUtils.HTTP_SSL_CERT, description = "SSL distinguished name (if any). Used for provenance event.")}) -@SeeAlso(value = {HandleHttpRequest.class}, classNames = {"org.apache.nifi.http.StandardHttpContextMap", "org.apache.nifi.ssl.StandardSSLContextService"}) +@SeeAlso(value = {HandleHttpRequest.class}, classNames = {"org.apache.nifi.http.StandardHttpContextMap", "org.apache.nifi.ssl.SSLContextService"}) public class HandleHttpResponse extends AbstractProcessor { public static final PropertyDescriptor STATUS_CODE = new PropertyDescriptor.Builder() diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenFTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenFTP.java index bce6ac47b0..fdec028998 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenFTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ListenFTP.java @@ -61,7 +61,7 @@ import java.util.concurrent.atomic.AtomicReference; + "E.g.: file.txt is uploaded to /Folder1/SubFolder, then the value of the path attribute will be \"/Folder1/SubFolder/\" " + "(note that it ends with a separator character).") }) -@SeeAlso(classNames = {"org.apache.nifi.ssl.StandardRestrictedSSLContextService","org.apache.nifi.ssl.StandardSSLContextService"}) +@SeeAlso(classNames = {"org.apache.nifi.ssl.RestrictedSSLContextService","org.apache.nifi.ssl.SSLContextService"}) public class ListenFTP extends AbstractSessionFactoryProcessor { public static final PropertyDescriptor SSL_CONTEXT_SERVICE = new PropertyDescriptor.Builder() diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PostHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PostHTTP.java index 054e2e1b94..d172033d7b 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PostHTTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PostHTTP.java @@ -21,8 +21,6 @@ import static org.apache.nifi.processors.standard.util.HTTPUtils.PROXY_PORT; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -30,11 +28,6 @@ import java.net.InetAddress; import java.net.MalformedURLException; import java.net.UnknownHostException; import java.security.Principal; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; @@ -81,7 +74,6 @@ import org.apache.http.conn.ManagedHttpClientConnection; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.entity.ContentProducer; import org.apache.http.entity.EntityTemplate; import org.apache.http.impl.client.BasicCredentialsProvider; @@ -90,8 +82,6 @@ import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpCoreContext; -import org.apache.http.ssl.SSLContextBuilder; -import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import org.apache.http.util.VersionInfo; import org.apache.nifi.annotation.behavior.InputRequirement; @@ -122,7 +112,6 @@ import org.apache.nifi.processor.io.InputStreamCallback; import org.apache.nifi.processor.util.StandardValidators; import org.apache.nifi.processors.standard.util.HTTPUtils; import org.apache.nifi.security.util.CertificateUtils; -import org.apache.nifi.security.util.KeyStoreUtils; import org.apache.nifi.ssl.SSLContextService; import org.apache.nifi.stream.io.GZIPOutputStream; import org.apache.nifi.stream.io.LeakyBucketStreamThrottler; @@ -389,8 +378,7 @@ public class PostHTTP extends AbstractProcessor { } else { final SSLContext sslContext; try { - sslContext = createSSLContext(sslContextService); - getLogger().info("PostHTTP supports protocol: " + sslContext.getProtocol()); + sslContext = sslContextService.createContext(); } catch (final Exception e) { throw new ProcessException(e); } @@ -509,38 +497,6 @@ public class PostHTTP extends AbstractProcessor { return url.substring(0, index); } - private SSLContext createSSLContext(final SSLContextService service) - throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException { - SSLContextBuilder builder = SSLContexts.custom(); - final String trustFilename = service.getTrustStoreFile(); - if (trustFilename != null) { - final KeyStore truststore = KeyStoreUtils.getKeyStore(service.getTrustStoreType()); - try (final InputStream in = new FileInputStream(new File(service.getTrustStoreFile()))) { - truststore.load(in, service.getTrustStorePassword().toCharArray()); - } - builder = builder.loadTrustMaterial(truststore, new TrustSelfSignedStrategy()); - } - - final String keyFilename = service.getKeyStoreFile(); - if (keyFilename != null) { - final KeyStore keystore = KeyStoreUtils.getKeyStore(service.getKeyStoreType()); - try (final InputStream in = new FileInputStream(new File(service.getKeyStoreFile()))) { - keystore.load(in, service.getKeyStorePassword().toCharArray()); - } - builder = builder.loadKeyMaterial(keystore, service.getKeyStorePassword().toCharArray()); - final String alias = keystore.aliases().nextElement(); - final Certificate cert = keystore.getCertificate(alias); - if (cert instanceof X509Certificate) { - principal = ((X509Certificate) cert).getSubjectDN(); - } - } - - builder = builder.setProtocol(service.getSslAlgorithm()); - - final SSLContext sslContext = builder.build(); - return sslContext; - } - @Override public void onTrigger(final ProcessContext context, final ProcessSession session) { FlowFile firstFlowFile = session.get(); diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/groovy/org/apache/nifi/processors/standard/TestGetHTTPGroovy.groovy b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/groovy/org/apache/nifi/processors/standard/TestGetHTTPGroovy.groovy deleted file mode 100644 index 4b1c21f64b..0000000000 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/groovy/org/apache/nifi/processors/standard/TestGetHTTPGroovy.groovy +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.nifi.processors.standard - -import groovy.servlet.GroovyServlet -import groovy.test.GroovyAssert -import org.apache.nifi.ssl.SSLContextService -import org.apache.nifi.ssl.StandardSSLContextService -import org.apache.nifi.util.StandardProcessorTestRunner -import org.apache.nifi.util.TestRunner -import org.apache.nifi.util.TestRunners -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.eclipse.jetty.server.HttpConfiguration -import org.eclipse.jetty.server.HttpConnectionFactory -import org.eclipse.jetty.server.SecureRequestCustomizer -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.server.ServerConnector -import org.eclipse.jetty.server.SslConnectionFactory -import org.eclipse.jetty.servlet.ServletContextHandler -import org.eclipse.jetty.util.ssl.SslContextFactory -import org.junit.After -import org.junit.AfterClass -import org.junit.Before -import org.junit.BeforeClass -import org.junit.Ignore -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -import javax.crypto.Cipher -import javax.net.SocketFactory -import javax.net.ssl.HostnameVerifier -import javax.net.ssl.HttpsURLConnection -import javax.net.ssl.SSLContext -import javax.net.ssl.SSLEngine -import javax.net.ssl.SSLHandshakeException -import javax.net.ssl.SSLSocket -import javax.net.ssl.TrustManager -import javax.net.ssl.X509TrustManager -import java.security.Security - -@SuppressWarnings("deprecation") -@RunWith(JUnit4.class) -class TestGetHTTPGroovy extends GroovyTestCase { - private static final Logger logger = LoggerFactory.getLogger(TestGetHTTPGroovy.class) - - static private final String KEYSTORE_TYPE = "JKS" - - private static final String TLSv1 = "TLSv1" - private static final String TLSv1_1 = "TLSv1.1" - private static final String TLSv1_2 = "TLSv1.2" - private static final List DEFAULT_PROTOCOLS = [TLSv1, TLSv1_1, TLSv1_2] - - private static final String TLSv1_1_CIPHER_SUITE = "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA" - private static final SSLContext SSL_CONTEXT = SSLContext.default - private static final SSLEngine SSL_ENGINE = SSL_CONTEXT.createSSLEngine() - private static - final List DEFAULT_CIPHER_SUITES = SSL_ENGINE.supportedCipherSuites as List - - private static final String DEFAULT_HOSTNAME = "localhost" - private static final int DEFAULT_TLS_PORT = 8456 - private static final String HTTPS_URL = "https://${DEFAULT_HOSTNAME}:${DEFAULT_TLS_PORT}" - private static final String GET_URL = "${HTTPS_URL}/GetHandler.groovy" - - private static final String MOZILLA_INTERMEDIATE_URL = "https://mozilla-intermediate.badssl.com/" - private static final String TLS_1_URL = "https://nifi.apache.org/" - private static final String TLS_1_1_URL = "https://nifi.apache.org/" - - private static final String KEYSTORE_PATH = "src/test/resources/keystore.jks" - private static final String TRUSTSTORE_PATH = "src/test/resources/truststore.jks" - private static final String CACERTS_PATH = "/Library/Java/JavaVirtualMachines/jdk1.8.0_101.jdk/Contents/Home/jre/lib/security/cacerts" - - private static final String KEYSTORE_PASSWORD = "passwordpassword" - private static final String TRUSTSTORE_PASSWORD = "passwordpassword" - private static final String CACERTS_PASSWORD = "changeit" - - private static Server server - private static X509TrustManager nullTrustManager - private static HostnameVerifier nullHostnameVerifier - - private static TestRunner runner - - private - static Server createServer(List supportedProtocols = DEFAULT_PROTOCOLS, List supportedCipherSuites = DEFAULT_CIPHER_SUITES) { - // Create Server - Server server = new Server() - - // Add some secure config - final HttpConfiguration httpsConfiguration = new HttpConfiguration() - httpsConfiguration.setSecureScheme("https") - httpsConfiguration.setSecurePort(DEFAULT_TLS_PORT) - httpsConfiguration.addCustomizer(new SecureRequestCustomizer()) - - // Build the TLS connector - final ServerConnector https = createConnector(server, httpsConfiguration, supportedProtocols, supportedCipherSuites) - - // Add this connector - server.addConnector(https) - logger.info("Created server with supported protocols: ${supportedProtocols}") - - /** Create a simple Groovlet that responds to the incoming request by reversing the string parameter - * i.e. localhost:8456/ReverseHandler.groovy?string=Happy%20birthday -> yadhtrib yppaH - */ - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS) - context.with { - contextPath = '/' - resourceBase = 'src/test/resources/TestGetHTTP' - addServlet(GroovyServlet, '*.groovy') - } - server.setHandler(context) - server - } - - private - static ServerConnector createConnector(Server server, HttpConfiguration httpsConfiguration, List supportedProtocols = DEFAULT_PROTOCOLS, List supportedCipherSuites = DEFAULT_CIPHER_SUITES) { - ServerConnector https = new ServerConnector(server, - new SslConnectionFactory(createSslContextFactory(supportedProtocols, supportedCipherSuites), "http/1.1"), - new HttpConnectionFactory(httpsConfiguration)) - - // set host and port - https.setHost(DEFAULT_HOSTNAME) - https.setPort(DEFAULT_TLS_PORT) - https - } - - private - static SslContextFactory createSslContextFactory(List supportedProtocols = DEFAULT_PROTOCOLS, List supportedCipherSuites = DEFAULT_CIPHER_SUITES) { - final SslContextFactory contextFactory = new SslContextFactory.Server() - contextFactory.needClientAuth = false - contextFactory.wantClientAuth = false - - contextFactory.setKeyStorePath(KEYSTORE_PATH) - contextFactory.setKeyStoreType(KEYSTORE_TYPE) - contextFactory.setKeyStorePassword(KEYSTORE_PASSWORD) - - contextFactory.setIncludeProtocols(supportedProtocols as String[]) - if (supportedCipherSuites) { - contextFactory.setIncludeCipherSuites(supportedCipherSuites as String[]) - } - contextFactory - } - - @BeforeClass - static void setUpOnce() throws Exception { - Security.addProvider(new BouncyCastleProvider()) - - logger.metaClass.methodMissing = { String name, args -> - logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}") - } - - server = createServer() - - runner = configureRunner() - - // Print the default cipher suite list - logger.info("Default supported cipher suites: \n\t${DEFAULT_CIPHER_SUITES.join("\n\t")}") - } - - private static TestRunner configureRunner() { - // Set the default trust manager for the "default" tests (the outgoing Groovy call) to ignore certificate path verification for localhost - nullTrustManager = [ - checkClientTrusted: { chain, authType -> }, - checkServerTrusted: { chain, authType -> }, - getAcceptedIssuers: { null } - ] as X509TrustManager - - nullHostnameVerifier = [ - verify: { String hostname, session -> - // Will always return true if the hostname is "localhost" or the Mozilla intermediate site - hostname.equalsIgnoreCase(DEFAULT_HOSTNAME) || hostname.equalsIgnoreCase(new URL(MOZILLA_INTERMEDIATE_URL).host) - } - ] as HostnameVerifier - - // Configure the test runner - TestRunner runner = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class) - final SSLContextService sslContextService = new StandardSSLContextService() - runner.addControllerService("ssl-context", sslContextService) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, TRUSTSTORE_PATH) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, TRUSTSTORE_PASSWORD) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, KEYSTORE_TYPE) - runner.enableControllerService(sslContextService) - - runner.setProperty(org.apache.nifi.processors.standard.GetHTTP.URL, GET_URL) - runner.setProperty(org.apache.nifi.processors.standard.GetHTTP.SSL_CONTEXT_SERVICE, "ssl-context") - - runner - } - - @AfterClass - static void tearDownOnce() { - - } - - @Before - void setUp() throws Exception { - // This must be executed before each test, or the connections will be re-used and if a TLSv1.1 connection is re-used against a server that only supports TLSv1.2, it will fail - SSLContext sc = SSLContext.getInstance(TLSv1_2) - sc.init(null, [nullTrustManager] as TrustManager[], null) - SocketFactory socketFactory = sc.getSocketFactory() - logger.info("JCE unlimited strength installed: ${Cipher.getMaxAllowedKeyLength("AES") > 128}") - logger.info("Supported client cipher suites: ${socketFactory.supportedCipherSuites}") - HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory) - HttpsURLConnection.setDefaultHostnameVerifier(nullHostnameVerifier) - - runner.setProperty(org.apache.nifi.processors.standard.GetHTTP.FILENAME, "mockFlowfile_${System.currentTimeMillis()}") - - (runner as StandardProcessorTestRunner).clearQueue() - } - - @After - void tearDown() throws Exception { - try { - server.stop() - } catch (Exception e) { - e.printStackTrace() - } - - runner.clearTransferState() - runner.clearProvenanceEvents() - (runner as StandardProcessorTestRunner).clearQueue() - } - - /** - * Jetty 9.4.0+ no longer supports TLSv1. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that supports TLSv1 is available") - void testDefaultShouldSupportTLSv1() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with TLSv1 only - server = createServer([TLSv1]) - - // Start server - server.start() - - // Act - String response = new URL(url).text - logger.info("Response from ${HTTPS_URL}: ${response}") - - // Assert - assert response == MSG.reverse() - } - - /** - * Jetty 9.4.0+ no longer supports TLSv1.1 unless compatible ("vulnerable" according to Jetty documentation, see https://github.com/eclipse/jetty.project/issues/860) cipher suites are explicitly provided. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that supports TLSv1.1 is available") - void testDefaultShouldSupportTLSv1_1() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with TLSv1.1 only - server = createServer([TLSv1_1]) - - // Start server - server.start() - - // Act - String response = new URL(url).text - logger.info("Response from ${HTTPS_URL}: ${response}") - - // Assert - assert response == MSG.reverse() - } - - /** - * Jetty 9.4.0+ no longer supports TLSv1.1 unless compatible ("vulnerable" according to Jetty documentation, see https://github.com/eclipse/jetty.project/issues/860) cipher suites are explicitly provided. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that supports TLSv1 is available") - void testDefaultShouldSupportTLSv1_1WithVulnerableCipherSuites() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with TLSv1.1 only but explicitly provide the legacy cipher suite - server = createServer([TLSv1_1], [TLSv1_1_CIPHER_SUITE]) - - // Start server - server.start() - - // Act - String response = new URL(url).text - logger.info("Response from ${HTTPS_URL}: ${response}") - - // Assert - assert response == MSG.reverse() - } - - @Test - void testDefaultShouldSupportTLSv1_2() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with TLSv1.2 only - server = createServer([TLSv1_2]) - - // Start server - server.start() - - // Act - String response = new URL(url).text - logger.info("Response from ${HTTPS_URL}: ${response}") - - // Assert - assert response == MSG.reverse() - } - - @Test - void testDefaultShouldPreferTLSv1_2() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with all TLS protocols - server = createServer() - - // Start server - server.start() - - // Create a connection that could use TLSv1, TLSv1.1, or TLSv1.2 - SSLContext sc = SSLContext.getInstance("TLS") - sc.init(null, [nullTrustManager] as TrustManager[], null) - SocketFactory socketFactory = sc.getSocketFactory() - - URL formedUrl = new URL(url) - SSLSocket socket = (SSLSocket) socketFactory.createSocket(formedUrl.host, formedUrl.port) - logger.info("Enabled protocols: ${socket.enabledProtocols}") - - // Act - socket.startHandshake() - String selectedProtocol = socket.getSession().protocol - logger.info("Selected protocol: ${selectedProtocol}") - - // Assert - assert selectedProtocol == TLSv1_2 - } - - private static void enableContextServiceProtocol(TestRunner runner, String protocol, String truststorePath = TRUSTSTORE_PATH, String truststorePassword = TRUSTSTORE_PASSWORD) { - final SSLContextService sslContextService = new StandardSSLContextService() - runner.addControllerService("ssl-context", sslContextService) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, truststorePath) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, truststorePassword) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, KEYSTORE_TYPE) - runner.setProperty(sslContextService, StandardSSLContextService.SSL_ALGORITHM, protocol) - runner.enableControllerService(sslContextService) - def sslContext = sslContextService.createContext(); - logger.info("GetHTTP supported protocols: ${sslContext.protocol}") - logger.info("GetHTTP supported cipher suites: ${sslContext.supportedSSLParameters.cipherSuites}") - } - - /** - * This test connects to a server running TLSv1/1.1/1.2. It iterates over an {@link SSLContextService} with TLSv1, TLSv1.1, and TLSv1.2 support. All three context services should be able to communicate successfully. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that supports TLSv1 is available") - void testGetHTTPShouldConnectToServerWithTLSv1() { - // Arrange - - // Connect to a server that still runs TLSv1/1.1/1.2 - runner.setProperty(org.apache.nifi.processors.standard.GetHTTP.URL, TLS_1_URL) - - // Act - [TLSv1, TLSv1_1, TLSv1_2].each { String tlsVersion -> - logger.info("Set context service protocol to ${tlsVersion}") - enableContextServiceProtocol(runner, tlsVersion, CACERTS_PATH, CACERTS_PASSWORD) - runner.assertQueueEmpty() - logger.info("Queue size (before run): ${runner.queueSize}") - runner.run() - - // Assert - logger.info("Queue size (after run): ${runner.queueSize}") - runner.assertAllFlowFilesTransferred(REL_SUCCESS, 1) - runner.clearTransferState() - logger.info("Ran successfully") - } - } - - /** - * This test creates a server that supports TLSv1.1. It iterates over an {@link SSLContextService} with TLSv1, TLSv1.1, and TLSv1.2 support. The context service with TLSv1 should not be able to communicate with a server that does not support it, but TLSv1.1 and TLSv1.2 should be able to communicate successfully. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that only supports TLSv1.1 is available") - void testGetHTTPShouldConnectToServerWithTLSv1_1() { - // Arrange - final String MSG = "This is a test message" - - // Configure server with TLSv1.1 only - server = createServer([TLSv1_1]) - - // Start server - server.start() - - // Act - logger.info("Set context service protocol to ${TLSv1}") - enableContextServiceProtocol(runner, TLSv1) - runner.enqueue(MSG.getBytes()) - - def ae = GroovyAssert.shouldFail(AssertionError) { - runner.run() - } - logger.expected(ae.getMessage()) - logger.expected("Cause: ${ae.cause?.class?.name}") - logger.expected("Original cause: ${ae.cause?.cause?.class?.name}") - - // Assert - assert ae.cause.cause instanceof SSLHandshakeException - runner.clearTransferState() - logger.expected("Unable to connect") - - [TLSv1_1, TLSv1_2].each { String tlsVersion -> - logger.info("Set context service protocol to ${tlsVersion}") - enableContextServiceProtocol(runner, tlsVersion) - runner.enqueue(MSG.getBytes()) - runner.run() - - // Assert - runner.assertAllFlowFilesTransferred(REL_SUCCESS) - runner.clearTransferState() - logger.info("Ran successfully") - } - } - - /** - * This test creates a server that supports TLSv1.2. It iterates over an {@link SSLContextService} with TLSv1, TLSv1.1, and TLSv1.2 support. The context services with TLSv1 and TLSv1.1 should not be able to communicate with a server that does not support it, but TLSv1.2 should be able to communicate successfully. - */ - @Test - void testGetHTTPShouldConnectToServerWithTLSv1_2() { - // Arrange - final String MSG = "This is a test message" - - // Configure server with TLSv1.2 only - server = createServer([TLSv1_2]) - - // Start server - server.start() - - // Act - [TLSv1, TLSv1_1].each { String tlsVersion -> - logger.info("Set context service protocol to ${tlsVersion}") - enableContextServiceProtocol(runner, tlsVersion) - runner.enqueue(MSG.getBytes()) - def ae = GroovyAssert.shouldFail(AssertionError) { - runner.run() - } - logger.expected(ae.getMessage()) - logger.expected("Cause: ${ae.cause?.class?.name}") - logger.expected("Original cause: ${ae.cause?.cause?.class?.name}") - - // Assert - assert ae.cause.cause instanceof SSLHandshakeException - runner.clearTransferState() - logger.expected("Unable to connect") - } - - logger.info("Set context service protocol to ${TLSv1_2}") - enableContextServiceProtocol(runner, TLSv1_2) - runner.enqueue(MSG.getBytes()) - runner.run() - - // Assert - runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.GetHTTP.REL_SUCCESS) - runner.clearTransferState() - logger.info("Ran successfully") - } -} diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/groovy/org/apache/nifi/processors/standard/TestPostHTTPGroovy.groovy b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/groovy/org/apache/nifi/processors/standard/TestPostHTTPGroovy.groovy deleted file mode 100644 index 06ea0ac55c..0000000000 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/groovy/org/apache/nifi/processors/standard/TestPostHTTPGroovy.groovy +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.nifi.processors.standard - -import groovy.servlet.GroovyServlet -import org.apache.nifi.security.util.TlsPlatform -import org.apache.nifi.ssl.SSLContextService -import org.apache.nifi.ssl.StandardSSLContextService -import org.apache.nifi.util.TestRunner -import org.apache.nifi.util.TestRunners -import org.bouncycastle.jce.provider.BouncyCastleProvider -import org.eclipse.jetty.server.HttpConfiguration -import org.eclipse.jetty.server.HttpConnectionFactory -import org.eclipse.jetty.server.SecureRequestCustomizer -import org.eclipse.jetty.server.Server -import org.eclipse.jetty.server.ServerConnector -import org.eclipse.jetty.server.SslConnectionFactory -import org.eclipse.jetty.servlet.ServletContextHandler -import org.eclipse.jetty.util.ssl.SslContextFactory -import org.junit.After -import org.junit.AfterClass -import org.junit.Before -import org.junit.BeforeClass -import org.junit.Ignore -import org.junit.Test -import org.junit.runner.RunWith -import org.junit.runners.JUnit4 -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -import javax.crypto.Cipher -import javax.net.SocketFactory -import javax.net.ssl.HostnameVerifier -import javax.net.ssl.HttpsURLConnection -import javax.net.ssl.SSLContext -import javax.net.ssl.SSLEngine -import javax.net.ssl.SSLSocket -import javax.net.ssl.TrustManager -import javax.net.ssl.X509TrustManager -import java.security.Security - -@SuppressWarnings("deprecation") -@RunWith(JUnit4.class) -class TestPostHTTPGroovy extends GroovyTestCase { - private static final Logger logger = LoggerFactory.getLogger(TestPostHTTPGroovy.class) - - - static private final String KEYSTORE_TYPE = "JKS" - - private static final String TLSv1 = "TLSv1" - private static final String TLSv1_1 = "TLSv1.1" - private static final String TLSv1_2 = "TLSv1.2" - private static final List DEFAULT_PROTOCOLS = new ArrayList(TlsPlatform.supportedProtocols) - - private static final SSLContext SSL_CONTEXT = SSLContext.default - private static final SSLEngine SSL_ENGINE = SSL_CONTEXT.createSSLEngine() - private static - final List DEFAULT_CIPHER_SUITES = SSL_ENGINE.supportedCipherSuites as List - - private static final String DEFAULT_HOSTNAME = "localhost" - private static final int DEFAULT_TLS_PORT = 8456 - private static final String HTTPS_URL = "https://${DEFAULT_HOSTNAME}:${DEFAULT_TLS_PORT}" - private static final String POST_URL = "${HTTPS_URL}/PostHandler.groovy" - - private static final String KEYSTORE_PATH = "src/test/resources/keystore.jks" - private static final String TRUSTSTORE_PATH = "src/test/resources/truststore.jks" - - private static final String KEYSTORE_PASSWORD = "passwordpassword" - private static final String TRUSTSTORE_PASSWORD = "passwordpassword" - - private static Server server - private static X509TrustManager nullTrustManager - private static HostnameVerifier nullHostnameVerifier - - private static TestRunner runner - - private - static Server createServer(List supportedProtocols = DEFAULT_PROTOCOLS, List supportedCipherSuites = DEFAULT_CIPHER_SUITES) { - // Create Server - Server server = new Server() - - // Add some secure config - final HttpConfiguration httpsConfiguration = new HttpConfiguration() - httpsConfiguration.setSecureScheme("https") - httpsConfiguration.setSecurePort(DEFAULT_TLS_PORT) - httpsConfiguration.addCustomizer(new SecureRequestCustomizer()) - - // Build the TLS connector - final ServerConnector https = createConnector(server, httpsConfiguration, supportedProtocols, supportedCipherSuites) - - // Add this connector - server.addConnector(https) - logger.info("Created server with supported protocols: ${supportedProtocols}") - - /** Create a simple Groovlet that responds to the incoming request by reversing the string parameter - * i.e. localhost:8456/ReverseHandler.groovy?string=Happy%20birthday -> yadhtrib yppaH - */ - ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS) - context.with { - contextPath = '/' - resourceBase = 'src/test/resources/TestPostHTTP' - addServlet(GroovyServlet, '*.groovy') - } - server.setHandler(context) - server - } - - private - static ServerConnector createConnector(Server server, HttpConfiguration httpsConfiguration, List supportedProtocols = DEFAULT_PROTOCOLS, List supportedCipherSuites = DEFAULT_CIPHER_SUITES) { - ServerConnector https = new ServerConnector(server, - new SslConnectionFactory(createSslContextFactory(supportedProtocols, supportedCipherSuites), "http/1.1"), - new HttpConnectionFactory(httpsConfiguration)) - - // set host and port - https.setHost(DEFAULT_HOSTNAME) - https.setPort(DEFAULT_TLS_PORT) - https - } - - private - static SslContextFactory createSslContextFactory(List supportedProtocols = DEFAULT_PROTOCOLS, List supportedCipherSuites = DEFAULT_CIPHER_SUITES) { - final SslContextFactory contextFactory = new SslContextFactory.Server() - contextFactory.needClientAuth = false - contextFactory.wantClientAuth = false - - contextFactory.setKeyStorePath(KEYSTORE_PATH) - contextFactory.setKeyStoreType(KEYSTORE_TYPE) - contextFactory.setKeyStorePassword(KEYSTORE_PASSWORD) - - contextFactory.setIncludeProtocols(supportedProtocols as String[]) - if (supportedCipherSuites) { - contextFactory.setIncludeCipherSuites(supportedCipherSuites as String[]) - } - contextFactory - } - - @BeforeClass - static void setUpOnce() throws Exception { - Security.addProvider(new BouncyCastleProvider()) - - logger.metaClass.methodMissing = { String name, args -> - logger.info("[${name?.toUpperCase()}] ${(args as List).join(" ")}") - } - - server = createServer() - - runner = configureRunner() - - // Print the default cipher suite list - logger.info("Default supported cipher suites: \n\t${DEFAULT_CIPHER_SUITES.join("\n\t")}") - } - - private static TestRunner configureRunner() { - // Set the default trust manager for the "default" tests (the outgoing Groovy call) to ignore certificate path verification for localhost - nullTrustManager = [ - checkClientTrusted: { chain, authType -> }, - checkServerTrusted: { chain, authType -> }, - getAcceptedIssuers: { null } - ] as X509TrustManager - - nullHostnameVerifier = [ - verify: { String hostname, session -> - // Will always return true if the hostname is "localhost" - hostname.equalsIgnoreCase(DEFAULT_HOSTNAME) - } - ] as HostnameVerifier - - // Configure the test runner - TestRunner runner = TestRunners.newTestRunner(org.apache.nifi.processors.standard.PostHTTP.class) - final SSLContextService sslContextService = new StandardSSLContextService() - runner.addControllerService("ssl-context", sslContextService) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, TRUSTSTORE_PATH) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, TRUSTSTORE_PASSWORD) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, KEYSTORE_TYPE) - runner.enableControllerService(sslContextService) - - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, POST_URL) - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SSL_CONTEXT_SERVICE, "ssl-context") - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false") - - runner - } - - @AfterClass - static void tearDownOnce() { - - } - - @Before - void setUp() throws Exception { - // This must be executed before each test, or the connections will be re-used and if a TLSv1.1 connection is re-used against a server that only supports TLSv1.2, it will fail - SSLContext sc = SSLContext.getInstance(TLSv1_2) - sc.init(null, [nullTrustManager] as TrustManager[], null) - SocketFactory socketFactory = sc.getSocketFactory() - logger.info("JCE unlimited strength installed: ${Cipher.getMaxAllowedKeyLength("AES") > 128}") - logger.info("Supported client cipher suites: ${socketFactory.supportedCipherSuites}") - HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory) - HttpsURLConnection.setDefaultHostnameVerifier(nullHostnameVerifier) - } - - @After - void tearDown() throws Exception { - try { - server.stop() - } catch (Exception e) { - e.printStackTrace() - } - - runner.clearTransferState() - runner.clearProvenanceEvents() - } - - /** - * Jetty 9.4.0+ no longer supports TLSv1. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that supports TLSv1 is available") - void testDefaultShouldSupportTLSv1() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with TLSv1 only - server = createServer([TLSv1]) - - // Start server - server.start() - - // Act - String response = new URL(url).text - logger.info("Response from ${HTTPS_URL}: ${response}") - - // Assert - assert response == MSG.reverse() - } - - /** - * Jetty 9.4.0+ no longer supports TLSv1. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that supports TLSv1.1 is available") - void testDefaultShouldSupportTLSv1_1() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with TLSv1.1 only - server = createServer([TLSv1_1]) - - // Start server - server.start() - - // Act - String response = new URL(url).text - logger.info("Response from ${HTTPS_URL}: ${response}") - - // Assert - assert response == MSG.reverse() - } - - @Test - void testDefaultShouldSupportTLSv1_2() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with TLSv1.2 only - server = createServer([TLSv1_2]) - - // Start server - server.start() - - // Act - String response = new URL(url).text - logger.info("Response from ${HTTPS_URL}: ${response}") - - // Assert - assert response == MSG.reverse() - } - - @Test - void testDefaultShouldPreferHighestSupportedVersion() { - // Arrange - final String MSG = "This is a test message" - final String url = "${HTTPS_URL}/ReverseHandler.groovy?string=${URLEncoder.encode(MSG, "UTF-8")}" - - // Configure server with all TLS protocols - server = createServer() - - // Start server - server.start() - - // Create a connection that could use TLSv1, TLSv1.1, or TLSv1.2 - SSLContext sc = SSLContext.getInstance("TLS") - sc.init(null, [nullTrustManager] as TrustManager[], null) - SocketFactory socketFactory = sc.getSocketFactory() - - URL formedUrl = new URL(url) - SSLSocket socket = (SSLSocket) socketFactory.createSocket(formedUrl.host, formedUrl.port) - logger.info("Enabled protocols: ${socket.enabledProtocols}") - - // Act - socket.startHandshake() - String selectedProtocol = socket.getSession().protocol - logger.info("Selected protocol: ${selectedProtocol}") - - // Assert - assert selectedProtocol == TlsPlatform.latestProtocol - } - - private static void enableContextServiceProtocol(TestRunner runner, String protocol) { - final SSLContextService sslContextService = new StandardSSLContextService() - runner.addControllerService("ssl-context", sslContextService) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, TRUSTSTORE_PATH) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, TRUSTSTORE_PASSWORD) - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, KEYSTORE_TYPE) - runner.setProperty(sslContextService, StandardSSLContextService.SSL_ALGORITHM, protocol) - runner.enableControllerService(sslContextService) - def sslContext = sslContextService.createContext(); - logger.info("PostHTTP supported protocols: ${sslContext.protocol}") - logger.info("PostHTTP supported cipher suites: ${sslContext.supportedSSLParameters.cipherSuites}") - } - - /** - * This test creates a server that supports TLSv1. It iterates over an {@link SSLContextService} with TLSv1, TLSv1.1, and TLSv1.2 support. All three context services should be able to communicate successfully. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that supports TLSv1 is available") - void testPostHTTPShouldConnectToServerWithTLSv1() { - // Arrange - final String MSG = "This is a test message" - - // Configure server with TLSv1 only - server = createServer([TLSv1]) - - // Start server - server.start() - - // Act - [TLSv1, TLSv1_1, TLSv1_2].each { String tlsVersion -> - logger.info("Set context service protocol to ${tlsVersion}") - enableContextServiceProtocol(runner, tlsVersion) - runner.enqueue(MSG.getBytes()) - runner.run() - - // Assert - runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_SUCCESS, 1) - runner.clearTransferState() - logger.info("Ran successfully") - } - } - - /** - * This test creates a server that supports TLSv1.1. It iterates over an {@link SSLContextService} with TLSv1, TLSv1.1, and TLSv1.2 support. The context service with TLSv1 should not be able to communicate with a server that does not support it, but TLSv1.1 and TLSv1.2 should be able to communicate successfully. - */ - @Test - @Ignore("Ignore until embeddable test HTTPS server that supports TLSv1.1 is available") - void testPostHTTPShouldConnectToServerWithTLSv1_1() { - // Arrange - final String MSG = "This is a test message" - - // Configure server with TLSv1.1 only - server = createServer([TLSv1_1]) - - // Start server - server.start() - - // Act - logger.info("Set context service protocol to ${TLSv1}") - enableContextServiceProtocol(runner, TLSv1) - runner.enqueue(MSG.getBytes()) - runner.run() - - // Assert - runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_FAILURE, 1) - runner.clearTransferState() - logger.expected("Unable to connect") - - [TLSv1_1, TLSv1_2].each { String tlsVersion -> - logger.info("Set context service protocol to ${tlsVersion}") - enableContextServiceProtocol(runner, tlsVersion) - runner.enqueue(MSG.getBytes()) - runner.run() - - // Assert - runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_SUCCESS, 1) - runner.clearTransferState() - logger.info("Ran successfully") - } - } - - /** - * This test creates a server that supports TLSv1.2. It iterates over an {@link SSLContextService} with TLSv1, TLSv1.1, and TLSv1.2 support. The context services with TLSv1 and TLSv1.1 should not be able to communicate with a server that does not support it, but TLSv1.2 should be able to communicate successfully. - */ - @Test - void testPostHTTPShouldConnectToServerWithTLSv1_2() { - // Arrange - final String MSG = "This is a test message" - - // Configure server with TLSv1.2 only - server = createServer([TLSv1_2]) - - // Start server - server.start() - - // Act - [TLSv1, TLSv1_1].each { String tlsVersion -> - logger.info("Set context service protocol to ${tlsVersion}") - enableContextServiceProtocol(runner, tlsVersion) - runner.enqueue(MSG.getBytes()) - runner.run() - - // Assert - runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_FAILURE, 1) - runner.clearTransferState() - logger.expected("Unable to connect") - } - - logger.info("Set context service protocol to ${TLSv1_2}") - enableContextServiceProtocol(runner, TLSv1_2) - runner.enqueue(MSG.getBytes()) - runner.run() - - // Assert - runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_SUCCESS, 1) - runner.clearTransferState() - logger.info("Ran successfully") - } -} diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestGetHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITGetHTTP.java similarity index 78% rename from nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestGetHTTP.java rename to nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITGetHTTP.java index 0bc97cbf6e..b9a1a764c5 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestGetHTTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITGetHTTP.java @@ -20,37 +20,52 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.net.URLEncoder; -import java.util.HashMap; -import java.util.Map; +import javax.net.ssl.SSLContext; import javax.servlet.http.HttpServletResponse; import org.apache.nifi.components.state.Scope; import org.apache.nifi.flowfile.attributes.CoreAttributes; +import org.apache.nifi.remote.io.socket.NetworkUtils; import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.security.util.ClientAuth; +import org.apache.nifi.security.util.TlsException; import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.ssl.StandardSSLContextService; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; -import org.apache.nifi.web.util.TestServer; +import org.apache.nifi.web.util.JettyServerUtils; +import org.apache.nifi.web.util.ssl.SslContextUtils; +import org.eclipse.jetty.server.Server; import org.eclipse.jetty.servlet.ServletHandler; -import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; /** - * + * Integration Test for deprecated GetHTTP Processor */ @SuppressWarnings("deprecation") -public class TestGetHTTP { +public class ITGetHTTP { + private static final String SSL_CONTEXT_IDENTIFIER = SSLContextService.class.getName(); + + private static final String HTTP_URL = "http://localhost:%d"; + + private static final String HTTPS_URL = "https://localhost:%d"; + + private static SSLContext keyStoreSslContext; + + private static SSLContext trustStoreSslContext; private TestRunner controller; @BeforeClass - public static void before() { + public static void configureServices() throws TlsException { System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info"); System.setProperty("org.slf4j.simpleLogger.showDateTime", "true"); System.setProperty("org.slf4j.simpleLogger.log.nifi.processors.standard.GetHTTP", "debug"); System.setProperty("org.slf4j.simpleLogger.log.nifi.processors.standard.TestGetHTTP", "debug"); + + keyStoreSslContext = SslContextUtils.createKeyStoreSslContext(); + trustStoreSslContext = SslContextUtils.createTrustStoreSslContext(); } @Test @@ -60,14 +75,15 @@ public class TestGetHTTP { handler.addServletWithMapping(RESTServiceContentModified.class, "/*"); // create the service - TestServer server = new TestServer(); - server.addHandler(handler); + final int port = NetworkUtils.availablePort(); + final Server server = JettyServerUtils.createServer(port, null, null); + server.setHandler(handler); try { - server.startServer(); + JettyServerUtils.startServer(server); // this is the base url with the random port - String destination = server.getUrl(); + String destination = String.format(HTTP_URL, port); // set up NiFi mock controller controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); @@ -139,34 +155,32 @@ public class TestGetHTTP { } finally { // shutdown web service - server.shutdownServer(); + server.stop(); + server.destroy(); } } - @Test public final void testContentModifiedTwoServers() throws Exception { - // set up web services - ServletHandler handler1 = new ServletHandler(); + final int port1 = NetworkUtils.availablePort(); + final Server server1 = JettyServerUtils.createServer(port1, null, null); + final ServletHandler handler1 = new ServletHandler(); handler1.addServletWithMapping(RESTServiceContentModified.class, "/*"); + JettyServerUtils.addHandler(server1, handler1); - ServletHandler handler2 = new ServletHandler(); + final int port2 = NetworkUtils.availablePort(); + final Server server2 = JettyServerUtils.createServer(port2, null, null); + final ServletHandler handler2 = new ServletHandler(); handler2.addServletWithMapping(RESTServiceContentModified.class, "/*"); - - // create the services - TestServer server1 = new TestServer(); - server1.addHandler(handler1); - - TestServer server2 = new TestServer(); - server2.addHandler(handler2); + JettyServerUtils.addHandler(server2, handler2); try { - server1.startServer(); - server2.startServer(); + JettyServerUtils.startServer(server1); + JettyServerUtils.startServer(server2); // this is the base urls with the random ports - String destination1 = server1.getUrl(); - String destination2 = server2.getUrl(); + String destination1 = String.format(HTTP_URL, port1); + String destination2 = String.format(HTTP_URL, port2); // set up NiFi mock controller controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); @@ -205,8 +219,10 @@ public class TestGetHTTP { } finally { // shutdown web services - server1.shutdownServer(); - server2.shutdownServer(); + server1.stop(); + server1.destroy(); + server2.stop(); + server2.destroy(); } } @@ -217,13 +233,13 @@ public class TestGetHTTP { handler.addServletWithMapping(UserAgentTestingServlet.class, "/*"); // create the service - TestServer server = new TestServer(); - server.addHandler(handler); + final int port = NetworkUtils.availablePort(); + Server server = JettyServerUtils.createServer(port, null, null); + server.setHandler(handler); try { - server.startServer(); - - String destination = server.getUrl(); + JettyServerUtils.startServer(server); + final String destination = String.format(HTTP_URL, port); // set up NiFi mock controller controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); @@ -241,7 +257,8 @@ public class TestGetHTTP { // shutdown web service } finally { - server.shutdownServer(); + server.stop(); + server.destroy(); } } @@ -252,13 +269,13 @@ public class TestGetHTTP { handler.addServletWithMapping(UserAgentTestingServlet.class, "/*"); // create the service - TestServer server = new TestServer(); - server.addHandler(handler); + final int port = NetworkUtils.availablePort(); + Server server = JettyServerUtils.createServer(port, null, null); + server.setHandler(handler); try { - server.startServer(); - - String destination = server.getUrl(); + JettyServerUtils.startServer(server); + final String destination = String.format(HTTP_URL, port); // set up NiFi mock controller controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); @@ -275,7 +292,8 @@ public class TestGetHTTP { // shutdown web service } finally { - server.shutdownServer(); + server.stop(); + server.destroy(); } } @@ -286,13 +304,13 @@ public class TestGetHTTP { handler.addServletWithMapping(UserAgentTestingServlet.class, "/*"); // create the service - TestServer server = new TestServer(); - server.addHandler(handler); + final int port = NetworkUtils.availablePort(); + Server server = JettyServerUtils.createServer(port, null, null); + server.setHandler(handler); try { - server.startServer(); - - String destination = server.getUrl(); + JettyServerUtils.startServer(server); + final String destination = String.format(HTTP_URL, port); // set up NiFi mock controller controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); @@ -311,7 +329,8 @@ public class TestGetHTTP { assertTrue(fileName.matches("test_\\d\\d\\d\\d/\\d\\d/\\d\\d_\\d\\d:\\d\\d:\\d\\d")); // shutdown web service } finally { - server.shutdownServer(); + server.stop(); + server.destroy(); } } @@ -326,13 +345,14 @@ public class TestGetHTTP { handler.addServletWithMapping(HttpErrorServlet.class, "/*"); // create the service - TestServer server = new TestServer(); - server.addHandler(handler); + final int port = NetworkUtils.availablePort(); + Server server = JettyServerUtils.createServer(port, null, null); + server.setHandler(handler); try { - server.startServer(); + JettyServerUtils.startServer(server); + final String destination = String.format(HTTP_URL, port); HttpErrorServlet servlet = (HttpErrorServlet) handler.getServlets()[0].getServlet(); - String destination = server.getUrl(); this.controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); this.controller.setProperty(org.apache.nifi.processors.standard.GetHTTP.CONNECTION_TIMEOUT, "5 secs"); @@ -357,31 +377,30 @@ public class TestGetHTTP { this.controller.assertTransferCount(org.apache.nifi.processors.standard.GetHTTP.REL_SUCCESS, 0); } finally { // shutdown web service - server.shutdownServer(); + server.stop(); + server.destroy(); } } @Test - public final void testSecure_oneWaySsl() throws Exception { + public final void testTlsClientAuthenticationNone() throws Exception { // set up web service final ServletHandler handler = new ServletHandler(); handler.addServletWithMapping(HelloWorldServlet.class, "/*"); // create the service, disabling the need for client auth - final Map serverSslProperties = getKeystoreProperties(); - serverSslProperties.put(TestServer.NEED_CLIENT_AUTH, Boolean.toString(false)); - final TestServer server = new TestServer(serverSslProperties); - server.addHandler(handler); + final int port = NetworkUtils.availablePort(); + final Server server = JettyServerUtils.createServer(port, keyStoreSslContext, ClientAuth.NONE); + server.setHandler(handler); try { - server.startServer(); - - final String destination = server.getSecureUrl(); + JettyServerUtils.startServer(server); + final String destination = String.format(HTTPS_URL, port); // set up NiFi mock controller controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); // Use context service with only a truststore - useSSLContextService(getTruststoreProperties()); + enableSslContextService(trustStoreSslContext); controller.setProperty(org.apache.nifi.processors.standard.GetHTTP.CONNECTION_TIMEOUT, "5 secs"); controller.setProperty(org.apache.nifi.processors.standard.GetHTTP.URL, destination); @@ -393,31 +412,30 @@ public class TestGetHTTP { final MockFlowFile mff = controller.getFlowFilesForRelationship(org.apache.nifi.processors.standard.GetHTTP.REL_SUCCESS).get(0); mff.assertContentEquals("Hello, World!"); } finally { - server.shutdownServer(); + server.stop(); + server.destroy(); } } @Test - public final void testSecure_twoWaySsl() throws Exception { + public final void testTlsClientAuthenticationRequired() throws Exception { // set up web service final ServletHandler handler = new ServletHandler(); handler.addServletWithMapping(HelloWorldServlet.class, "/*"); // create the service, providing both truststore and keystore properties, requiring client auth (default) - final Map twoWaySslProperties = getKeystoreProperties(); - twoWaySslProperties.putAll(getTruststoreProperties()); - final TestServer server = new TestServer(twoWaySslProperties); - server.addHandler(handler); + final int port = NetworkUtils.availablePort(); + final Server server = JettyServerUtils.createServer(port, keyStoreSslContext, ClientAuth.REQUIRED); + server.setHandler(handler); try { - server.startServer(); - - final String destination = server.getSecureUrl(); + JettyServerUtils.startServer(server); + final String destination = String.format(HTTPS_URL, port); // set up NiFi mock controller controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); // Use context service with a keystore and a truststore - useSSLContextService(twoWaySslProperties); + enableSslContextService(keyStoreSslContext); controller.setProperty(org.apache.nifi.processors.standard.GetHTTP.CONNECTION_TIMEOUT, "10 secs"); controller.setProperty(org.apache.nifi.processors.standard.GetHTTP.URL, destination); @@ -429,33 +447,32 @@ public class TestGetHTTP { final MockFlowFile mff = controller.getFlowFilesForRelationship(org.apache.nifi.processors.standard.GetHTTP.REL_SUCCESS).get(0); mff.assertContentEquals("Hello, World!"); } finally { - server.shutdownServer(); + server.stop(); + server.destroy(); } } @Test public final void testCookiePolicy() throws Exception { - // set up web services - ServletHandler handler1 = new ServletHandler(); + final int port1 = NetworkUtils.availablePort(); + final Server server1 = JettyServerUtils.createServer(port1, null, null); + final ServletHandler handler1 = new ServletHandler(); handler1.addServletWithMapping(CookieTestingServlet.class, "/*"); + JettyServerUtils.addHandler(server1, handler1); - ServletHandler handler2 = new ServletHandler(); + final int port2 = NetworkUtils.availablePort(); + final Server server2 = JettyServerUtils.createServer(port2, null, null); + final ServletHandler handler2 = new ServletHandler(); handler2.addServletWithMapping(CookieVerificationTestingServlet.class, "/*"); - - // create the services - TestServer server1 = new TestServer(); - server1.addHandler(handler1); - - TestServer server2 = new TestServer(); - server2.addHandler(handler2); + JettyServerUtils.addHandler(server2, handler2); try { - server1.startServer(); - server2.startServer(); + JettyServerUtils.startServer(server1); + JettyServerUtils.startServer(server2); // this is the base urls with the random ports - String destination1 = server1.getUrl(); - String destination2 = server2.getUrl(); + String destination1 = String.format(HTTP_URL, port1); + String destination2 = String.format(HTTP_URL, port2); // set up NiFi mock controller controller = TestRunners.newTestRunner(org.apache.nifi.processors.standard.GetHTTP.class); @@ -498,38 +515,19 @@ public class TestGetHTTP { } finally { // shutdown web services - server1.shutdownServer(); - server2.shutdownServer(); + server1.stop(); + server1.destroy(); + server2.stop(); + server2.destroy(); } } - private static Map getTruststoreProperties() { - final Map props = new HashMap<>(); - props.put(StandardSSLContextService.TRUSTSTORE.getName(), "src/test/resources/truststore.jks"); - props.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), "passwordpassword"); - props.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), "JKS"); - return props; + private void enableSslContextService(final SSLContext configuredSslContext) throws InitializationException { + final SSLContextService sslContextService = Mockito.mock(SSLContextService.class); + Mockito.when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_IDENTIFIER); + Mockito.when(sslContextService.createContext()).thenReturn(configuredSslContext); + controller.addControllerService(SSL_CONTEXT_IDENTIFIER, sslContextService); + controller.enableControllerService(sslContextService); + controller.setProperty(org.apache.nifi.processors.standard.GetHTTP.SSL_CONTEXT_SERVICE, SSL_CONTEXT_IDENTIFIER); } - - private static Map getKeystoreProperties() { - final Map properties = new HashMap<>(); - properties.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/keystore.jks"); - properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), "passwordpassword"); - properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), "JKS"); - return properties; - } - - private void useSSLContextService(final Map sslProperties) { - final SSLContextService service = new StandardSSLContextService(); - try { - controller.addControllerService("ssl-service", service, sslProperties); - controller.enableControllerService(service); - } catch (InitializationException ex) { - ex.printStackTrace(); - Assert.fail("Could not create SSL Context Service"); - } - - controller.setProperty(org.apache.nifi.processors.standard.GetHTTP.SSL_CONTEXT_SERVICE, "ssl-service"); - } - } diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITListenAndPutSyslog.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITListenAndPutSyslog.java index c655d00d26..a7adf26d1b 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITListenAndPutSyslog.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITListenAndPutSyslog.java @@ -21,28 +21,34 @@ import java.nio.charset.StandardCharsets; import org.apache.nifi.processor.ProcessContext; import org.apache.nifi.processor.ProcessSessionFactory; import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.security.util.TlsException; import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.ssl.StandardSSLContextService; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; +import org.apache.nifi.web.util.ssl.SslContextUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.net.ssl.SSLContext; + /** * Tests PutSyslog sending messages to ListenSyslog to simulate a syslog server forwarding * to ListenSyslog, or PutSyslog sending to a syslog server. */ public class ITListenAndPutSyslog { - static final Logger LOGGER = LoggerFactory.getLogger(ITListenAndPutSyslog.class); + private static final String SSL_SERVICE_IDENTIFIER = SSLContextService.class.getName(); - // TODO: The NiFi SSL classes don't yet support TLSv1.3, so set the CS version explicitly - private static final String TLS_PROTOCOL_VERSION = "TLSv1.2"; + private static SSLContext keyStoreSslContext; + + static final Logger LOGGER = LoggerFactory.getLogger(ITListenAndPutSyslog.class); private ListenSyslog listenSyslog; private TestRunner listenSyslogRunner; @@ -50,6 +56,11 @@ public class ITListenAndPutSyslog { private PutSyslog putSyslog; private TestRunner putSyslogRunner; + @BeforeClass + public static void configureServices() throws TlsException { + keyStoreSslContext = SslContextUtils.createKeyStoreSslContext(); + } + @Before public void setup() { this.listenSyslog = new ListenSyslog(); @@ -86,10 +97,10 @@ public class ITListenAndPutSyslog { @Test public void testTLS() throws InitializationException, IOException, InterruptedException { configureSSLContextService(listenSyslogRunner); - listenSyslogRunner.setProperty(ListenSyslog.SSL_CONTEXT_SERVICE, "ssl-context"); + listenSyslogRunner.setProperty(ListenSyslog.SSL_CONTEXT_SERVICE, SSL_SERVICE_IDENTIFIER); configureSSLContextService(putSyslogRunner); - putSyslogRunner.setProperty(PutSyslog.SSL_CONTEXT_SERVICE, "ssl-context"); + putSyslogRunner.setProperty(PutSyslog.SSL_CONTEXT_SERVICE, SSL_SERVICE_IDENTIFIER); run(ListenSyslog.TCP_VALUE.getValue(), 7, 7); } @@ -97,24 +108,19 @@ public class ITListenAndPutSyslog { @Test public void testTLSListenerNoTLSPut() throws InitializationException, IOException, InterruptedException { configureSSLContextService(listenSyslogRunner); - listenSyslogRunner.setProperty(ListenSyslog.SSL_CONTEXT_SERVICE, "ssl-context"); + listenSyslogRunner.setProperty(ListenSyslog.SSL_CONTEXT_SERVICE, SSL_SERVICE_IDENTIFIER); // send 7 but expect 0 because sender didn't use TLS run(ListenSyslog.TCP_VALUE.getValue(), 7, 0); } - private SSLContextService configureSSLContextService(TestRunner runner) throws InitializationException { - final SSLContextService sslContextService = new StandardSSLContextService(); - runner.addControllerService("ssl-context", 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"); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, "src/test/resources/keystore.jks"); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, "passwordpassword"); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, "JKS"); - runner.setProperty(sslContextService, StandardSSLContextService.SSL_ALGORITHM, TLS_PROTOCOL_VERSION); + private void configureSSLContextService(TestRunner runner) throws InitializationException { + final SSLContextService sslContextService = Mockito.mock(SSLContextService.class); + Mockito.when(sslContextService.getIdentifier()).thenReturn(SSL_SERVICE_IDENTIFIER); + Mockito.when(sslContextService.createContext()).thenReturn(keyStoreSslContext); + + runner.addControllerService(SSL_SERVICE_IDENTIFIER, sslContextService); runner.enableControllerService(sslContextService); - return sslContextService; } /** diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPostHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITPostHTTP.java similarity index 64% rename from nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPostHTTP.java rename to nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITPostHTTP.java index ff26e38ebe..ef626a1e43 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPostHTTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITPostHTTP.java @@ -23,6 +23,7 @@ import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -30,133 +31,115 @@ import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.apache.nifi.flowfile.attributes.CoreAttributes; +import org.apache.nifi.remote.io.socket.NetworkUtils; +import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.security.util.ClientAuth; +import org.apache.nifi.security.util.TlsException; import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.ssl.StandardSSLContextService; import org.apache.nifi.util.FlowFileUnpackagerV3; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; -import org.apache.nifi.web.util.TestServer; +import org.apache.nifi.web.util.JettyServerUtils; +import org.apache.nifi.web.util.ssl.SslContextUtils; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletHandler; import org.junit.After; import org.junit.Assert; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; +import javax.net.ssl.SSLContext; + +/** + * Integration Test for deprecated PostHTTP Processor + */ @SuppressWarnings("deprecation") -public class TestPostHTTP { - private TestServer server; +public class ITPostHTTP { + private Server server; private TestRunner runner; private CaptureServlet servlet; - private final String KEYSTORE_PATH = "src/test/resources/keystore.jks"; - private final String KEYSTORE_AND_TRUSTSTORE_PASSWORD = "passwordpassword"; - private final String TRUSTSTORE_PATH = "src/test/resources/truststore.jks"; - private final String JKS_TYPE = "JKS"; + private static final String SSL_CONTEXT_IDENTIFIER = SSLContextService.class.getName(); + + private static final String TEST_MESSAGE = String.class.getName(); + + private static SSLContext keyStoreSslContext; + + private static SSLContext trustStoreSslContext; + + @BeforeClass + public static void configureServices() throws TlsException { + keyStoreSslContext = SslContextUtils.createKeyStoreSslContext(); + trustStoreSslContext = SslContextUtils.createTrustStoreSslContext(); + } + + private static String getUrl(final SSLContext sslContext, final int port) { + final String protocol = sslContext == null ? "http" : "https"; + return String.format("%s://localhost:%d", protocol, port); + } + + private void setup(final SSLContext serverSslContext, final ClientAuth clientAuth) throws Exception { + runner = TestRunners.newTestRunner(org.apache.nifi.processors.standard.PostHTTP.class); + final int port = NetworkUtils.availablePort(); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, getUrl(serverSslContext, port)); - private void setup(final Map sslProperties) throws Exception { // set up web service ServletHandler handler = new ServletHandler(); handler.addServletWithMapping(CaptureServlet.class, "/*"); - // create the service - server = new TestServer(sslProperties); - server.addHandler(handler); - server.startServer(); + final Server configuredServer = JettyServerUtils.createServer(port, serverSslContext, clientAuth); + configuredServer.setHandler(handler); + final ServerConnector connector = new ServerConnector(configuredServer); + connector.setPort(port); + + JettyServerUtils.startServer(configuredServer); servlet = (CaptureServlet) handler.getServlets()[0].getServlet(); - runner = TestRunners.newTestRunner(org.apache.nifi.processors.standard.PostHTTP.class); } @After public void cleanup() throws Exception { if (server != null) { - server.shutdownServer(); + server.stop(); + server.destroy(); server = null; } } @Test - public void testTruststoreSSLOnly() throws Exception { - final Map sslProps = new HashMap<>(); - sslProps.put(TestServer.NEED_CLIENT_AUTH, "false"); - sslProps.put(StandardSSLContextService.KEYSTORE.getName(), KEYSTORE_PATH); - sslProps.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEYSTORE_AND_TRUSTSTORE_PASSWORD); - sslProps.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), JKS_TYPE); - setup(sslProps); + public void testUnauthenticatedTls() throws Exception { + setup(keyStoreSslContext, ClientAuth.NONE); + enableSslContextService(trustStoreSslContext); - final SSLContextService sslContextService = new StandardSSLContextService(); - runner.addControllerService("ssl-context", sslContextService); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, TRUSTSTORE_PATH); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, KEYSTORE_AND_TRUSTSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, JKS_TYPE); - runner.enableControllerService(sslContextService); - - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getSecureUrl()); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SSL_CONTEXT_SERVICE, "ssl-context"); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false"); - - runner.enqueue("Hello world".getBytes()); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, Boolean.FALSE.toString()); + runner.enqueue(TEST_MESSAGE); runner.run(); runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_SUCCESS, 1); } @Test - public void testTwoWaySSL() throws Exception { - final Map sslProps = new HashMap<>(); - sslProps.put(StandardSSLContextService.KEYSTORE.getName(), KEYSTORE_PATH); - sslProps.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEYSTORE_AND_TRUSTSTORE_PASSWORD); - sslProps.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), JKS_TYPE); - sslProps.put(StandardSSLContextService.TRUSTSTORE.getName(), TRUSTSTORE_PATH); - sslProps.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), KEYSTORE_AND_TRUSTSTORE_PASSWORD); - sslProps.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), JKS_TYPE); - sslProps.put(TestServer.NEED_CLIENT_AUTH, "true"); - setup(sslProps); + public void testMutualTls() throws Exception { + setup(keyStoreSslContext, ClientAuth.REQUIRED); + enableSslContextService(keyStoreSslContext); - final SSLContextService sslContextService = new StandardSSLContextService(); - runner.addControllerService("ssl-context", sslContextService); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, TRUSTSTORE_PATH); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, KEYSTORE_AND_TRUSTSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, JKS_TYPE); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, KEYSTORE_PATH); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, KEYSTORE_AND_TRUSTSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, JKS_TYPE); - runner.enableControllerService(sslContextService); - - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getSecureUrl()); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SSL_CONTEXT_SERVICE, "ssl-context"); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false"); - - runner.enqueue("Hello world".getBytes()); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, Boolean.FALSE.toString()); + runner.enqueue(TEST_MESSAGE); runner.run(); runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_SUCCESS, 1); } @Test - public void testOneWaySSLWhenServerConfiguredForTwoWay() throws Exception { - final Map sslProps = new HashMap<>(); - sslProps.put(StandardSSLContextService.KEYSTORE.getName(), KEYSTORE_PATH); - sslProps.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEYSTORE_AND_TRUSTSTORE_PASSWORD); - sslProps.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), JKS_TYPE); - sslProps.put(StandardSSLContextService.TRUSTSTORE.getName(), TRUSTSTORE_PATH); - sslProps.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), KEYSTORE_AND_TRUSTSTORE_PASSWORD); - sslProps.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), JKS_TYPE); - sslProps.put(TestServer.NEED_CLIENT_AUTH, "true"); - setup(sslProps); + public void testMutualTlsClientCertificateMissing() throws Exception { + setup(keyStoreSslContext, ClientAuth.REQUIRED); + enableSslContextService(trustStoreSslContext); - final SSLContextService sslContextService = new StandardSSLContextService(); - runner.addControllerService("ssl-context", 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_TYPE); - runner.enableControllerService(sslContextService); - - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getSecureUrl()); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SSL_CONTEXT_SERVICE, "ssl-context"); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false"); - - runner.enqueue("Hello world".getBytes()); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, Boolean.FALSE.toString()); + runner.enqueue(TEST_MESSAGE); runner.run(); runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_FAILURE, 1); @@ -164,14 +147,14 @@ public class TestPostHTTP { @Test public void testSendAsFlowFile() throws Exception { - setup(null); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()); + setup( null, null); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SEND_AS_FLOWFILE, "true"); final Map attrs = new HashMap<>(); attrs.put("abc", "cba"); - runner.enqueue("Hello".getBytes(), attrs); + runner.enqueue(TEST_MESSAGE, attrs); attrs.put("abc", "abc"); attrs.put("filename", "xyz.txt"); runner.enqueue("World".getBytes(), attrs); @@ -188,7 +171,7 @@ public class TestPostHTTP { // unpack first flowfile received Map receivedAttrs = unpacker.unpackageFlowFile(bais, baos); byte[] contentReceived = baos.toByteArray(); - assertEquals("Hello", new String(contentReceived)); + assertEquals(TEST_MESSAGE, new String(contentReceived)); assertEquals("cba", receivedAttrs.get("abc")); assertTrue(unpacker.hasMoreData()); @@ -204,35 +187,16 @@ public class TestPostHTTP { } @Test - public void testSendAsFlowFileSecure() throws Exception { - final Map sslProps = new HashMap<>(); - sslProps.put(StandardSSLContextService.KEYSTORE.getName(), KEYSTORE_PATH); - sslProps.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEYSTORE_AND_TRUSTSTORE_PASSWORD); - sslProps.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), JKS_TYPE); - sslProps.put(StandardSSLContextService.TRUSTSTORE.getName(), TRUSTSTORE_PATH); - sslProps.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), KEYSTORE_AND_TRUSTSTORE_PASSWORD); - sslProps.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), JKS_TYPE); - sslProps.put(TestServer.NEED_CLIENT_AUTH, "true"); - setup(sslProps); + public void testMutualTlsSendFlowFile() throws Exception { + setup(keyStoreSslContext, ClientAuth.REQUIRED); + enableSslContextService(keyStoreSslContext); - final SSLContextService sslContextService = new StandardSSLContextService(); - runner.addControllerService("ssl-context", sslContextService); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, TRUSTSTORE_PATH); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, KEYSTORE_AND_TRUSTSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, JKS_TYPE); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, KEYSTORE_PATH); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, KEYSTORE_AND_TRUSTSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, JKS_TYPE); - runner.enableControllerService(sslContextService); - - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getSecureUrl()); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SEND_AS_FLOWFILE, "true"); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SSL_CONTEXT_SERVICE, "ssl-context"); final Map attrs = new HashMap<>(); attrs.put("abc", "cba"); - runner.enqueue("Hello".getBytes(), attrs); + runner.enqueue(TEST_MESSAGE, attrs); attrs.put("abc", "abc"); attrs.put("filename", "xyz.txt"); runner.enqueue("World".getBytes(), attrs); @@ -249,7 +213,7 @@ public class TestPostHTTP { // unpack first flowfile received Map receivedAttrs = unpacker.unpackageFlowFile(bais, baos); byte[] contentReceived = baos.toByteArray(); - assertEquals("Hello", new String(contentReceived)); + assertEquals(TEST_MESSAGE, new String(contentReceived)); assertEquals("cba", receivedAttrs.get("abc")); assertTrue(unpacker.hasMoreData()); @@ -265,15 +229,14 @@ public class TestPostHTTP { @Test public void testSendWithMimeType() throws Exception { - setup(null); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()); + setup(null, null); final Map attrs = new HashMap<>(); final String suppliedMimeType = "text/plain"; attrs.put(CoreAttributes.MIME_TYPE.key(), suppliedMimeType); runner.enqueue("Camping is great!".getBytes(), attrs); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false"); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, Boolean.FALSE.toString()); runner.run(1); runner.assertAllFlowFilesTransferred(org.apache.nifi.processors.standard.PostHTTP.REL_SUCCESS); @@ -285,9 +248,9 @@ public class TestPostHTTP { @Test public void testSendWithEmptyELExpression() throws Exception { - setup(null); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false"); + setup( null, null); + + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, Boolean.FALSE.toString()); final Map attrs = new HashMap<>(); attrs.put(CoreAttributes.MIME_TYPE.key(), ""); @@ -302,12 +265,11 @@ public class TestPostHTTP { @Test public void testSendWithContentTypeProperty() throws Exception { - setup(null); + setup(null, null); final String suppliedMimeType = "text/plain"; - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CONTENT_TYPE, suppliedMimeType); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false"); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, Boolean.FALSE.toString()); final Map attrs = new HashMap<>(); attrs.put(CoreAttributes.MIME_TYPE.key(), "text/csv"); @@ -322,10 +284,9 @@ public class TestPostHTTP { @Test public void testSendWithCompressionServerAcceptGzip() throws Exception { - setup(null); + setup(null, null); final String suppliedMimeType = "text/plain"; - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CONTENT_TYPE, suppliedMimeType); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.COMPRESSION_LEVEL, "9"); @@ -346,10 +307,9 @@ public class TestPostHTTP { @Test public void testSendWithoutCompressionServerAcceptGzip() throws Exception { - setup(null); + setup(null, null); final String suppliedMimeType = "text/plain"; - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CONTENT_TYPE, suppliedMimeType); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.COMPRESSION_LEVEL, "0"); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false"); @@ -371,11 +331,14 @@ public class TestPostHTTP { @Test public void testSendWithCompressionServerNotAcceptGzip() throws Exception { - setup(null); + setup(null, null); final String suppliedMimeType = "text/plain"; // Specify a property to the URL to have the CaptureServlet specify it doesn't accept gzip - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()+"?acceptGzip=false"); + + final String serverUrl = runner.getProcessContext().getProperty(PostHTTP.URL).getValue(); + final String url = String.format("%s?acceptGzip=false", serverUrl); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, url); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CONTENT_TYPE, suppliedMimeType); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.COMPRESSION_LEVEL, "9"); @@ -395,12 +358,11 @@ public class TestPostHTTP { @Test public void testSendChunked() throws Exception { - setup(null); + setup(null, null); final String suppliedMimeType = "text/plain"; - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CONTENT_TYPE, suppliedMimeType); - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "true"); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, Boolean.TRUE.toString()); final Map attrs = new HashMap<>(); attrs.put(CoreAttributes.MIME_TYPE.key(), "text/plain"); @@ -421,10 +383,9 @@ public class TestPostHTTP { @Test public void testSendWithThrottler() throws Exception { - setup(null); + setup(null, null); final String suppliedMimeType = "text/plain"; - runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, server.getUrl()); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CONTENT_TYPE, suppliedMimeType); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.CHUNKED_ENCODING, "false"); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.MAX_DATA_RATE, "10kb"); @@ -448,31 +409,28 @@ public class TestPostHTTP { @Test public void testDefaultUserAgent() throws Exception { - setup(null); + setup(null, null); Assert.assertTrue(runner.getProcessContext().getProperty(org.apache.nifi.processors.standard.PostHTTP.USER_AGENT).getValue().startsWith("Apache-HttpClient")); } @Test public void testBatchWithMultipleUrls() throws Exception { - CaptureServlet servletA, servletB; - TestServer serverA, serverB; + setup(null,null); + final CaptureServlet servletA = servlet; + final String urlA = runner.getProcessContext().getProperty(org.apache.nifi.processors.standard.PostHTTP.URL).getValue(); - { // setup test servers - setup(null); - servletA = servlet; - serverA = server; + // set up second web service + ServletHandler handler = new ServletHandler(); + handler.addServletWithMapping(CaptureServlet.class, "/*"); - // set up second web service - ServletHandler handler = new ServletHandler(); - handler.addServletWithMapping(CaptureServlet.class, "/*"); + // create the second service + final int portB = NetworkUtils.availablePort(); + final String urlB = getUrl(null, portB); + final Server serverB = JettyServerUtils.createServer(portB, null, null); + serverB.setHandler(handler); + JettyServerUtils.startServer(serverB); - // create the second service - serverB = new TestServer(null); - serverB.addHandler(handler); - serverB.startServer(); - - servletB = (CaptureServlet) handler.getServlets()[0].getServlet(); - } + final CaptureServlet servletB = (CaptureServlet) handler.getServlets()[0].getServlet(); runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.URL, "${url}"); // use EL for the URL runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SEND_AS_FLOWFILE, "true"); @@ -486,8 +444,8 @@ public class TestPostHTTP { // enqueue 9 FlowFiles for (int i = 0; i < 9; i++) { - enqueueWithURL("a" + i, serverA.getUrl()); - enqueueWithURL("b" + i, serverB.getUrl()); + enqueueWithURL("a" + i, urlA); + enqueueWithURL("b" + i, urlB); expectedContentA.add("a" + i); expectedContentB.add("b" + i); @@ -503,10 +461,10 @@ public class TestPostHTTP { MockFlowFile mff = successFiles.get(0); final String urlAttr = mff.getAttribute("url"); - if (serverA.getUrl().equals(urlAttr)) { - checkBatch(serverA, servletA, actualContentA, (actualContentA.isEmpty() ? 5 : 4)); - } else if (serverB.getUrl().equals(urlAttr)) { - checkBatch(serverB, servletB, actualContentB, (actualContentB.isEmpty() ? 5 : 4)); + if (urlA.equals(urlAttr)) { + checkBatch(urlA, servletA, actualContentA, (actualContentA.isEmpty() ? 5 : 4)); + } else if (urlB.equals(urlAttr)) { + checkBatch(urlB, servletB, actualContentB, (actualContentB.isEmpty() ? 5 : 4)); } else { fail("unexpected url attribute"); } @@ -526,7 +484,7 @@ public class TestPostHTTP { runner.enqueue(data.getBytes(), attrs); } - private void checkBatch(TestServer server, CaptureServlet servlet, Set actualContent, int expectedCount) throws Exception { + private void checkBatch(final String url, CaptureServlet servlet, Set actualContent, int expectedCount) throws Exception { FlowFileUnpackagerV3 unpacker = new FlowFileUnpackagerV3(); Set actualFFContent = new HashSet<>(); Set actualPostContent = new HashSet<>(); @@ -538,7 +496,7 @@ public class TestPostHTTP { final List successFlowFiles = runner.getFlowFilesForRelationship(org.apache.nifi.processors.standard.PostHTTP.REL_SUCCESS); for (int i = 0; i < expectedCount; i++) { MockFlowFile mff = successFlowFiles.get(i); - mff.assertAttributeEquals("url", server.getUrl()); + mff.assertAttributeEquals("url", url); String content = new String(mff.toByteArray()); actualFFContent.add(content); } @@ -549,9 +507,10 @@ public class TestPostHTTP { ByteArrayOutputStream baos = new ByteArrayOutputStream()) { for (int i = 0; i < expectedCount; i++) { Map receivedAttrs = unpacker.unpackageFlowFile(bais, baos); - String receivedContent = new String(baos.toByteArray()); + final byte[] bytesReceived = baos.toByteArray(); + String receivedContent = new String(bytesReceived, StandardCharsets.UTF_8); actualPostContent.add(receivedContent); - assertEquals(server.getUrl(), receivedAttrs.get("url")); + assertEquals(url, receivedAttrs.get("url")); assertTrue(unpacker.hasMoreData() || i == (expectedCount - 1)); baos.reset(); } @@ -560,8 +519,17 @@ public class TestPostHTTP { // confirm that the transferred and POSTed content match assertEquals(actualFFContent, actualPostContent); - // accumulate actial content + // accumulate actual content actualContent.addAll(actualPostContent); runner.clearTransferState(); } + + private void enableSslContextService(final SSLContext configuredSslContext) throws InitializationException { + final SSLContextService sslContextService = Mockito.mock(SSLContextService.class); + Mockito.when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_IDENTIFIER); + Mockito.when(sslContextService.createContext()).thenReturn(configuredSslContext); + runner.addControllerService(SSL_CONTEXT_IDENTIFIER, sslContextService); + runner.enableControllerService(sslContextService); + runner.setProperty(org.apache.nifi.processors.standard.PostHTTP.SSL_CONTEXT_SERVICE, SSL_CONTEXT_IDENTIFIER); + } } diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITestHandleHttpRequest.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITestHandleHttpRequest.java index b5b32464ea..67954f1852 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITestHandleHttpRequest.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/ITestHandleHttpRequest.java @@ -25,9 +25,7 @@ import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -60,72 +58,36 @@ import org.apache.nifi.http.HttpContextMap; import org.apache.nifi.processor.ProcessContext; 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.security.util.StandardTlsConfiguration; -import org.apache.nifi.security.util.TlsConfiguration; -import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.ssl.StandardRestrictedSSLContextService; -import org.apache.nifi.ssl.StandardSSLContextService; +import org.apache.nifi.security.util.TlsException; +import org.apache.nifi.ssl.RestrictedSSLContextService; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; +import org.apache.nifi.web.util.ssl.SslContextUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; public class ITestHandleHttpRequest { - private static final String KEYSTORE = "src/test/resources/keystore.jks"; - private static final String KEYSTORE_PASSWORD = "passwordpassword"; - private static final String KEYSTORE_TYPE = "JKS"; - private static final String TRUSTSTORE = "src/test/resources/truststore.jks"; - private static final String TRUSTSTORE_PASSWORD = "passwordpassword"; - private static final String TRUSTSTORE_TYPE = "JKS"; - private static final String CLIENT_KEYSTORE = "src/test/resources/client-keystore.p12"; - private static final String CLIENT_KEYSTORE_TYPE = "PKCS12"; - private HandleHttpRequest processor; - private TlsConfiguration clientTlsConfiguration; - private TlsConfiguration trustOnlyTlsConfiguration; + private static SSLContext keyStoreSslContext; - private static Map getTruststoreProperties() { - final Map props = new HashMap<>(); - props.put(StandardSSLContextService.TRUSTSTORE.getName(), TRUSTSTORE); - props.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), TRUSTSTORE_PASSWORD); - props.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), TRUSTSTORE_TYPE); - return props; - } + private static SSLContext trustStoreSslContext; - private static Map getServerKeystoreProperties() { - final Map properties = new HashMap<>(); - properties.put(StandardSSLContextService.KEYSTORE.getName(), KEYSTORE); - properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), KEYSTORE_PASSWORD); - properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), KEYSTORE_TYPE); - return properties; - } - - private static SSLContext useSSLContextService(final TestRunner controller, final Map sslProperties) { - final SSLContextService service = new StandardRestrictedSSLContextService(); - try { - controller.addControllerService("ssl-service", service, sslProperties); - controller.enableControllerService(service); - } catch (InitializationException ex) { - ex.printStackTrace(); - Assert.fail("Could not create SSL Context Service"); - } - - controller.setProperty(HandleHttpRequest.SSL_CONTEXT, "ssl-service"); - return service.createContext(); + @BeforeClass + public static void configureServices() throws TlsException { + keyStoreSslContext = SslContextUtils.createKeyStoreSslContext(); + trustStoreSslContext = SslContextUtils.createTrustStoreSslContext(); } @Before public void setUp() throws Exception { - clientTlsConfiguration = new StandardTlsConfiguration(CLIENT_KEYSTORE, KEYSTORE_PASSWORD, null, CLIENT_KEYSTORE_TYPE, - TRUSTSTORE, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE, TlsConfiguration.getHighestCurrentSupportedTlsProtocolVersion()); - trustOnlyTlsConfiguration = new StandardTlsConfiguration(null, null, null, null, - TRUSTSTORE, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE, TlsConfiguration.getHighestCurrentSupportedTlsProtocolVersion()); + } @After @@ -136,7 +98,7 @@ public class ITestHandleHttpRequest { } @Test(timeout = 30000) - public void testRequestAddedToService() throws InitializationException, IOException, InterruptedException { + public void testRequestAddedToService() throws InitializationException { CountDownLatch serverReady = new CountDownLatch(1); CountDownLatch requestSent = new CountDownLatch(1); @@ -191,7 +153,7 @@ public class ITestHandleHttpRequest { } @Test(timeout = 30000) - public void testMultipartFormDataRequest() throws InitializationException, IOException, InterruptedException { + public void testMultipartFormDataRequest() throws InitializationException { CountDownLatch serverReady = new CountDownLatch(1); CountDownLatch requestSent = new CountDownLatch(1); @@ -304,8 +266,7 @@ public class ITestHandleHttpRequest { } @Test(timeout = 30000) - public void testMultipartFormDataRequestCaptureFormAttributes() throws InitializationException, IOException, - InterruptedException { + public void testMultipartFormDataRequestCaptureFormAttributes() throws InitializationException { CountDownLatch serverReady = new CountDownLatch(1); CountDownLatch requestSent = new CountDownLatch(1); @@ -374,7 +335,7 @@ public class ITestHandleHttpRequest { } @Test(timeout = 30000) - public void testMultipartFormDataRequestFailToRegisterContext() throws InitializationException, IOException, InterruptedException { + public void testMultipartFormDataRequestFailToRegisterContext() throws InitializationException, InterruptedException { CountDownLatch serverReady = new CountDownLatch(1); CountDownLatch requestSent = new CountDownLatch(1); CountDownLatch resultReady = new CountDownLatch(1); @@ -427,7 +388,7 @@ public class ITestHandleHttpRequest { } @Override - public void onResponse(Call call, Response response) throws IOException { + public void onResponse(Call call, Response response) { responseCode.set(response.code()); resultReady.countDown(); } @@ -473,7 +434,7 @@ public class ITestHandleHttpRequest { @Test(timeout = 30000) - public void testFailToRegister() throws InitializationException, IOException, InterruptedException { + public void testFailToRegister() throws InitializationException, InterruptedException { CountDownLatch serverReady = new CountDownLatch(1); CountDownLatch requestSent = new CountDownLatch(1); CountDownLatch resultReady = new CountDownLatch(1); @@ -649,10 +610,13 @@ public class ITestHandleHttpRequest { runner.enableControllerService(contextMap); runner.setProperty(HandleHttpRequest.HTTP_CONTEXT_MAP, "http-context-map"); - final Map sslProperties = getServerKeystoreProperties(); - sslProperties.putAll(getTruststoreProperties()); - sslProperties.put(StandardSSLContextService.SSL_ALGORITHM.getName(), TlsConfiguration.getHighestCurrentSupportedTlsProtocolVersion()); - useSSLContextService(runner, sslProperties); + final RestrictedSSLContextService sslContextService = Mockito.mock(RestrictedSSLContextService.class); + final String serviceIdentifier = RestrictedSSLContextService.class.getName(); + Mockito.when(sslContextService.getIdentifier()).thenReturn(serviceIdentifier); + Mockito.when(sslContextService.createContext()).thenReturn(keyStoreSslContext); + runner.addControllerService(serviceIdentifier, sslContextService); + runner.enableControllerService(sslContextService); + runner.setProperty(HandleHttpRequest.SSL_CONTEXT, serviceIdentifier); final Thread httpThread = new Thread(new Runnable() { @Override @@ -667,10 +631,10 @@ public class ITestHandleHttpRequest { SSLContext clientSslContext; if (twoWaySsl) { // Use a client certificate, do not reuse the server's keystore - clientSslContext = SslContextFactory.createSslContext(clientTlsConfiguration); + clientSslContext = keyStoreSslContext; } else { // With one-way SSL, the client still needs a truststore - clientSslContext = SslContextFactory.createSslContext(trustOnlyTlsConfiguration); + clientSslContext = trustStoreSslContext; } connection.setSSLSocketFactory(clientSslContext.getSocketFactory()); connection.setDoOutput(false); diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestInvokeHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestInvokeHTTP.java index 561b44f869..ee3a62c8ea 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestInvokeHTTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestInvokeHTTP.java @@ -27,12 +27,15 @@ import java.io.PrintWriter; import java.lang.reflect.Field; import java.net.URL; import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; +import javax.net.ssl.SSLContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.nifi.processors.standard.util.TestInvokeHttpCommon; -import org.apache.nifi.ssl.StandardSSLContextService; +import org.apache.nifi.security.util.KeystoreType; +import org.apache.nifi.security.util.SslContextFactory; +import org.apache.nifi.security.util.StandardTlsConfiguration; +import org.apache.nifi.security.util.TlsConfiguration; +import org.apache.nifi.ssl.SSLContextService; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunners; import org.eclipse.jetty.server.Request; @@ -41,12 +44,29 @@ import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestInvokeHTTP extends TestInvokeHttpCommon { private static final Logger logger = LoggerFactory.getLogger(TestInvokeHTTP.class); + private static final String TRUSTSTORE_PATH = "src/test/resources/truststore.jks"; + private static final String TRUSTSTORE_PASSWORD = "passwordpassword"; + private static final KeystoreType TRUSTSTORE_TYPE = KeystoreType.JKS; + private static final String KEYSTORE_PATH = "src/test/resources/keystore.jks"; + private static final String KEYSTORE_PASSWORD = "passwordpassword"; + private static final KeystoreType KEYSTORE_TYPE = KeystoreType.JKS; + + private static final TlsConfiguration TLS_CONFIGURATION = new StandardTlsConfiguration( + KEYSTORE_PATH, + KEYSTORE_PASSWORD, + KEYSTORE_TYPE, + TRUSTSTORE_PATH, + TRUSTSTORE_PASSWORD, + TRUSTSTORE_TYPE + ); + @BeforeClass public static void beforeClass() throws Exception { configureServer(null, null); @@ -59,20 +79,18 @@ public class TestInvokeHTTP extends TestInvokeHttpCommon { @Test public void testSslSetHttpRequest() throws Exception { - - final Map sslProperties = new HashMap<>(); - sslProperties.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/keystore.jks"); - sslProperties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), "passwordpassword"); - sslProperties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), "JKS"); - sslProperties.put(StandardSSLContextService.TRUSTSTORE.getName(), "src/test/resources/truststore.jks"); - sslProperties.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), "passwordpassword"); - sslProperties.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), "JKS"); + final String serviceIdentifier = SSLContextService.class.getName(); + final SSLContextService sslContextService = Mockito.mock(SSLContextService.class); + Mockito.when(sslContextService.getIdentifier()).thenReturn(serviceIdentifier); + final SSLContext sslContext = SslContextFactory.createSslContext(TLS_CONFIGURATION); + Mockito.when(sslContextService.createContext()).thenReturn(sslContext); + Mockito.when(sslContextService.createTlsConfiguration()).thenReturn(TLS_CONFIGURATION); runner = TestRunners.newTestRunner(InvokeHTTP.class); - final StandardSSLContextService sslService = new StandardSSLContextService(); - runner.addControllerService("ssl-context", sslService, sslProperties); - runner.enableControllerService(sslService); - runner.setProperty(InvokeHTTP.PROP_SSL_CONTEXT_SERVICE, "ssl-context"); + + runner.addControllerService(serviceIdentifier, sslContextService); + runner.enableControllerService(sslContextService); + runner.setProperty(InvokeHTTP.PROP_SSL_CONTEXT_SERVICE, serviceIdentifier); addHandler(new GetOrHeadHandler()); diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java index 31f706dbcc..7fc620a90f 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenHTTP.java @@ -63,7 +63,6 @@ import org.apache.nifi.security.util.TlsConfiguration; import org.apache.nifi.security.util.TlsException; import org.apache.nifi.ssl.RestrictedSSLContextService; import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.ssl.StandardSSLContextService; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; @@ -314,16 +313,6 @@ public class TestListenHTTP { testPOSTRequestsReceived(HttpServletResponse.SC_NO_CONTENT, true, true); } - @Test - public void testSecureInvalidSSLConfiguration() throws Exception { - SSLContextService sslContextService = configureInvalidProcessorSslContextService(); - runner.enableControllerService(sslContextService); - - runner.setProperty(ListenHTTP.PORT, HTTP_SERVER_PORT_EL); - runner.setProperty(ListenHTTP.BASE_PATH, HTTP_SERVER_BASEPATH_EL); - runner.assertNotValid(); - } - @Test public void testSecureServerSupportsCurrentTlsProtocolVersion() throws Exception { configureProcessorSslContextService(ListenHTTP.ClientAuthentication.AUTO, SERVER_NO_TRUSTSTORE_CONFIGURATION); @@ -539,22 +528,8 @@ public class TestListenHTTP { runner.enableControllerService(sslContextService); } - private SSLContextService configureInvalidProcessorSslContextService() throws InitializationException { - final SSLContextService sslContextService = new StandardSSLContextService(); - runner.addControllerService(SSL_CONTEXT_SERVICE_IDENTIFIER, sslContextService); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, TRUSTSTORE); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, TRUSTSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, KeystoreType.JKS.getType()); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, KEYSTORE); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, KEYSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, KeystoreType.JKS.getType()); - runner.setProperty(ListenHTTP.SSL_CONTEXT_SERVICE, SSL_CONTEXT_SERVICE_IDENTIFIER); - return sslContextService; - } - - - @Test(/*timeout=10000*/) + @Test public void testMultipartFormDataRequest() throws Exception { runner.setProperty(ListenHTTP.PORT, Integer.toString(availablePort)); diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenRELP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenRELP.java index 51851f3f5b..e48fe7650e 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenRELP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenRELP.java @@ -38,11 +38,12 @@ import org.apache.nifi.processors.standard.relp.response.RELPResponse; import org.apache.nifi.provenance.ProvenanceEventRecord; import org.apache.nifi.provenance.ProvenanceEventType; import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.security.util.TlsException; import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.ssl.StandardSSLContextService; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; +import org.apache.nifi.web.util.ssl.SslContextUtils; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -50,9 +51,6 @@ import org.mockito.Mockito; public class TestListenRELP { - // TODO: The NiFi SSL classes don't yet support TLSv1.3, so set the CS version explicitly - private static final String TLS_PROTOCOL_VERSION = "TLSv1.2"; - public static final String OPEN_FRAME_DATA = "relp_version=0\nrelp_software=librelp,1.2.7,http://librelp.adiscon.com\ncommands=syslog"; public static final String SYSLOG_FRAME_DATA = "this is a syslog message here"; @@ -151,19 +149,16 @@ public class TestListenRELP { } @Test - public void testTLS() throws InitializationException, IOException, InterruptedException { - final SSLContextService sslContextService = new StandardSSLContextService(); - runner.addControllerService("ssl-context", sslContextService); - runner.setProperty(sslContextService, StandardSSLContextService.SSL_ALGORITHM, TLS_PROTOCOL_VERSION); - 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"); + public void testMutualTls() throws IOException, InterruptedException, TlsException, InitializationException { + final SSLContextService sslContextService = Mockito.mock(SSLContextService.class); + final String serviceIdentifier = SSLContextService.class.getName(); + Mockito.when(sslContextService.getIdentifier()).thenReturn(serviceIdentifier); + final SSLContext sslContext = SslContextUtils.createKeyStoreSslContext(); + Mockito.when(sslContextService.createContext()).thenReturn(sslContext); + runner.addControllerService(serviceIdentifier, sslContextService); runner.enableControllerService(sslContextService); - runner.setProperty(ListenRELP.SSL_CONTEXT_SERVICE, "ssl-context"); + runner.setProperty(ListenRELP.SSL_CONTEXT_SERVICE, serviceIdentifier); final List frames = new ArrayList<>(); frames.add(OPEN_FRAME); @@ -174,8 +169,7 @@ public class TestListenRELP { frames.add(SYSLOG_FRAME); frames.add(CLOSE_FRAME); - // three syslog frames should be transferred and three responses should be sent - run(frames, 5, 5, sslContextService); + run(frames, 5, 5, sslContext); } @Test @@ -210,7 +204,7 @@ public class TestListenRELP { } - protected void run(final List frames, final int expectedTransferred, final int expectedResponses, final SSLContextService sslContextService) + protected void run(final List frames, final int expectedTransferred, final int expectedResponses, final SSLContext sslContext) throws IOException, InterruptedException { Socket socket = null; @@ -224,11 +218,10 @@ public class TestListenRELP { final int realPort = proc.getDispatcherPort(); // create either a regular socket or ssl socket based on context being passed in - if (sslContextService != null) { - final SSLContext sslContext = sslContextService.createContext(); - socket = sslContext.getSocketFactory().createSocket("localhost", realPort); - } else { + if (sslContext == null) { socket = new Socket("localhost", realPort); + } else { + socket = sslContext.getSocketFactory().createSocket("localhost", realPort); } Thread.sleep(100); diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenTCP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenTCP.java index ab7d5b77f7..83f4a754d7 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenTCP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenTCP.java @@ -21,56 +21,51 @@ import java.net.Socket; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import javax.net.SocketFactory; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLException; + import org.apache.commons.io.IOUtils; import org.apache.nifi.processor.ProcessContext; import org.apache.nifi.processor.ProcessSessionFactory; import org.apache.nifi.reporting.InitializationException; import org.apache.nifi.security.util.ClientAuth; -import org.apache.nifi.security.util.SslContextFactory; -import org.apache.nifi.security.util.StandardTlsConfiguration; -import org.apache.nifi.security.util.TlsConfiguration; import org.apache.nifi.security.util.TlsException; +import org.apache.nifi.ssl.RestrictedSSLContextService; import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.ssl.StandardRestrictedSSLContextService; -import org.apache.nifi.ssl.StandardSSLContextService; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; +import org.apache.nifi.web.util.ssl.SslContextUtils; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; public class TestListenTCP { + private static final long RESPONSE_TIMEOUT = 10000; - private static final String KEYSTORE = "src/test/resources/keystore.jks"; - private static final String KEYSTORE_PASSWORD = "passwordpassword"; - private static final String KEYSTORE_TYPE = "JKS"; - private static final String TRUSTSTORE = "src/test/resources/truststore.jks"; - private static final String TRUSTSTORE_PASSWORD = "passwordpassword"; - private static final String TRUSTSTORE_TYPE = "JKS"; - private static final String CLIENT_KEYSTORE = "src/test/resources/client-keystore.p12"; - private static final String CLIENT_KEYSTORE_TYPE = "PKCS12"; + private static final String SSL_CONTEXT_IDENTIFIER = SSLContextService.class.getName(); - // TODO: The NiFi SSL classes don't yet support TLSv1.3, so set the CS version explicitly - private static final String TLS_PROTOCOL_VERSION = "TLSv1.2"; + private static SSLContext keyStoreSslContext; - private static TlsConfiguration clientTlsConfiguration; - private static TlsConfiguration trustOnlyTlsConfiguration; + private static SSLContext trustStoreSslContext; private ListenTCP proc; private TestRunner runner; + @BeforeClass + public static void configureServices() throws TlsException { + keyStoreSslContext = SslContextUtils.createKeyStoreSslContext(); + trustStoreSslContext = SslContextUtils.createTrustStoreSslContext(); + } + @Before public void setup() { proc = new ListenTCP(); runner = TestRunners.newTestRunner(proc); runner.setProperty(ListenTCP.PORT, "0"); - - clientTlsConfiguration = new StandardTlsConfiguration(CLIENT_KEYSTORE, KEYSTORE_PASSWORD, null, CLIENT_KEYSTORE_TYPE, - TRUSTSTORE, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE, TLS_PROTOCOL_VERSION); - trustOnlyTlsConfiguration = new StandardTlsConfiguration(null, null, null, null, - TRUSTSTORE, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE, TLS_PROTOCOL_VERSION); } @Test @@ -78,7 +73,7 @@ public class TestListenTCP { runner.setProperty(ListenTCP.PORT, "1"); runner.assertValid(); - configureProcessorSslContextService(); + enableSslContextService(keyStoreSslContext); runner.setProperty(ListenTCP.CLIENT_AUTH, ""); runner.assertNotValid(); @@ -126,11 +121,11 @@ public class TestListenTCP { } @Test - public void testTLSClientAuthRequiredAndClientCertProvided() throws InitializationException, IOException, InterruptedException, - TlsException { + public void testTLSClientAuthRequiredAndClientCertProvided() throws IOException, InterruptedException, + InitializationException { runner.setProperty(ListenTCP.CLIENT_AUTH, ClientAuth.REQUIRED.name()); - configureProcessorSslContextService(); + enableSslContextService(keyStoreSslContext); final List messages = new ArrayList<>(); messages.add("This is message 1\n"); @@ -140,9 +135,7 @@ public class TestListenTCP { messages.add("This is message 5\n"); // Make an SSLContext with a key and trust store to send the test messages - final SSLContext clientSslContext = SslContextFactory.createSslContext(clientTlsConfiguration); - - runTCP(messages, messages.size(), clientSslContext); + runTCP(messages, messages.size(), keyStoreSslContext); List mockFlowFiles = runner.getFlowFilesForRelationship(ListenTCP.REL_SUCCESS); for (int i = 0; i < mockFlowFiles.size(); i++) { @@ -151,10 +144,9 @@ public class TestListenTCP { } @Test - public void testTLSClientAuthRequiredAndClientCertNotProvided() throws InitializationException, TlsException { - + public void testTLSClientAuthRequiredAndClientCertNotProvided() throws InitializationException { runner.setProperty(ListenTCP.CLIENT_AUTH, ClientAuth.REQUIRED.name()); - configureProcessorSslContextService(); + enableSslContextService(keyStoreSslContext); final List messages = new ArrayList<>(); messages.add("This is message 1\n"); @@ -164,21 +156,15 @@ public class TestListenTCP { messages.add("This is message 5\n"); // Make an SSLContext that only has the trust store, this should not work since the processor has client auth REQUIRED - final SSLContext clientSslContext = SslContextFactory.createSslContext(trustOnlyTlsConfiguration); - - try { - runTCP(messages, messages.size(), clientSslContext); - Assert.fail("Should have thrown exception"); - } catch (Exception e) { - - } + Assert.assertThrows(SSLException.class, () -> + runTCP(messages, messages.size(), trustStoreSslContext) + ); } @Test - public void testTLSClientAuthNoneAndClientCertNotProvided() throws InitializationException, IOException, InterruptedException, TlsException { - + public void testTLSClientAuthNoneAndClientCertNotProvided() throws IOException, InterruptedException, InitializationException { runner.setProperty(ListenTCP.CLIENT_AUTH, ClientAuth.NONE.name()); - configureProcessorSslContextService(); + enableSslContextService(keyStoreSslContext); final List messages = new ArrayList<>(); messages.add("This is message 1\n"); @@ -188,9 +174,7 @@ public class TestListenTCP { messages.add("This is message 5\n"); // Make an SSLContext that only has the trust store, this should not work since the processor has client auth REQUIRED - final SSLContext clientSslContext = SslContextFactory.createSslContext(trustOnlyTlsConfiguration); - - runTCP(messages, messages.size(), clientSslContext); + runTCP(messages, messages.size(), trustStoreSslContext); List mockFlowFiles = runner.getFlowFilesForRelationship(ListenTCP.REL_SUCCESS); for (int i = 0; i < mockFlowFiles.size(); i++) { @@ -212,10 +196,11 @@ public class TestListenTCP { final int realPort = proc.getDispatcherPort(); // create either a regular socket or ssl socket based on context being passed in - if (sslContext != null) { - socket = sslContext.getSocketFactory().createSocket("localhost", realPort); - } else { + if (sslContext == null) { socket = new Socket("localhost", realPort); + } else { + final SocketFactory socketFactory = sslContext.getSocketFactory(); + socket = socketFactory.createSocket("localhost", realPort); } Thread.sleep(100); @@ -226,14 +211,12 @@ public class TestListenTCP { } socket.getOutputStream().flush(); - long responseTimeout = 10000; - // this first loop waits until the internal queue of the processor has the expected // number of messages ready before proceeding, we want to guarantee they are all there // before onTrigger gets a chance to run long startTimeQueueSizeCheck = System.currentTimeMillis(); while (proc.getQueueSize() < messages.size() - && (System.currentTimeMillis() - startTimeQueueSizeCheck < responseTimeout)) { + && (System.currentTimeMillis() - startTimeQueueSizeCheck < RESPONSE_TIMEOUT)) { Thread.sleep(100); } @@ -243,7 +226,7 @@ public class TestListenTCP { // call onTrigger until we processed all the frames, or a certain amount of time passes int numTransferred = 0; long startTime = System.currentTimeMillis(); - while (numTransferred < expectedTransferred && (System.currentTimeMillis() - startTime < responseTimeout)) { + while (numTransferred < expectedTransferred && (System.currentTimeMillis() - startTime < RESPONSE_TIMEOUT)) { proc.onTrigger(context, processSessionFactory); numTransferred = runner.getFlowFilesForRelationship(ListenTCP.REL_SUCCESS).size(); Thread.sleep(100); @@ -258,20 +241,12 @@ public class TestListenTCP { } } - private SSLContextService configureProcessorSslContextService() throws InitializationException { - final SSLContextService sslContextService = new StandardRestrictedSSLContextService(); - runner.addControllerService("ssl-context", sslContextService); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, KEYSTORE); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, KEYSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, KEYSTORE_TYPE); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE, TRUSTSTORE); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_PASSWORD, TRUSTSTORE_PASSWORD); - runner.setProperty(sslContextService, StandardSSLContextService.TRUSTSTORE_TYPE, TRUSTSTORE_TYPE); - runner.setProperty(sslContextService, StandardSSLContextService.SSL_ALGORITHM, TLS_PROTOCOL_VERSION); + private void enableSslContextService(final SSLContext sslContext) throws InitializationException { + final RestrictedSSLContextService sslContextService = Mockito.mock(RestrictedSSLContextService.class); + Mockito.when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_IDENTIFIER); + Mockito.when(sslContextService.createContext()).thenReturn(sslContext); + runner.addControllerService(SSL_CONTEXT_IDENTIFIER, sslContextService); runner.enableControllerService(sslContextService); - - runner.setProperty(ListenTCP.SSL_CONTEXT_SERVICE, "ssl-context"); - return sslContextService; + runner.setProperty(ListenTCP.SSL_CONTEXT_SERVICE, SSL_CONTEXT_IDENTIFIER); } - } diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenTCPRecord.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenTCPRecord.java index 8af404cfd4..e0d1a15e65 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenTCPRecord.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestListenTCPRecord.java @@ -31,43 +31,27 @@ import org.apache.nifi.processor.ProcessSessionFactory; import org.apache.nifi.reporting.InitializationException; import org.apache.nifi.schema.access.SchemaAccessUtils; import org.apache.nifi.security.util.ClientAuth; -import org.apache.nifi.security.util.SslContextFactory; -import org.apache.nifi.security.util.StandardTlsConfiguration; -import org.apache.nifi.security.util.TlsConfiguration; import org.apache.nifi.security.util.TlsException; import org.apache.nifi.serialization.RecordReaderFactory; import org.apache.nifi.serialization.RecordSetWriterFactory; import org.apache.nifi.serialization.record.MockRecordWriter; +import org.apache.nifi.ssl.RestrictedSSLContextService; import org.apache.nifi.ssl.SSLContextService; -import org.apache.nifi.ssl.StandardRestrictedSSLContextService; -import org.apache.nifi.ssl.StandardSSLContextService; import org.apache.nifi.util.MockFlowFile; import org.apache.nifi.util.TestRunner; import org.apache.nifi.util.TestRunners; +import org.apache.nifi.web.util.ssl.SslContextUtils; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; +import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TestListenTCPRecord { static final Logger LOGGER = LoggerFactory.getLogger(TestListenTCPRecord.class); - private static final String KEYSTORE = "src/test/resources/keystore.jks"; - private static final String KEYSTORE_PASSWORD = "passwordpassword"; - private static final String KEYSTORE_TYPE = "JKS"; - private static final String TRUSTSTORE = "src/test/resources/truststore.jks"; - private static final String TRUSTSTORE_PASSWORD = "passwordpassword"; - private static final String TRUSTSTORE_TYPE = "JKS"; - private static final String CLIENT_KEYSTORE = "src/test/resources/client-keystore.p12"; - private static final String CLIENT_KEYSTORE_TYPE = "PKCS12"; - - // TODO: The NiFi SSL classes don't yet support TLSv1.3, so set the CS version explicitly - private static final String TLS_PROTOCOL_VERSION = "TLSv1.2"; - - private static TlsConfiguration clientTlsConfiguration; - private static TlsConfiguration trustOnlyTlsConfiguration; - static final String SCHEMA_TEXT = "{\n" + " \"name\": \"syslogRecord\",\n" + " \"namespace\": \"nifi\",\n" + @@ -91,9 +75,21 @@ public class TestListenTCPRecord { DATA = Collections.unmodifiableList(data); } + private static final String SSL_CONTEXT_IDENTIFIER = SSLContextService.class.getName(); + + private static SSLContext keyStoreSslContext; + + private static SSLContext trustStoreSslContext; + private ListenTCPRecord proc; private TestRunner runner; + @BeforeClass + public static void configureServices() throws TlsException { + keyStoreSslContext = SslContextUtils.createKeyStoreSslContext(); + trustStoreSslContext = SslContextUtils.createTrustStoreSslContext(); + } + @Before public void setup() throws InitializationException { proc = new ListenTCPRecord(); @@ -115,10 +111,6 @@ public class TestListenTCPRecord { runner.setProperty(ListenTCPRecord.RECORD_READER, readerId); runner.setProperty(ListenTCPRecord.RECORD_WRITER, writerId); - clientTlsConfiguration = new StandardTlsConfiguration(CLIENT_KEYSTORE, KEYSTORE_PASSWORD, null, CLIENT_KEYSTORE_TYPE, - TRUSTSTORE, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE, TLS_PROTOCOL_VERSION); - trustOnlyTlsConfiguration = new StandardTlsConfiguration(null, null, null, null, - TRUSTSTORE, TRUSTSTORE_PASSWORD, TRUSTSTORE_TYPE, TLS_PROTOCOL_VERSION); } @Test @@ -126,7 +118,7 @@ public class TestListenTCPRecord { runner.setProperty(ListenTCPRecord.PORT, "1"); runner.assertValid(); - configureProcessorSslContextService(); + enableSslContextService(keyStoreSslContext); runner.setProperty(ListenTCPRecord.CLIENT_AUTH, ""); runner.assertNotValid(); @@ -171,15 +163,11 @@ public class TestListenTCPRecord { } @Test - public void testTLSClientAuthRequiredAndClientCertProvided() throws InitializationException, IOException, InterruptedException, TlsException { - + public void testTLSClientAuthRequiredAndClientCertProvided() throws InitializationException, IOException, InterruptedException { runner.setProperty(ListenTCPRecord.CLIENT_AUTH, ClientAuth.REQUIRED.name()); - configureProcessorSslContextService(); + enableSslContextService(keyStoreSslContext); - // Make an SSLContext with a key and trust store to send the test messages - final SSLContext clientSslContext = SslContextFactory.createSslContext(clientTlsConfiguration); - - runTCP(DATA, 1, clientSslContext); + runTCP(DATA, 1, keyStoreSslContext); final List mockFlowFiles = runner.getFlowFilesForRelationship(ListenTCPRecord.REL_SUCCESS); Assert.assertEquals(1, mockFlowFiles.size()); @@ -192,28 +180,21 @@ public class TestListenTCPRecord { } @Test - public void testTLSClientAuthRequiredAndClientCertNotProvided() throws InitializationException, IOException, InterruptedException, TlsException { - + public void testTLSClientAuthRequiredAndClientCertNotProvided() throws InitializationException, IOException, InterruptedException { runner.setProperty(ListenTCPRecord.CLIENT_AUTH, ClientAuth.REQUIRED.name()); runner.setProperty(ListenTCPRecord.READ_TIMEOUT, "5 seconds"); - configureProcessorSslContextService(); + enableSslContextService(keyStoreSslContext); - // Make an SSLContext that only has the trust store, this should not work since the processor has client auth REQUIRED - final SSLContext clientSslContext = SslContextFactory.createSslContext(trustOnlyTlsConfiguration); - - runTCP(DATA, 0, clientSslContext); + runTCP(DATA, 0, trustStoreSslContext); } @Test - public void testTLSClientAuthNoneAndClientCertNotProvided() throws InitializationException, IOException, InterruptedException, TlsException { + public void testTLSClientAuthNoneAndClientCertNotProvided() throws InitializationException, IOException, InterruptedException { runner.setProperty(ListenTCPRecord.CLIENT_AUTH, ClientAuth.NONE.name()); - configureProcessorSslContextService(); + enableSslContextService(keyStoreSslContext); - // Make an SSLContext that only has the trust store, this should work since the processor has client auth NONE - final SSLContext clientSslContext = SslContextFactory.createSslContext(trustOnlyTlsConfiguration); - - runTCP(DATA, 1, clientSslContext); + runTCP(DATA, 1, trustStoreSslContext); final List mockFlowFiles = runner.getFlowFilesForRelationship(ListenTCPRecord.REL_SUCCESS); Assert.assertEquals(1, mockFlowFiles.size()); @@ -262,21 +243,6 @@ public class TestListenTCPRecord { } } - private SSLContextService configureProcessorSslContextService() throws InitializationException { - final SSLContextService sslContextService = new StandardRestrictedSSLContextService(); - runner.addControllerService("ssl-context", 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"); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE, "src/test/resources/keystore.jks"); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_PASSWORD, "passwordpassword"); - runner.setProperty(sslContextService, StandardSSLContextService.KEYSTORE_TYPE, "JKS"); - runner.enableControllerService(sslContextService); - - runner.setProperty(ListenTCPRecord.SSL_CONTEXT_SERVICE, "ssl-context"); - return sslContextService; - } - private static class SocketSender implements Runnable, Closeable { private final int port; @@ -324,4 +290,12 @@ public class TestListenTCPRecord { } } + private void enableSslContextService(final SSLContext sslContext) throws InitializationException { + final RestrictedSSLContextService sslContextService = Mockito.mock(RestrictedSSLContextService.class); + Mockito.when(sslContextService.getIdentifier()).thenReturn(SSL_CONTEXT_IDENTIFIER); + Mockito.when(sslContextService.createContext()).thenReturn(sslContext); + runner.addControllerService(SSL_CONTEXT_IDENTIFIER, sslContextService); + runner.enableControllerService(sslContextService); + runner.setProperty(ListenTCPRecord.SSL_CONTEXT_SERVICE, SSL_CONTEXT_IDENTIFIER); + } } diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-web-test-utils/src/main/java/org/apache/nifi/web/util/ssl/SslContextUtils.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-web-test-utils/src/main/java/org/apache/nifi/web/util/ssl/SslContextUtils.java new file mode 100644 index 0000000000..e527da96d3 --- /dev/null +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-web-test-utils/src/main/java/org/apache/nifi/web/util/ssl/SslContextUtils.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.nifi.web.util.ssl; + +import org.apache.nifi.security.util.KeystoreType; +import org.apache.nifi.security.util.SslContextFactory; +import org.apache.nifi.security.util.StandardTlsConfiguration; +import org.apache.nifi.security.util.TlsConfiguration; +import org.apache.nifi.security.util.TlsException; + +import javax.net.ssl.SSLContext; + +public class SslContextUtils { + private static final String KEYSTORE_PATH = "src/test/resources/keystore.jks"; + + private static final String KEYSTORE_AND_TRUSTSTORE_PASSWORD = "passwordpassword"; + + private static final String TRUSTSTORE_PATH = "src/test/resources/truststore.jks"; + + private static final TlsConfiguration KEYSTORE_TLS_CONFIGURATION = new StandardTlsConfiguration( + KEYSTORE_PATH, + KEYSTORE_AND_TRUSTSTORE_PASSWORD, + KEYSTORE_AND_TRUSTSTORE_PASSWORD, + KeystoreType.JKS, + TRUSTSTORE_PATH, + KEYSTORE_AND_TRUSTSTORE_PASSWORD, + KeystoreType.JKS, + TlsConfiguration.TLS_1_2_PROTOCOL + ); + + private static final TlsConfiguration TRUSTSTORE_TLS_CONFIGURATION = new StandardTlsConfiguration( + null, + null, + null, + null, + TRUSTSTORE_PATH, + KEYSTORE_AND_TRUSTSTORE_PASSWORD, + KeystoreType.JKS, + TlsConfiguration.TLS_1_2_PROTOCOL + ); + + /** + * Create SSLContext with Key Store and Trust Store configured + * + * @return SSLContext configured with Key Store and Trust Store + * @throws TlsException Thrown on SslContextFactory.createSslContext() + */ + public static SSLContext createKeyStoreSslContext() throws TlsException { + return SslContextFactory.createSslContext(KEYSTORE_TLS_CONFIGURATION); + } + + /** + * Create SSLContext with Trust Store configured + * + * @return SSLContext configured with Trust Store + * @throws TlsException Thrown on SslContextFactory.createSslContext() + */ + public static SSLContext createTrustStoreSslContext() throws TlsException { + return SslContextFactory.createSslContext(TRUSTSTORE_TLS_CONFIGURATION); + } +}