diff --git a/core/src/main/java/org/jclouds/Constants.java b/core/src/main/java/org/jclouds/Constants.java index 6c2143f589..b952fee4e2 100644 --- a/core/src/main/java/org/jclouds/Constants.java +++ b/core/src/main/java/org/jclouds/Constants.java @@ -375,6 +375,14 @@ public final class Constants { * Default value: 2 minutes. */ public static final String PROPERTY_MAX_RATE_LIMIT_WAIT = "jclouds.max-ratelimit-wait"; + + /** + * Boolean property. + *

+ * When true, the proxy server type is HTTPS i.e HTTP and SSL + * + */ + public static final String PROPERTY_PROXY_ENABLE_SSL_PROXY = "jclouds.enable-ssl-proxy"; private Constants() { throw new AssertionError("intentionally unimplemented"); diff --git a/core/src/main/java/org/jclouds/proxy/internal/GuiceProxyConfig.java b/core/src/main/java/org/jclouds/proxy/internal/GuiceProxyConfig.java index bc20f7a4b9..86121b2966 100644 --- a/core/src/main/java/org/jclouds/proxy/internal/GuiceProxyConfig.java +++ b/core/src/main/java/org/jclouds/proxy/internal/GuiceProxyConfig.java @@ -24,6 +24,7 @@ import static org.jclouds.Constants.PROPERTY_PROXY_PORT; import static org.jclouds.Constants.PROPERTY_PROXY_SYSTEM; import static org.jclouds.Constants.PROPERTY_PROXY_TYPE; import static org.jclouds.Constants.PROPERTY_PROXY_USER; +import static org.jclouds.Constants.PROPERTY_PROXY_ENABLE_SSL_PROXY; import java.net.Proxy; import java.net.Proxy.Type; @@ -69,6 +70,9 @@ public class GuiceProxyConfig implements ProxyConfig { @Inject(optional = true) @Named(PROPERTY_PROXY_TYPE) private Proxy.Type type = Proxy.Type.HTTP; + @Inject(optional = true) + @Named(PROPERTY_PROXY_ENABLE_SSL_PROXY) + private Boolean sslProxyEnabled = false; @Override public Optional getProxy() { @@ -117,6 +121,10 @@ public class GuiceProxyConfig implements ProxyConfig { public boolean isJvmProxyEnabled() { return jvmProxyEnabled; } + + public boolean isSslProxyEnabled() { + return sslProxyEnabled; + } /** * {@inheritDoc} diff --git a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/DelegatingSocketFactory.java b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/DelegatingSocketFactory.java new file mode 100644 index 0000000000..9d4a3089f6 --- /dev/null +++ b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/DelegatingSocketFactory.java @@ -0,0 +1,81 @@ +/* + * 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.jclouds.http.okhttp; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; + +import javax.net.SocketFactory; + +/** + * The {@code DelegatingSocketFactory} class delegates instance of + * SSLSocketFactory to SocketFactory. + * + *

+ * Note: + * {@link okhttp3.OkHttpClient.Builder#sslSocketFactory(javax.net.ssl.SSLSocketFactory)} + * method deprecated. + * + *

+ * Note: {@link okhttp3.OkHttpClient.Builder#socketFactory(SocketFactory)} + * method doesn't accept {@code javax.net.ssl.SSLSocketFactory.getDefault()} at + * runtime, throws {@code java.lang.IllegalArgumentException}. + * + */ +public class DelegatingSocketFactory extends SocketFactory { + private final SocketFactory delegate; + + public DelegatingSocketFactory(SocketFactory delegate) { + this.delegate = delegate; + } + + @Override + public Socket createSocket() throws IOException { + Socket socket = delegate.createSocket(); + return configureSocket(socket); + } + + @Override + public Socket createSocket(String host, int port) throws IOException { + Socket socket = delegate.createSocket(host, port); + return configureSocket(socket); + } + + @Override + public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException { + Socket socket = delegate.createSocket(host, port, localAddress, localPort); + return configureSocket(socket); + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + Socket socket = delegate.createSocket(host, port); + return configureSocket(socket); + } + + @Override + public Socket createSocket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException { + Socket socket = delegate.createSocket(host, port, localAddress, localPort); + return configureSocket(socket); + } + + protected Socket configureSocket(Socket socket) throws IOException { + // No-op by default. + return socket; + } +} diff --git a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java index d3144de57f..c9167028ea 100644 --- a/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java +++ b/drivers/okhttp/src/main/java/org/jclouds/http/okhttp/OkHttpCommandExecutorService.java @@ -31,6 +31,7 @@ import java.util.Map; import javax.annotation.Nullable; import javax.inject.Named; +import javax.net.ssl.SSLSocketFactory; import okhttp3.Authenticator; import okhttp3.Credentials; @@ -197,6 +198,10 @@ public final class OkHttpCommandExecutorService extends BaseHttpCommandExecutorS }; okHttpClientBuilder.proxyAuthenticator(proxyAuthenticator); } + + if (proxyConfig.isSslProxyEnabled()) { + okHttpClientBuilder.socketFactory(new DelegatingSocketFactory(SSLSocketFactory.getDefault())); + } OkHttpClient requestScopedClient = okHttpClientBuilder.build(); Response response = requestScopedClient.newCall(nativeRequest).execute();