fix permissions bugs

This commit is contained in:
Robert Muir 2015-05-04 16:27:24 -04:00
parent fe046df125
commit 2ed2c4f884
9 changed files with 55 additions and 27 deletions

Binary file not shown.

View File

@ -37,7 +37,7 @@
<testframework.version>2.1.14</testframework.version> <testframework.version>2.1.14</testframework.version>
<tests.jvms>auto</tests.jvms> <tests.jvms>auto</tests.jvms>
<tests.shuffle>true</tests.shuffle> <tests.shuffle>true</tests.shuffle>
<tests.output>always</tests.output> <tests.output>onerror</tests.output>
<tests.client.ratio></tests.client.ratio> <tests.client.ratio></tests.client.ratio>
<tests.bwc.path>${project.basedir}/backwards</tests.bwc.path> <tests.bwc.path>${project.basedir}/backwards</tests.bwc.path>
<tests.locale>random</tests.locale> <tests.locale>random</tests.locale>
@ -584,7 +584,6 @@
<param>-Des.logger.prefix=</param> <param>-Des.logger.prefix=</param>
<param>-XX:+HeapDumpOnOutOfMemoryError</param> <param>-XX:+HeapDumpOnOutOfMemoryError</param>
<param>-XX:HeapDumpPath=${tests.heapdump.path}</param> <param>-XX:HeapDumpPath=${tests.heapdump.path}</param>
<param>-Djava.security.debug=access:failure,policy</param>
</jvmArgs> </jvmArgs>
<shuffleOnSlave>${tests.shuffle}</shuffleOnSlave> <shuffleOnSlave>${tests.shuffle}</shuffleOnSlave>
<sysouts>${tests.verbose}</sysouts> <sysouts>${tests.verbose}</sysouts>

View File

@ -19,8 +19,6 @@
package org.elasticsearch.bootstrap; package org.elasticsearch.bootstrap;
import org.elasticsearch.common.SuppressForbidden;
import java.net.URI; import java.net.URI;
import java.security.Permission; import java.security.Permission;
import java.security.PermissionCollection; import java.security.PermissionCollection;
@ -37,17 +35,14 @@ public class ESPolicy extends Policy {
final Policy template; final Policy template;
final PermissionCollection dynamic; final PermissionCollection dynamic;
@SuppressForbidden(reason = "ok")
public ESPolicy(PermissionCollection dynamic) throws Exception { public ESPolicy(PermissionCollection dynamic) throws Exception {
URI uri = getClass().getResource(POLICY_RESOURCE).toURI(); URI uri = getClass().getResource(POLICY_RESOURCE).toURI();
System.out.println("temp=" + System.getProperty("java.io.tmpdir"));
this.template = Policy.getInstance("JavaPolicy", new URIParameter(uri)); this.template = Policy.getInstance("JavaPolicy", new URIParameter(uri));
this.dynamic = dynamic; this.dynamic = dynamic;
} }
@Override @SuppressForbidden(reason = "ok") @Override
public boolean implies(ProtectionDomain domain, Permission permission) { public boolean implies(ProtectionDomain domain, Permission permission) {
//System.out.println("domain=" + domain);
return template.implies(domain, permission) || dynamic.implies(permission); return template.implies(domain, permission) || dynamic.implies(permission);
} }
} }

View File

