diff --git a/provider/indexer-gcp/src/main/appengine/app.yaml b/provider/indexer-gcp/src/main/appengine/app.yaml index dee4515740c38e195f4afeada8a4b66471a32833..363b4097e3a611b59391832910b92ca518800872 100644 --- a/provider/indexer-gcp/src/main/appengine/app.yaml +++ b/provider/indexer-gcp/src/main/appengine/app.yaml @@ -39,3 +39,4 @@ env_variables: LEGAL_HOSTNAME: "LEGAL_HOSTNAME_VAR" REGION: "REGION_VAR" SPRING_PROFILES_ACTIVE: 'ENVIRONMENT' + SECURITY_HTTPS_CERTIFICATE_TRUST: 'SECURITY_HTTPS_CERTIFICATE_TRUST_VAR' diff --git a/provider/indexer-gcp/src/main/java/org/opengroup/osdu/indexer/util/ElasticClientHandlerGcp.java b/provider/indexer-gcp/src/main/java/org/opengroup/osdu/indexer/util/ElasticClientHandlerGcp.java new file mode 100644 index 0000000000000000000000000000000000000000..1643e331084e85a87a10984fddcaae43847e9ece --- /dev/null +++ b/provider/indexer-gcp/src/main/java/org/opengroup/osdu/indexer/util/ElasticClientHandlerGcp.java @@ -0,0 +1,146 @@ +package org.opengroup.osdu.indexer.util; + +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import javax.net.ssl.SSLContext; +import lombok.extern.java.Log; +import org.apache.http.Header; +import org.apache.http.HttpHost; +import org.apache.http.HttpStatus; +import org.apache.http.conn.ssl.NoopHostnameVerifier; +import org.apache.http.conn.ssl.TrustSelfSignedStrategy; +import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; +import org.apache.http.message.BasicHeader; +import org.apache.http.ssl.SSLContextBuilder; +import org.elasticsearch.client.RestClient; +import org.elasticsearch.client.RestClientBuilder; +import org.elasticsearch.client.RestHighLevelClient; +import org.opengroup.osdu.core.common.model.http.AppException; +import org.opengroup.osdu.core.common.model.indexer.IElasticSettingService; +import org.opengroup.osdu.core.common.model.search.ClusterSettings; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Component; + +@Component +@Primary +@Log +public class ElasticClientHandlerGcp extends ElasticClientHandler { + + // Elastic cluster Rest client settings + private static final int CLOUD_REST_CLIENT_PORT = 9243; + private static final int REST_CLIENT_CONNECT_TIMEOUT = 60000; + private static final int REST_CLIENT_SOCKET_TIMEOUT = 60000; + private static final int REST_CLIENT_RETRY_TIMEOUT = 60000; + + @Value("#{new Boolean('${security.https.certificate.trust}')}") + private Boolean securityHttpsCertificateTrust; + + @Autowired + private IElasticSettingService elasticSettingService; + + public RestHighLevelClient createRestClient() { + return getCloudRestClient(elasticSettingService.getElasticClusterInformation()); + } + + // TODO: Remove this temporary implementation when ECE CCS is utilized + public RestHighLevelClient createRestClient(final ClusterSettings clusterSettings) { + return getCloudRestClient(clusterSettings); + } + + private RestHighLevelClient getCloudRestClient(final ClusterSettings clusterSettings) { + + String cluster = null; + String host = null; + int port = CLOUD_REST_CLIENT_PORT; + String protocolScheme = "https"; + String tls = "true"; + + try { + cluster = clusterSettings.getHost(); + host = clusterSettings.getHost(); + port = clusterSettings.getPort(); + if (!clusterSettings.isHttps()) { + protocolScheme = "http"; + } + + if (!clusterSettings.isTls()) { + tls = "false"; + } + String basicEncoded = Base64 + .getEncoder().encodeToString(clusterSettings.getUserNameAndPassword().getBytes()); + String basicAuthenticationHeaderVal = String.format("Basic %s", basicEncoded); + + RestClientBuilder builder = createClientBuilder(host, basicAuthenticationHeaderVal, port, + protocolScheme, tls); + + return new RestHighLevelClient(builder); + } catch (AppException e) { + throw e; + } catch (Exception e) { + throw new AppException( + HttpStatus.SC_INTERNAL_SERVER_ERROR, + "search client error", + "error creating search client", + String + .format("Elastic client connection params, cluster: %s, host: %s, port: %s", cluster, + host, port), + e); + } + } + + public RestClientBuilder createClientBuilder(String host, String basicAuthenticationHeaderVal, + int port, String protocolScheme, String tls) { + RestClientBuilder builder = RestClient.builder(new HttpHost(host, port, protocolScheme)); + builder.setRequestConfigCallback( + requestConfigBuilder -> requestConfigBuilder.setConnectTimeout(REST_CLIENT_CONNECT_TIMEOUT) + .setSocketTimeout(REST_CLIENT_SOCKET_TIMEOUT)); + builder.setMaxRetryTimeoutMillis(REST_CLIENT_RETRY_TIMEOUT); + + Header[] defaultHeaders = new Header[]{ + new BasicHeader("client.transport.nodes_sampler_interval", "30s"), + new BasicHeader("client.transport.ping_timeout", "30s"), + new BasicHeader("client.transport.sniff", "false"), + new BasicHeader("request.headers.X-Found-Cluster", host), + new BasicHeader("cluster.name", host), + new BasicHeader("xpack.security.transport.ssl.enabled", tls), + new BasicHeader("Authorization", basicAuthenticationHeaderVal), + }; + log.info(String.format( + "Elastic client connection uses protocolScheme = %s with a flag " + + "'security.https.certificate.trust' = %s", + protocolScheme, securityHttpsCertificateTrust)); + if ("https".equals(protocolScheme) && securityHttpsCertificateTrust) { + log.warning("Elastic client connection uses TrustSelfSignedStrategy()"); + SSLContext sslContext = createSSLContext(); + builder.setHttpClientConfigCallback(httpClientBuilder -> + { + HttpAsyncClientBuilder httpAsyncClientBuilder = httpClientBuilder.setSSLContext(sslContext) + .setSSLHostnameVerifier( + NoopHostnameVerifier.INSTANCE); + return httpAsyncClientBuilder; + }); + } + + builder.setDefaultHeaders(defaultHeaders); + return builder; + } + + private SSLContext createSSLContext() { + SSLContextBuilder sslContextBuilder = new SSLContextBuilder(); + try { + sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); + return sslContextBuilder.build(); + } catch (NoSuchAlgorithmException e) { + log.severe(e.getMessage()); + } catch (KeyStoreException e) { + log.severe(e.getMessage()); + } catch (KeyManagementException e) { + log.severe(e.getMessage()); + } + return null; + } +} diff --git a/provider/indexer-gcp/src/main/resources/application-dev.properties b/provider/indexer-gcp/src/main/resources/application-dev.properties index 61da3c7139e0f8e834b2ec5b90173b2c517d075d..4644fef832ea9080e6eb94055f65e8e6211ff73b 100644 --- a/provider/indexer-gcp/src/main/resources/application-dev.properties +++ b/provider/indexer-gcp/src/main/resources/application-dev.properties @@ -18,4 +18,6 @@ CRS_API=https://crs-converter-gae-dot-opendes.appspot.com/api/crs/v1 REDIS_GROUP_HOST=10.0.16.28 REDIS_SEARCH_HOST=10.0.16.20 -GOOGLE_AUDIENCES=245464679631-ktfdfpl147m1mjpbutl00b3cmffissgq.apps.googleusercontent.com \ No newline at end of file +GOOGLE_AUDIENCES=245464679631-ktfdfpl147m1mjpbutl00b3cmffissgq.apps.googleusercontent.com + +security.https.certificate.trust=${SECURITY_HTTPS_CERTIFICATE_TRUST} \ No newline at end of file diff --git a/provider/indexer-gcp/src/main/resources/application-kuber.properties b/provider/indexer-gcp/src/main/resources/application-kuber.properties index af85274d4030d56204400765876db4eeb3c9d70a..4a92f155ba1e1b400b15ea2fcfb12474872f3a35 100644 --- a/provider/indexer-gcp/src/main/resources/application-kuber.properties +++ b/provider/indexer-gcp/src/main/resources/application-kuber.properties @@ -22,3 +22,5 @@ GOOGLE_AUDIENCES=${GOOGLE_AUDIENCES} DEPLOYMENT_ENVIRONMENT=CLOUD disable.appengine.log.factory=true + +security.https.certificate.trust=${SECURITY_HTTPS_CERTIFICATE_TRUST} \ No newline at end of file diff --git a/provider/indexer-gcp/src/main/resources/application-testing.properties b/provider/indexer-gcp/src/main/resources/application-testing.properties index 5368d291c5653bcf9bd31bfbc9c31af3765e9b1f..ef983cb6104fc6b8ad09a34a729043b9f14d0336 100644 --- a/provider/indexer-gcp/src/main/resources/application-testing.properties +++ b/provider/indexer-gcp/src/main/resources/application-testing.properties @@ -19,3 +19,5 @@ REDIS_GROUP_HOST=10.253.209.196 REDIS_SEARCH_HOST=10.118.2.140 GOOGLE_AUDIENCES=833591776864-oobhqvmtdg9rpreubjvn44m5f8revglk.apps.googleusercontent.com + +security.https.certificate.trust=false \ No newline at end of file