diff --git a/core/src/main/java/org/elasticsearch/bootstrap/BootstrapInfo.java b/core/src/main/java/org/elasticsearch/bootstrap/BootstrapInfo.java index abaa784d0b9..fc7e28534c5 100644 --- a/core/src/main/java/org/elasticsearch/bootstrap/BootstrapInfo.java +++ b/core/src/main/java/org/elasticsearch/bootstrap/BootstrapInfo.java @@ -54,6 +54,6 @@ public final class BootstrapInfo { * that require additional privileges as a workaround. */ public static Set getInsecurePluginList() { - return Collections.unmodifiableSet(Security.INSECURE_PLUGINS.keySet()); + return Collections.unmodifiableSet(Security.SPECIAL_PLUGINS.keySet()); } } diff --git a/core/src/main/java/org/elasticsearch/bootstrap/Security.java b/core/src/main/java/org/elasticsearch/bootstrap/Security.java index a8ed511be13..df2f6481739 100644 --- a/core/src/main/java/org/elasticsearch/bootstrap/Security.java +++ b/core/src/main/java/org/elasticsearch/bootstrap/Security.java @@ -20,8 +20,6 @@ package org.elasticsearch.bootstrap; import org.elasticsearch.common.SuppressForbidden; -import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.env.Environment; import java.io.*; @@ -159,15 +157,39 @@ final class Security { } } - // mapping of insecure plugins to codebase properties + // mapping of plugins to plugin class name. see getPluginClass why we need this. + // plugin codebase property is always implicit (es.security.plugin.foobar) // note that this is only read once, when policy is parsed. - static final Map INSECURE_PLUGINS; + static final Map SPECIAL_PLUGINS; static { Map m = new HashMap<>(); - m.put("repository-s3", "es.security.insecure.plugin.repository-s3"); - m.put("discovery-ec2", "es.security.insecure.plugin.discovery-ec2"); - m.put("cloud-gce", "es.security.insecure.plugin.cloud-gce" ); - INSECURE_PLUGINS = Collections.unmodifiableMap(m); + m.put("repository-s3", "org.elasticsearch.plugin.repository.s3.S3RepositoryPlugin"); + m.put("discovery-ec2", "org.elasticsearch.plugin.discovery.ec2.Ec2DiscoveryPlugin"); + m.put("cloud-gce", "org.elasticsearch.plugin.cloud.gce.CloudGcePlugin"); + SPECIAL_PLUGINS = Collections.unmodifiableMap(m); + } + + /** + * Returns policy property for plugin, if it has special permissions. + * otherwise returns null. + */ + static String getPluginProperty(String pluginName) { + if (SPECIAL_PLUGINS.containsKey(pluginName)) { + return "es.security.plugin." + pluginName; + } else { + return null; + } + } + + /** + * Returns plugin class name, if it has special permissions. + * otherwise returns null. + */ + // this is only here to support the intellij IDE + // it sucks to duplicate information, but its worth the tradeoff: sanity + // if it gets out of sync, tests will fail. + static String getPluginClass(String pluginName) { + return SPECIAL_PLUGINS.get(pluginName); } /** @@ -179,20 +201,18 @@ final class Security { if (Files.exists(environment.pluginsFile())) { try (DirectoryStream stream = Files.newDirectoryStream(environment.pluginsFile())) { for (Path plugin : stream) { - String prop = INSECURE_PLUGINS.get(plugin.getFileName().toString()); + String prop = getPluginProperty(plugin.getFileName().toString()); if (prop != null) { if (System.getProperty(prop) != null) { throw new IllegalStateException("property: " + prop + " is unexpectedly set: " + System.getProperty(prop)); } System.setProperty(prop, plugin.toUri().toURL().toString() + "*"); - ESLogger logger = Loggers.getLogger(Security.class); - logger.warn("Adding permissions for insecure plugin [{}]", plugin.getFileName()); - logger.warn("There are unresolved issues with third-party code that may reduce the security of the system"); } } } } - for (String prop : INSECURE_PLUGINS.values()) { + for (String plugin : SPECIAL_PLUGINS.keySet()) { + String prop = getPluginProperty(plugin); if (System.getProperty(prop) == null) { System.setProperty(prop, "file:/dev/null"); // no chance to be interpreted as "all" } diff --git a/core/src/main/resources/org/elasticsearch/bootstrap/security.policy b/core/src/main/resources/org/elasticsearch/bootstrap/security.policy index 72ccc19acc3..c21e58d1d53 100644 --- a/core/src/main/resources/org/elasticsearch/bootstrap/security.policy +++ b/core/src/main/resources/org/elasticsearch/bootstrap/security.policy @@ -37,22 +37,22 @@ grant codeBase "${es.security.jar.lucene.core}" { permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; }; -//// Insecure plugin permissions: -//// These are dangerous permissions due to problems in third-party library code -//// We try our best to contain and protect the issues, but ultimately warn the user -//// when installing these plugins that it can introduce a security risk +//// Special plugin permissions: +//// These are dangerous permissions only needed by special plugins that we don't +//// want to grant in general. Some may be due to problems in third-party library code, +//// others may just be more obscure integrations. -grant codeBase "${es.security.insecure.plugin.repository-s3}" { +grant codeBase "${es.security.plugin.repository-s3}" { // needed because of problems in aws-sdk permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; }; -grant codeBase "${es.security.insecure.plugin.discovery-ec2}" { +grant codeBase "${es.security.plugin.discovery-ec2}" { // needed because of problems in aws-sdk permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; }; -grant codeBase "${es.security.insecure.plugin.cloud-gce}" { +grant codeBase "${es.security.plugin.cloud-gce}" { // needed because of problems in cloud-gce permission java.lang.reflect.ReflectPermission "suppressAccessChecks"; }; diff --git a/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java b/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java index 8e155fa6915..5b2d9de9af6 100644 --- a/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java +++ b/core/src/test/java/org/elasticsearch/bootstrap/BootstrapForTesting.java @@ -32,6 +32,7 @@ import java.net.URL; import java.nio.file.Path; import java.security.Permissions; import java.security.Policy; +import java.util.Map; import java.util.Objects; import static com.carrotsearch.randomizedtesting.RandomizedTest.systemPropertyAsBoolean; @@ -115,16 +116,24 @@ public class BootstrapForTesting { } final Policy policy; - // if its an insecure plugin, we use a wrapper policy impl to try + // if its a plugin with special permissions, we use a wrapper policy impl to try // to simulate what happens with a real distribution String artifact = System.getProperty("tests.artifact"); // in case we are running from the IDE: - if (artifact == null || System.getProperty("tests.maven") == null) { - artifact = PathUtils.get(System.getProperty("user.dir")).toAbsolutePath().getFileName().toString(); + if (artifact == null && System.getProperty("tests.maven") == null) { + // look for plugin classname as a resource to determine what project we are. + // while gross, this will work with any IDE. + for (Map.Entry kv : Security.SPECIAL_PLUGINS.entrySet()) { + String resource = kv.getValue().replace('.', '/') + ".class"; + if (BootstrapForTesting.class.getClassLoader().getResource(resource) != null) { + artifact = kv.getKey(); + break; + } + } } - String insecurePluginProp = Security.INSECURE_PLUGINS.get(artifact); - if (insecurePluginProp != null) { - policy = new MockPluginPolicy(perms, insecurePluginProp); + String pluginProp = Security.getPluginProperty(artifact); + if (pluginProp != null) { + policy = new MockPluginPolicy(perms, pluginProp); } else { policy = new ESPolicy(perms); } @@ -132,14 +141,10 @@ public class BootstrapForTesting { System.setSecurityManager(new TestSecurityManager()); Security.selfTest(); - if (insecurePluginProp != null) { + if (pluginProp != null) { // initialize the plugin class, in case it has one-time hacks (unit tests often won't do this) - String clazz = System.getProperty("tests.plugin.classname"); - if (clazz != null) { - Class.forName(clazz); - } else if (System.getProperty("tests.maven") != null) { - throw new IllegalStateException("plugin classname is needed for insecure plugin unit tests: something wrong with build"); - } + String clazz = Security.getPluginClass(artifact); + Class.forName(clazz); } } catch (Exception e) { throw new RuntimeException("unable to install test security manager", e); diff --git a/pom.xml b/pom.xml index 5a24723776f..6c23819ff4d 100644 --- a/pom.xml +++ b/pom.xml @@ -664,9 +664,8 @@ ${tests.cluster} ${tests.iters} ${project.groupId}:${project.artifactId} - + ${project.artifactId} - ${elasticsearch.plugin.classname} ${tests.maxfailures} ${tests.failfast} ${tests.class}