Support tests for insecure plugins on systems with multiple fs roots.

This commit is contained in:
Robert Muir 2015-09-17 02:30:45 -04:00
parent d4e53d8393
commit dc0bebada1
1 changed files with 52 additions and 9 deletions

View File

@ -29,10 +29,14 @@ import org.elasticsearch.common.logging.Loggers;
import java.io.FilePermission;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Policy;
import java.security.cert.Certificate;
import java.util.Collections;
import java.util.Objects;
import static com.carrotsearch.randomizedtesting.RandomizedTest.systemPropertyAsBoolean;
@ -83,14 +87,7 @@ 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.
// initialize paths the same exact way as bootstrap
Permissions perms = new Permissions();
// add permissions to everything in classpath
for (URL url : JarHell.parseClassPath()) {
@ -121,6 +118,14 @@ public class BootstrapForTesting {
// in case we get fancy and use the -integration goals later:
perms.add(new FilePermission(coverageDir.resolve("jacoco-it.exec").toString(), "read,write"));
}
// 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) {
setInsecurePluginPermissions(perms, insecurePluginProp);
}
Policy.setPolicy(new ESPolicy(perms));
System.setSecurityManager(new TestSecurityManager());
Security.selfTest();
@ -139,6 +144,44 @@ public class BootstrapForTesting {
}
}
/**
* with a real plugin install, we just set a property to plugin/foo*, which matches
* plugin code and all dependencies. when running unit tests, things are disorganized,
* and might even be on different filesystem roots (windows), so we can't even make
* a URL that will match everything. instead, add the extra permissions globally.
*/
// TODO: maybe wrap with a policy so the extra permissions aren't applied to test classes/framework,
// so that stacks are always polluted and tests fail for missing AccessController blocks...
static void setInsecurePluginPermissions(Permissions permissions, String insecurePluginProp) throws Exception {
// the hack begins!
// parse whole policy file, with and without the substitution, compute the delta, then add globally.
URL bogus = new URL("file:/bogus");
ESPolicy policy = new ESPolicy(new Permissions());
PermissionCollection small = policy.template.getPermissions(new CodeSource(bogus, (Certificate[])null));
System.setProperty(insecurePluginProp, bogus.toString());
policy = new ESPolicy(new Permissions());
System.clearProperty(insecurePluginProp);
PermissionCollection big = policy.template.getPermissions(new CodeSource(bogus, (Certificate[])null));
PermissionCollection delta = delta(small, big);
for (Permission p : Collections.list(delta.elements())) {
permissions.add(p);
}
}
// computes delta of small and big, the slow way
static PermissionCollection delta(PermissionCollection small, PermissionCollection big) {
Permissions extra = new Permissions();
for (Permission p : Collections.list(big.elements())) {
// check big too, to remove UnresolvedPermissions (acts like NaN)
if (big.implies(p) && small.implies(p) == false) {
extra.add(p);
}
}
return extra;
}
// does nothing, just easy way to make sure the class is loaded.
public static void ensureInitialized() {}
}