Added oparent to sdc main
[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
21 package org.openecomp.sdc.common.http.client.api;
22
23 import org.apache.commons.lang3.StringUtils;
24 import org.apache.http.config.Registry;
25 import org.apache.http.config.RegistryBuilder;
26 import org.apache.http.conn.HttpClientConnectionManager;
27 import org.apache.http.conn.socket.ConnectionSocketFactory;
28 import org.apache.http.conn.socket.PlainConnectionSocketFactory;
29 import org.apache.http.conn.ssl.NoopHostnameVerifier;
30 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
31 import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
32 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
33 import org.apache.http.ssl.SSLContextBuilder;
34 import org.openecomp.sdc.common.api.Constants;
35 import org.openecomp.sdc.common.http.config.ClientCertificate;
36 import org.openecomp.sdc.common.log.wrappers.Logger;
37
38 import java.io.FileInputStream;
39 import java.io.IOException;
40 import java.io.InputStream;
41 import java.security.GeneralSecurityException;
42 import java.security.KeyStore;
43 import java.util.Map;
44 import java.util.concurrent.ConcurrentHashMap;
45
46 public class HttpConnectionMngFactory {
47
48     private static final String P12_KEYSTORE_EXTENTION = ".p12";
49     private static final String PFX_KEYSTORE_EXTENTION = ".pfx";
50     private static final String JKS_KEYSTORE_EXTENTION = ".jks";
51     
52     private static final String P12_KEYSTORE_TYPE = "pkcs12";
53     private static final String JKS_KEYSTORE_TYPE = "jks";
54     
55     private static final Logger logger = Logger.getLogger(HttpConnectionMngFactory.class.getName());
56     private static final int DEFAULT_CONNECTION_POOL_SIZE = 30;
57     private static final int DEFAULT_MAX_CONNECTION_PER_ROUTE = 5;
58     private static final int VALIDATE_CONNECTION_AFTER_INACTIVITY_MS = 10000;
59     
60     private Map<ClientCertificate, HttpClientConnectionManager> sslClientConnectionManagers = new ConcurrentHashMap<>();
61     private HttpClientConnectionManager plainClientConnectionManager;
62     
63     HttpConnectionMngFactory() {
64         plainClientConnectionManager = createConnectionMng(null);
65     }
66
67     HttpClientConnectionManager getOrCreate(ClientCertificate clientCertificate) {
68         if(clientCertificate == null) {
69             return plainClientConnectionManager;
70         }
71         return sslClientConnectionManagers.computeIfAbsent(clientCertificate, k -> createConnectionMng(clientCertificate));
72     }
73     
74     private HttpClientConnectionManager createConnectionMng(ClientCertificate clientCertificate) {
75
76         SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
77         SSLConnectionSocketFactory sslsf = null;
78         try {
79             sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy());
80             
81             if(clientCertificate != null) {
82                 setClientSsl(clientCertificate, sslContextBuilder);
83             }
84             sslsf = new SSLConnectionSocketFactory(sslContextBuilder.build(), NoopHostnameVerifier.INSTANCE);
85         }
86         catch (GeneralSecurityException e) {
87             logger.debug("Create SSL connection socket factory failed with exception, use default SSL factory ", e);
88             sslsf = SSLConnectionSocketFactory.getSocketFactory();
89         }
90
91         Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
92                 .register(Constants.HTTP, PlainConnectionSocketFactory.getSocketFactory())
93                 .register(Constants.HTTPS, sslsf).build();
94
95         PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(registry);
96
97         manager.setMaxTotal(DEFAULT_CONNECTION_POOL_SIZE);
98         manager.setDefaultMaxPerRoute(DEFAULT_MAX_CONNECTION_PER_ROUTE);
99         manager.setValidateAfterInactivity(VALIDATE_CONNECTION_AFTER_INACTIVITY_MS);
100
101         return manager;
102     }
103
104     private void setClientSsl(ClientCertificate clientCertificate, SSLContextBuilder sslContextBuilder) {
105         try {
106             char[] keyStorePassword = clientCertificate.getKeyStorePassword().toCharArray();
107             KeyStore clientKeyStore = createClientKeyStore(clientCertificate.getKeyStore(), keyStorePassword);
108             sslContextBuilder.loadKeyMaterial(clientKeyStore, keyStorePassword);
109             logger.debug("#setClientSsl - Set Client Certificate authentication");
110         }
111         catch (IOException | GeneralSecurityException e) {
112             logger.debug("#setClientSsl - Set Client Certificate authentication failed with exception, diasable client SSL authentication ", e);
113         }
114     }
115         
116     private KeyStore createClientKeyStore(String keyStorePath, char[] keyStorePassword) throws IOException, GeneralSecurityException {
117         KeyStore keyStore = null;
118         try (InputStream stream = new FileInputStream(keyStorePath)) {
119             keyStore = KeyStore.getInstance(getKeyStoreType(keyStorePath));
120             keyStore.load(stream, keyStorePassword);
121         }
122         return keyStore;
123     }
124     
125     private String getKeyStoreType(String keyStore) {
126         if(!StringUtils.isEmpty(keyStore)) {
127             if(keyStore.endsWith(P12_KEYSTORE_EXTENTION) || keyStore.endsWith(PFX_KEYSTORE_EXTENTION)) {
128                 return P12_KEYSTORE_TYPE;
129             }
130             else if(keyStore.endsWith(JKS_KEYSTORE_EXTENTION)) {
131                 return JKS_KEYSTORE_TYPE;
132             }            
133         }
134         return KeyStore.getDefaultType();
135     }
136 }