21700: Install Bundler system-wide in Rails postinst
[arvados.git] / sdk / java-v2 / src / main / java / org / arvados / client / api / client / factory / OkHttpClientFactory.java
1 /*
2  * Copyright (C) The Arvados Authors. All rights reserved.
3  *
4  * SPDX-License-Identifier: AGPL-3.0 OR Apache-2.0
5  *
6  */
7
8 package org.arvados.client.api.client.factory;
9
10 import com.google.common.base.Suppliers;
11 import okhttp3.OkHttpClient;
12 import org.arvados.client.exception.ArvadosClientException;
13 import org.slf4j.Logger;
14
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;
24
25 /**
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.
28  */
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);
35
36     private OkHttpClientFactory() { /* singleton */}
37
38     public OkHttpClient create(boolean apiHostInsecure) {
39         return apiHostInsecure ? getDefaultUnsecureClient() : getDefaultClient();
40     }
41
42     /**
43      * @return default secure {@link OkHttpClient} with shared resource pool.
44      */
45     public OkHttpClient getDefaultClient() {
46         return clientSecure;
47     }
48
49     /**
50      * @return default {@link OkHttpClient} with shared resource pool
51      * that will accept all SSL certificates by default.
52      */
53     public OkHttpClient getDefaultUnsecureClient() {
54         return clientUnsecure.get();
55     }
56
57     /**
58      * @return default {@link OkHttpClient.Builder} with shared resource pool.
59      */
60     public OkHttpClient.Builder getDefaultClientBuilder() {
61         return clientSecure.newBuilder();
62     }
63
64     /**
65      * @return default {@link OkHttpClient.Builder} with shared resource pool
66      * that is preconfigured to accept all SSL certificates.
67      */
68     public OkHttpClient.Builder getDefaultUnsecureClientBuilder() {
69         return clientUnsecure.get().newBuilder();
70     }
71
72     private OkHttpClient getDefaultClientAcceptingAllCertificates() {
73         log.warn("Creating unsafe OkHttpClient. All SSL certificates will be accepted.");
74         try {
75             // Create a trust manager that does not validate certificate chains
76             final TrustManager[] trustAllCerts = {createX509TrustManager()};
77
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();
83
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);
91         }
92     }
93
94     private static X509TrustManager createX509TrustManager() {
95         return new X509TrustManager() {
96
97             @Override
98             public void checkClientTrusted(X509Certificate[] chain, String authType) {
99             }
100
101             @Override
102             public void checkServerTrusted(X509Certificate[] chain, String authType) {
103             }
104
105             @Override
106             public X509Certificate[] getAcceptedIssuers() {
107                 return new X509Certificate[]{};
108             }
109         };
110     }
111 }