From 37795d259a634d36f74be6d302cd48ae0c51615e Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 7 Apr 2020 23:20:17 -0700 Subject: [PATCH] Remove guava from transitive compile classpath (#54309) (#54695) Guava was removed from Elasticsearch many years ago, but remnants of it remain due to transitive dependencies. When a dependency pulls guava into the compile classpath, devs can inadvertently begin using methods from guava without realizing it. This commit moves guava to a runtime dependency in the modules that it is needed. Note that one special case is the html sanitizer in watcher. The third party dep uses guava in the PolicyFactory class signature. However, only calling a method on the PolicyFactory actually causes the class to be loaded, a reference alone does not trigger compilation to look at the class implementation. There we utilize a MethodHandle for invoking the relevant method at runtime, where guava will continue to exist. --- build.gradle | 1 + .../elasticsearch/gradle/BuildPlugin.groovy | 1 + .../gradle/plugin/PluginBuildPlugin.groovy | 5 +-- .../gradle/precommit/PrecommitTasks.groovy | 14 ++++++++ .../gradle/precommit/ThirdPartyAuditTask.java | 2 +- distribution/tools/keystore-cli/build.gradle | 2 +- distribution/tools/plugin-cli/build.gradle | 4 +-- gradle/forbidden-dependencies.gradle | 27 +++++++++++++++ plugins/repository-azure/build.gradle | 2 +- plugins/repository-gcs/build.gradle | 2 +- plugins/repository-hdfs/build.gradle | 2 +- server/build.gradle | 2 -- .../common/util/iterable/Iterables.java | 4 +++ .../fieldcaps/FieldCapabilitiesTests.java | 17 +++++----- .../index/mapper/TypeParsersTests.java | 22 +++++++----- x-pack/plugin/identity-provider/build.gradle | 2 +- .../ml/integration/ClassificationIT.java | 7 ++-- .../ml/process/ProcessResultsParserTests.java | 3 +- x-pack/plugin/security/build.gradle | 2 +- x-pack/plugin/security/cli/build.gradle | 6 +++- .../security/authc/ApiKeyIntegTests.java | 2 +- .../xpack/sql/parser/SqlParserTests.java | 30 +++++++++------- x-pack/plugin/watcher/build.gradle | 4 +-- .../watcher/execution/ExecutionService.java | 3 +- .../notification/email/HtmlSanitizer.java | 34 ++++++++++++++++--- .../attachment/ReportingAttachmentParser.java | 7 ++-- .../watcher/actions/ActionWrapperTests.java | 9 +++-- .../http/SizeLimitInputStreamTests.java | 4 +-- .../email/EmailTemplateTests.java | 21 ++++++------ .../ReportingAttachmentParserTests.java | 7 ++-- x-pack/qa/security-tools-tests/build.gradle | 2 +- x-pack/snapshot-tool/build.gradle | 2 +- 32 files changed, 168 insertions(+), 84 deletions(-) create mode 100644 gradle/forbidden-dependencies.gradle diff --git a/build.gradle b/build.gradle index 990e3577708..a2e40533e31 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,7 @@ apply from: 'gradle/build-scan.gradle' apply from: 'gradle/build-complete.gradle' apply from: 'gradle/runtime-jdk-provision.gradle' apply from: 'gradle/ide.gradle' +apply from: 'gradle/forbidden-dependencies.gradle' apply from: 'gradle/formatting.gradle' // common maven publishing configuration diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy index 5a00f2a7683..3bcd65460df 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy @@ -301,6 +301,7 @@ class BuildPlugin implements Plugin { project.configurations.getByName(JavaPlugin.COMPILE_CONFIGURATION_NAME).dependencies.all(disableTransitiveDeps) project.configurations.getByName(JavaPlugin.TEST_COMPILE_CONFIGURATION_NAME).dependencies.all(disableTransitiveDeps) project.configurations.getByName(JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME).dependencies.all(disableTransitiveDeps) + project.configurations.getByName(JavaPlugin.RUNTIME_ONLY_CONFIGURATION_NAME).dependencies.all(disableTransitiveDeps) } /** Adds repositories used by ES dependencies */ diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/plugin/PluginBuildPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/plugin/PluginBuildPlugin.groovy index d71fb2ad218..2b9c3dcacd8 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/plugin/PluginBuildPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/plugin/PluginBuildPlugin.groovy @@ -134,7 +134,8 @@ class PluginBuildPlugin implements Plugin { } createIntegTestTask(project) createBundleTasks(project, extension) - project.configurations.getByName('default').extendsFrom(project.configurations.getByName('runtime')) + project.configurations.getByName('default') + .extendsFrom(project.configurations.getByName('runtimeClasspath')) // allow running ES with this plugin in the foreground of a build project.tasks.register('run', RunTask) { dependsOn(project.tasks.bundlePlugin) @@ -227,7 +228,7 @@ class PluginBuildPlugin implements Plugin { * that shadow jar. */ from { project.plugins.hasPlugin(ShadowPlugin) ? project.shadowJar : project.jar } - from project.configurations.runtime - project.configurations.compileOnly + from project.configurations.runtimeClasspath - project.configurations.compileOnly // extra files for the plugin to go into the zip from('src/main/packaging') // TODO: move all config/bin/_size/etc into packaging from('src/main') { diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy index 6643cf484f6..17ce9af418b 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/precommit/PrecommitTasks.groovy @@ -28,6 +28,7 @@ import org.elasticsearch.gradle.util.Util import org.gradle.api.JavaVersion import org.gradle.api.Project import org.gradle.api.artifacts.Configuration +import org.gradle.api.file.FileCollection import org.gradle.api.plugins.JavaBasePlugin import org.gradle.api.plugins.quality.Checkstyle import org.gradle.api.tasks.TaskProvider @@ -142,6 +143,19 @@ class PrecommitTasks { ExportElasticsearchBuildResourcesTask buildResources = project.tasks.getByName('buildResources') project.tasks.withType(CheckForbiddenApis).configureEach { dependsOn(buildResources) + + // use the runtime classpath if we have it, but some qa projects don't have one... + if (name.endsWith('Test')) { + FileCollection runtime = project.sourceSets.test.runtimeClasspath + if (runtime != null) { + classpath = runtime.plus(project.sourceSets.test.compileClasspath) + } + } else { + FileCollection runtime = project.sourceSets.main.runtimeClasspath + if (runtime != null) { + classpath = runtime.plus(project.sourceSets.main.compileClasspath) + } + } targetCompatibility = BuildParams.runtimeJavaVersion.majorVersion if (BuildParams.runtimeJavaVersion > JavaVersion.VERSION_13) { project.logger.warn( diff --git a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditTask.java b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditTask.java index 4393aff11ee..0d7ac0bc64d 100644 --- a/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditTask.java +++ b/buildSrc/src/main/java/org/elasticsearch/gradle/precommit/ThirdPartyAuditTask.java @@ -388,7 +388,7 @@ public class ThirdPartyAuditTask extends DefaultTask { } private Configuration getRuntimeConfiguration() { - Configuration runtime = getProject().getConfigurations().findByName("runtime"); + Configuration runtime = getProject().getConfigurations().findByName("runtimeClasspath"); if (runtime == null) { return getProject().getConfigurations().getByName("testCompile"); } diff --git a/distribution/tools/keystore-cli/build.gradle b/distribution/tools/keystore-cli/build.gradle index de09e78e374..108344c9569 100644 --- a/distribution/tools/keystore-cli/build.gradle +++ b/distribution/tools/keystore-cli/build.gradle @@ -24,5 +24,5 @@ dependencies { compileOnly project(":libs:elasticsearch-cli") testCompile project(":test:framework") testCompile 'com.google.jimfs:jimfs:1.1' - testCompile 'com.google.guava:guava:18.0' + testRuntimeOnly 'com.google.guava:guava:18.0' } diff --git a/distribution/tools/plugin-cli/build.gradle b/distribution/tools/plugin-cli/build.gradle index b6af1c18ac6..519fef4c0eb 100644 --- a/distribution/tools/plugin-cli/build.gradle +++ b/distribution/tools/plugin-cli/build.gradle @@ -1,5 +1,3 @@ -import org.elasticsearch.gradle.info.BuildParams - /* * Licensed to Elasticsearch under one or more contributor * license agreements. See the NOTICE file distributed with @@ -30,7 +28,7 @@ dependencies { compile "org.bouncycastle:bc-fips:1.0.1" testCompile project(":test:framework") testCompile 'com.google.jimfs:jimfs:1.1' - testCompile 'com.google.guava:guava:18.0' + testRuntimeOnly 'com.google.guava:guava:18.0' } dependencyLicenses { diff --git a/gradle/forbidden-dependencies.gradle b/gradle/forbidden-dependencies.gradle new file mode 100644 index 00000000000..2970c6a96dd --- /dev/null +++ b/gradle/forbidden-dependencies.gradle @@ -0,0 +1,27 @@ + +// we do not want any of these dependencies on the compilation classpath +// because they could then be used within Elasticsearch +List FORBIDDEN_DEPENDENCIES = [ + 'guava' +] + +Closure checkDeps = { Configuration configuration -> + configuration.resolutionStrategy.eachDependency { + String artifactName = it.target.name + if (FORBIDDEN_DEPENDENCIES.contains(artifactName)) { + throw new GradleException("Dependency '${artifactName}' on configuration '${configuration.name}' is not allowed. " + + "If it is needed as a transitive depenency, try adding it to the runtime classpath") + } + } +} + +subprojects { + if (project.path.startsWith(':test:fixtures:') || project.path.equals(':build-tools')) { + // fixtures are allowed to use whatever dependencies they want... + return + } + pluginManager.withPlugin('java') { + checkDeps(configurations.compileClasspath) + checkDeps(configurations.testCompileClasspath) + } +} diff --git a/plugins/repository-azure/build.gradle b/plugins/repository-azure/build.gradle index 418eccc87ec..4b9148b7cf7 100644 --- a/plugins/repository-azure/build.gradle +++ b/plugins/repository-azure/build.gradle @@ -27,7 +27,7 @@ esplugin { dependencies { compile 'com.microsoft.azure:azure-storage:8.6.2' compile 'com.microsoft.azure:azure-keyvault-core:1.0.0' - compile 'com.google.guava:guava:20.0' + runtimeOnly 'com.google.guava:guava:20.0' compile 'org.apache.commons:commons-lang3:3.4' testCompile project(':test:fixtures:azure-fixture') } diff --git a/plugins/repository-gcs/build.gradle b/plugins/repository-gcs/build.gradle index fdcafab3d23..76047ccf0bb 100644 --- a/plugins/repository-gcs/build.gradle +++ b/plugins/repository-gcs/build.gradle @@ -27,7 +27,7 @@ esplugin { dependencies { compile 'com.google.cloud:google-cloud-storage:1.106.0' compile 'com.google.cloud:google-cloud-core:1.93.3' - compile 'com.google.guava:guava:26.0-jre' + runtimeOnly 'com.google.guava:guava:26.0-jre' compile 'com.google.http-client:google-http-client:1.34.2' compile "commons-logging:commons-logging:${versions.commonslogging}" compile "org.apache.logging.log4j:log4j-1.2-api:${versions.log4j}" diff --git a/plugins/repository-hdfs/build.gradle b/plugins/repository-hdfs/build.gradle index 6e4949e150d..8f20cae705d 100644 --- a/plugins/repository-hdfs/build.gradle +++ b/plugins/repository-hdfs/build.gradle @@ -52,7 +52,7 @@ dependencies { compile "org.apache.hadoop:hadoop-hdfs:${versions.hadoop2}" compile "org.apache.hadoop:hadoop-hdfs-client:${versions.hadoop2}" compile 'org.apache.htrace:htrace-core4:4.0.1-incubating' - compile 'com.google.guava:guava:11.0.2' + runtimeOnly 'com.google.guava:guava:11.0.2' compile 'com.google.protobuf:protobuf-java:2.5.0' compile 'commons-logging:commons-logging:1.1.3' compile "org.apache.logging.log4j:log4j-1.2-api:${versions.log4j}" diff --git a/server/build.gradle b/server/build.gradle index 810e75bb032..2c30396a0f8 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -131,8 +131,6 @@ dependencies { // tests use the locally compiled version of server exclude group: 'org.elasticsearch', module: 'server' } - - testCompile 'com.google.guava:guava:18.0' } compileJava.options.compilerArgs << "-Xlint:-cast,-rawtypes,-unchecked" diff --git a/server/src/main/java/org/elasticsearch/common/util/iterable/Iterables.java b/server/src/main/java/org/elasticsearch/common/util/iterable/Iterables.java index 0574895af65..6d1dab4a9d0 100644 --- a/server/src/main/java/org/elasticsearch/common/util/iterable/Iterables.java +++ b/server/src/main/java/org/elasticsearch/common/util/iterable/Iterables.java @@ -102,4 +102,8 @@ public class Iterables { return it.next(); } } + + public static long size(Iterable iterable) { + return StreamSupport.stream(iterable.spliterator(), true).count(); + } } diff --git a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java index 178ba3d0876..5fb21bca3f3 100644 --- a/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java +++ b/server/src/test/java/org/elasticsearch/action/fieldcaps/FieldCapabilitiesTests.java @@ -19,8 +19,6 @@ package org.elasticsearch.action.fieldcaps; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import org.elasticsearch.common.io.stream.Writeable; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.test.AbstractSerializingTestCase; @@ -28,6 +26,7 @@ import org.elasticsearch.test.AbstractSerializingTestCase; import java.io.IOException; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.Map; import java.util.Set; @@ -101,8 +100,8 @@ public class FieldCapabilitiesTests extends AbstractSerializingTestCase(Arrays.asList("bar", "quux"))), cap1.meta()); FieldCapabilities cap2 = builder.build(true); assertThat(cap2.isSearchable(), equalTo(true)); @@ -119,7 +118,7 @@ public class FieldCapabilitiesTests extends AbstractSerializingTestCase(Arrays.asList("bar", "quux"))), cap2.meta()); } } @@ -152,10 +151,10 @@ public class FieldCapabilitiesTests extends AbstractSerializingTestCase(Arrays.asList("bar", "baz"))); break; } @@ -232,7 +231,7 @@ public class FieldCapabilitiesTests extends AbstractSerializingTestCase> newMeta; if (meta.isEmpty()) { - newMeta = ImmutableMap.of("foo", ImmutableSet.of("bar")); + newMeta = Collections.singletonMap("foo", Collections.singleton("bar")); } else { newMeta = Collections.emptyMap(); } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/TypeParsersTests.java b/server/src/test/java/org/elasticsearch/index/mapper/TypeParsersTests.java index 3f305480c7a..98b94ab059c 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/TypeParsersTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/TypeParsersTests.java @@ -19,7 +19,6 @@ package org.elasticsearch.index.mapper; -import com.google.common.collect.ImmutableMap; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.standard.StandardAnalyzer; @@ -219,14 +218,15 @@ public class TypeParsersTests extends ESTestCase { Mapper.TypeParser.ParserContext parserContext = new Mapper.TypeParser.ParserContext(null, null, null, null, null); { - Map mapping = new HashMap<>(ImmutableMap.of("meta", 3)); + Map mapping = new HashMap<>(Collections.singletonMap("meta", 3)); MapperParsingException e = expectThrows(MapperParsingException.class, () -> TypeParsers.parseField(builder, builder.name, mapping, parserContext)); assertEquals("[meta] must be an object, got Integer[3] for field [foo]", e.getMessage()); } { - Map mapping = new HashMap<>(ImmutableMap.of("meta", ImmutableMap.of("veryloooooooooooongkey", 3L))); + Map mapping = new HashMap<>(Collections.singletonMap("meta", + Collections.singletonMap("veryloooooooooooongkey", 3L))); MapperParsingException e = expectThrows(MapperParsingException.class, () -> TypeParsers.parseField(builder, builder.name, mapping, parserContext)); assertEquals("[meta] keys can't be longer than 20 chars, but got [veryloooooooooooongkey] for field [foo]", @@ -241,7 +241,7 @@ public class TypeParsersTests extends ESTestCase { meta.put("foo4", "3"); meta.put("foo5", "3"); meta.put("foo6", "3"); - Map mapping = new HashMap<>(ImmutableMap.of("meta", meta)); + Map mapping = new HashMap<>(Collections.singletonMap("meta", meta)); MapperParsingException e = expectThrows(MapperParsingException.class, () -> TypeParsers.parseField(builder, builder.name, mapping, parserContext)); assertEquals("[meta] can't have more than 5 entries, but got 6 on field [foo]", @@ -249,15 +249,19 @@ public class TypeParsersTests extends ESTestCase { } { - Map mapping = new HashMap<>(ImmutableMap.of("meta", ImmutableMap.of("foo", ImmutableMap.of("bar", "baz")))); + Map mapping = new HashMap<>(Collections.singletonMap("meta", + Collections.singletonMap("foo", Collections.singletonMap("bar", "baz")))); MapperParsingException e = expectThrows(MapperParsingException.class, () -> TypeParsers.parseField(builder, builder.name, mapping, parserContext)); - assertEquals("[meta] values can only be strings, but got SingletonImmutableBiMap[{bar=baz}] for field [foo]", + assertEquals("[meta] values can only be strings, but got SingletonMap[{bar=baz}] for field [foo]", e.getMessage()); } { - Map mapping = new HashMap<>(ImmutableMap.of("meta", ImmutableMap.of("bar", "baz", "foo", 3))); + Map inner = new HashMap<>(); + inner.put("bar", "baz"); + inner.put("foo", 3); + Map mapping = new HashMap<>(Collections.singletonMap("meta", inner)); MapperParsingException e = expectThrows(MapperParsingException.class, () -> TypeParsers.parseField(builder, builder.name, mapping, parserContext)); assertEquals("[meta] values can only be strings, but got Integer[3] for field [foo]", @@ -267,7 +271,7 @@ public class TypeParsersTests extends ESTestCase { { Map meta = new HashMap<>(); meta.put("foo", null); - Map mapping = new HashMap<>(ImmutableMap.of("meta", meta)); + Map mapping = new HashMap<>(Collections.singletonMap("meta", meta)); MapperParsingException e = expectThrows(MapperParsingException.class, () -> TypeParsers.parseField(builder, builder.name, mapping, parserContext)); assertEquals("[meta] values can't be null (field [foo])", @@ -278,7 +282,7 @@ public class TypeParsersTests extends ESTestCase { String longString = IntStream.range(0, 51) .mapToObj(Integer::toString) .collect(Collectors.joining()); - Map mapping = new HashMap<>(ImmutableMap.of("meta", ImmutableMap.of("foo", longString))); + Map mapping = new HashMap<>(Collections.singletonMap("meta", Collections.singletonMap("foo", longString))); MapperParsingException e = expectThrows(MapperParsingException.class, () -> TypeParsers.parseField(builder, builder.name, mapping, parserContext)); assertThat(e.getMessage(), Matchers.startsWith("[meta] values can't be longer than 50 chars")); diff --git a/x-pack/plugin/identity-provider/build.gradle b/x-pack/plugin/identity-provider/build.gradle index d4959d6a0f1..bc84fc3afc7 100644 --- a/x-pack/plugin/identity-provider/build.gradle +++ b/x-pack/plugin/identity-provider/build.gradle @@ -48,7 +48,7 @@ dependencies { compile "org.apache.httpcomponents:httpasyncclient:${versions.httpasyncclient}" compile "org.apache.httpcomponents:httpcore-nio:${versions.httpcore}" compile "org.apache.httpcomponents:httpclient-cache:${versions.httpclient}" - compile 'com.google.guava:guava:19.0' + runtimeOnly 'com.google.guava:guava:19.0' testCompile 'org.elasticsearch:securemock:1.2' testCompile "org.elasticsearch:mocksocket:${versions.mocksocket}" diff --git a/x-pack/plugin/ml/qa/native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/ClassificationIT.java b/x-pack/plugin/ml/qa/native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/ClassificationIT.java index 6537235c760..c01f5de8af3 100644 --- a/x-pack/plugin/ml/qa/native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/ClassificationIT.java +++ b/x-pack/plugin/ml/qa/native-multi-node-tests/src/test/java/org/elasticsearch/xpack/ml/integration/ClassificationIT.java @@ -5,7 +5,6 @@ */ package org.elasticsearch.xpack.ml.integration; -import com.google.common.collect.Ordering; import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.action.admin.indices.refresh.RefreshRequest; import org.elasticsearch.action.bulk.BulkRequestBuilder; @@ -634,7 +633,11 @@ public class ClassificationIT extends MlNativeDataFrameAnalyticsIntegTestCase { // Assert that all the class probabilities lie within [0, 1] interval. classProbabilities.forEach(p -> assertThat(p, allOf(greaterThanOrEqualTo(0.0), lessThanOrEqualTo(1.0)))); // Assert that the top classes are listed in the order of decreasing scores. - assertThat(Ordering.natural().reverse().isOrdered(classScores), is(true)); + double prevScore = classScores.get(0); + for (int i = 1; i < classScores.size(); ++i) { + double score = classScores.get(i); + assertThat("class " + i, score, lessThanOrEqualTo(prevScore)); + } } private void assertEvaluation(String dependentVariable, List dependentVariableValues, String predictedClassField) { diff --git a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/process/ProcessResultsParserTests.java b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/process/ProcessResultsParserTests.java index 77428c23049..efb9655cfe0 100644 --- a/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/process/ProcessResultsParserTests.java +++ b/x-pack/plugin/ml/src/test/java/org/elasticsearch/xpack/ml/process/ProcessResultsParserTests.java @@ -5,7 +5,6 @@ */ package org.elasticsearch.xpack.ml.process; -import com.google.common.base.Charsets; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.xcontent.ConstructingObjectParser; @@ -59,7 +58,7 @@ public class ProcessResultsParserTests extends ESTestCase { public void testParseResults() throws IOException { String input = "[{\"field_1\": \"a\", \"field_2\": 1.0}, {\"field_1\": \"b\", \"field_2\": 2.0}," + " {\"field_1\": \"c\", \"field_2\": 3.0}]"; - try (InputStream inputStream = new ByteArrayInputStream(input.getBytes(Charsets.UTF_8))) { + try (InputStream inputStream = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8))) { ProcessResultsParser parser = new ProcessResultsParser<>(TestResult.PARSER, NamedXContentRegistry.EMPTY); Iterator testResultIterator = parser.parseResults(inputStream); diff --git a/x-pack/plugin/security/build.gradle b/x-pack/plugin/security/build.gradle index 29e4be4f52e..8410c57f196 100644 --- a/x-pack/plugin/security/build.gradle +++ b/x-pack/plugin/security/build.gradle @@ -55,7 +55,7 @@ dependencies { compile "org.apache.httpcomponents:httpasyncclient:${versions.httpasyncclient}" compile "org.apache.httpcomponents:httpcore-nio:${versions.httpcore}" compile "org.apache.httpcomponents:httpclient-cache:${versions.httpclient}" - compile 'com.google.guava:guava:19.0' + runtimeOnly 'com.google.guava:guava:19.0' // Dependencies for oidc compile "com.nimbusds:oauth2-oidc-sdk:7.0.2" diff --git a/x-pack/plugin/security/cli/build.gradle b/x-pack/plugin/security/cli/build.gradle index 78048537bfb..efefb6dc3e7 100644 --- a/x-pack/plugin/security/cli/build.gradle +++ b/x-pack/plugin/security/cli/build.gradle @@ -10,7 +10,11 @@ dependencies { compileOnly project(path: xpackModule('core'), configuration: 'default') compile "org.bouncycastle:bcpkix-jdk15on:${versions.bouncycastle}" compile "org.bouncycastle:bcprov-jdk15on:${versions.bouncycastle}" - testImplementation 'com.google.jimfs:jimfs:1.1' + testImplementation('com.google.jimfs:jimfs:1.1') { + // this is provided by the runtime classpath, from the security project + exclude group: 'com.google.guava', module: 'guava' + } + testRuntimeOnly 'com.google.guava:guava:19.0' testCompile project(":test:framework") testCompile project(path: xpackModule('core'), configuration: 'testArtifacts') } diff --git a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java index 81203a43b51..e9878c6fb0f 100644 --- a/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java +++ b/x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java @@ -6,7 +6,6 @@ package org.elasticsearch.xpack.security.authc; -import com.google.common.collect.Sets; import org.elasticsearch.ElasticsearchSecurityException; import org.elasticsearch.action.DocWriteResponse; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; @@ -22,6 +21,7 @@ import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.test.SecurityIntegTestCase; import org.elasticsearch.test.SecuritySettingsSource; diff --git a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/SqlParserTests.java b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/SqlParserTests.java index a82144840b8..0510329e3be 100644 --- a/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/SqlParserTests.java +++ b/x-pack/plugin/sql/src/test/java/org/elasticsearch/xpack/sql/parser/SqlParserTests.java @@ -5,8 +5,6 @@ */ package org.elasticsearch.xpack.sql.parser; -import com.google.common.base.Joiner; - import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.ql.expression.Alias; import org.elasticsearch.xpack.ql.expression.Literal; @@ -214,11 +212,11 @@ public class SqlParserTests extends ESTestCase { // Create expression in the form of a = b OR a = b OR ... a = b // 1000 elements is ok - new SqlParser().createExpression(Joiner.on(" OR ").join(nCopies(1000, "a = b"))); + new SqlParser().createExpression(join(" OR ", nCopies(1000, "a = b"))); // 5000 elements cause stack overflow ParsingException e = expectThrows(ParsingException.class, () -> - new SqlParser().createExpression(Joiner.on(" OR ").join(nCopies(5000, "a = b")))); + new SqlParser().createExpression(join(" OR ", nCopies(5000, "a = b")))); assertThat(e.getMessage(), startsWith("line -1:0: SQL statement is too large, causing stack overflow when generating the parsing tree: [")); } @@ -228,11 +226,11 @@ public class SqlParserTests extends ESTestCase { // 200 elements is ok new SqlParser().createExpression( - Joiner.on("").join(nCopies(200, "abs(")).concat("i").concat(Joiner.on("").join(nCopies(200, ")")))); + join("", nCopies(200, "abs(")).concat("i").concat(join("", nCopies(200, ")")))); // 5000 elements cause stack overflow ParsingException e = expectThrows(ParsingException.class, () -> new SqlParser().createExpression( - Joiner.on("").join(nCopies(1000, "abs(")).concat("i").concat(Joiner.on("").join(nCopies(1000, ")"))))); + join("", nCopies(1000, "abs(")).concat("i").concat(join("", nCopies(1000, ")"))))); assertThat(e.getMessage(), startsWith("line -1:0: SQL statement is too large, causing stack overflow when generating the parsing tree: [")); } @@ -241,11 +239,11 @@ public class SqlParserTests extends ESTestCase { // Create expression in the form of a + a + a + ... + a // 1000 elements is ok - new SqlParser().createExpression(Joiner.on(" + ").join(nCopies(1000, "a"))); + new SqlParser().createExpression(join(" + ", nCopies(1000, "a"))); // 5000 elements cause stack overflow ParsingException e = expectThrows(ParsingException.class, () -> - new SqlParser().createExpression(Joiner.on(" + ").join(nCopies(5000, "a")))); + new SqlParser().createExpression(join(" + ", nCopies(5000, "a")))); assertThat(e.getMessage(), startsWith("line -1:0: SQL statement is too large, causing stack overflow when generating the parsing tree: [")); } @@ -255,15 +253,15 @@ public class SqlParserTests extends ESTestCase { // 200 elements is ok new SqlParser().createStatement( - Joiner.on(" (").join(nCopies(200, "SELECT * FROM")) + join(" (", nCopies(200, "SELECT * FROM")) .concat("t") - .concat(Joiner.on("").join(nCopies(199, ")")))); + .concat(join("", nCopies(199, ")")))); // 500 elements cause stack overflow ParsingException e = expectThrows(ParsingException.class, () -> new SqlParser().createStatement( - Joiner.on(" (").join(nCopies(500, "SELECT * FROM")) + join(" (", nCopies(500, "SELECT * FROM")) .concat("t") - .concat(Joiner.on("").join(nCopies(499, ")"))))); + .concat(join("", nCopies(499, ")"))))); assertThat(e.getMessage(), startsWith("line -1:0: SQL statement is too large, causing stack overflow when generating the parsing tree: [")); } @@ -308,4 +306,12 @@ public class SqlParserTests extends ESTestCase { String dirStr = dir.toString(); return randomBoolean() && dirStr.equals("ASC") ? "" : " " + dirStr; } + + private String join(String delimiter, Iterable strings) { + StringJoiner joiner = new StringJoiner(delimiter); + for (String s : strings) { + joiner.add(s); + } + return joiner.toString(); + } } diff --git a/x-pack/plugin/watcher/build.gradle b/x-pack/plugin/watcher/build.gradle index 0c67c7d9dc7..2f360c31486 100644 --- a/x-pack/plugin/watcher/build.gradle +++ b/x-pack/plugin/watcher/build.gradle @@ -35,8 +35,8 @@ dependencies { // watcher deps compile 'com.googlecode.owasp-java-html-sanitizer:owasp-java-html-sanitizer:20191001.1' - compile 'com.google.guava:guava:27.1-jre' // needed by watcher for the html sanitizer - compile 'com.google.guava:failureaccess:1.0.1' + runtimeOnly 'com.google.guava:guava:27.1-jre' // needed by watcher for the html sanitizer + runtimeOnly 'com.google.guava:failureaccess:1.0.1' compile 'com.sun.mail:jakarta.mail:1.6.4' compile 'com.sun.activation:jakarta.activation:1.2.1' compileOnly "org.apache.httpcomponents:httpclient:${versions.httpclient}" diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/execution/ExecutionService.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/execution/ExecutionService.java index 5ca4d14385b..296c521771f 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/execution/ExecutionService.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/execution/ExecutionService.java @@ -5,8 +5,6 @@ */ package org.elasticsearch.xpack.watcher.execution; -import com.google.common.collect.Iterables; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; @@ -33,6 +31,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; import org.elasticsearch.common.util.concurrent.ThreadContext; +import org.elasticsearch.common.util.iterable.Iterables; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/HtmlSanitizer.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/HtmlSanitizer.java index c7be7e6db0f..32eb25f2165 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/HtmlSanitizer.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/HtmlSanitizer.java @@ -14,12 +14,16 @@ import org.owasp.html.ElementPolicy; import org.owasp.html.HtmlPolicyBuilder; import org.owasp.html.PolicyFactory; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Locale; import java.util.function.Function; +import java.util.function.UnaryOperator; public class HtmlSanitizer { @@ -47,23 +51,43 @@ public class HtmlSanitizer { private static Setting> SETTING_SANITIZATION_DISALLOW = Setting.listSetting("xpack.notification.email.html.sanitization.disallow", Collections.emptyList(), Function.identity(), Property.NodeScope); + private static final MethodHandle sanitizeHandle; + static { + try { + MethodHandles.Lookup methodLookup = MethodHandles.publicLookup(); + MethodType sanitizeSignature = MethodType.methodType(String.class, String.class); + sanitizeHandle = methodLookup.findVirtual(PolicyFactory.class, "sanitize", sanitizeSignature); + } catch (NoSuchMethodException|IllegalAccessException e) { + throw new RuntimeException("Missing guava on runtime classpath", e); + } + } private final boolean enabled; - @SuppressForbidden( reason = "PolicyFactory uses guava Function") - private final PolicyFactory policy; - + private final UnaryOperator sanitizer; + public HtmlSanitizer(Settings settings) { enabled = SETTING_SANITIZATION_ENABLED.get(settings); List allow = SETTING_SANITIZATION_ALLOW.get(settings); List disallow = SETTING_SANITIZATION_DISALLOW.get(settings); - policy = createCommonPolicy(allow, disallow); + + // The sanitize method of PolicyFactory pulls in guava dependencies, which we want to isolate to + // runtime only rather than compile time where more guava uses can be accidentally pulled in. + // Here we lookup the sanitize method at runtime and grab a method handle to invoke. + PolicyFactory policy = createCommonPolicy(allow, disallow); + sanitizer = s -> { + try { + return (String) sanitizeHandle.invokeExact(policy, s); + } catch (Throwable e) { + throw new RuntimeException("Failed to invoke sanitize method of PolicyFactory", e); + } + }; } public String sanitize(String html) { if (!enabled) { return html; } - return policy.sanitize(html); + return sanitizer.apply(html); } @SuppressForbidden( reason = "PolicyFactory uses guava Function") diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParser.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParser.java index 1a5e853f3f2..2f8035cad9f 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParser.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParser.java @@ -5,7 +5,6 @@ */ package org.elasticsearch.xpack.watcher.notification.email.attachment; -import com.google.common.collect.ImmutableMap; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.message.ParameterizedMessage; @@ -42,6 +41,7 @@ import java.io.InputStream; import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -70,8 +70,9 @@ public class ReportingAttachmentParser implements EmailAttachmentParser PAYLOAD_PARSER = new ObjectParser<>("reporting_attachment_kibana_payload", true, null); - static final Map WARNINGS = ImmutableMap.of("kbn-csv-contains-formulas", "Warning: The attachment [%s] contains " + - "characters which spreadsheet applications may interpret as formulas. Please ensure that the attachment is safe prior to opening."); + static final Map WARNINGS = Collections.singletonMap("kbn-csv-contains-formulas", + "Warning: The attachment [%s] contains characters which spreadsheet applications may interpret as formulas." + + "Please ensure that the attachment is safe prior to opening."); static { PARSER.declareInt(Builder::retries, ReportingAttachment.RETRIES); diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/ActionWrapperTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/ActionWrapperTests.java index cc89c7a8d49..610f10e23de 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/ActionWrapperTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/actions/ActionWrapperTests.java @@ -5,7 +5,6 @@ */ package org.elasticsearch.xpack.watcher.actions; -import com.google.common.collect.ImmutableMap; import org.elasticsearch.common.Strings; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -209,12 +208,12 @@ public class ActionWrapperTests extends ESTestCase { List> itemsPayload = new ArrayList<>(); for (int i = 0; i < randomMaxIterations + 1; i++) { final Action.Result actionResult = new LoggingAction.Result.Success("log_message " + i);; - final Payload singleItemPayload = new Payload.Simple(ImmutableMap.of("key", String.valueOf(i))); - itemsPayload.add(ImmutableMap.of("key", String.valueOf(i))); + final Payload singleItemPayload = new Payload.Simple(Collections.singletonMap("key", String.valueOf(i))); + itemsPayload.add(Collections.singletonMap("key", String.valueOf(i))); when(executableAction.execute(eq("_action"), eq(ctx), eq(singleItemPayload))).thenReturn(actionResult); } - Payload.Simple payload = new Payload.Simple(ImmutableMap.of("my_path", itemsPayload)); + Payload.Simple payload = new Payload.Simple(Collections.singletonMap("my_path", itemsPayload)); when(ctx.payload()).thenReturn(payload); when(executableAction.logger()).thenReturn(logger); @@ -233,7 +232,7 @@ public class ActionWrapperTests extends ESTestCase { assertThat(map, hasKey("max_iterations")); assertThat(map.get("max_iterations"), is(randomMaxIterations)); assertThat(map, hasKey("number_of_actions_executed")); - assertThat(map.get("number_of_actions_executed"), is(randomMaxIterations)); + assertThat(map.get("number_of_actions_executed"), is(randomMaxIterations)); } } diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/SizeLimitInputStreamTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/SizeLimitInputStreamTests.java index fa9af2367bc..15de48eb4a6 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/SizeLimitInputStreamTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/common/http/SizeLimitInputStreamTests.java @@ -12,7 +12,7 @@ import org.elasticsearch.test.ESTestCase; import java.io.ByteArrayInputStream; import java.io.IOException; -import static com.google.common.base.Charsets.UTF_8; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.hamcrest.Matchers.is; public class SizeLimitInputStreamTests extends ESTestCase { @@ -52,4 +52,4 @@ public class SizeLimitInputStreamTests extends ESTestCase { } } } -} \ No newline at end of file +} diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/EmailTemplateTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/EmailTemplateTests.java index 4ba038b22f4..48ec88d5382 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/EmailTemplateTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/EmailTemplateTests.java @@ -5,8 +5,6 @@ */ package org.elasticsearch.xpack.watcher.notification.email; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -18,8 +16,10 @@ import org.elasticsearch.xpack.watcher.test.MockTextTemplateEngine; import org.mockito.ArgumentCaptor; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -185,14 +185,15 @@ public class EmailTemplateTests extends ESTestCase { ArgumentCaptor htmlSanitizeArguments = ArgumentCaptor.forClass(String.class); //4 attachments, zero warning, one warning, two warnings, and one with html that should be stripped - Map attachments = ImmutableMap.of( - "one", new Attachment.Bytes("one", "one", randomByteArrayOfLength(100), randomAlphaOfLength(5), false, Collections.emptySet()), - "two", new Attachment.Bytes("two", "two", randomByteArrayOfLength(100), randomAlphaOfLength(5), false, - ImmutableSet.of("warning0")), - "thr", new Attachment.Bytes("thr", "thr", randomByteArrayOfLength(100), randomAlphaOfLength(5), false, - ImmutableSet.of("warning1", "warning2")), - "for", new Attachment.Bytes("for", "for", randomByteArrayOfLength(100), randomAlphaOfLength(5), false, - ImmutableSet.of(""))); + Map attachments = new HashMap<>(); + attachments.put("one", + new Attachment.Bytes("one", "one", randomByteArrayOfLength(100), randomAlphaOfLength(5), false, Collections.emptySet())); + attachments.put("two", new Attachment.Bytes("two", "two", randomByteArrayOfLength(100), randomAlphaOfLength(5), false, + Collections.singleton("warning0"))); + attachments.put("thr", new Attachment.Bytes("thr", "thr", randomByteArrayOfLength(100), randomAlphaOfLength(5), false, + Collections.unmodifiableSet(new HashSet<>(Arrays.asList("warning1", "warning2"))))); + attachments.put("for", new Attachment.Bytes("for", "for", randomByteArrayOfLength(100), randomAlphaOfLength(5), false, + Collections.singleton(""))); Email.Builder emailBuilder = parsedEmailTemplate.render(new MockTextTemplateEngine(), model, htmlSanitizer, attachments); emailBuilder.id("_id"); diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParserTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParserTests.java index fd7ceb7790b..bfce940fd70 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParserTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/notification/email/attachment/ReportingAttachmentParserTests.java @@ -6,11 +6,11 @@ package org.elasticsearch.xpack.watcher.notification.email.attachment; import com.fasterxml.jackson.core.io.JsonEOFException; -import com.google.common.collect.ImmutableSet; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.ClusterSettings; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentBuilder; @@ -39,6 +39,7 @@ import java.nio.charset.StandardCharsets; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -569,8 +570,8 @@ public class ReportingAttachmentParserTests extends ESTestCase { private ClusterService mockClusterService() { ClusterService clusterService = mock(ClusterService.class); ClusterSettings clusterSettings = - new ClusterSettings(Settings.EMPTY, - ImmutableSet.of(INTERVAL_SETTING, RETRIES_SETTING, REPORT_WARNING_ENABLED_SETTING, REPORT_WARNING_TEXT)); + new ClusterSettings(Settings.EMPTY, Collections.unmodifiableSet(new HashSet>( + Arrays.asList(INTERVAL_SETTING, RETRIES_SETTING, REPORT_WARNING_ENABLED_SETTING, REPORT_WARNING_TEXT)))); when(clusterService.getClusterSettings()).thenReturn(clusterSettings); return clusterService; } diff --git a/x-pack/qa/security-tools-tests/build.gradle b/x-pack/qa/security-tools-tests/build.gradle index 135f82bb4a6..1c5581bf7f6 100644 --- a/x-pack/qa/security-tools-tests/build.gradle +++ b/x-pack/qa/security-tools-tests/build.gradle @@ -4,7 +4,7 @@ dependencies { testCompile project(xpackModule('security')) testCompile project(path: xpackModule('security'), configuration: 'testArtifacts') testCompile 'com.google.jimfs:jimfs:1.1' - testCompile 'com.google.guava:guava:16.0.1' + testRuntimeOnly 'com.google.guava:guava:16.0.1' } // add test resources from security, so certificate tool tests can use example certs diff --git a/x-pack/snapshot-tool/build.gradle b/x-pack/snapshot-tool/build.gradle index 4adabef7e38..fbac8866ddb 100644 --- a/x-pack/snapshot-tool/build.gradle +++ b/x-pack/snapshot-tool/build.gradle @@ -32,7 +32,6 @@ dependencies { // GCS dependencies compile 'com.google.cloud:google-cloud-storage:1.106.0' compile 'com.google.cloud:google-cloud-core:1.93.3' - compile 'com.google.guava:guava:26.0-jre' compile 'com.google.http-client:google-http-client:1.34.2' compile "org.apache.httpcomponents:httpclient:${versions.httpclient}" compile "org.apache.httpcomponents:httpcore:${versions.httpcore}" @@ -59,6 +58,7 @@ dependencies { compile 'io.opencensus:opencensus-api:0.18.0' compile 'io.opencensus:opencensus-contrib-http-util:0.18.0' compile 'com.google.apis:google-api-services-storage:v1-rev20200226-1.30.9' + runtimeOnly 'com.google.guava:guava:26.0-jre' // HACK: javax.xml.bind was removed from default modules in java 9, so we pull the api in here, // and whitelist this hack in JarHell