mirror of https://github.com/apache/nifi.git
NIFI-4790 - support HTTPS Proxy in InvokeHTTP
Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com> This closes #2426.
This commit is contained in:
parent
84848f7cbb
commit
37271e8241
|
@ -148,6 +148,9 @@ public final class InvokeHTTP extends AbstractProcessor {
|
||||||
EXCEPTION_CLASS, EXCEPTION_MESSAGE,
|
EXCEPTION_CLASS, EXCEPTION_MESSAGE,
|
||||||
"uuid", "filename", "path")));
|
"uuid", "filename", "path")));
|
||||||
|
|
||||||
|
public static final String HTTP = "http";
|
||||||
|
public static final String HTTPS = "https";
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
public static final PropertyDescriptor PROP_METHOD = new PropertyDescriptor.Builder()
|
public static final PropertyDescriptor PROP_METHOD = new PropertyDescriptor.Builder()
|
||||||
.name("HTTP Method")
|
.name("HTTP Method")
|
||||||
|
@ -213,11 +216,21 @@ public final class InvokeHTTP extends AbstractProcessor {
|
||||||
|
|
||||||
public static final PropertyDescriptor PROP_SSL_CONTEXT_SERVICE = new PropertyDescriptor.Builder()
|
public static final PropertyDescriptor PROP_SSL_CONTEXT_SERVICE = new PropertyDescriptor.Builder()
|
||||||
.name("SSL Context Service")
|
.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)
|
.required(false)
|
||||||
.identifiesControllerService(SSLContextService.class)
|
.identifiesControllerService(SSLContextService.class)
|
||||||
.build();
|
.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()
|
public static final PropertyDescriptor PROP_PROXY_HOST = new PropertyDescriptor.Builder()
|
||||||
.name("Proxy Host")
|
.name("Proxy Host")
|
||||||
.description("The fully qualified hostname or IP address of the proxy server")
|
.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_BASIC_AUTH_PASSWORD,
|
||||||
PROP_PROXY_HOST,
|
PROP_PROXY_HOST,
|
||||||
PROP_PROXY_PORT,
|
PROP_PROXY_PORT,
|
||||||
|
PROP_PROXY_TYPE,
|
||||||
PROP_PROXY_USER,
|
PROP_PROXY_USER,
|
||||||
PROP_PROXY_PASSWORD,
|
PROP_PROXY_PASSWORD,
|
||||||
PROP_PUT_OUTPUT_IN_ATTRIBUTE,
|
PROP_PUT_OUTPUT_IN_ATTRIBUTE,
|
||||||
|
@ -509,10 +523,22 @@ public final class InvokeHTTP extends AbstractProcessor {
|
||||||
if ((proxyUserSet && !proxyPwdSet) || (!proxyUserSet && proxyPwdSet)) {
|
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());
|
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());
|
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;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,9 +551,12 @@ public final class InvokeHTTP extends AbstractProcessor {
|
||||||
// Add a proxy if set
|
// Add a proxy if set
|
||||||
final String proxyHost = context.getProperty(PROP_PROXY_HOST).evaluateAttributeExpressions().getValue();
|
final String proxyHost = context.getProperty(PROP_PROXY_HOST).evaluateAttributeExpressions().getValue();
|
||||||
final Integer proxyPort = context.getProperty(PROP_PROXY_PORT).evaluateAttributeExpressions().asInteger();
|
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) {
|
if (proxyHost != null && proxyPort != null) {
|
||||||
final Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
|
final Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
|
||||||
okHttpClientBuilder.proxy(proxy);
|
okHttpClientBuilder.proxy(proxy);
|
||||||
|
isHttpsProxy = HTTPS.equals(proxyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set timeouts
|
// 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
|
// check if the ssl context is set and add the factory if so
|
||||||
if (sslContext != null) {
|
if (sslContext != null) {
|
||||||
setSslSocketFactory(okHttpClientBuilder, sslService, sslContext);
|
setSslSocketFactory(okHttpClientBuilder, sslService, sslContext, isHttpsProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the trusted hostname property and override the HostnameVerifier
|
// 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:
|
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
|
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 {
|
throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
|
||||||
|
|
||||||
final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
final KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||||
|
@ -622,6 +651,9 @@ public final class InvokeHTTP extends AbstractProcessor {
|
||||||
|
|
||||||
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||||
okHttpClientBuilder.sslSocketFactory(sslSocketFactory, x509TrustManager);
|
okHttpClientBuilder.sslSocketFactory(sslSocketFactory, x509TrustManager);
|
||||||
|
if (setAsSocketFactory) {
|
||||||
|
okHttpClientBuilder.socketFactory(sslSocketFactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAuthenticator(OkHttpClient.Builder okHttpClientBuilder, ProcessContext context) {
|
private void setAuthenticator(OkHttpClient.Builder okHttpClientBuilder, ProcessContext context) {
|
||||||
|
|
Loading…
Reference in New Issue