Remove java.lang.reflect.ReflectPermission "suppressAccessChecks"
Closes #13603
Squashed commit of the following:
commit 8799fb42d80297a79285beaf407b1bbecdb5854d
Author: Robert Muir <rmuir@apache.org>
Date: Wed Sep 16 03:32:29 2015 -0400
Add randomizedtesting snapshot note
commit 0d874d9f0f5fddaeab8f48f9816a052dcaa691be
Author: Robert Muir <rmuir@apache.org>
Date: Wed Sep 16 03:11:01 2015 -0400
Add a mechanism for insecure plugins and get all tests passing
commit 80540aeb9a264f6f299aaa3bc89df7f9b7923a60
Author: Robert Muir <rmuir@apache.org>
Date: Tue Sep 15 22:59:29 2015 -0400
Really remove, we are killing this
commit 884818c1ad44ca2e7572a6998c086580be919657
Author: Robert Muir <rmuir@apache.org>
Date: Tue Sep 15 22:57:22 2015 -0400
fill in TODOs
commit 34f4cb81f249edfec4d8d211da892f8c987e5948
Author: Robert Muir <rmuir@apache.org>
Date: Tue Sep 15 22:31:43 2015 -0400
Publish snapshots of RR and lucene and cutover
commit d68eb9d66ce059761805c64d67e41a29098c9afa
Merge: f27e208 f62da59
Author: Robert Muir <rmuir@apache.org>
Date: Tue Sep 15 12:32:41 2015 -0400
Merge branch 'master' into kill-setaccessible
commit f27e20855216dab6a6ad035d41018d8c67f3144c
Author: Robert Muir <rmuir@apache.org>
Date: Tue Sep 15 12:32:21 2015 -0400
make a real lucene snapshot
This commit is contained in:
parent
76b027a979
commit
01e6d8e3dc
|
@ -19,6 +19,9 @@
|
|||
|
||||
package org.elasticsearch.bootstrap;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Exposes system startup information
|
||||
*/
|
||||
|
@ -43,4 +46,14 @@ public final class BootstrapInfo {
|
|||
public static boolean isMemoryLocked() {
|
||||
return Natives.isMemoryLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns set of insecure plugins.
|
||||
* <p>
|
||||
* These are plugins with unresolved issues in third-party libraries,
|
||||
* that require additional privileges as a workaround.
|
||||
*/
|
||||
public static Set<String> getInsecurePluginList() {
|
||||
return Collections.unmodifiableSet(Security.INSECURE_PLUGINS.keySet());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,11 +20,14 @@
|
|||
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.*;
|
||||
import java.net.URL;
|
||||
import java.nio.file.AccessMode;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NotDirectoryException;
|
||||
|
@ -32,6 +35,7 @@ import java.nio.file.Path;
|
|||
import java.security.Permissions;
|
||||
import java.security.Policy;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -95,6 +99,8 @@ final class Security {
|
|||
static void configure(Environment environment) throws Exception {
|
||||
// set properties for jar locations
|
||||
setCodebaseProperties();
|
||||
// set properties for problematic plugins
|
||||
setPluginCodebaseProperties(environment);
|
||||
|
||||
// enable security policy: union of template and environment-based paths.
|
||||
Policy.setPolicy(new ESPolicy(createPermissions(environment)));
|
||||
|
@ -121,6 +127,9 @@ final class Security {
|
|||
static {
|
||||
Map<Pattern,String> m = new IdentityHashMap<>();
|
||||
m.put(Pattern.compile(".*lucene-core-.*\\.jar$"), "es.security.jar.lucene.core");
|
||||
m.put(Pattern.compile(".*lucene-test-framework-.*\\.jar$"), "es.security.jar.lucene.testframework");
|
||||
m.put(Pattern.compile(".*randomizedtesting-runner-.*\\.jar$"), "es.security.jar.randomizedtesting.runner");
|
||||
m.put(Pattern.compile(".*junit4-ant-.*\\.jar$"), "es.security.jar.randomizedtesting.junit4");
|
||||
m.put(Pattern.compile(".*securemock-.*\\.jar$"), "es.security.jar.elasticsearch.securemock");
|
||||
SPECIAL_JARS = Collections.unmodifiableMap(m);
|
||||
}
|
||||
|
@ -150,6 +159,46 @@ final class Security {
|
|||
}
|
||||
}
|
||||
|
||||
// mapping of insecure plugins to codebase properties
|
||||
// note that this is only read once, when policy is parsed.
|
||||
static final Map<String,String> INSECURE_PLUGINS;
|
||||
static {
|
||||
Map<String,String> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets properties (codebase URLs) for policy files.
|
||||
* we look for matching plugins and set URLs to fit
|
||||
*/
|
||||
@SuppressForbidden(reason = "proper use of URL")
|
||||
static void setPluginCodebaseProperties(Environment environment) throws IOException {
|
||||
if (Files.exists(environment.pluginsFile())) {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(environment.pluginsFile())) {
|
||||
for (Path plugin : stream) {
|
||||
String prop = INSECURE_PLUGINS.get(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()) {
|
||||
if (System.getProperty(prop) == null) {
|
||||
System.setProperty(prop, "file:/dev/null"); // no chance to be interpreted as "all"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** returns dynamic Permissions to configured paths */
|
||||
static Permissions createPermissions(Environment environment) throws IOException {
|
||||
Permissions policy = new Permissions();
|
||||
|
|
|
@ -34,6 +34,27 @@ grant codeBase "file:${{java.ext.dirs}}/*" {
|
|||
grant codeBase "${es.security.jar.lucene.core}" {
|
||||
// needed to allow MMapDirectory's "unmap hack"
|
||||
permission java.lang.RuntimePermission "accessClassInPackage.sun.misc";
|
||||
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
|
||||
|
||||
grant codeBase "${es.security.insecure.plugin.repository-s3}" {
|
||||
// needed because of problems in aws-sdk
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
};
|
||||
|
||||
grant codeBase "${es.security.insecure.plugin.discovery-ec2}" {
|
||||
// needed because of problems in aws-sdk
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
};
|
||||
|
||||
grant codeBase "${es.security.insecure.plugin.cloud-gce}" {
|
||||
// needed because of problems in cloud-gce
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
};
|
||||
|
||||
//// test framework permissions.
|
||||
|
@ -43,6 +64,22 @@ grant codeBase "${es.security.jar.lucene.core}" {
|
|||
grant codeBase "${es.security.jar.elasticsearch.securemock}" {
|
||||
// needed to support creation of mocks
|
||||
permission java.lang.RuntimePermission "reflectionFactoryAccess";
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
};
|
||||
|
||||
grant codeBase "${es.security.jar.lucene.testframework}" {
|
||||
// needed by RamUsageTester
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
};
|
||||
|
||||
grant codeBase "${es.security.jar.randomizedtesting.runner}" {
|
||||
// optionally needed for access to private test methods (e.g. beforeClass)
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
};
|
||||
|
||||
grant codeBase "${es.security.jar.randomizedtesting.junit4}" {
|
||||
// needed for gson serialization
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
};
|
||||
|
||||
//// Everything else:
|
||||
|
@ -58,9 +95,6 @@ grant {
|
|||
// Allow read/write to all system properties
|
||||
permission java.util.PropertyPermission "*", "read,write";
|
||||
|
||||
// needed by junit4's gson usage
|
||||
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
|
||||
|
||||
// needed by scripting engines, etc
|
||||
permission java.lang.RuntimePermission "createClassLoader";
|
||||
|
||||
|
|
|
@ -83,6 +83,13 @@ public class BootstrapForTesting {
|
|||
if (systemPropertyAsBoolean("tests.security.manager", true)) {
|
||||
try {
|
||||
Security.setCodebaseProperties();
|
||||
// if its an insecure plugin, its not easy to simulate here, since we don't have a real plugin install.
|
||||
// we just do our best so unit testing can work. integration tests for such plugins are essential.
|
||||
String artifact = System.getProperty("tests.artifact");
|
||||
String insecurePluginProp = Security.INSECURE_PLUGINS.get(artifact);
|
||||
if (insecurePluginProp != null) {
|
||||
System.setProperty(insecurePluginProp, "file:/-");
|
||||
}
|
||||
// initialize paths the same exact way as bootstrap.
|
||||
Permissions perms = new Permissions();
|
||||
// add permissions to everything in classpath
|
||||
|
@ -117,6 +124,15 @@ public class BootstrapForTesting {
|
|||
Policy.setPolicy(new ESPolicy(perms));
|
||||
System.setSecurityManager(new TestSecurityManager());
|
||||
Security.selfTest();
|
||||
|
||||
if (insecurePluginProp != 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) {
|
||||
throw new IllegalStateException("plugin classname is needed for insecure plugin unit tests");
|
||||
}
|
||||
Class.forName(clazz);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("unable to install test security manager", e);
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
8243b938b75818e86aa8d270d8d99529e1847578
|
|
@ -0,0 +1 @@
|
|||
5792c4b38aa2cf1f66c9dea8bf139907e33fa018
|
|
@ -1 +0,0 @@
|
|||
ba85c6e5e77e1f76c52c31d34a59558afa135d47
|
|
@ -0,0 +1 @@
|
|||
cd6fa25bc29718d8c964b0734fc9a009547453db
|
|
@ -1 +0,0 @@
|
|||
f8a38658b6393015c9b33c16b1b4122167b526b2
|
|
@ -0,0 +1 @@
|
|||
e4e0076ce4331309d1270a9c5b2edb51915fe32a
|
|
@ -1 +0,0 @@
|
|||
fa5d27ecadbe346caaf5a571ba71944b51761acf
|
|
@ -0,0 +1 @@
|
|||
ecfb9a923b19fac61b4e9a79275f6bd242b1f091
|
|
@ -1 +0,0 @@
|
|||
2c1464fcf6ede7819f8ba434b9bc7c79f5968407
|
|
@ -0,0 +1 @@
|
|||
49992ef742b6d3a24b551e06c96c0ab9cbad21e7
|
|
@ -1 +0,0 @@
|
|||
a40f9a3ef224bc042ef2ad1b713e318911b6057a
|
|
@ -0,0 +1 @@
|
|||
85544da78c2d33b2fdfa6f76eb621c8c963eae37
|
|
@ -1 +0,0 @@
|
|||
0a7642c9b98cb3d9013fb33be5c0751baf9f0b31
|
|
@ -0,0 +1 @@
|
|||
5c8b58d902a01cfce046e656eddee5c4e0578316
|
|
@ -1 +0,0 @@
|
|||
a0d6461ab9cda93ea530560b0c074a28fe0dd717
|
|
@ -0,0 +1 @@
|
|||
55202617e88437dd6def4e42ceb42d18d08a9f6e
|
|
@ -1 +0,0 @@
|
|||
85c5c7b78715c50157700c90ffd101537446533d
|
|
@ -0,0 +1 @@
|
|||
50b8439558061d0bbf09ddf8144d769143d33f00
|
|
@ -1 +0,0 @@
|
|||
70ca782d6ed458b5f777141353e09600083ed4fe
|
|
@ -0,0 +1 @@
|
|||
ce470e38912676ebc63838635663f17d8db844f5
|
|
@ -1 +0,0 @@
|
|||
b4832cdfe7a6cc7c586a3e28d7cd530acb182232
|
|
@ -0,0 +1 @@
|
|||
318e192d61eb28de09cc62c42d4e9d044a497e8b
|
|
@ -1 +0,0 @@
|
|||
bde73ae2b2324e1576c5789a7e6dd88b6543b939
|
|
@ -0,0 +1 @@
|
|||
043b3c3c03a5e0687884e5894754933d7e8f2f3e
|
|
@ -1 +0,0 @@
|
|||
8d261ff1c2333ce1e040c3aefca9784d1ae71acc
|
|
@ -0,0 +1 @@
|
|||
a9ab07d808456d9a2de248f3b4eba9765808b1cb
|
|
@ -1 +0,0 @@
|
|||
ee041e52dfcdb33a1aa6fab112042b5f33fc0c0c
|
|
@ -0,0 +1 @@
|
|||
c9ae48e40c89364e0e69f27c514c924d52e0d57e
|
|
@ -1 +0,0 @@
|
|||
a8ceb11b26e53612eee9a265ff454351f6dc99f2
|
|
@ -0,0 +1 @@
|
|||
8bd8fb7e75746fd7bce00b4d2813fca738d68f0b
|
|
@ -1 +0,0 @@
|
|||
1f92d0376ca9219b0bf96fe5bd9a913089608d6a
|
|
@ -0,0 +1 @@
|
|||
a71d7e2780ae064a6e6ea5b43357d070351620b8
|
|
@ -1 +0,0 @@
|
|||
60ee5bc1ac8ec102434e7064141a1f40281918b5
|
|
@ -0,0 +1 @@
|
|||
a82b7a125e7cc16c6eb050b68bafc9f1e63eb646
|
|
@ -1 +0,0 @@
|
|||
977aa506485d358b40602347c11238b0f912fe2c
|
|
@ -0,0 +1 @@
|
|||
64b4db89ab7612284b5c685769c3550fb3018bbc
|
|
@ -1 +0,0 @@
|
|||
61911b8400160bd206ea6ea46ba08fd9ba09e72b
|
|
@ -0,0 +1 @@
|
|||
a79e5ed1671d9f511c5aff273ba287557f5f9103
|
|
@ -1 +0,0 @@
|
|||
5a9bdf48b63562bf1ac8a73c1c6bdb4cc450439e
|
|
@ -0,0 +1 @@
|
|||
7b0b74aebbbfdd2175d6ce045fc538261e016417
|
|
@ -27,6 +27,7 @@ import com.google.api.client.json.jackson2.JacksonFactory;
|
|||
import com.google.api.services.compute.Compute;
|
||||
import com.google.api.services.compute.model.Instance;
|
||||
import com.google.api.services.compute.model.InstanceList;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
|
@ -34,7 +35,9 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.unit.TimeValue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -122,7 +125,15 @@ public class GceComputeServiceImpl extends AbstractLifecycleComponent<GceCompute
|
|||
.setTokenServerEncodedUrl(TOKEN_SERVER_ENCODED_URL)
|
||||
.build();
|
||||
|
||||
credential.refreshToken();
|
||||
// hack around code messiness in GCE code
|
||||
// TODO: get this fixed
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
|
||||
@Override
|
||||
public Void run() throws IOException {
|
||||
credential.refreshToken();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
logger.debug("token [{}] will expire in [{}] s", credential.getAccessToken(), credential.getExpiresInSeconds());
|
||||
if (credential.getExpiresInSeconds() != null) {
|
||||
|
|
|
@ -28,6 +28,8 @@ import org.elasticsearch.discovery.ec2.AwsEc2UnicastHostsProvider;
|
|||
import org.elasticsearch.discovery.ec2.Ec2Discovery;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
|
@ -35,6 +37,23 @@ import java.util.Collection;
|
|||
*
|
||||
*/
|
||||
public class Ec2DiscoveryPlugin extends Plugin {
|
||||
|
||||
static {
|
||||
// This internal config is deserialized but with wrong access modifiers,
|
||||
// cannot work without suppressAccessChecks permission right now. We force
|
||||
// a one time load with elevated privileges as a workaround.
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
try {
|
||||
Class.forName("com.amazonaws.internal.config.InternalConfig$Factory");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Unable to initialize internal aws config", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
|
|
|
@ -27,6 +27,8 @@ import org.elasticsearch.plugins.Plugin;
|
|||
import org.elasticsearch.repositories.RepositoriesModule;
|
||||
import org.elasticsearch.repositories.s3.S3Repository;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -35,6 +37,23 @@ import java.util.Collections;
|
|||
*
|
||||
*/
|
||||
public class S3RepositoryPlugin extends Plugin {
|
||||
|
||||
static {
|
||||
// This internal config is deserialized but with wrong access modifiers,
|
||||
// cannot work without suppressAccessChecks permission right now. We force
|
||||
// a one time load with elevated privileges as a workaround.
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
try {
|
||||
Class.forName("com.amazonaws.internal.config.InternalConfig$Factory");
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Unable to initialize internal aws config", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
|
|
23
pom.xml
23
pom.xml
|
@ -45,9 +45,14 @@
|
|||
|
||||
<!-- libraries -->
|
||||
<lucene.version>5.4.0</lucene.version>
|
||||
<lucene.snapshot.revision>1702265</lucene.snapshot.revision>
|
||||
<lucene.snapshot.revision>1702855</lucene.snapshot.revision>
|
||||
<lucene.maven.version>5.4.0-snapshot-${lucene.snapshot.revision}</lucene.maven.version>
|
||||
<testframework.version>2.1.16</testframework.version>
|
||||
<!-- we are using a snapshot of randomizedtesting with this PR:
|
||||
https://github.com/randomizedtesting/randomizedtesting/pull/202
|
||||
This allows us to only give the test-framework jars dangerous permissions and not
|
||||
all of our code/test code. It is temporary while Dawid is on vacation. -->
|
||||
<testframework.snapshot.revision>pr202</testframework.snapshot.revision>
|
||||
<testframework.version>2.2.0-snapshot-${testframework.snapshot.revision}</testframework.version>
|
||||
<jackson.version>2.5.3</jackson.version>
|
||||
<slf4j.version>1.6.2</slf4j.version>
|
||||
<log4j.version>1.2.17</log4j.version>
|
||||
|
@ -145,8 +150,19 @@
|
|||
<id>Lucene snapshots</id>
|
||||
<url>https://download.elasticsearch.org/lucenesnapshots/${lucene.snapshot.revision}</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>Randomized Runner snapshot</id>
|
||||
<url>https://download.elasticsearch.org/lucenesnapshots/rr-${testframework.snapshot.revision}</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>Randomized Runner snapshot</id>
|
||||
<url>https://download.elasticsearch.org/lucenesnapshots/rr-${testframework.snapshot.revision}</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
@ -633,6 +649,9 @@
|
|||
<tests.cluster>${tests.cluster}</tests.cluster>
|
||||
<tests.iters>${tests.iters}</tests.iters>
|
||||
<tests.project>${project.groupId}:${project.artifactId}</tests.project>
|
||||
<!-- these two are needed for insecure plugins, remove if possible! -->
|
||||
<tests.artifact>${project.artifactId}</tests.artifact>
|
||||
<tests.plugin.classname>${elasticsearch.plugin.classname}</tests.plugin.classname>
|
||||
<tests.maxfailures>${tests.maxfailures}</tests.maxfailures>
|
||||
<tests.failfast>${tests.failfast}</tests.failfast>
|
||||
<tests.class>${tests.class}</tests.class>
|
||||
|
|
Loading…
Reference in New Issue