PageRenderTime 32ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ConfigurableRestSource/configurable-rest-source/src/main/java/com/davis/ddf/crs/client/TrustSpecifiedOkHttpClient.java

https://gitlab.com/samuel-davis/DDF-TestSource
Java | 301 lines | 163 code | 20 blank | 118 comment | 10 complexity | e1513957c0e8ba2339518ee214a70a07 MD5 | raw file
  1. package com.davis.ddf.crs.client;
  2. import java.io.File;
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.io.SequenceInputStream;
  6. import java.nio.charset.Charset;
  7. import java.nio.charset.StandardCharsets;
  8. import java.nio.file.Files;
  9. import java.nio.file.Path;
  10. import java.nio.file.Paths;
  11. import java.security.GeneralSecurityException;
  12. import java.security.KeyStore;
  13. import java.security.cert.Certificate;
  14. import java.security.cert.CertificateFactory;
  15. import java.util.ArrayList;
  16. import java.util.Arrays;
  17. import java.util.Collection;
  18. import java.util.concurrent.TimeUnit;
  19. import javax.net.ssl.KeyManagerFactory;
  20. import javax.net.ssl.SSLContext;
  21. import javax.net.ssl.SSLSocketFactory;
  22. import javax.net.ssl.TrustManager;
  23. import javax.net.ssl.TrustManagerFactory;
  24. import javax.net.ssl.X509TrustManager;
  25. import okhttp3.CertificatePinner;
  26. import okhttp3.OkHttpClient;
  27. import okio.Buffer;
  28. import org.slf4j.Logger;
  29. import org.slf4j.LoggerFactory;
  30. /**
  31. * Class to create a custom Okhttp client that only trusts the specified certificates.
  32. *
  33. * **/
  34. public final class TrustSpecifiedOkHttpClient {
  35. private static final String ROOT_FILE_PATH="certs/";
  36. private static final Logger logger = LoggerFactory.getLogger(TrustSpecifiedOkHttpClient.class.getName());
  37. private OkHttpClient client;
  38. /**
  39. * Public constructor, this constructor will created a TrustSpecified client that only trusts the
  40. * certificates it is given.
  41. * The certificates must be located within the Jar's resources directory
  42. * @param pathToJarResources a list of absolute paths leading to jar resources
  43. * These certificates must be in PEM
  44. * **/
  45. public TrustSpecifiedOkHttpClient(String[] pathToJarResources,int connectTimeout, int readTimeout) {
  46. X509TrustManager trustManager;
  47. SSLSocketFactory sslSocketFactory;
  48. InputStream inputStream = createInputStreamFromFiles(pathToJarResources);
  49. try {
  50. trustManager = trustManagerForCertificates(inputStream);
  51. SSLContext sslContext = SSLContext.getInstance("TLS");
  52. sslContext.init(null,
  53. new TrustManager[] {trustManager},
  54. null
  55. );
  56. sslSocketFactory = sslContext.getSocketFactory();
  57. } catch (GeneralSecurityException e) {
  58. throw new RuntimeException(e);
  59. }
  60. OkHttpClient.Builder builder = new OkHttpClient.Builder();
  61. builder.connectTimeout(connectTimeout, TimeUnit.SECONDS);
  62. builder.readTimeout(readTimeout, TimeUnit.SECONDS);
  63. builder.sslSocketFactory(sslSocketFactory, trustManager);
  64. client = builder.build();
  65. }
  66. /**
  67. * Creates a custom okhttp client where all certificates within the jar resources folder cert
  68. * are trusted. This is a convenience method so you dont have to pass a array of file paths.
  69. * **/
  70. public TrustSpecifiedOkHttpClient(boolean useCertFolder,int connectTimeout, int readTimeout) {
  71. if(!useCertFolder){
  72. return;
  73. }
  74. X509TrustManager trustManager;
  75. SSLSocketFactory sslSocketFactory;
  76. ArrayList<String> certArray = getCertDirectoryFileNames();
  77. String[] certNames = new String[certArray.size()];
  78. certNames = certArray.toArray(certNames);
  79. InputStream inputStream = createInputStreamFromFiles(certNames);
  80. try {
  81. trustManager = trustManagerForCertificates(inputStream);
  82. SSLContext sslContext = SSLContext.getInstance("TLS");
  83. sslContext.init(null,
  84. new TrustManager[] {trustManager},
  85. null
  86. );
  87. sslSocketFactory = sslContext.getSocketFactory();
  88. } catch (GeneralSecurityException e) {
  89. throw new RuntimeException(e);
  90. }
  91. OkHttpClient.Builder builder = new OkHttpClient.Builder();
  92. builder.connectTimeout(connectTimeout, TimeUnit.SECONDS);
  93. builder.readTimeout(readTimeout, TimeUnit.SECONDS);
  94. builder.sslSocketFactory(sslSocketFactory, trustManager);
  95. client = builder.build();
  96. }
  97. private InputStream createInputStreamFromFiles(String[] pathToJarResources){
  98. ArrayList<String> certArray = new ArrayList<>();
  99. for(String cert : pathToJarResources){
  100. String crtFromFile =readFile(cert,StandardCharsets.UTF_8);
  101. certArray.add(crtFromFile);
  102. logger.debug(crtFromFile);
  103. }
  104. return trustedCertificatesInputStream(certArray);
  105. }
  106. public OkHttpClient getClient() {
  107. return client;
  108. }
  109. private ArrayList<String> getCertDirectoryFileNames(){
  110. File f=new File(ROOT_FILE_PATH);
  111. File[] allSubFiles=f.listFiles();
  112. ArrayList<String> certNames = new ArrayList<String>();
  113. for(File file : allSubFiles) {
  114. certNames.add(file.getName());
  115. }
  116. return certNames;
  117. }
  118. /**Reads a
  119. * @param path the file to be read
  120. * into a string with the
  121. * @param encoding the specified encoding
  122. * @return the encoded string.
  123. **/
  124. private static String readFile(String path, Charset encoding)
  125. {
  126. String result = null;
  127. byte[] encoded = new byte[0];
  128. try {
  129. encoded = TrustSpecifiedOkHttpClient.class.getClassLoader().getResource(path).getFile().getBytes();
  130. } catch (Exception e) {
  131. e.printStackTrace();
  132. }
  133. if(encoded.length < 1){
  134. result ="";
  135. }else{
  136. result = new String(encoded,encoding);
  137. }
  138. return result;
  139. }
  140. /**
  141. * Reads a array list of cert strings into a single input stream.
  142. * @param certificates the cert strings to read
  143. * @return a inputstream containing them all
  144. * **/
  145. private InputStream trustedCertificatesInputStream(ArrayList<String> certificates) {
  146. Buffer buffer = new Buffer();
  147. for(String certString : certificates){
  148. buffer.writeUtf8(certString);
  149. }
  150. return buffer.inputStream();
  151. }
  152. /**
  153. * Returns a trust manager that trusts {@code certificates} and none other. HTTPS services whose
  154. * certificates have not been signed by these certificates will fail with a {@code
  155. * SSLHandshakeException}.
  156. *
  157. * <p>This can be used to replace the host platform's built-in trusted certificates with a custom
  158. * set. This is useful in development where certificate authority-trusted certificates aren't
  159. * available. Or in production, to avoid reliance on third-party certificate authorities.
  160. *
  161. * <p>See also {@link CertificatePinner}, which can limit trusted certificates while still using
  162. * the host platform's built-in trust store.
  163. *
  164. * <h3>Warning: Customizing Trusted Certificates is Dangerous!</h3>
  165. *
  166. * <p>Relying on your own trusted certificates limits your server team's ability to update their
  167. * TLS certificates. By installing a specific set of trusted certificates, you take on additional
  168. * operational complexity and limit your ability to migrate between certificate authorities. Do
  169. * not use custom trusted certificates in production without the blessing of your server's TLS
  170. * administrator.
  171. */
  172. private X509TrustManager trustManagerForCertificates(InputStream in)
  173. throws GeneralSecurityException {
  174. CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
  175. Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);
  176. if (certificates.isEmpty()) {
  177. throw new IllegalArgumentException("expected non-empty set of trusted certificates");
  178. }
  179. // Put the certificates a key store.
  180. char[] password = "password".toCharArray(); // Any password will work.
  181. KeyStore keyStore = newEmptyKeyStore(password);
  182. int index = 0;
  183. for (Certificate certificate : certificates) {
  184. String certificateAlias = Integer.toString(index++);
  185. keyStore.setCertificateEntry(certificateAlias, certificate);
  186. }
  187. // Use it to build an X509 trust manager.
  188. KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
  189. KeyManagerFactory.getDefaultAlgorithm());
  190. keyManagerFactory.init(keyStore, password);
  191. TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
  192. TrustManagerFactory.getDefaultAlgorithm());
  193. trustManagerFactory.init(keyStore);
  194. TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
  195. if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
  196. throw new IllegalStateException("Unexpected default trust managers:"
  197. + Arrays.toString(trustManagers));
  198. }
  199. return (X509TrustManager) trustManagers[0];
  200. }
  201. private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
  202. try {
  203. KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
  204. InputStream in = null; // By convention, 'null' creates an empty key store.
  205. keyStore.load(in, password);
  206. return keyStore;
  207. } catch (IOException e) {
  208. throw new AssertionError(e);
  209. }
  210. }
  211. /*Keeping these for convenience purposes
  212. *
  213. * // PEM files for root certificates of Comodo and Entrust. These two CAs are sufficient to view
  214. // https://publicobject.com (Comodo) and https://squareup.com (Entrust). But they aren't
  215. // sufficient to connect to most HTTPS sites including https://godaddy.com and https://visa.com.
  216. // Typically developers will need to get a PEM file from their organization's TLS administrator.
  217. *
  218. * String comodoRsaCertificationAuthority = ""
  219. + "-----BEGIN CERTIFICATE-----\n"
  220. + "MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB\n"
  221. + "hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G\n"
  222. + "A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV\n"
  223. + "BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5\n"
  224. + "MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT\n"
  225. + "EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR\n"
  226. + "Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh\n"
  227. + "dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR\n"
  228. + "6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X\n"
  229. + "pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC\n"
  230. + "9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV\n"
  231. + "/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf\n"
  232. + "Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z\n"
  233. + "+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w\n"
  234. + "qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah\n"
  235. + "SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC\n"
  236. + "u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf\n"
  237. + "Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq\n"
  238. + "crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E\n"
  239. + "FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB\n"
  240. + "/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl\n"
  241. + "wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM\n"
  242. + "4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV\n"
  243. + "2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna\n"
  244. + "FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ\n"
  245. + "CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK\n"
  246. + "boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke\n"
  247. + "jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL\n"
  248. + "S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb\n"
  249. + "QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl\n"
  250. + "0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB\n"
  251. + "NVOFBkpdn627G190\n"
  252. + "-----END CERTIFICATE-----\n";
  253. String entrustRootCertificateAuthority = ""
  254. + "-----BEGIN CERTIFICATE-----\n"
  255. + "MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC\n"
  256. + "VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0\n"
  257. + "Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW\n"
  258. + "KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl\n"
  259. + "cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw\n"
  260. + "NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw\n"
  261. + "NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy\n"
  262. + "ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV\n"
  263. + "BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ\n"
  264. + "KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo\n"
  265. + "Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4\n"
  266. + "4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9\n"
  267. + "KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI\n"
  268. + "rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi\n"
  269. + "94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB\n"
  270. + "sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi\n"
  271. + "gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo\n"
  272. + "kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE\n"
  273. + "vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA\n"
  274. + "A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t\n"
  275. + "O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua\n"
  276. + "AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP\n"
  277. + "9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/\n"
  278. + "eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m\n"
  279. + "0vdXcDazv/wor3ElhVsT/h5/WrQ8\n"
  280. + "-----END CERTIFICATE-----\n";*/
  281. }