2 * Copyright (C) The Arvados Authors. All rights reserved.
4 * SPDX-License-Identifier: AGPL-3.0 OR Apache-2.0
8 package org.arvados.client.api.client.factory;
10 import com.google.common.base.Suppliers;
11 import okhttp3.OkHttpClient;
12 import org.arvados.client.exception.ArvadosClientException;
13 import org.slf4j.Logger;
15 import javax.net.ssl.SSLContext;
16 import javax.net.ssl.SSLSocketFactory;
17 import javax.net.ssl.TrustManager;
18 import javax.net.ssl.X509TrustManager;
19 import java.security.KeyManagementException;
20 import java.security.NoSuchAlgorithmException;
21 import java.security.SecureRandom;
22 import java.security.cert.X509Certificate;
23 import java.util.function.Supplier;
26 * {@link OkHttpClient} instance factory that builds and configures client instances sharing
27 * the common resource pool: this is the recommended approach to optimize resource usage.
29 public final class OkHttpClientFactory {
30 public static final OkHttpClientFactory INSTANCE = new OkHttpClientFactory();
31 private final Logger log = org.slf4j.LoggerFactory.getLogger(OkHttpClientFactory.class);
32 private final OkHttpClient clientSecure = new OkHttpClient();
33 private final Supplier<OkHttpClient> clientUnsecure =
34 Suppliers.memoize(this::getDefaultClientAcceptingAllCertificates);
36 private OkHttpClientFactory() { /* singleton */}
38 public OkHttpClient create(boolean apiHostInsecure) {
39 return apiHostInsecure ? getDefaultUnsecureClient() : getDefaultClient();
43 * @return default secure {@link OkHttpClient} with shared resource pool.
45 public OkHttpClient getDefaultClient() {
50 * @return default {@link OkHttpClient} with shared resource pool
51 * that will accept all SSL certificates by default.
53 public OkHttpClient getDefaultUnsecureClient() {
54 return clientUnsecure.get();
58 * @return default {@link OkHttpClient.Builder} with shared resource pool.
60 public OkHttpClient.Builder getDefaultClientBuilder() {
61 return clientSecure.newBuilder();
65 * @return default {@link OkHttpClient.Builder} with shared resource pool
66 * that is preconfigured to accept all SSL certificates.
68 public OkHttpClient.Builder getDefaultUnsecureClientBuilder() {
69 return clientUnsecure.get().newBuilder();
72 private OkHttpClient getDefaultClientAcceptingAllCertificates() {
73 log.warn("Creating unsafe OkHttpClient. All SSL certificates will be accepted.");
75 // Create a trust manager that does not validate certificate chains
76 final TrustManager[] trustAllCerts = {createX509TrustManager()};
78 // Install the all-trusting trust manager
79 SSLContext sslContext = SSLContext.getInstance("SSL");
80 sslContext.init(null, trustAllCerts, new SecureRandom());
81 // Create an ssl socket factory with our all-trusting manager
82 final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
84 // Create the OkHttpClient.Builder with shared resource pool
85 final OkHttpClient.Builder builder = clientSecure.newBuilder();
86 builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
87 builder.hostnameVerifier((hostname, session) -> true);
88 return builder.build();
89 } catch (NoSuchAlgorithmException | KeyManagementException e) {
90 throw new ArvadosClientException("Error establishing SSL context", e);
94 private static X509TrustManager createX509TrustManager() {
95 return new X509TrustManager() {
98 public void checkClientTrusted(X509Certificate[] chain, String authType) {
102 public void checkServerTrusted(X509Certificate[] chain, String authType) {
106 public X509Certificate[] getAcceptedIssuers() {
107 return new X509Certificate[]{};