Merge "Added support for using oauth token for Kafka"
[nonrtric/plt/ranpm.git] / datafilecollector / src / main / java / org / oran / datafile / http / HttpsClientConnectionManagerUtil.java
1 /*-
2  * ============LICENSE_START======================================================================
3  * Copyright (C) 2021 Nokia. All rights reserved.
4  * ===============================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
6  * in compliance with the License. You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software distributed under the License
11  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12  * or implied. See the License for the specific language governing permissions and limitations under
13  * the License.
14  * ============LICENSE_END========================================================================
15  */
16 package org.oran.datafile.http;
17
18 import java.io.File;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.nio.file.Paths;
22 import java.security.KeyStore;
23 import java.security.KeyStoreException;
24 import java.security.NoSuchAlgorithmException;
25 import java.security.UnrecoverableKeyException;
26 import java.security.cert.CertificateException;
27
28 import javax.net.ssl.HostnameVerifier;
29 import javax.net.ssl.SSLContext;
30
31 import org.apache.http.config.Registry;
32 import org.apache.http.config.RegistryBuilder;
33 import org.apache.http.conn.socket.ConnectionSocketFactory;
34 import org.apache.http.conn.ssl.DefaultHostnameVerifier;
35 import org.apache.http.conn.ssl.NoopHostnameVerifier;
36 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
37 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
38 import org.apache.http.ssl.SSLContextBuilder;
39 import org.apache.http.ssl.SSLContexts;
40 import org.oran.datafile.commons.SecurityUtil;
41 import org.oran.datafile.exceptions.DatafileTaskException;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.springframework.core.io.FileSystemResource;
45
46 /**
47  * Utility class supplying connection manager for HTTPS protocol.
48  *
49  */
50 public class HttpsClientConnectionManagerUtil {
51
52     private HttpsClientConnectionManagerUtil() {
53     }
54
55     private static final Logger logger = LoggerFactory.getLogger(HttpsClientConnectionManagerUtil.class);
56     // Be aware to be less than ScheduledTasks.NUMBER_OF_WORKER_THREADS
57     private static final int MAX_NUMBER_OF_CONNECTIONS = 200;
58     private static PoolingHttpClientConnectionManager connectionManager;
59
60     public static PoolingHttpClientConnectionManager instance() throws DatafileTaskException {
61         if (connectionManager == null) {
62             throw new DatafileTaskException("ConnectionManager has to be set or update first");
63         }
64         return connectionManager;
65     }
66
67     public static void setupOrUpdate(String keyCertPath, String keyCertPasswordPath, String trustedCaPath,
68         String trustedCaPasswordPath, boolean useHostnameVerifier) throws DatafileTaskException {
69         synchronized (HttpsClientConnectionManagerUtil.class) {
70             if (connectionManager != null) {
71                 connectionManager.close();
72                 connectionManager = null;
73             }
74             setup(keyCertPath, keyCertPasswordPath, trustedCaPath, trustedCaPasswordPath, useHostnameVerifier);
75         }
76         logger.trace("HttpsConnectionManager setup or updated");
77     }
78
79     private static void setup(String keyCertPath, String keyCertPasswordPath, String trustedCaPath,
80         String trustedCaPasswordPath, boolean useHostnameVerifier) throws DatafileTaskException {
81         try {
82             SSLContextBuilder sslBuilder = SSLContexts.custom();
83             sslBuilder = supplyKeyInfo(keyCertPath, keyCertPasswordPath, sslBuilder);
84             if (!trustedCaPath.isEmpty()) {
85                 sslBuilder = supplyTrustInfo(trustedCaPath, trustedCaPasswordPath, sslBuilder);
86             }
87
88             SSLContext sslContext = sslBuilder.build();
89
90             HostnameVerifier hostnameVerifier =
91                 useHostnameVerifier ? new DefaultHostnameVerifier() : NoopHostnameVerifier.INSTANCE;
92
93             SSLConnectionSocketFactory sslConnectionSocketFactory =
94                 new SSLConnectionSocketFactory(sslContext, new String[] {"TLSv1.2"}, null, hostnameVerifier);
95
96             Registry<ConnectionSocketFactory> socketFactoryRegistry =
97                 RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslConnectionSocketFactory).build();
98
99             connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
100             connectionManager.setMaxTotal(MAX_NUMBER_OF_CONNECTIONS);
101
102         } catch (Exception e) {
103             throw new DatafileTaskException("Unable to prepare HttpsConnectionManager  : ", e);
104         }
105     }
106
107     private static SSLContextBuilder supplyKeyInfo(String keyCertPath, String keyCertPasswordPath,
108         SSLContextBuilder sslBuilder) throws IOException, KeyStoreException, NoSuchAlgorithmException,
109         CertificateException, UnrecoverableKeyException {
110         String keyPass = SecurityUtil.getKeystorePasswordFromFile(keyCertPasswordPath);
111         KeyStore keyFile = createKeyStore(keyCertPath, keyPass);
112         return sslBuilder.loadKeyMaterial(keyFile, keyPass.toCharArray());
113     }
114
115     private static KeyStore createKeyStore(String path, String storePassword)
116         throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
117         logger.trace("Creating manager from file: {}", path);
118         try (InputStream fis = createInputStream(path)) {
119             KeyStore keyStore = KeyStore.getInstance("PKCS12");
120             keyStore.load(fis, storePassword.toCharArray());
121             return keyStore;
122         }
123     }
124
125     private static InputStream createInputStream(String localFileName) throws IOException {
126         FileSystemResource realResource = new FileSystemResource(Paths.get(localFileName));
127         return realResource.getInputStream();
128     }
129
130     private static SSLContextBuilder supplyTrustInfo(String trustedCaPath, String trustedCaPasswordPath,
131         SSLContextBuilder sslBuilder)
132         throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException {
133         String trustPass = SecurityUtil.getTruststorePasswordFromFile(trustedCaPasswordPath);
134         File trustStoreFile = new File(trustedCaPath);
135         return sslBuilder.loadTrustMaterial(trustStoreFile, trustPass.toCharArray());
136     }
137 }