diff options
Diffstat (limited to 'pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils')
7 files changed, 270 insertions, 126 deletions
diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java new file mode 100644 index 0000000..e0b8cc2 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/CertificateReader.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.GeneralSecurityException; +import java.security.KeyStore; + +class CertificateReader { + + KeyStore read(String certificate, String password, String type) throws GeneralSecurityException, IOException { + try (InputStream keyStoreStream = new FileInputStream(certificate)) { + KeyStore keyStore = KeyStore.getInstance(type); + keyStore.load(keyStoreStream, PasswordConverter.convert(password)); + return keyStore; + } + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java new file mode 100644 index 0000000..ca57a64 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactory.java @@ -0,0 +1,104 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import io.vavr.control.Try; +import org.apache.http.client.HttpClient; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.HttpClients; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; + +class HttpClientFactory { + private static final int CONNECTION_TIMEOUT = 1000; + private static final RequestConfig CONFIG = RequestConfig.custom() + .setConnectTimeout(CONNECTION_TIMEOUT) + .setConnectionRequestTimeout(CONNECTION_TIMEOUT) + .setSocketTimeout(CONNECTION_TIMEOUT) + .build(); + private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientFactory.class); + private final SSLContextFactory sslContextFactory; + + HttpClientFactory(SSLContextFactory sslContextFactory) { + this.sslContextFactory = sslContextFactory; + } + + HttpClient create(String url, SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException { + HttpClient client; + if (!sslAuthenticationHelper.isClientCertificateEnabled()) { + client = "https".equals(new URL(url).getProtocol()) ? createForHttps() : createBasic(); + } else if (sslAuthenticationHelper.isStrictHostnameVerification()) { + client = createSecured(sslContextFactory.create(sslAuthenticationHelper), new DefaultHostnameVerifier()); + } else { + client = createSecured(sslContextFactory.create(sslAuthenticationHelper), new NoopHostnameVerifier()); + } + return client; + } + + private HttpClient createForHttps() { + return Try.of(this::createSecuredTrustAlways) + .onFailure(this::logErrorMessage) + .getOrElse(createBasic()); + } + + private void logErrorMessage(Throwable e) { + String message = String.format( + "Could not initialize client due to SSL exception: %s. " + + "Default client without SSL support will be used instead." + + "\nCause: %s", + e.getMessage(), + e.getCause() + ); + LOGGER.error(message, e); + } + + + private HttpClient createBasic() { + return HttpClientBuilder + .create() + .setDefaultRequestConfig(CONFIG) + .build(); + } + + private HttpClient createSecuredTrustAlways() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { + return createSecured(sslContextFactory.createTrustAlways(), new NoopHostnameVerifier()); + } + + private HttpClient createSecured(SSLContext trustAlways, HostnameVerifier hostnameVerifier) { + return HttpClients.custom() + .setSSLContext(trustAlways) + .setDefaultRequestConfig(CONFIG) + .setSSLHostnameVerifier(hostnameVerifier) + .build(); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java new file mode 100644 index 0000000..521b584 --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/HttpClientFactoryFacade.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import org.apache.http.client.HttpClient; + +import java.io.IOException; +import java.security.GeneralSecurityException; + +public class HttpClientFactoryFacade { + + private HttpClientFactoryFacade() { + } + + private static final CertificateReader CERTIFICATE_READER = new CertificateReader(); + private static final SSLContextFactory SSL_CONTEXT_FACTORY = new SSLContextFactory(CERTIFICATE_READER); + private static final HttpClientFactory HTTP_CLIENT_FACTORY = new HttpClientFactory(SSL_CONTEXT_FACTORY); + + public static HttpClient create(String url, SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException { + return HTTP_CLIENT_FACTORY.create(url, sslAuthenticationHelper); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java new file mode 100644 index 0000000..7a645ae --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/PasswordConverter.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import java.util.Optional; + +class PasswordConverter { + private PasswordConverter() { + } + + static char[] convert(String password) { + return Optional.ofNullable(password).map(String::toCharArray).orElse(null); + } +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java new file mode 100644 index 0000000..c4839fb --- /dev/null +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SSLContextFactory.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2020 Nokia. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +package org.onap.pnfsimulator.simulator.client.utils.ssl; + +import org.apache.http.conn.ssl.TrustAllStrategy; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.conn.ssl.TrustStrategy; +import org.apache.http.ssl.SSLContextBuilder; +import org.apache.http.ssl.SSLContexts; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; + +class SSLContextFactory { + private static final TrustStrategy TRUST_STRATEGY_ALWAYS = new TrustAllStrategy(); + + private final CertificateReader certificateReader; + + SSLContextFactory(CertificateReader certificateReader) { + this.certificateReader = certificateReader; + } + SSLContext create(SslAuthenticationHelper sslAuthenticationHelper) throws GeneralSecurityException, IOException { + return SSLContexts.custom() + .loadKeyMaterial(certificateReader.read(sslAuthenticationHelper.getClientCertificateDir(), sslAuthenticationHelper.getClientCertificatePassword(), "PKCS12"), PasswordConverter.convert(sslAuthenticationHelper.getClientCertificatePassword())) + .loadTrustMaterial(certificateReader.read(sslAuthenticationHelper.getTrustStoreDir(), sslAuthenticationHelper.getTrustStorePassword(), "JKS"), new TrustSelfSignedStrategy()) + .build(); + } + + SSLContext createTrustAlways() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException { + return SSLContextBuilder.create().loadTrustMaterial(TRUST_STRATEGY_ALWAYS).build(); + } + +} diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java index 1887d37..b785be6 100644 --- a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java +++ b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslAuthenticationHelper.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * PNF-REGISTRATION-HANDLER * ================================================================================ - * Copyright (C) 2019 Nokia. All rights reserved. + * Copyright (C) 2020 Nokia. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ import org.springframework.stereotype.Component; public class SslAuthenticationHelper implements Serializable { private boolean clientCertificateEnabled; + private boolean strictHostnameVerification; private String clientCertificateDir; private String clientCertificatePassword; private String trustStoreDir; diff --git a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevel.java b/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevel.java deleted file mode 100644 index fb3b958..0000000 --- a/pnfsimulator/src/main/java/org/onap/pnfsimulator/simulator/client/utils/ssl/SslSupportLevel.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * PNF-REGISTRATION-HANDLER - * ================================================================================ - * Copyright (C) 2018 Nokia. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END========================================================= - */ - -package org.onap.pnfsimulator.simulator.client.utils.ssl; - -import org.apache.http.client.HttpClient; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.TrustAllStrategy; -import org.apache.http.conn.ssl.TrustSelfSignedStrategy; -import org.apache.http.conn.ssl.TrustStrategy; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.ssl.SSLContextBuilder; -import org.apache.http.ssl.SSLContexts; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.net.ssl.SSLContext; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.util.Optional; - -public enum SslSupportLevel { - - NONE { - public HttpClient getClient(RequestConfig requestConfig, SslAuthenticationHelper sslAuthenticationHelper) { - LOGGER.info("<!-----IN SslSupportLevel.NONE, Creating BasicHttpClient for http protocol----!>"); - return HttpClientBuilder - .create() - .setDefaultRequestConfig(requestConfig) - .build(); - } - }, - ALWAYS_TRUST { - public HttpClient getClient(RequestConfig requestConfig, SslAuthenticationHelper sslAuthenticationHelper) - throws GeneralSecurityException, IOException { - LoggerFactory.getLogger(SslSupportLevel.class).info("<!-----IN SslSupportLevel.ALWAYS_TRUST, Creating client with SSL support for https protocol----!>"); - HttpClient client; - try { - SSLContext alwaysTrustSslContext = SSLContextBuilder.create().loadTrustMaterial(TRUST_STRATEGY_ALWAYS).build(); - client = HttpClients.custom() - .setSSLContext(alwaysTrustSslContext) - .setSSLHostnameVerifier(new NoopHostnameVerifier()) - .setDefaultRequestConfig(requestConfig) - .build(); - - } catch (GeneralSecurityException e) { - String errorMessage = - String.format( - "Could not initialize client due to SSL exception: %s. " + - "Default client without SSL support will be used instead." + - "\nCause: %s", - e.getMessage(), - e.getCause() - ); - LOGGER.error(errorMessage, e); - client = NONE.getClient(requestConfig, sslAuthenticationHelper); - } - return client; - } - }, - CLIENT_CERT_AUTH { - @Override - public HttpClient getClient(RequestConfig requestConfig, SslAuthenticationHelper sslAuthenticationHelper) - throws GeneralSecurityException, IOException { - - SSLContext sslContext = SSLContexts.custom() - .loadKeyMaterial(readCertificate(sslAuthenticationHelper.getClientCertificateDir(), sslAuthenticationHelper.getClientCertificatePassword(), "PKCS12"), getPasswordAsCharArray(sslAuthenticationHelper.getClientCertificatePassword())) - .loadTrustMaterial(readCertificate(sslAuthenticationHelper.getTrustStoreDir(), sslAuthenticationHelper.getTrustStorePassword(), "JKS"), new TrustSelfSignedStrategy()) - .build(); - - return HttpClients.custom() - .setSSLContext(sslContext) - .setSSLHostnameVerifier(new NoopHostnameVerifier()) - .setDefaultRequestConfig(requestConfig) - .build(); - } - - private KeyStore readCertificate(String certificate, String password, String type) throws GeneralSecurityException, IOException { - try (InputStream keyStoreStream = new FileInputStream(certificate)) { - KeyStore keyStore = KeyStore.getInstance(type); - keyStore.load(keyStoreStream, getPasswordAsCharArray(password)); - return keyStore; - } - } - - private char[] getPasswordAsCharArray(String clientCertificatePassword) { - return Optional.ofNullable(clientCertificatePassword).map(String::toCharArray).orElse(null); - } - }; - - private static final Logger LOGGER = LoggerFactory.getLogger(SslSupportLevel.class); - private static final TrustStrategy TRUST_STRATEGY_ALWAYS = new TrustAllStrategy(); - - public static SslSupportLevel getSupportLevelBasedOnProtocol(String url) throws MalformedURLException { - return "https".equals(new URL(url).getProtocol()) ? SslSupportLevel.ALWAYS_TRUST : SslSupportLevel.NONE; - } - - public abstract HttpClient getClient(RequestConfig config, SslAuthenticationHelper sslAuthenticationHelper) - throws GeneralSecurityException, IOException; - -} |