Repository: nifi Updated Branches: refs/heads/master 84848f7cb -> 37271e824
NIFI-4790 - support HTTPS Proxy in InvokeHTTP Signed-off-by: Pierre Villard <[email protected]> This closes #2426. Project: http://git-wip-us.apache.org/repos/asf/nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/37271e82 Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/37271e82 Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/37271e82 Branch: refs/heads/master Commit: 37271e82414b9386bb735b61ef54e891300117bf Parents: 84848f7 Author: Marco Gaido <[email protected]> Authored: Fri Jan 19 11:02:56 2018 +0100 Committer: Pierre Villard <[email protected]> Committed: Wed Jan 24 17:51:28 2018 +0100 ---------------------------------------------------------------------- .../nifi/processors/standard/InvokeHTTP.java | 40 ++++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi/blob/37271e82/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java index 300e9cb..5f6e66c 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/InvokeHTTP.java @@ -148,6 +148,9 @@ public final class InvokeHTTP extends AbstractProcessor { EXCEPTION_CLASS, EXCEPTION_MESSAGE, "uuid", "filename", "path"))); + public static final String HTTP = "http"; + public static final String HTTPS = "https"; + // properties public static final PropertyDescriptor PROP_METHOD = new PropertyDescriptor.Builder() .name("HTTP Method") @@ -213,11 +216,21 @@ public final class InvokeHTTP extends AbstractProcessor { public static final PropertyDescriptor PROP_SSL_CONTEXT_SERVICE = new PropertyDescriptor.Builder() .name("SSL Context Service") - .description("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections.") + .description("The SSL Context Service used to provide client certificate information for TLS/SSL (https) connections." + + " It is also used to connect to HTTPS Proxy.") .required(false) .identifiesControllerService(SSLContextService.class) .build(); + public static final PropertyDescriptor PROP_PROXY_TYPE = new PropertyDescriptor.Builder() + .name("Proxy Type") + .displayName("Proxy Type") + .description("The type of the proxy we are connecting to. Must be either " + HTTP + " or " + HTTPS) + .defaultValue(HTTP) + .expressionLanguageSupported(true) + .addValidator(StandardValidators.NON_EMPTY_EL_VALIDATOR) + .build(); + public static final PropertyDescriptor PROP_PROXY_HOST = new PropertyDescriptor.Builder() .name("Proxy Host") .description("The fully qualified hostname or IP address of the proxy server") @@ -388,6 +401,7 @@ public final class InvokeHTTP extends AbstractProcessor { PROP_BASIC_AUTH_PASSWORD, PROP_PROXY_HOST, PROP_PROXY_PORT, + PROP_PROXY_TYPE, PROP_PROXY_USER, PROP_PROXY_PASSWORD, PROP_PUT_OUTPUT_IN_ATTRIBUTE, @@ -509,10 +523,22 @@ public final class InvokeHTTP extends AbstractProcessor { if ((proxyUserSet && !proxyPwdSet) || (!proxyUserSet && proxyPwdSet)) { results.add(new ValidationResult.Builder().subject("Proxy User and Password").valid(false).explanation("If Proxy Username or Proxy Password is set, both must be set").build()); } - if(proxyUserSet && !proxyHostSet) { + if (proxyUserSet && !proxyHostSet) { results.add(new ValidationResult.Builder().subject("Proxy").valid(false).explanation("If Proxy username is set, proxy host must be set").build()); } + final String proxyType = validationContext.getProperty(PROP_PROXY_TYPE).evaluateAttributeExpressions().getValue(); + + if (!HTTP.equals(proxyType) && !HTTPS.equals(proxyType)) { + results.add(new ValidationResult.Builder().subject(PROP_PROXY_TYPE.getDisplayName()).valid(false) + .explanation(PROP_PROXY_TYPE.getDisplayName() + " must be either " + HTTP + " or " + HTTPS).build()); + } + + if (HTTPS.equals(proxyType) + && !validationContext.getProperty(PROP_SSL_CONTEXT_SERVICE).isSet()) { + results.add(new ValidationResult.Builder().subject("SSL Context Service").valid(false).explanation("If Proxy Type is HTTPS, SSL Context Service must be set").build()); + } + return results; } @@ -525,9 +551,12 @@ public final class InvokeHTTP extends AbstractProcessor { // Add a proxy if set final String proxyHost = context.getProperty(PROP_PROXY_HOST).evaluateAttributeExpressions().getValue(); final Integer proxyPort = context.getProperty(PROP_PROXY_PORT).evaluateAttributeExpressions().asInteger(); + final String proxyType = context.getProperty(PROP_PROXY_TYPE).evaluateAttributeExpressions().getValue(); + boolean isHttpsProxy = false; if (proxyHost != null && proxyPort != null) { final Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); okHttpClientBuilder.proxy(proxy); + isHttpsProxy = HTTPS.equals(proxyType); } // Set timeouts @@ -542,7 +571,7 @@ public final class InvokeHTTP extends AbstractProcessor { // check if the ssl context is set and add the factory if so if (sslContext != null) { - setSslSocketFactory(okHttpClientBuilder, sslService, sslContext); + setSslSocketFactory(okHttpClientBuilder, sslService, sslContext, isHttpsProxy); } // check the trusted hostname property and override the HostnameVerifier @@ -566,7 +595,7 @@ public final class InvokeHTTP extends AbstractProcessor { In-depth documentation on Java Secure Socket Extension (JSSE) Classes and interfaces: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#JSSEClasses */ - private void setSslSocketFactory(OkHttpClient.Builder okHttpClientBuilder, SSLContextService sslService, SSLContext sslContext) + private void setSslSocketFactory(OkHttpClient.Builder okHttpClientBuilder, SSLContextService sslService, SSLContext sslContext, boolean setAsSocketFactory) throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException { final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); @@ -622,6 +651,9 @@ public final class InvokeHTTP extends AbstractProcessor { final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); okHttpClientBuilder.sslSocketFactory(sslSocketFactory, x509TrustManager); + if (setAsSocketFactory) { + okHttpClientBuilder.socketFactory(sslSocketFactory); + } } private void setAuthenticator(OkHttpClient.Builder okHttpClientBuilder, ProcessContext context) {
