Merge "Added support for using oauth token for Kafka"
[nonrtric/plt/ranpm.git] / datafilecollector / src / main / java / org / onap / dcaegen2 / collectors / 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.onap.dcaegen2.collectors.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.onap.dcaegen2.collectors.datafile.commons.SecurityUtil;
41 import org.onap.dcaegen2.collectors.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  * @author <a href="mailto:krzysztof.gajewski@nokia.com">Krzysztof Gajewski</a>
50  */
51 public class HttpsClientConnectionManagerUtil {
52
53     private HttpsClientConnectionManagerUtil() {
54     }
55
56     private static final Logger logger = LoggerFactory.getLogger(HttpsClientConnectionManagerUtil.class);
57     // Be aware to be less than ScheduledTasks.NUMBER_OF_WORKER_THREADS
58     private static final int MAX_NUMBER_OF_CONNECTIONS = 200;
59     private static PoolingHttpClientConnectionManager connectionManager;
60
61     public static PoolingHttpClientConnectionManager instance() throws DatafileTaskException {
62         if (connectionManager == null) {
63             throw new DatafileTaskException("ConnectionManager has to be set or update first");
64         }
65         return connectionManager;
66     }
67
68     public static void setupOrUpdate(String keyCertPath, String keyCertPasswordPath, String trustedCaPath,
69         String trustedCaPasswordPath, boolean useHostnameVerifier) throws DatafileTaskException {
70         synchronized (HttpsClientConnectionManagerUtil.class) {
71             if (connectionManager != null) {
72                 connectionManager.close();
73                 connectionManager = null;
74             }
75             setup(keyCertPath, keyCertPasswordPath, trustedCaPath, trustedCaPasswordPath, useHostnameVerifier);
76         }
77         logger.trace("HttpsConnectionManager setup or updated");
78     }
79
80     private static void setup(String keyCertPath, String keyCertPasswordPath, String trustedCaPath,
81         String trustedCaPasswordPath, boolean useHostnameVerifier) throws DatafileTaskException {
82         try {
83             SSLContextBuilder sslBuilder = SSLContexts.custom();
84             sslBuilder = supplyKeyInfo(keyCertPath, keyCertPasswordPath, sslBuilder);
85             if (!trustedCaPath.isEmpty()) {
86                 sslBuilder = supplyTrustInfo(trustedCaPath, trustedCaPasswordPath, sslBuilder);
87             }
88
89             SSLContext sslContext = sslBuilder.build();
90
91             HostnameVerifier hostnameVerifier =
92                 useHostnameVerifier ? new DefaultHostnameVerifier() : NoopHostnameVerifier.INSTANCE;
93
94             SSLConnectionSocketFactory sslConnectionSocketFactory =
95                 new SSLConnectionSocketFactory(sslContext, new String[] {"TLSv1.2"}, null, hostnameVerifier);
96
97             Registry<ConnectionSocketFactory> socketFactoryRegistry =
98                 RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslConnectionSocketFactory).build();
99
100             connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
101             connectionManager.setMaxTotal(MAX_NUMBER_OF_CONNECTIONS);
102
103         } catch (Exception e) {
104             throw new DatafileTaskException("Unable to prepare HttpsConnectionManager  : ", e);
105         }
106     }
107
108     private static SSLContextBuilder supplyKeyInfo(String keyCertPath, String keyCertPasswordPath,
109         SSLContextBuilder sslBuilder) throws IOException, KeyStoreException, NoSuchAlgorithmException,
110         CertificateException, UnrecoverableKeyException {
111         String keyPass = SecurityUtil.getKeystorePasswordFromFile(keyCertPasswordPath);
112         KeyStore keyFile = createKeyStore(keyCertPath, keyPass);
113         return sslBuilder.loadKeyMaterial(keyFile, keyPass.toCharArray());
114     }
115
116     private static KeyStore createKeyStore(String path, String storePassword)
117         throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
118         logger.trace("Creating manager from file: {}", path);
119         try (InputStream fis = createInputStream(path)) {
120             KeyStore keyStore = KeyStore.getInstance("PKCS12");
121             keyStore.load(fis, storePassword.toCharArray());
122             return keyStore;
123         }
124     }
125
126     private static InputStream createInputStream(String localFileName) throws IOException {
127         FileSystemResource realResource = new FileSystemResource(Paths.get(localFileName));
128         return realResource.getInputStream();
129     }
130
131     private static SSLContextBuilder supplyTrustInfo(String trustedCaPath, String trustedCaPasswordPath,
132         SSLContextBuilder sslBuilder)
133         throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException {
134         String trustPass = SecurityUtil.getTruststorePasswordFromFile(trustedCaPasswordPath);
135         File trustStoreFile = new File(trustedCaPath);
136         return sslBuilder.loadTrustMaterial(trustStoreFile, trustPass.toCharArray());
137     }
138 }