From ecca717339c6c3e3e3003678de936f8afe0e27cc Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Sat, 27 Feb 2016 22:08:42 +0100 Subject: [PATCH 1/2] Add setFactory permission to GceDiscoveryPlugin This commit adds a missing permission and a simple test that ensures we discover other nodes via a mock http endpoint. Closes #16485 --- .../cloud/gce/GceComputeService.java | 2 - .../cloud/gce/GceComputeServiceImpl.java | 43 +++- .../plugin-metadata/plugin-security.policy | 1 + .../discovery/gce/GceComputeServiceMock.java | 10 +- .../discovery/gce/GceDiscoverTests.java | 209 ++++++++++++++++++ .../elasticsearch/discovery/gce/keystore.jks | Bin 0 -> 2290 bytes 6 files changed, 250 insertions(+), 15 deletions(-) create mode 100644 plugins/discovery-gce/src/test/java/org/elasticsearch/discovery/gce/GceDiscoverTests.java create mode 100644 plugins/discovery-gce/src/test/resources/org/elasticsearch/discovery/gce/keystore.jks diff --git a/plugins/discovery-gce/src/main/java/org/elasticsearch/cloud/gce/GceComputeService.java b/plugins/discovery-gce/src/main/java/org/elasticsearch/cloud/gce/GceComputeService.java index a352bc02418..ce5154b3436 100644 --- a/plugins/discovery-gce/src/main/java/org/elasticsearch/cloud/gce/GceComputeService.java +++ b/plugins/discovery-gce/src/main/java/org/elasticsearch/cloud/gce/GceComputeService.java @@ -22,10 +22,8 @@ package org.elasticsearch.cloud.gce; import com.google.api.services.compute.model.Instance; import org.elasticsearch.common.component.LifecycleComponent; import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; -import java.util.Arrays; import java.io.IOException; import java.util.Collection; import java.util.Collections; diff --git a/plugins/discovery-gce/src/main/java/org/elasticsearch/cloud/gce/GceComputeServiceImpl.java b/plugins/discovery-gce/src/main/java/org/elasticsearch/cloud/gce/GceComputeServiceImpl.java index cfddaf2548f..d9033b602d2 100644 --- a/plugins/discovery-gce/src/main/java/org/elasticsearch/cloud/gce/GceComputeServiceImpl.java +++ b/plugins/discovery-gce/src/main/java/org/elasticsearch/cloud/gce/GceComputeServiceImpl.java @@ -25,6 +25,7 @@ import com.google.api.client.http.GenericUrl; import com.google.api.client.http.HttpHeaders; import com.google.api.client.http.HttpResponse; import com.google.api.client.http.HttpTransport; +import com.google.api.client.http.javanet.NetHttpTransport; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson2.JacksonFactory; import com.google.api.services.compute.Compute; @@ -36,12 +37,14 @@ import org.elasticsearch.cloud.gce.network.GceNameResolver; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.network.NetworkService; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.discovery.gce.RetryHttpInitializerWrapper; import java.io.IOException; import java.net.URL; +import java.nio.file.Files; import java.security.AccessController; import java.security.GeneralSecurityException; import java.security.PrivilegedAction; @@ -51,18 +54,29 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Function; public class GceComputeServiceImpl extends AbstractLifecycleComponent implements GceComputeService { + // all settings just used for testing - not registered by default + public static final Setting GCE_VALIDATE_CERTIFICATES = + Setting.boolSetting("cloud.gce.validate_certificates", true, false, Setting.Scope.CLUSTER); + public static final Setting GCE_HOST = + new Setting<>("cloud.gce.host", "http://metadata.google.internal", Function.identity(), false, Setting.Scope.CLUSTER); + public static final Setting GCE_ROOT_URL = + new Setting<>("cloud.gce.root_url", "https://www.googleapis.com", Function.identity(), false, Setting.Scope.CLUSTER); + private final String project; private final List zones; - // Forcing Google Token API URL as set in GCE SDK to // http://metadata/computeMetadata/v1/instance/service-accounts/default/token // See https://developers.google.com/compute/docs/metadata#metadataserver - public static final String GCE_METADATA_URL = "http://metadata.google.internal/computeMetadata/v1/instance"; - public static final String TOKEN_SERVER_ENCODED_URL = GCE_METADATA_URL + "/service-accounts/default/token"; + private final String gceHost; + private final String metaDataUrl; + private final String tokenServerEncodedUrl; + private String gceRootUrl; + @Override public Collection instances() { @@ -85,7 +99,7 @@ public class GceComputeServiceImpl extends AbstractLifecycleComponentemptyList() : instanceList.getItems(); } catch (PrivilegedActionException e) { - logger.warn("Problem fetching instance list for zone {}", zoneId); + logger.warn("Problem fetching instance list for zone {}", e, zoneId); logger.debug("Full exception:", e); // assist type inference return Collections.emptyList(); @@ -104,7 +118,7 @@ public class GceComputeServiceImpl extends AbstractLifecycleComponent read mock file from [{}]", mockFileName); URL resource = GceComputeServiceMock.class.getResource(mockFileName); if (resource == null) { throw new IOException("can't read [" + url + "] in src/test/resources/org/elasticsearch/discovery/gce"); @@ -106,7 +107,6 @@ public class GceComputeServiceMock extends GceComputeServiceImpl { } }); String response = sb.toString(); - logger.trace("{}", response); return response; } } diff --git a/plugins/discovery-gce/src/test/java/org/elasticsearch/discovery/gce/GceDiscoverTests.java b/plugins/discovery-gce/src/test/java/org/elasticsearch/discovery/gce/GceDiscoverTests.java new file mode 100644 index 00000000000..cefe7e434b2 --- /dev/null +++ b/plugins/discovery-gce/src/test/java/org/elasticsearch/discovery/gce/GceDiscoverTests.java @@ -0,0 +1,209 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you 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. + */ + +package org.elasticsearch.discovery.gce; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import org.elasticsearch.cloud.gce.GceComputeServiceImpl; +import org.elasticsearch.common.SuppressForbidden; +import org.elasticsearch.common.io.FileSystemUtils; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.settings.SettingsModule; +import org.elasticsearch.plugin.discovery.gce.GceDiscoveryPlugin; +import org.elasticsearch.plugins.Plugin; +import org.elasticsearch.test.ESIntegTestCase; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; +import java.io.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyStore; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; + +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoTimeout; + + +@ESIntegTestCase.SuppressLocalMode +@ESIntegTestCase.ClusterScope(numDataNodes = 2, numClientNodes = 0) +@SuppressForbidden(reason = "use http server") +// TODO this should be a IT but currently all ITs in this project run against a real cluster +public class GceDiscoverTests extends ESIntegTestCase { + + public static class TestPlugin extends Plugin { + + @Override + public String name() { + return "GceDiscoverTests"; + } + + @Override + public String description() { + return "GceDiscoverTests"; + } + + public void onModule(SettingsModule module) { + module.registerSetting(GceComputeServiceImpl.GCE_HOST); + module.registerSetting(GceComputeServiceImpl.GCE_ROOT_URL); + module.registerSetting(GceComputeServiceImpl.GCE_VALIDATE_CERTIFICATES); + } + } + + private static HttpsServer httpsServer; + private static HttpServer httpServer; + private static Path logDir; + + @Override + protected Collection> nodePlugins() { + return pluginList(GceDiscoveryPlugin.class, TestPlugin.class); + } + + @Override + protected Settings nodeSettings(int nodeOrdinal) { + Path resolve = logDir.resolve(Integer.toString(nodeOrdinal)); + try { + Files.createDirectory(resolve); + } catch (IOException e) { + throw new RuntimeException(e); + } + return Settings.builder().put(super.nodeSettings(nodeOrdinal)) + .put("discovery.type", "gce") + .put("path.logs", resolve) + .put("transport.tcp.port", 0) + .put("node.portsfile", "true") + .put("cloud.gce.project_id", "testproject") + .put("cloud.gce.zone", "primaryzone") + .put("discovery.initial_state_timeout", "1s") + .put("cloud.gce.host", "http://" + httpServer.getAddress().getHostName() + ":" + httpServer.getAddress().getPort()) + .put("cloud.gce.root_url", "https://" + httpsServer.getAddress().getHostName() + + ":" + httpsServer.getAddress().getPort()) + // this is annoying but by default the client pulls a static list of trusted CAs + .put("cloud.gce.validate_certificates", false) + .build(); + } + + @BeforeClass + public static void startHttpd() throws Exception { + logDir = createTempDir(); + httpsServer = HttpsServer.create(new InetSocketAddress("127.0.0.1", 0), 0); + httpServer = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(getSSLContext())); + httpServer.createContext("/computeMetadata/v1/instance/service-accounts/default/token", (s) -> { + String response = GceComputeServiceMock.readGoogleInternalJsonResponse( + "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"); + byte[] responseAsBytes = response.getBytes(StandardCharsets.UTF_8); + s.sendResponseHeaders(200, responseAsBytes.length); + OutputStream responseBody = s.getResponseBody(); + responseBody.write(responseAsBytes); + responseBody.close(); + }); + + httpsServer.createContext("/compute/v1/projects/testproject/zones/primaryzone/instances", (s) -> { + Headers headers = s.getResponseHeaders(); + headers.add("Content-Type", "application/json; charset=UTF-8"); + ESLogger logger = Loggers.getLogger(GceDiscoverTests.class); + try { + Path[] files = FileSystemUtils.files(logDir); + StringBuilder builder = new StringBuilder("{\"id\": \"dummy\",\"items\":["); + int foundFiles = 0; + for (int i = 0; i < files.length; i++) { + Path resolve = files[i].resolve("transport.ports"); + if (Files.exists(resolve)) { + if (foundFiles++ > 0) { + builder.append(","); + } + List addressses = Files.readAllLines(resolve); + Collections.shuffle(addressses, random()); + logger.debug("addresses for node: [{}] published addresses [{}]", files[i].getFileName(), addressses); + builder.append("{\"description\": \"ES Node ").append(files[i].getFileName()) + .append("\",\"networkInterfaces\": [ {"); + builder.append("\"networkIP\": \"").append(addressses.get(0)).append("\"}],"); + builder.append("\"status\" : \"RUNNING\"}"); + } + } + builder.append("]}"); + String responseString = builder.toString(); + final byte[] responseAsBytes = responseString.getBytes(StandardCharsets.UTF_8); + s.sendResponseHeaders(200, responseAsBytes.length); + OutputStream responseBody = s.getResponseBody(); + responseBody.write(responseAsBytes); + responseBody.close(); + } catch (Exception e) { + // + byte[] responseAsBytes = ("{ \"error\" : {\"message\" : \"" + e.toString() + "\" } }").getBytes(StandardCharsets.UTF_8); + s.sendResponseHeaders(500, responseAsBytes.length); + OutputStream responseBody = s.getResponseBody(); + responseBody.write(responseAsBytes); + responseBody.close(); + } + + + }); + httpsServer.start(); + httpServer.start(); + } + + private static SSLContext getSSLContext() throws Exception{ + char[] passphrase = "passphrase".toCharArray(); + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(GceDiscoverTests.class.getResourceAsStream("keystore.jks"), passphrase); + KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); + kmf.init(ks, passphrase); + TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); + tmf.init(ks); + SSLContext ssl = SSLContext.getInstance("TLS"); + ssl.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + return ssl; + } + + @AfterClass + public static void stopHttpd() throws IOException { + for (int i = 0; i < internalCluster().size(); i++) { + // shut them all down otherwise we get spammed with connection refused exceptions + internalCluster().stopRandomDataNode(); + } + httpsServer.stop(0); + httpServer.stop(0); + httpsServer = null; + httpServer = null; + logDir = null; + } + + public void testJoin() throws ExecutionException, InterruptedException { + // only wait for the cluster to form + assertNoTimeout(client().admin().cluster().prepareHealth().setWaitForNodes(Integer.toString(2)).get()); + // add one more node and wait for it to join + internalCluster().startDataOnlyNodeAsync().get(); + assertNoTimeout(client().admin().cluster().prepareHealth().setWaitForNodes(Integer.toString(3)).get()); + } +} diff --git a/plugins/discovery-gce/src/test/resources/org/elasticsearch/discovery/gce/keystore.jks b/plugins/discovery-gce/src/test/resources/org/elasticsearch/discovery/gce/keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..3819a4a697f69174f8aa45db66f917d0656f64d9 GIT binary patch literal 2290 zcmd6oX*AS}8^`B2GbS?{>)0y^ZNhKHI@SuMbW@frQN}uBElc)oERiLq+hB}!tc6@; z8KlHbB1@==>p7=lSj|>?}Ya5a^zOzl8F3 zbaV11IeR!d>>(35o8ROh5Do}PhW`Y)5hz&%00&M&`2c_e0w=>~v@zHFZ)e;31jluK znlUkL`!*>2Xh(#ztZ(kf%BZWvh=K|}Lf54LZbuX;JHo>uxjY(akJCKve-qh*4;AZx z-5KnEtda&Eb-`(wYU>C&Ox0o)dBWT0Ex*yH3M%TCoeIwK&fT#N+NOqU+#iqic-?0{ zvqh6q7^+`FF>M7q6f-PW=woIUP)1&og8G6s<;1z@b(+F}W+=v2B0F(d1A?%;8iUFy z(Y(}JYC<@18;SfJcGI5jq7x-G1+Mc_YxQf^Q^YTvOoiQp>_@y+6xUk2!Nvu0a7mhe zo$r3z<{_7yqMa=9jAH6oeTj?nIqaiuZNi}mxxV(r3rpaBrtFvW#CCHM?w#HH*rfv0 zFqYR@SQ%{r%j>$~mpsxZ$xLE>A8YF#7Wyg*T%*vs-V}N&_V4n=tG#i;>pi(z7T)i_ zB5-{!z0#0?ys=&L#teseR5Dn{)v$G(Ej8ba$mffCDUhOWnj>t>oe=EpWkdEF;QFnZyaCCHX z|8)hEghOEwX~xWU7eD=pO15Sxisp8-I<=6#9T7=AtiJXp2l0Nnr%h*U;Na*seAK{D zb4FC}Aw=toO?c9#(2wDthApAFyZ-3zz+06Q^5cyOyVPmAyvTv4{K0(t$a*~Lp)U^R zR!|JD`S!AOVvmMAm0m%uM`@7P@=zObZmwvC(4?oQ`7&`~8%4@t!C2O_Bj4>OL#{ZE zGlImaNyarj83KC6UDnOAGFT~NXooN~xm-({WpI*CP)qc^b66LnxP!h*do@GY)e+rZ z290X4*NRI5Br8R6S&! zoV8eI`8qKs)n^(?&hYt290%=PF`we^eowPGdEX`BJZ%%R5=O}hiX0zpI3UW+-F7a^ zhdM3MFDQdcGcnj=qw)%Z4S5cWKlk#Y2{l#m;+0gYt^t zgW({?Aft#CWXNYV+Zgx=vARwoR{f5g!UaU`=MHqgBFwQF5@)Lrt_;r4Mudu;<6c)$ zZr$lye|aqa#`Ko#YKwq#;ws|-`a_o9!lYA065h_mvAL4HvHZdJCKmZSR?D{Z``R)0 zsNI$gxND4r;{l!dj7Put$Lmiwem?5{%|Yfu(udIiTYFDY zSRtJvai0;BCTm)Gc5-KU5Mh1BH0tY}r$p8R}8kHVBAh^~3 zTuHxa&6VUuq_iG=mZ7s!AEmy&l;CG#TELODrfPHQtmI7!`c{n1J^9Ymx{K5n44s`R zB6Q(0CXlA^9&{I_h&SBUykQoDh{jP$P3JDm>Ce|EMKm0T(uwnoJX4VO18jt za;M@Q#^ef!8vL}v#9z#1%@K2+mzoTui_@E5zFr`Z7jJTXd)DXSoi2u?j?{HY)>a&R zSX&wJYx29-v-+i{Tqo^+ZP^j%S-hM{6yMo`gu(y_z>owbz=M1H zJ;)6gf@2h?N#!rkhD0q-#`R}Ei`5(uyb%0%6Zh_K&qM&?pEga(@}`|Q4IP*)2Ywha zIUV#n$JP}_A?uOdV$3Hh~MbiXpxo?O_P5n{|OQxPf2e{K0mY?$-@ z@X#3}HgQc!memaTP}s0paBQbg@=WM*b(B0~8g*K4=gV46RbBw>j#a8PiFr@Zs;dce zf0Gy^qXE};Rek4rSbwouCd)`r(hSejSiD3G$My`?X_pvH$a>{kP$H(P$9c~4r8__& z+~^KRDG7dh+s5&3{&xb%@4HMT;i8TguXnwzodfC+vZkFQuHq(>Q3sx~?yJXqLC|gg E00Lt5o&W#< literal 0 HcmV?d00001 From 948ee3ee3f6f35512015645b89d889c3b8c18879 Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Mon, 29 Feb 2016 22:01:39 +0100 Subject: [PATCH 2/2] Move keystore creation to gradle - this prevents committing a keystore to the source repo --- plugins/discovery-gce/build.gradle | 31 ++++++++++++++++++ .../discovery/gce/GceDiscoverTests.java | 16 ++++++--- .../elasticsearch/discovery/gce/keystore.jks | Bin 2290 -> 0 bytes 3 files changed, 42 insertions(+), 5 deletions(-) delete mode 100644 plugins/discovery-gce/src/test/resources/org/elasticsearch/discovery/gce/keystore.jks diff --git a/plugins/discovery-gce/build.gradle b/plugins/discovery-gce/build.gradle index b888b817679..bbd2221d8e0 100644 --- a/plugins/discovery-gce/build.gradle +++ b/plugins/discovery-gce/build.gradle @@ -1,3 +1,4 @@ +import org.elasticsearch.gradle.LoggedExec esplugin { description 'The Google Compute Engine (GCE) Discovery plugin allows to use GCE API for the unicast discovery mechanism.' @@ -21,6 +22,36 @@ dependencies { compile "commons-codec:commons-codec:${versions.commonscodec}" } + +// needed to be consistent with ssl host checking +String host = InetAddress.getLoopbackAddress().getHostAddress(); + +// location of keystore and files to generate it +File keystore = new File(project.buildDir, 'keystore/test-node.jks') + +// generate the keystore +task createKey(type: LoggedExec) { + doFirst { + project.delete(keystore.parentFile) + keystore.parentFile.mkdirs() + } + executable = 'keytool' + standardInput = new ByteArrayInputStream('FirstName LastName\nUnit\nOrganization\nCity\nState\nNL\nyes\n\n'.getBytes('UTF-8')) + args '-genkey', + '-alias', 'test-node', + '-keystore', keystore, + '-keyalg', 'RSA', + '-keysize', '2048', + '-validity', '712', + '-dname', 'CN=' + host, + '-keypass', 'keypass', + '-storepass', 'keypass' +} + +// add keystore to test classpath: it expects it there +sourceSets.test.resources.srcDir(keystore.parentFile) +processTestResources.dependsOn(createKey) + dependencyLicenses { mapping from: /google-.*/, to: 'google' } diff --git a/plugins/discovery-gce/src/test/java/org/elasticsearch/discovery/gce/GceDiscoverTests.java b/plugins/discovery-gce/src/test/java/org/elasticsearch/discovery/gce/GceDiscoverTests.java index cefe7e434b2..dbedbe1a6a9 100644 --- a/plugins/discovery-gce/src/test/java/org/elasticsearch/discovery/gce/GceDiscoverTests.java +++ b/plugins/discovery-gce/src/test/java/org/elasticsearch/discovery/gce/GceDiscoverTests.java @@ -40,7 +40,9 @@ import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -115,9 +117,10 @@ public class GceDiscoverTests extends ESIntegTestCase { @BeforeClass public static void startHttpd() throws Exception { logDir = createTempDir(); - httpsServer = HttpsServer.create(new InetSocketAddress("127.0.0.1", 0), 0); - httpServer = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0); - httpsServer.setHttpsConfigurator(new HttpsConfigurator(getSSLContext())); + SSLContext sslContext = getSSLContext(); + httpsServer = HttpsServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress().getHostAddress(), 0), 0); + httpServer = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress().getHostAddress(), 0), 0); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext)); httpServer.createContext("/computeMetadata/v1/instance/service-accounts/default/token", (s) -> { String response = GceComputeServiceMock.readGoogleInternalJsonResponse( "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"); @@ -174,9 +177,12 @@ public class GceDiscoverTests extends ESIntegTestCase { } private static SSLContext getSSLContext() throws Exception{ - char[] passphrase = "passphrase".toCharArray(); + char[] passphrase = "keypass".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS"); - ks.load(GceDiscoverTests.class.getResourceAsStream("keystore.jks"), passphrase); + try (InputStream stream = GceDiscoverTests.class.getResourceAsStream("/test-node.jks")) { + assertNotNull("can't find keystore file", stream); + ks.load(stream, passphrase); + } KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); diff --git a/plugins/discovery-gce/src/test/resources/org/elasticsearch/discovery/gce/keystore.jks b/plugins/discovery-gce/src/test/resources/org/elasticsearch/discovery/gce/keystore.jks deleted file mode 100644 index 3819a4a697f69174f8aa45db66f917d0656f64d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2290 zcmd6oX*AS}8^`B2GbS?{>)0y^ZNhKHI@SuMbW@frQN}uBElc)oERiLq+hB}!tc6@; z8KlHbB1@==>p7=lSj|>?}Ya5a^zOzl8F3 zbaV11IeR!d>>(35o8ROh5Do}PhW`Y)5hz&%00&M&`2c_e0w=>~v@zHFZ)e;31jluK znlUkL`!*>2Xh(#ztZ(kf%BZWvh=K|}Lf54LZbuX;JHo>uxjY(akJCKve-qh*4;AZx z-5KnEtda&Eb-`(wYU>C&Ox0o)dBWT0Ex*yH3M%TCoeIwK&fT#N+NOqU+#iqic-?0{ zvqh6q7^+`FF>M7q6f-PW=woIUP)1&og8G6s<;1z@b(+F}W+=v2B0F(d1A?%;8iUFy z(Y(}JYC<@18;SfJcGI5jq7x-G1+Mc_YxQf^Q^YTvOoiQp>_@y+6xUk2!Nvu0a7mhe zo$r3z<{_7yqMa=9jAH6oeTj?nIqaiuZNi}mxxV(r3rpaBrtFvW#CCHM?w#HH*rfv0 zFqYR@SQ%{r%j>$~mpsxZ$xLE>A8YF#7Wyg*T%*vs-V}N&_V4n=tG#i;>pi(z7T)i_ zB5-{!z0#0?ys=&L#teseR5Dn{)v$G(Ej8ba$mffCDUhOWnj>t>oe=EpWkdEF;QFnZyaCCHX z|8)hEghOEwX~xWU7eD=pO15Sxisp8-I<=6#9T7=AtiJXp2l0Nnr%h*U;Na*seAK{D zb4FC}Aw=toO?c9#(2wDthApAFyZ-3zz+06Q^5cyOyVPmAyvTv4{K0(t$a*~Lp)U^R zR!|JD`S!AOVvmMAm0m%uM`@7P@=zObZmwvC(4?oQ`7&`~8%4@t!C2O_Bj4>OL#{ZE zGlImaNyarj83KC6UDnOAGFT~NXooN~xm-({WpI*CP)qc^b66LnxP!h*do@GY)e+rZ z290X4*NRI5Br8R6S&! zoV8eI`8qKs)n^(?&hYt290%=PF`we^eowPGdEX`BJZ%%R5=O}hiX0zpI3UW+-F7a^ zhdM3MFDQdcGcnj=qw)%Z4S5cWKlk#Y2{l#m;+0gYt^t zgW({?Aft#CWXNYV+Zgx=vARwoR{f5g!UaU`=MHqgBFwQF5@)Lrt_;r4Mudu;<6c)$ zZr$lye|aqa#`Ko#YKwq#;ws|-`a_o9!lYA065h_mvAL4HvHZdJCKmZSR?D{Z``R)0 zsNI$gxND4r;{l!dj7Put$Lmiwem?5{%|Yfu(udIiTYFDY zSRtJvai0;BCTm)Gc5-KU5Mh1BH0tY}r$p8R}8kHVBAh^~3 zTuHxa&6VUuq_iG=mZ7s!AEmy&l;CG#TELODrfPHQtmI7!`c{n1J^9Ymx{K5n44s`R zB6Q(0CXlA^9&{I_h&SBUykQoDh{jP$P3JDm>Ce|EMKm0T(uwnoJX4VO18jt za;M@Q#^ef!8vL}v#9z#1%@K2+mzoTui_@E5zFr`Z7jJTXd)DXSoi2u?j?{HY)>a&R zSX&wJYx29-v-+i{Tqo^+ZP^j%S-hM{6yMo`gu(y_z>owbz=M1H zJ;)6gf@2h?N#!rkhD0q-#`R}Ei`5(uyb%0%6Zh_K&qM&?pEga(@}`|Q4IP*)2Ywha zIUV#n$JP}_A?uOdV$3Hh~MbiXpxo?O_P5n{|OQxPf2e{K0mY?$-@ z@X#3}HgQc!memaTP}s0paBQbg@=WM*b(B0~8g*K4=gV46RbBw>j#a8PiFr@Zs;dce zf0Gy^qXE};Rek4rSbwouCd)`r(hSejSiD3G$My`?X_pvH$a>{kP$H(P$9c~4r8__& z+~^KRDG7dh+s5&3{&xb%@4HMT;i8TguXnwzodfC+vZkFQuHq(>Q3sx~?yJXqLC|gg E00Lt5o&W#<