@ -19,10 +19,10 @@
package org.elasticsearch.bootstrap; package org.elasticsearch.bootstrap;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
import java.io.*; import java.io.*;
import java.net.URI;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.security.Permissions; import java.security.Permissions;
@ -34,7 +34,7 @@ import java.security.Policy;
* We use a template file (the one we test with), and add additional * We use a template file (the one we test with), and add additional
* permissions based on the environment (data paths, etc) * permissions based on the environment (data paths, etc)
*/ */
class Security { public class Security {
/** /**
* Initializes securitymanager for the environment * Initializes securitymanager for the environment
@ -42,7 +42,7 @@ class Security {
*/ */
static void configure(Environment environment) throws Exception { static void configure(Environment environment) throws Exception {
// enable security policy: union of template and environment-based paths. // enable security policy: union of template and environment-based paths.
Policy.setPolicy(new ESPolicy(createPermissions(environment))); Policy.setPolicy(new ESPolicy(createPermissions(environment, true)));
// enable security manager // enable security manager
System.setSecurityManager(new SecurityManager()); System.setSecurityManager(new SecurityManager());
@ -52,10 +52,13 @@ class Security {
} }
/** returns dynamic Permissions to configured paths */ /** returns dynamic Permissions to configured paths */
static Permissions createPermissions(Environment environment) throws IOException { static Permissions createPermissions(Environment environment, boolean addTempDir) throws IOException {
// TODO: improve test infra so we can reduce permissions where read/write // TODO: improve test infra so we can reduce permissions where read/write
// is not really needed... // is not really needed...
Permissions policy = new Permissions(); Permissions policy = new Permissions();
if (addTempDir) {
addPath(policy, PathUtils.get(System.getProperty("java.io.tmpdir")), "read,readlink,write,delete");
}
addPath(policy, environment.homeFile(), "read,readlink,write,delete"); addPath(policy, environment.homeFile(), "read,readlink,write,delete");
addPath(policy, environment.configFile(), "read,readlink,write,delete"); addPath(policy, environment.configFile(), "read,readlink,write,delete");
addPath(policy, environment.logsFile(), "read,readlink,write,delete"); addPath(policy, environment.logsFile(), "read,readlink,write,delete");
@ -71,7 +74,7 @@ class Security {
} }
/** Add access to path (and all files underneath it */ /** Add access to path (and all files underneath it */
static void addPath(Permissions policy, Path path, String permissions) throws IOException { public static void addPath(Permissions policy, Path path, String permissions) throws IOException {
// paths may not exist yet // paths may not exist yet
Files.createDirectories(path); Files.createDirectories(path);
// add each path twice: once for itself, again for files underneath it // add each path twice: once for itself, again for files underneath it
@ -80,7 +83,7 @@ class Security {
} }
/** Simple checks that everything is ok */ /** Simple checks that everything is ok */
static void selfTest() { public static void selfTest() {
// check we can manipulate temporary files // check we can manipulate temporary files
try { try {
Files.delete(Files.createTempFile(null, null)); Files.delete(Files.createTempFile(null, null));

View File

@ -21,15 +21,36 @@
// On startup, BootStrap reads environment and adds additional permissions // On startup, BootStrap reads environment and adds additional permissions
// for configured paths to these. // for configured paths to these.
//// System code permissions:
// These permissions apply to javac
grant codeBase "file:${java.home}/lib/-" {
permission java.security.AllPermission;
};
// These permissions apply to all shared system extensions
grant codeBase "file:${java.home}/jre/lib/ext/-" {
permission java.security.AllPermission;
};
// These permissions apply to javac when ${java.home] points at $JAVA_HOME/jre
grant codeBase "file:${java.home}/../lib/-" {
permission java.security.AllPermission;
};
// These permissions apply to all shared system extensions when
// ${java.home} points at $JAVA_HOME/jre
grant codeBase "file:${java.home}/lib/ext/-" {
permission java.security.AllPermission;
};
//// Everything else:
grant { grant {
// system jar resources // system jar resources
permission java.io.FilePermission "${java.home}${/}-", "read"; permission java.io.FilePermission "${java.home}${/}-", "read";
// temporary files
permission java.io.FilePermission "${java.io.tmpdir}", "read,write";
permission java.io.FilePermission "${java.io.tmpdir}${/}-", "read,write,delete";
// paths used for running tests // paths used for running tests
// compiled classes // compiled classes
permission java.io.FilePermission "${project.basedir}${/}target${/}classes${/}-", "read"; permission java.io.FilePermission "${project.basedir}${/}target${/}classes${/}-", "read";

View File

@ -40,11 +40,12 @@ public class SecurityTests extends ElasticsearchTestCase {
Settings settings = settingsBuilder.build(); Settings settings = settingsBuilder.build();
Environment environment = new Environment(settings); Environment environment = new Environment(settings);
Permissions permissions = Security.createPermissions(environment); // we pass false to not include temp (or it will grant permissions to everything here)
Permissions permissions = Security.createPermissions(environment, false);
// the fake es home // the fake es home
assertTrue(permissions.implies(new FilePermission(esHome.toString(), "read"))); assertTrue(permissions.implies(new FilePermission(esHome.toString(), "read")));
// its parent // its filesystem root
assertFalse(permissions.implies(new FilePermission(path.toString(), "read"))); assertFalse(permissions.implies(new FilePermission(path.toString(), "read")));
// some other sibling // some other sibling
assertFalse(permissions.implies(new FilePermission(path.resolve("other").toString(), "read"))); assertFalse(permissions.implies(new FilePermission(path.resolve("other").toString(), "read")));
@ -63,7 +64,7 @@ public class SecurityTests extends ElasticsearchTestCase {
Settings settings = settingsBuilder.build(); Settings settings = settingsBuilder.build();
Environment environment = new Environment(settings); Environment environment = new Environment(settings);
Permissions permissions = Security.createPermissions(environment); Permissions permissions = Security.createPermissions(environment, false);
// check that all directories got permissions: // check that all directories got permissions:
// homefile: this is needed unless we break out rules for "lib" dir. // homefile: this is needed unless we break out rules for "lib" dir.

View File

@ -93,7 +93,7 @@ import static com.google.common.collect.Lists.newArrayList;
public abstract class ElasticsearchTestCase extends LuceneTestCase { public abstract class ElasticsearchTestCase extends LuceneTestCase {
static { static {
SecurityHack.ensureInitialized(); SecurityBootstrap.ensureInitialized();
} }
protected final ESLogger logger = Loggers.getLogger(getClass()); protected final ESLogger logger = Loggers.getLogger(getClass());

View File

@ -43,7 +43,7 @@ import org.elasticsearch.test.junit.listeners.ReproduceInfoPrinter;
public abstract class ElasticsearchTokenStreamTestCase extends BaseTokenStreamTestCase { public abstract class ElasticsearchTokenStreamTestCase extends BaseTokenStreamTestCase {
static { static {
SecurityHack.ensureInitialized(); SecurityBootstrap.ensureInitialized();
} }
public static Version randomVersion() { public static Version randomVersion() {

View File

@ -22,6 +22,8 @@ package org.elasticsearch.test;
import org.apache.lucene.util.TestSecurityManager; import org.apache.lucene.util.TestSecurityManager;
import org.elasticsearch.bootstrap.Bootstrap; import org.elasticsearch.bootstrap.Bootstrap;
import org.elasticsearch.bootstrap.ESPolicy; import org.elasticsearch.bootstrap.ESPolicy;
import org.elasticsearch.bootstrap.Security;
import org.elasticsearch.common.io.PathUtils;
import java.security.Permissions; import java.security.Permissions;
import java.security.Policy; import java.security.Policy;
@ -32,10 +34,13 @@ import static com.carrotsearch.randomizedtesting.RandomizedTest.systemPropertyAs
* Installs test security manager (ensures it happens regardless of which * Installs test security manager (ensures it happens regardless of which
* test case happens to be first, test ordering, etc). * test case happens to be first, test ordering, etc).
* <p> * <p>
* Note that this is BS, this should be done by the jvm (by passing -Djava.security.manager). * The idea is to mimic as much as possible what happens with ES in production
* turning it on/off needs to be the role of maven, not this stuff. * mode (e.g. assign permissions and install security manager the same way)
*/ */
class SecurityHack { class SecurityBootstrap {
// TODO: can we share more code with the non-test side here
// without making things complex???
static { static {
// just like bootstrap, initialize natives, then SM // just like bootstrap, initialize natives, then SM
@ -43,8 +48,12 @@ class SecurityHack {
// install security manager if requested // install security manager if requested
if (systemPropertyAsBoolean("tests.security.manager", false)) { if (systemPropertyAsBoolean("tests.security.manager", false)) {
try { try {
Policy.setPolicy(new ESPolicy(new Permissions())); // initialize tmpdir the same exact way as bootstrap.
Permissions perms = new Permissions();
Security.addPath(perms, PathUtils.get(System.getProperty("java.io.tmpdir")), "read,readlink,write,delete");
Policy.setPolicy(new ESPolicy(perms));
System.setSecurityManager(new TestSecurityManager()); System.setSecurityManager(new TestSecurityManager());
Security.selfTest();
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("unable to install test security manager", e); throw new RuntimeException("unable to install test security manager", e);
} }