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