summaryrefslogtreecommitdiffstats
path: root/dcae-analytics/dcae-analytics-web/src/main/java/org/onap/dcae/analytics/web/http/HttpClientPreferencesCustomizer.java
diff options
context:
space:
mode:
Diffstat (limited to 'dcae-analytics/dcae-analytics-web/src/main/java/org/onap/dcae/analytics/web/http/HttpClientPreferencesCustomizer.java')
-rw-r--r--dcae-analytics/dcae-analytics-web/src/main/java/org/onap/dcae/analytics/web/http/HttpClientPreferencesCustomizer.java277
1 files changed, 277 insertions, 0 deletions
diff --git a/dcae-analytics/dcae-analytics-web/src/main/java/org/onap/dcae/analytics/web/http/HttpClientPreferencesCustomizer.java b/dcae-analytics/dcae-analytics-web/src/main/java/org/onap/dcae/analytics/web/http/HttpClientPreferencesCustomizer.java
new file mode 100644
index 0000000..c5f66be
--- /dev/null
+++ b/dcae-analytics/dcae-analytics-web/src/main/java/org/onap/dcae/analytics/web/http/HttpClientPreferencesCustomizer.java
@@ -0,0 +1,277 @@
+/*
+ * ================================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. 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.dcae.analytics.web.http;
+
+
+import java.io.IOException;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
+import org.apache.http.ssl.SSLContextBuilder;
+import org.onap.dcae.analytics.model.AnalyticsHttpConstants;
+import org.onap.dcae.analytics.model.util.function.StringToURLFunction;
+import org.onap.dcae.analytics.web.util.AnalyticsWebUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.web.client.RestTemplateCustomizer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.BufferingClientHttpRequestFactory;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.http.client.support.BasicAuthorizationInterceptor;
+import org.springframework.util.ReflectionUtils;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+
+/**
+ * Creates a {@link RestTemplateCustomizer} which can be used to configure the spring rest templates
+ * based on given {@link HttpClientPreferences}
+ *
+ * @param <T> Http Client Configurations
+ *
+ * @author Rajiv Singla
+ */
+public class HttpClientPreferencesCustomizer<T extends HttpClientPreferences> implements RestTemplateCustomizer {
+
+ private static final Logger logger = LoggerFactory.getLogger(HttpClientPreferencesCustomizer.class);
+
+ private final T httpClientConfig;
+
+ public HttpClientPreferencesCustomizer(final T httpClientConfig) {
+ this.httpClientConfig = httpClientConfig;
+ }
+
+ @Override
+ public void customize(final RestTemplate restTemplate) {
+
+ final String httpClientId = httpClientConfig.getHttpClientId() != null ? httpClientConfig.getHttpClientId()
+ : AnalyticsHttpConstants.DEFAULT_HTTP_CLIENT_ID_PREFIX + AnalyticsWebUtils.RANDOM_ID_SUPPLIER.get();
+ logger.debug("Customizing Rest Template for Http Client Id: {}", httpClientId);
+
+ // set request url
+ final URL requestURL = new StringToURLFunction().apply(httpClientConfig.getRequestURL())
+ .orElseThrow(() -> new IllegalArgumentException("Http Client URL is required"));
+ restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(requestURL.toString()));
+
+ // add basic authentication headers
+ final String username = httpClientConfig.getUsername();
+ if (username != null) {
+ restTemplate.getInterceptors().add(
+ new BasicAuthorizationInterceptor(username, httpClientConfig.getPassword()));
+ }
+
+ // set default request headers
+ final HttpHeaders defaultRequestHeaders = httpClientConfig.getRequestHeaders();
+ if (defaultRequestHeaders != null) {
+ restTemplate.getInterceptors().add(new DefaultHeadersRequestInterceptor(defaultRequestHeaders));
+ }
+
+ // create new http client builder
+ final HttpClientBuilder httpClientBuilder = HttpClients.custom().useSystemProperties()
+ .disableContentCompression();
+ final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+
+ // set basic authentication credentials
+ configureAuthenticationCredentials(httpClientId, requestURL, credentialsProvider);
+ // set up proxy url
+ configureProxySettings(httpClientId, httpClientBuilder, credentialsProvider);
+ // setup credentials provider
+ httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
+ // set up ssl Context
+ configureSSLContext(httpClientId, httpClientBuilder);
+
+ // set rest client builder
+ final HttpComponentsClientHttpRequestFactory httpRequestFactory =
+ new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
+
+ // set ecomp logging interceptor
+ if (httpClientConfig.getEnableEcompAuditLogging()) {
+ restTemplate.getInterceptors().add(new EelfAuditLogInterceptor(httpClientConfig));
+ }
+
+ restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(httpRequestFactory));
+ }
+
+ /**
+ * Configures authentication credentials
+ *
+ * @param httpClientId http client id
+ * @param requestURL request url
+ * @param credentialsProvider credentials provider
+ */
+ private void configureAuthenticationCredentials(final String httpClientId, final URL requestURL,
+ final CredentialsProvider credentialsProvider) {
+ final String username = httpClientConfig.getUsername();
+ if (username != null) {
+ logger.info("Setting basic Authentication credentials for Http Client Id: {} with username: {}",
+ httpClientId, username);
+ final String requestURLProtocol = requestURL.getProtocol();
+ final String requestUrlHost = requestURL.getHost();
+ final Integer requestUrlPortNumber = requestURL.getPort();
+ final HttpHost requestURLHost = new HttpHost(requestUrlHost, requestUrlPortNumber, requestURLProtocol);
+ final String password = httpClientConfig.getPassword();
+ final AuthScope httpClientAuthScope = new AuthScope(requestURLHost);
+ final Credentials credentials = new UsernamePasswordCredentials(username, password);
+ credentialsProvider.setCredentials(httpClientAuthScope, credentials);
+ } else {
+ logger.warn("No credentials set for Http Client Id: {}. No username present", httpClientId);
+ }
+ }
+
+ /**
+ * Configures proxy host, port and authentication
+ *
+ * @param httpClientId http client id
+ * @param httpClientBuilder http client builder
+ * @param credentialsProvider http credentials provider
+ */
+ private void configureProxySettings(final String httpClientId, final HttpClientBuilder httpClientBuilder,
+ final CredentialsProvider credentialsProvider) {
+
+ final URL proxyURL = httpClientConfig.getProxyURL();
+
+ if (proxyURL == null) {
+ logger.debug("Proxy not Enabled - bypassing setting Proxy settings for Http Client Id: {}", httpClientId);
+ return;
+ }
+
+ final String proxyProtocol = proxyURL.getProtocol();
+ final String proxyHost = proxyURL.getHost();
+ final Integer proxyPort = proxyURL.getPort();
+ final HttpHost proxy = new HttpHost(proxyHost, proxyPort, proxyProtocol);
+
+ logger.info("Setting up proxy for Http Client Id: {} as: {}", httpClientId, proxy);
+
+ final DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
+ httpClientBuilder.setRoutePlanner(routePlanner);
+
+ // get proxy credentials information
+ final String userInfo = proxyURL.getUserInfo();
+
+ if (!StringUtils.hasText(userInfo)) {
+ logger.debug("Proxy username not present. " +
+ "No proxy authentication credentials will be set for Http Client Id: {}", httpClientId);
+ return;
+ }
+
+ final String[] userInfoArray = userInfo.split(":");
+ final String proxyUsername = userInfoArray[0];
+ String proxyPassword = null;
+ if (userInfoArray.length > 1) {
+ proxyPassword = userInfoArray[1];
+ }
+ logger.info("Setting proxy credentials with username: {} for Http Client Id: {}", proxyUsername, httpClientId);
+ final AuthScope proxyAuthScope = new AuthScope(proxyHost, proxyPort);
+ final Credentials proxyCredentials = new UsernamePasswordCredentials(proxyUsername, proxyPassword);
+ credentialsProvider.setCredentials(proxyAuthScope, proxyCredentials);
+ }
+
+ /**
+ * Configures SSL Context
+ *
+ * @param httpClientId http client id
+ * @param httpClientBuilder http client builder
+ */
+ private void configureSSLContext(final String httpClientId, final HttpClientBuilder httpClientBuilder) {
+
+ // Setup SSL Context to ignore SSL certificate issues if ignoreSSLCertificateErrors is true
+ final boolean ignoreSSLValidation =
+ Optional.ofNullable(httpClientConfig.getIgnoreSSLValidation()).orElse(false);
+ logger.info("Ignore SSL Certificate Errors attributed is set to: {} for Http Client Id: {}",
+ ignoreSSLValidation, httpClientId);
+
+ if (!ignoreSSLValidation) {
+ logger.info("SSL Validation will be enforced for Http Client Id: {}", httpClientId);
+ return;
+ }
+
+ logger.warn("SSL Certificate Errors will be ignored for Http Client Id: {}", httpClientId);
+ try {
+ SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
+ sslContextBuilder.loadTrustMaterial(null, new AlwaysTrustingTrustStrategy());
+ httpClientBuilder.setSSLContext(sslContextBuilder.build());
+ } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
+ ReflectionUtils.rethrowRuntimeException(e);
+ }
+ httpClientBuilder.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE);
+
+ }
+
+
+ /**
+ * Header Request Interceptor adds defaults headers if not set explicitly
+ */
+ private static class DefaultHeadersRequestInterceptor implements ClientHttpRequestInterceptor {
+ private final HttpHeaders httpHeaders;
+
+ DefaultHeadersRequestInterceptor(final HttpHeaders httpHeaders) {
+ this.httpHeaders = httpHeaders;
+ }
+
+ @Override
+ public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
+ final ClientHttpRequestExecution execution) throws IOException {
+ final HttpHeaders currentRequestHeaders = request.getHeaders();
+ for (Map.Entry<String, List<String>> defaultHttpHeader : httpHeaders.entrySet()) {
+ if (!currentRequestHeaders.containsKey(defaultHttpHeader.getKey())) {
+ currentRequestHeaders.addAll(defaultHttpHeader.getKey(), defaultHttpHeader.getValue());
+ }
+ }
+ currentRequestHeaders.setAccept(httpHeaders.getAccept());
+ currentRequestHeaders.setAcceptCharset(httpHeaders.getAcceptCharset());
+ currentRequestHeaders.remove(HttpHeaders.ACCEPT_ENCODING);
+ return execution.execute(request, body);
+ }
+ }
+
+ /**
+ * An implementation of SSL Trust Strategy which does no SSL certificate validation effectively
+ * bypassing any SSL certificate related issues
+ */
+ private static class AlwaysTrustingTrustStrategy implements TrustStrategy {
+ @Override
+ public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ return true;
+ }
+ }
+
+}