mirror of https://github.com/apache/nifi.git
NIFI-1163: Providing handling of SSLContext creation in GetHTTP in case of only performing a one-way SSL request and accompanying test to verify the configuration/usage.
Reviewed by Tony Kurc (tkurc@apache.org)
This commit is contained in:
parent
90f6830003
commit
01539ed323
|
@ -49,6 +49,7 @@ import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
|
@ -64,11 +65,11 @@ import org.apache.http.conn.HttpClientConnectionManager;
|
||||||
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
import org.apache.http.conn.socket.ConnectionSocketFactory;
|
||||||
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
|
||||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
import org.apache.http.conn.ssl.SSLContexts;
|
|
||||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
||||||
|
import org.apache.http.ssl.SSLContextBuilder;
|
||||||
import org.apache.nifi.annotation.behavior.InputRequirement;
|
import org.apache.nifi.annotation.behavior.InputRequirement;
|
||||||
import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
|
import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
|
||||||
import org.apache.nifi.annotation.behavior.WritesAttribute;
|
import org.apache.nifi.annotation.behavior.WritesAttribute;
|
||||||
|
@ -320,19 +321,26 @@ public class GetHTTP extends AbstractSessionFactoryProcessor {
|
||||||
|
|
||||||
private SSLContext createSSLContext(final SSLContextService service)
|
private SSLContext createSSLContext(final SSLContextService service)
|
||||||
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
|
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
|
||||||
|
|
||||||
|
final SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(service.getTrustStoreFile())) {
|
||||||
final KeyStore truststore = KeyStore.getInstance(service.getTrustStoreType());
|
final KeyStore truststore = KeyStore.getInstance(service.getTrustStoreType());
|
||||||
try (final InputStream in = new FileInputStream(new File(service.getTrustStoreFile()))) {
|
try (final InputStream in = new FileInputStream(new File(service.getTrustStoreFile()))) {
|
||||||
truststore.load(in, service.getTrustStorePassword().toCharArray());
|
truststore.load(in, service.getTrustStorePassword().toCharArray());
|
||||||
}
|
}
|
||||||
|
sslContextBuilder.loadTrustMaterial(truststore, new TrustSelfSignedStrategy());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(service.getKeyStoreFile())){
|
||||||
final KeyStore keystore = KeyStore.getInstance(service.getKeyStoreType());
|
final KeyStore keystore = KeyStore.getInstance(service.getKeyStoreType());
|
||||||
try (final InputStream in = new FileInputStream(new File(service.getKeyStoreFile()))) {
|
try (final InputStream in = new FileInputStream(new File(service.getKeyStoreFile()))) {
|
||||||
keystore.load(in, service.getKeyStorePassword().toCharArray());
|
keystore.load(in, service.getKeyStorePassword().toCharArray());
|
||||||
}
|
}
|
||||||
|
sslContextBuilder.loadKeyMaterial(keystore, service.getKeyStorePassword().toCharArray());
|
||||||
|
}
|
||||||
|
|
||||||
final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(truststore, new TrustSelfSignedStrategy()).loadKeyMaterial(keystore, service.getKeyStorePassword().toCharArray()).build();
|
return sslContextBuilder.build();
|
||||||
|
|
||||||
return sslContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -317,48 +317,27 @@ public class TestGetHTTP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> getSslProperties() {
|
|
||||||
Map<String, String> props = new HashMap<String, String>();
|
|
||||||
props.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/localhost-ks.jks");
|
|
||||||
props.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), "localtest");
|
|
||||||
props.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), "JKS");
|
|
||||||
props.put(StandardSSLContextService.TRUSTSTORE.getName(), "src/test/resources/localhost-ts.jks");
|
|
||||||
props.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), "localtest");
|
|
||||||
props.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), "JKS");
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void useSSLContextService() {
|
|
||||||
final SSLContextService service = new StandardSSLContextService();
|
|
||||||
try {
|
|
||||||
controller.addControllerService("ssl-service", service, getSslProperties());
|
|
||||||
controller.enableControllerService(service);
|
|
||||||
} catch (InitializationException ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
Assert.fail("Could not create SSL Context Service");
|
|
||||||
}
|
|
||||||
|
|
||||||
controller.setProperty(GetHTTP.SSL_CONTEXT_SERVICE, "ssl-service");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public final void testSecure() throws Exception {
|
public final void testSecure_oneWaySsl() throws Exception {
|
||||||
// set up web service
|
// set up web service
|
||||||
ServletHandler handler = new ServletHandler();
|
final ServletHandler handler = new ServletHandler();
|
||||||
handler.addServletWithMapping(HelloWorldServlet.class, "/*");
|
handler.addServletWithMapping(HelloWorldServlet.class, "/*");
|
||||||
|
|
||||||
// create the service
|
// create the service, disabling the need for client auth
|
||||||
TestServer server = new TestServer(getSslProperties());
|
final Map<String, String> serverSslProperties = getKeystoreProperties();
|
||||||
|
serverSslProperties.put(TestServer.NEED_CLIENT_AUTH, Boolean.toString(false));
|
||||||
|
final TestServer server = new TestServer(serverSslProperties);
|
||||||
server.addHandler(handler);
|
server.addHandler(handler);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
server.startServer();
|
server.startServer();
|
||||||
|
|
||||||
String destination = server.getSecureUrl();
|
final String destination = server.getSecureUrl();
|
||||||
|
|
||||||
// set up NiFi mock controller
|
// set up NiFi mock controller
|
||||||
controller = TestRunners.newTestRunner(GetHTTP.class);
|
controller = TestRunners.newTestRunner(GetHTTP.class);
|
||||||
useSSLContextService();
|
// Use context service with only a truststore
|
||||||
|
useSSLContextService(getTruststoreProperties());
|
||||||
|
|
||||||
controller.setProperty(GetHTTP.CONNECTION_TIMEOUT, "5 secs");
|
controller.setProperty(GetHTTP.CONNECTION_TIMEOUT, "5 secs");
|
||||||
controller.setProperty(GetHTTP.URL, destination);
|
controller.setProperty(GetHTTP.URL, destination);
|
||||||
|
@ -374,4 +353,69 @@ public class TestGetHTTP {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void testSecure_twoWaySsl() 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<String, String> twoWaySslProperties = getKeystoreProperties();
|
||||||
|
twoWaySslProperties.putAll(getTruststoreProperties());
|
||||||
|
final TestServer server = new TestServer(twoWaySslProperties);
|
||||||
|
server.addHandler(handler);
|
||||||
|
|
||||||
|
try {
|
||||||
|
server.startServer();
|
||||||
|
|
||||||
|
final String destination = server.getSecureUrl();
|
||||||
|
|
||||||
|
// set up NiFi mock controller
|
||||||
|
controller = TestRunners.newTestRunner(GetHTTP.class);
|
||||||
|
// Use context service with a keystore and a truststore
|
||||||
|
useSSLContextService(twoWaySslProperties);
|
||||||
|
|
||||||
|
controller.setProperty(GetHTTP.CONNECTION_TIMEOUT, "5 secs");
|
||||||
|
controller.setProperty(GetHTTP.URL, destination);
|
||||||
|
controller.setProperty(GetHTTP.FILENAME, "testFile");
|
||||||
|
controller.setProperty(GetHTTP.ACCEPT_CONTENT_TYPE, "application/json");
|
||||||
|
|
||||||
|
controller.run();
|
||||||
|
controller.assertAllFlowFilesTransferred(GetHTTP.REL_SUCCESS, 1);
|
||||||
|
final MockFlowFile mff = controller.getFlowFilesForRelationship(GetHTTP.REL_SUCCESS).get(0);
|
||||||
|
mff.assertContentEquals("Hello, World!");
|
||||||
|
} finally {
|
||||||
|
server.shutdownServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> getTruststoreProperties() {
|
||||||
|
final Map<String, String> props = new HashMap<>();
|
||||||
|
props.put(StandardSSLContextService.TRUSTSTORE.getName(), "src/test/resources/localhost-ts.jks");
|
||||||
|
props.put(StandardSSLContextService.TRUSTSTORE_PASSWORD.getName(), "localtest");
|
||||||
|
props.put(StandardSSLContextService.TRUSTSTORE_TYPE.getName(), "JKS");
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> getKeystoreProperties() {
|
||||||
|
final Map<String, String> properties = new HashMap<>();
|
||||||
|
properties.put(StandardSSLContextService.KEYSTORE.getName(), "src/test/resources/localhost-ks.jks");
|
||||||
|
properties.put(StandardSSLContextService.KEYSTORE_PASSWORD.getName(), "localtest");
|
||||||
|
properties.put(StandardSSLContextService.KEYSTORE_TYPE.getName(), "JKS");
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void useSSLContextService(final Map<String, String> 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(GetHTTP.SSL_CONTEXT_SERVICE, "ssl-service");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue