966bf857c80b5ce24396245a13df43bb77c27763
[sdc.git] / common-app-api / src / main / java / org / openecomp / sdc / common / http / client / api / HttpConnectionMngFactory.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20 package org.openecomp.sdc.common.http.client.api;
21
22 import java.io.FileInputStream;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.security.GeneralSecurityException;
26 import java.security.KeyStore;
27 import java.util.Map;
28 import java.util.concurrent.ConcurrentHashMap;
29 import org.apache.commons.lang3.StringUtils;
30 import org.apache.http.config.Registry;
31 import org.apache.http.config.RegistryBuilder;
32 import org.apache.http.conn.HttpClientConnectionManager;
33 import org.apache.http.conn.socket.ConnectionSocketFactory;
34 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
35 import org.apache.http.conn.ssl.NoopHostnameVerifier;
36 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
37 import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
38 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
39 import org.apache.http.ssl.SSLContextBuilder;
40 import org.openecomp.sdc.common.api.Constants;
41 import org.openecomp.sdc.common.http.config.ClientCertificate;
42 import org.openecomp.sdc.common.log.wrappers.Logger;
43
44 public class HttpConnectionMngFactory {
45
46     private static final String P12_KEYSTORE_EXTENTION = ".p12";
47     private static final String PFX_KEYSTORE_EXTENTION = ".pfx";
48     private static final String JKS_KEYSTORE_EXTENTION = ".jks";
49     private static final String P12_KEYSTORE_TYPE = "pkcs12";
50     private static final String JKS_KEYSTORE_TYPE = "jks";
51     private static final Logger logger = Logger.getLogger(HttpConnectionMngFactory.class.getName());
52     private static final int DEFAULT_CONNECTION_POOL_SIZE = 30;
53     private static final int DEFAULT_MAX_CONNECTION_PER_ROUTE = 5;
54     private static final int VALIDATE_CONNECTION_AFTER_INACTIVITY_MS = 10000;
55     private Map<ClientCertificate, HttpClientConnectionManager> sslClientConnectionManagers = new ConcurrentHashMap<>();
56     private HttpClientConnectionManager plainClientConnectionManager;
57
58     HttpConnectionMngFactory() {
59         plainClientConnectionManager = createConnectionMng(null);
60     }
61
62     HttpClientConnectionManager getOrCreate(ClientCertificate clientCertificate) {
63         if (clientCertificate == null) {
64             return plainClientConnectionManager;
65         }
66         return sslClientConnectionManagers.computeIfAbsent(clientCertificate, k -> createConnectionMng(clientCertificate));
67     }
68
69     private HttpClientConnectionManager createConnectionMng(ClientCertificate clientCertificate) {
70         SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
71         SSLConnectionSocketFactory sslsf = null;
72         try {
73             sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy());
74             if (clientCertificate != null) {
75                 setClientSsl(clientCertificate, sslContextBuilder);
76             }
77             sslsf = new SSLConnectionSocketFactory(sslContextBuilder.build(), NoopHostnameVerifier.INSTANCE);
78         } catch (GeneralSecurityException e) {
79             logger.debug("Create SSL connection socket factory failed with exception, use default SSL factory ", e);
80             sslsf = SSLConnectionSocketFactory.getSocketFactory();
81         }
82         Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
83             .register(Constants.HTTP, PlainConnectionSocketFactory.getSocketFactory()).register(Constants.HTTPS, sslsf).build();
84         PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(registry);
85         manager.setMaxTotal(DEFAULT_CONNECTION_POOL_SIZE);
86         manager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTION_PER_ROUTE);
87         manager.setValidateAfterInactivity(VALIDATE_CONNECTION_AFTER_INACTIVITY_MS);
88         return manager;
89     }
90
91     private void setClientSsl(ClientCertificate clientCertificate, SSLContextBuilder sslContextBuilder) {
92         try {
93             char[] keyStorePassword = clientCertificate.getKeyStorePassword().toCharArray();
94             KeyStore clientKeyStore = createClientKeyStore(clientCertificate.getKeyStore(), keyStorePassword);
95             sslContextBuilder.loadKeyMaterial(clientKeyStore, keyStorePassword);
96             logger.debug("#setClientSsl - Set Client Certificate authentication");
97         } catch (IOException | GeneralSecurityException e) {
98             logger.debug("#setClientSsl - Set Client Certificate authentication failed with exception, diasable client SSL authentication ", e);
99         }
100     }
101
102     private KeyStore createClientKeyStore(String keyStorePath, char[] keyStorePassword) throws IOException, GeneralSecurityException {
103         KeyStore keyStore = null;
104         try (InputStream stream = new FileInputStream(keyStorePath)) {
105             keyStore = KeyStore.getInstance(getKeyStoreType(keyStorePath));
106             keyStore.load(stream, keyStorePassword);
107         }
108         return keyStore;
109     }
110
111     private String getKeyStoreType(String keyStore) {
112         if (!StringUtils.isEmpty(keyStore)) {
113             if (keyStore.endsWith(P12_KEYSTORE_EXTENTION) || keyStore.endsWith(PFX_KEYSTORE_EXTENTION)) {
114                 return P12_KEYSTORE_TYPE;
115             } else if (keyStore.endsWith(JKS_KEYSTORE_EXTENTION)) {
116                 return JKS_KEYSTORE_TYPE;
117             }
118         }
119         return KeyStore.getDefaultType();
120     }
121 }