mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-04-25 07:37:19 -04:00
Reuse policy parsing for plugins (#64089)
Plugin policy parsing is currently split, with different code executed for Elasticsearch startup vs installing a plugin. This commit refactors the policy parsing to be utilized by both places. The main benefit is policy files in both places now handle permissions not only for a global grant, but also codebase specific grants.
This commit is contained in:
parent
a740a6dd80
commit
2c58841887
11 changed files with 435 additions and 162 deletions
|
@ -38,6 +38,8 @@ import org.bouncycastle.openpgp.operator.jcajce.JcaPGPContentVerifierBuilderProv
|
||||||
import org.elasticsearch.Build;
|
import org.elasticsearch.Build;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
import org.elasticsearch.bootstrap.JarHell;
|
import org.elasticsearch.bootstrap.JarHell;
|
||||||
|
import org.elasticsearch.bootstrap.PluginPolicyInfo;
|
||||||
|
import org.elasticsearch.bootstrap.PolicyUtil;
|
||||||
import org.elasticsearch.cli.EnvironmentAwareCommand;
|
import org.elasticsearch.cli.EnvironmentAwareCommand;
|
||||||
import org.elasticsearch.cli.ExitCodes;
|
import org.elasticsearch.cli.ExitCodes;
|
||||||
import org.elasticsearch.cli.Terminal;
|
import org.elasticsearch.cli.Terminal;
|
||||||
|
@ -848,15 +850,11 @@ class InstallPluginCommand extends EnvironmentAwareCommand {
|
||||||
private PluginInfo installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot, Environment env, List<Path> deleteOnFailure)
|
private PluginInfo installPlugin(Terminal terminal, boolean isBatch, Path tmpRoot, Environment env, List<Path> deleteOnFailure)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final PluginInfo info = loadPluginInfo(terminal, tmpRoot, env);
|
final PluginInfo info = loadPluginInfo(terminal, tmpRoot, env);
|
||||||
// read optional security policy (extra permissions), if it exists, confirm or warn the user
|
PluginPolicyInfo pluginPolicy = PolicyUtil.getPluginPolicyInfo(tmpRoot);
|
||||||
Path policy = tmpRoot.resolve(PluginInfo.ES_PLUGIN_POLICY);
|
if (pluginPolicy != null) {
|
||||||
final Set<String> permissions;
|
Set<String> permissions = PluginSecurity.getPermissionDescriptions(pluginPolicy, env.tmpFile());
|
||||||
if (Files.exists(policy)) {
|
|
||||||
permissions = PluginSecurity.parsePermissions(policy, env.tmpFile());
|
|
||||||
} else {
|
|
||||||
permissions = Collections.emptySet();
|
|
||||||
}
|
|
||||||
PluginSecurity.confirmPolicyExceptions(terminal, permissions, isBatch);
|
PluginSecurity.confirmPolicyExceptions(terminal, permissions, isBatch);
|
||||||
|
}
|
||||||
|
|
||||||
final Path destination = env.pluginsFile().resolve(info.getName());
|
final Path destination = env.pluginsFile().resolve(info.getName());
|
||||||
deleteOnFailure.add(destination);
|
deleteOnFailure.add(destination);
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.bootstrap;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.SuppressForbidden;
|
||||||
|
import org.elasticsearch.plugins.PluginInfo;
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.security.Policy;
|
||||||
|
import java.security.URIParameter;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
|
import static org.hamcrest.Matchers.emptyIterable;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
|
||||||
|
import static org.hamcrest.collection.IsMapContaining.hasKey;
|
||||||
|
|
||||||
|
public class PolicyUtilTests extends ESTestCase {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void assumeSecurityManagerDisabled() {
|
||||||
|
assumeTrue(
|
||||||
|
"test cannot run with security manager enabled",
|
||||||
|
System.getSecurityManager() == null);
|
||||||
|
}
|
||||||
|
|
||||||
|
URL makeUrl(String s) {
|
||||||
|
try {
|
||||||
|
return new URL(s);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Path makeDummyPlugin(String policy, String... files) throws IOException {
|
||||||
|
Path plugin = createTempDir();
|
||||||
|
Files.copy(this.getDataPath(policy), plugin.resolve(PluginInfo.ES_PLUGIN_POLICY));
|
||||||
|
for (String file : files) {
|
||||||
|
Files.createFile(plugin.resolve(file));
|
||||||
|
}
|
||||||
|
return plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressForbidden(reason = "set for test")
|
||||||
|
void setProperty(String key, String value) {
|
||||||
|
System.setProperty(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressForbidden(reason = "cleanup test")
|
||||||
|
void clearProperty(String key) {
|
||||||
|
System.clearProperty(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCodebaseJarMap() throws Exception {
|
||||||
|
Set<URL> urls = new LinkedHashSet<>(List.of(
|
||||||
|
makeUrl("file:///foo.jar"),
|
||||||
|
makeUrl("file:///bar.txt"),
|
||||||
|
makeUrl("file:///a/bar.jar")
|
||||||
|
));
|
||||||
|
|
||||||
|
Map<String, URL> jarMap = PolicyUtil.getCodebaseJarMap(urls);
|
||||||
|
assertThat(jarMap, hasKey("foo.jar"));
|
||||||
|
assertThat(jarMap, hasKey("bar.jar"));
|
||||||
|
// only jars are grabbed
|
||||||
|
assertThat(jarMap, not(hasKey("bar.txt")));
|
||||||
|
|
||||||
|
// order matters
|
||||||
|
assertThat(jarMap.keySet(), contains("foo.jar", "bar.jar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPluginPolicyInfoEmpty() throws Exception {
|
||||||
|
assertThat(PolicyUtil.getPluginPolicyInfo(createTempDir()), is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPluginPolicyInfoNoJars() throws Exception {
|
||||||
|
Path noJarsPlugin = makeDummyPlugin("dummy.policy");
|
||||||
|
PluginPolicyInfo info = PolicyUtil.getPluginPolicyInfo(noJarsPlugin);
|
||||||
|
assertThat(info.policy, is(not(nullValue())));
|
||||||
|
assertThat(info.jars, emptyIterable());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPluginPolicyInfo() throws Exception {
|
||||||
|
Path plugin = makeDummyPlugin("dummy.policy",
|
||||||
|
"foo.jar", "foo.txt", "bar.jar");
|
||||||
|
PluginPolicyInfo info = PolicyUtil.getPluginPolicyInfo(plugin);
|
||||||
|
assertThat(info.policy, is(not(nullValue())));
|
||||||
|
assertThat(info.jars, containsInAnyOrder(
|
||||||
|
plugin.resolve("foo.jar").toUri().toURL(),
|
||||||
|
plugin.resolve("bar.jar").toUri().toURL()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPolicyPermissions() throws Exception {
|
||||||
|
Path plugin = makeDummyPlugin("global-and-jar.policy", "foo.jar", "bar.jar");
|
||||||
|
Path tmpDir = createTempDir();
|
||||||
|
try {
|
||||||
|
URL jarUrl = plugin.resolve("foo.jar").toUri().toURL();
|
||||||
|
setProperty("jarUrl", jarUrl.toString());
|
||||||
|
URL policyFile = plugin.resolve(PluginInfo.ES_PLUGIN_POLICY).toUri().toURL();
|
||||||
|
Policy policy = Policy.getInstance("JavaPolicy", new URIParameter(policyFile.toURI()));
|
||||||
|
|
||||||
|
Set<Permission> globalPermissions = PolicyUtil.getPolicyPermissions(null, policy, tmpDir);
|
||||||
|
assertThat(globalPermissions, contains(new RuntimePermission("queuePrintJob")));
|
||||||
|
|
||||||
|
Set<Permission> jarPermissions = PolicyUtil.getPolicyPermissions(jarUrl, policy, tmpDir);
|
||||||
|
assertThat(jarPermissions,
|
||||||
|
containsInAnyOrder(new RuntimePermission("getClassLoader"), new RuntimePermission("queuePrintJob")));
|
||||||
|
} finally {
|
||||||
|
clearProperty("jarUrl");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,8 +19,12 @@
|
||||||
|
|
||||||
package org.elasticsearch.plugins;
|
package org.elasticsearch.plugins;
|
||||||
|
|
||||||
|
import org.elasticsearch.bootstrap.PluginPolicyInfo;
|
||||||
|
import org.elasticsearch.bootstrap.PolicyUtil;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -30,14 +34,23 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||||
/** Tests plugin manager security check */
|
/** Tests plugin manager security check */
|
||||||
public class PluginSecurityTests extends ESTestCase {
|
public class PluginSecurityTests extends ESTestCase {
|
||||||
|
|
||||||
|
PluginPolicyInfo makeDummyPlugin(String policy, String... files) throws IOException {
|
||||||
|
Path plugin = createTempDir();
|
||||||
|
Files.copy(this.getDataPath(policy), plugin.resolve(PluginInfo.ES_PLUGIN_POLICY));
|
||||||
|
for (String file : files) {
|
||||||
|
Files.createFile(plugin.resolve(file));
|
||||||
|
}
|
||||||
|
return PolicyUtil.getPluginPolicyInfo(plugin);
|
||||||
|
}
|
||||||
|
|
||||||
/** Test that we can parse the set of permissions correctly for a simple policy */
|
/** Test that we can parse the set of permissions correctly for a simple policy */
|
||||||
public void testParsePermissions() throws Exception {
|
public void testParsePermissions() throws Exception {
|
||||||
assumeTrue(
|
assumeTrue(
|
||||||
"test cannot run with security manager enabled",
|
"test cannot run with security manager enabled",
|
||||||
System.getSecurityManager() == null);
|
System.getSecurityManager() == null);
|
||||||
Path scratch = createTempDir();
|
Path scratch = createTempDir();
|
||||||
Path testFile = this.getDataPath("security/simple-plugin-security.policy");
|
PluginPolicyInfo info = makeDummyPlugin("security/simple-plugin-security.policy");
|
||||||
Set<String> actual = PluginSecurity.parsePermissions(testFile, scratch);
|
Set<String> actual = PluginSecurity.getPermissionDescriptions(info, scratch);
|
||||||
assertThat(actual, contains(PluginSecurity.formatPermission(new RuntimePermission("queuePrintJob"))));
|
assertThat(actual, contains(PluginSecurity.formatPermission(new RuntimePermission("queuePrintJob"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,8 +60,8 @@ public class PluginSecurityTests extends ESTestCase {
|
||||||
"test cannot run with security manager enabled",
|
"test cannot run with security manager enabled",
|
||||||
System.getSecurityManager() == null);
|
System.getSecurityManager() == null);
|
||||||
Path scratch = createTempDir();
|
Path scratch = createTempDir();
|
||||||
Path testFile = this.getDataPath("security/complex-plugin-security.policy");
|
PluginPolicyInfo info = makeDummyPlugin("security/complex-plugin-security.policy");
|
||||||
Set<String> actual = PluginSecurity.parsePermissions(testFile, scratch);
|
Set<String> actual = PluginSecurity.getPermissionDescriptions(info, scratch);
|
||||||
assertThat(actual, containsInAnyOrder(
|
assertThat(actual, containsInAnyOrder(
|
||||||
PluginSecurity.formatPermission(new RuntimePermission("getClassLoader")),
|
PluginSecurity.formatPermission(new RuntimePermission("getClassLoader")),
|
||||||
PluginSecurity.formatPermission(new RuntimePermission("closeClassLoader"))));
|
PluginSecurity.formatPermission(new RuntimePermission("closeClassLoader"))));
|
||||||
|
@ -67,8 +80,8 @@ public class PluginSecurityTests extends ESTestCase {
|
||||||
"test cannot run with security manager enabled",
|
"test cannot run with security manager enabled",
|
||||||
System.getSecurityManager() == null);
|
System.getSecurityManager() == null);
|
||||||
Path scratch = createTempDir();
|
Path scratch = createTempDir();
|
||||||
Path testFile = this.getDataPath("security/unresolved-plugin-security.policy");
|
PluginPolicyInfo info = makeDummyPlugin("security/unresolved-plugin-security.policy");
|
||||||
Set<String> permissions = PluginSecurity.parsePermissions(testFile, scratch);
|
Set<String> permissions = PluginSecurity.getPermissionDescriptions(info, scratch);
|
||||||
assertThat(permissions, contains("org.fake.FakePermission fakeName"));
|
assertThat(permissions, contains("org.fake.FakePermission fakeName"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
grant {
|
||||||
|
// needed to waste paper
|
||||||
|
permission java.lang.RuntimePermission "queuePrintJob";
|
||||||
|
};
|
|
@ -0,0 +1,8 @@
|
||||||
|
grant {
|
||||||
|
// needed to waste paper
|
||||||
|
permission java.lang.RuntimePermission "queuePrintJob";
|
||||||
|
};
|
||||||
|
|
||||||
|
grant codeBase "${jarUrl}" {
|
||||||
|
permission java.lang.RuntimePermission "getClassLoader";
|
||||||
|
};
|
|
@ -52,9 +52,9 @@ final class ESPolicy extends Policy {
|
||||||
|
|
||||||
ESPolicy(Map<String, URL> codebases, PermissionCollection dynamic, Map<String,Policy> plugins, boolean filterBadDefaults,
|
ESPolicy(Map<String, URL> codebases, PermissionCollection dynamic, Map<String,Policy> plugins, boolean filterBadDefaults,
|
||||||
PermissionCollection dataPathPermission) {
|
PermissionCollection dataPathPermission) {
|
||||||
this.template = Security.readPolicy(getClass().getResource(POLICY_RESOURCE), codebases);
|
this.template = PolicyUtil.readPolicy(getClass().getResource(POLICY_RESOURCE), codebases);
|
||||||
this.dataPathPermission = dataPathPermission;
|
this.dataPathPermission = dataPathPermission;
|
||||||
this.untrusted = Security.readPolicy(getClass().getResource(UNTRUSTED_RESOURCE), Collections.emptyMap());
|
this.untrusted = PolicyUtil.readPolicy(getClass().getResource(UNTRUSTED_RESOURCE), Collections.emptyMap());
|
||||||
if (filterBadDefaults) {
|
if (filterBadDefaults) {
|
||||||
this.system = new SystemPolicy(Policy.getPolicy());
|
this.system = new SystemPolicy(Policy.getPolicy());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.bootstrap;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.Policy;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class PluginPolicyInfo {
|
||||||
|
public final Set<URL> jars;
|
||||||
|
public final Policy policy;
|
||||||
|
|
||||||
|
PluginPolicyInfo(Set<URL> jars, Policy policy) {
|
||||||
|
this.jars = jars;
|
||||||
|
this.policy = policy;
|
||||||
|
}
|
||||||
|
}
|
193
server/src/main/java/org/elasticsearch/bootstrap/PolicyUtil.java
Normal file
193
server/src/main/java/org/elasticsearch/bootstrap/PolicyUtil.java
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.elasticsearch.bootstrap;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.SuppressForbidden;
|
||||||
|
import org.elasticsearch.common.io.PathUtils;
|
||||||
|
import org.elasticsearch.core.internal.io.IOUtils;
|
||||||
|
import org.elasticsearch.plugins.PluginInfo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.security.CodeSource;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.security.PermissionCollection;
|
||||||
|
import java.security.Policy;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.security.URIParameter;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class PolicyUtil {
|
||||||
|
/**
|
||||||
|
* Return a map from codebase name to codebase url of jar codebases used by ES core.
|
||||||
|
*/
|
||||||
|
@SuppressForbidden(reason = "find URL path")
|
||||||
|
public static Map<String, URL> getCodebaseJarMap(Set<URL> urls) {
|
||||||
|
Map<String, URL> codebases = new LinkedHashMap<>(); // maintain order
|
||||||
|
for (URL url : urls) {
|
||||||
|
try {
|
||||||
|
String fileName = PathUtils.get(url.toURI()).getFileName().toString();
|
||||||
|
if (fileName.endsWith(".jar") == false) {
|
||||||
|
// tests :(
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
codebases.put(fileName, url);
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return codebases;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and returns the specified {@code policyFile}.
|
||||||
|
* <p>
|
||||||
|
* Jar files listed in {@code codebases} location will be provided to the policy file via
|
||||||
|
* a system property of the short name: e.g. <code>${codebase.joda-convert-1.2.jar}</code>
|
||||||
|
* would map to full URL.
|
||||||
|
*/
|
||||||
|
@SuppressForbidden(reason = "accesses fully qualified URLs to configure security")
|
||||||
|
public static Policy readPolicy(URL policyFile, Map<String, URL> codebases) {
|
||||||
|
try {
|
||||||
|
List<String> propertiesSet = new ArrayList<>();
|
||||||
|
try {
|
||||||
|
// set codebase properties
|
||||||
|
for (Map.Entry<String,URL> codebase : codebases.entrySet()) {
|
||||||
|
String name = codebase.getKey();
|
||||||
|
URL url = codebase.getValue();
|
||||||
|
|
||||||
|
// We attempt to use a versionless identifier for each codebase. This assumes a specific version
|
||||||
|
// format in the jar filename. While we cannot ensure all jars in all plugins use this format, nonconformity
|
||||||
|
// only means policy grants would need to include the entire jar filename as they always have before.
|
||||||
|
String property = "codebase." + name;
|
||||||
|
String aliasProperty = "codebase." + name.replaceFirst("-\\d+\\.\\d+.*\\.jar", "");
|
||||||
|
if (aliasProperty.equals(property) == false) {
|
||||||
|
propertiesSet.add(aliasProperty);
|
||||||
|
String previous = System.setProperty(aliasProperty, url.toString());
|
||||||
|
if (previous != null) {
|
||||||
|
throw new IllegalStateException("codebase property already set: " + aliasProperty + " -> " + previous +
|
||||||
|
", cannot set to " + url.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
propertiesSet.add(property);
|
||||||
|
String previous = System.setProperty(property, url.toString());
|
||||||
|
if (previous != null) {
|
||||||
|
throw new IllegalStateException("codebase property already set: " + property + " -> " + previous +
|
||||||
|
", cannot set to " + url.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Policy.getInstance("JavaPolicy", new URIParameter(policyFile.toURI()));
|
||||||
|
} finally {
|
||||||
|
// clear codebase properties
|
||||||
|
for (String property : propertiesSet) {
|
||||||
|
System.clearProperty(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NoSuchAlgorithmException | URISyntaxException e) {
|
||||||
|
throw new IllegalArgumentException("unable to parse policy file `" + policyFile + "`", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return info about the security policy for a plugin.
|
||||||
|
*/
|
||||||
|
public static PluginPolicyInfo getPluginPolicyInfo(Path pluginRoot) throws IOException {
|
||||||
|
Path policyFile = pluginRoot.resolve(PluginInfo.ES_PLUGIN_POLICY);
|
||||||
|
if (Files.exists(policyFile) == false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// first get a list of URLs for the plugins' jars:
|
||||||
|
// we resolve symlinks so map is keyed on the normalize codebase name
|
||||||
|
Set<URL> jars = new LinkedHashSet<>(); // order is already lost, but some filesystems have it
|
||||||
|
try (DirectoryStream<Path> jarStream = Files.newDirectoryStream(pluginRoot, "*.jar")) {
|
||||||
|
for (Path jar : jarStream) {
|
||||||
|
URL url = jar.toRealPath().toUri().toURL();
|
||||||
|
if (jars.add(url) == false) {
|
||||||
|
throw new IllegalStateException("duplicate module/plugin: " + url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse the plugin's policy file into a set of permissions
|
||||||
|
Policy policy = readPolicy(policyFile.toUri().toURL(), getCodebaseJarMap(jars));
|
||||||
|
|
||||||
|
return new PluginPolicyInfo(jars, policy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return permissions for a policy that apply to a jar.
|
||||||
|
*
|
||||||
|
* @param url The url of a jar to find permissions for, or {@code null} for global permissions.
|
||||||
|
*/
|
||||||
|
public static Set<Permission> getPolicyPermissions(URL url, Policy policy, Path tmpDir) throws IOException {
|
||||||
|
// create a zero byte file for "comparison"
|
||||||
|
// this is necessary because the default policy impl automatically grants two permissions:
|
||||||
|
// 1. permission to exitVM (which we ignore)
|
||||||
|
// 2. read permission to the code itself (e.g. jar file of the code)
|
||||||
|
|
||||||
|
Path emptyPolicyFile = Files.createTempFile(tmpDir, "empty", "tmp");
|
||||||
|
final Policy emptyPolicy;
|
||||||
|
try {
|
||||||
|
emptyPolicy = Policy.getInstance("JavaPolicy", new URIParameter(emptyPolicyFile.toUri()));
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
IOUtils.rm(emptyPolicyFile);
|
||||||
|
|
||||||
|
final ProtectionDomain protectionDomain;
|
||||||
|
if (url == null) {
|
||||||
|
// global, use PolicyUtil since it is part of core ES
|
||||||
|
protectionDomain = PolicyUtil.class.getProtectionDomain();
|
||||||
|
} else {
|
||||||
|
// we may not have the url loaded, so create a fake protection domain
|
||||||
|
protectionDomain = new ProtectionDomain(new CodeSource(url, (Certificate[]) null), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
PermissionCollection permissions = policy.getPermissions(protectionDomain);
|
||||||
|
// this method is supported with the specific implementation we use, but just check for safety.
|
||||||
|
if (permissions == Policy.UNSUPPORTED_EMPTY_COLLECTION) {
|
||||||
|
throw new UnsupportedOperationException("JavaPolicy implementation does not support retrieving permissions");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Set<Permission> actualPermissions = new HashSet<>();
|
||||||
|
for (Permission permission : Collections.list(permissions.elements())) {
|
||||||
|
if (emptyPolicy.implies(protectionDomain, permission) == false) {
|
||||||
|
actualPermissions.add(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return actualPermissions;
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,7 +25,6 @@ import org.elasticsearch.common.io.PathUtils;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.http.HttpTransportSettings;
|
import org.elasticsearch.http.HttpTransportSettings;
|
||||||
import org.elasticsearch.plugins.PluginInfo;
|
|
||||||
import org.elasticsearch.plugins.PluginsService;
|
import org.elasticsearch.plugins.PluginsService;
|
||||||
import org.elasticsearch.secure_sm.SecureSM;
|
import org.elasticsearch.secure_sm.SecureSM;
|
||||||
import org.elasticsearch.transport.TcpTransport;
|
import org.elasticsearch.transport.TcpTransport;
|
||||||
|
@ -35,7 +34,6 @@ import java.net.SocketPermission;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.AccessMode;
|
import java.nio.file.AccessMode;
|
||||||
import java.nio.file.DirectoryStream;
|
|
||||||
import java.nio.file.FileAlreadyExistsException;
|
import java.nio.file.FileAlreadyExistsException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.NotDirectoryException;
|
import java.nio.file.NotDirectoryException;
|
||||||
|
@ -43,14 +41,10 @@ import java.nio.file.Path;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.Permissions;
|
import java.security.Permissions;
|
||||||
import java.security.Policy;
|
import java.security.Policy;
|
||||||
import java.security.URIParameter;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -117,9 +111,9 @@ final class Security {
|
||||||
static void configure(Environment environment, boolean filterBadDefaults) throws IOException, NoSuchAlgorithmException {
|
static void configure(Environment environment, boolean filterBadDefaults) throws IOException, NoSuchAlgorithmException {
|
||||||
|
|
||||||
// enable security policy: union of template and environment-based paths, and possibly plugin permissions
|
// enable security policy: union of template and environment-based paths, and possibly plugin permissions
|
||||||
Map<String, URL> codebases = getCodebaseJarMap(JarHell.parseClassPath());
|
Map<String, URL> codebases = PolicyUtil.getCodebaseJarMap(JarHell.parseClassPath());
|
||||||
Policy.setPolicy(new ESPolicy(codebases, createPermissions(environment), getPluginPermissions(environment), filterBadDefaults,
|
Policy.setPolicy(new ESPolicy(codebases, createPermissions(environment),
|
||||||
createRecursiveDataPathPermission(environment)));
|
getPluginAndModulePermissions(environment), filterBadDefaults, createRecursiveDataPathPermission(environment)));
|
||||||
|
|
||||||
// enable security manager
|
// enable security manager
|
||||||
final String[] classesThatCanExit =
|
final String[] classesThatCanExit =
|
||||||
|
@ -133,33 +127,12 @@ final class Security {
|
||||||
selfTest();
|
selfTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a map from codebase name to codebase url of jar codebases used by ES core.
|
|
||||||
*/
|
|
||||||
@SuppressForbidden(reason = "find URL path")
|
|
||||||
static Map<String, URL> getCodebaseJarMap(Set<URL> urls) {
|
|
||||||
Map<String, URL> codebases = new LinkedHashMap<>(); // maintain order
|
|
||||||
for (URL url : urls) {
|
|
||||||
try {
|
|
||||||
String fileName = PathUtils.get(url.toURI()).getFileName().toString();
|
|
||||||
if (fileName.endsWith(".jar") == false) {
|
|
||||||
// tests :(
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
codebases.put(fileName, url);
|
|
||||||
} catch (URISyntaxException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return codebases;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets properties (codebase URLs) for policy files.
|
* Sets properties (codebase URLs) for policy files.
|
||||||
* we look for matching plugins and set URLs to fit
|
* we look for matching plugins and set URLs to fit
|
||||||
*/
|
*/
|
||||||
@SuppressForbidden(reason = "proper use of URL")
|
@SuppressForbidden(reason = "proper use of URL")
|
||||||
static Map<String,Policy> getPluginPermissions(Environment environment) throws IOException, NoSuchAlgorithmException {
|
static Map<String,Policy> getPluginAndModulePermissions(Environment environment) throws IOException {
|
||||||
Map<String,Policy> map = new HashMap<>();
|
Map<String,Policy> map = new HashMap<>();
|
||||||
// collect up set of plugins and modules by listing directories.
|
// collect up set of plugins and modules by listing directories.
|
||||||
Set<Path> pluginsAndModules = new LinkedHashSet<>(PluginsService.findPluginDirs(environment.pluginsFile()));
|
Set<Path> pluginsAndModules = new LinkedHashSet<>(PluginsService.findPluginDirs(environment.pluginsFile()));
|
||||||
|
@ -167,29 +140,16 @@ final class Security {
|
||||||
|
|
||||||
// now process each one
|
// now process each one
|
||||||
for (Path plugin : pluginsAndModules) {
|
for (Path plugin : pluginsAndModules) {
|
||||||
Path policyFile = plugin.resolve(PluginInfo.ES_PLUGIN_POLICY);
|
PluginPolicyInfo pluginPolicy = PolicyUtil.getPluginPolicyInfo(plugin);
|
||||||
if (Files.exists(policyFile)) {
|
if (pluginPolicy == null) {
|
||||||
// first get a list of URLs for the plugins' jars:
|
continue;
|
||||||
// we resolve symlinks so map is keyed on the normalize codebase name
|
|
||||||
Set<URL> codebases = new LinkedHashSet<>(); // order is already lost, but some filesystems have it
|
|
||||||
try (DirectoryStream<Path> jarStream = Files.newDirectoryStream(plugin, "*.jar")) {
|
|
||||||
for (Path jar : jarStream) {
|
|
||||||
URL url = jar.toRealPath().toUri().toURL();
|
|
||||||
if (codebases.add(url) == false) {
|
|
||||||
throw new IllegalStateException("duplicate module/plugin: " + url);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse the plugin's policy file into a set of permissions
|
|
||||||
Policy policy = readPolicy(policyFile.toUri().toURL(), getCodebaseJarMap(codebases));
|
|
||||||
|
|
||||||
// consult this policy for each of the plugin's jars:
|
// consult this policy for each of the plugin's jars:
|
||||||
for (URL url : codebases) {
|
for (URL jar : pluginPolicy.jars) {
|
||||||
if (map.put(url.getFile(), policy) != null) {
|
if (map.put(jar.getFile(), pluginPolicy.policy) != null) {
|
||||||
// just be paranoid ok?
|
// just be paranoid ok?
|
||||||
throw new IllegalStateException("per-plugin permissions already granted for jar file: " + url);
|
throw new IllegalStateException("per-plugin permissions already granted for jar file: " + jar);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,55 +157,6 @@ final class Security {
|
||||||
return Collections.unmodifiableMap(map);
|
return Collections.unmodifiableMap(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads and returns the specified {@code policyFile}.
|
|
||||||
* <p>
|
|
||||||
* Jar files listed in {@code codebases} location will be provided to the policy file via
|
|
||||||
* a system property of the short name: e.g. <code>${codebase.joda-convert-1.2.jar}</code>
|
|
||||||
* would map to full URL.
|
|
||||||
*/
|
|
||||||
@SuppressForbidden(reason = "accesses fully qualified URLs to configure security")
|
|
||||||
static Policy readPolicy(URL policyFile, Map<String, URL> codebases) {
|
|
||||||
try {
|
|
||||||
List<String> propertiesSet = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
// set codebase properties
|
|
||||||
for (Map.Entry<String,URL> codebase : codebases.entrySet()) {
|
|
||||||
String name = codebase.getKey();
|
|
||||||
URL url = codebase.getValue();
|
|
||||||
|
|
||||||
// We attempt to use a versionless identifier for each codebase. This assumes a specific version
|
|
||||||
// format in the jar filename. While we cannot ensure all jars in all plugins use this format, nonconformity
|
|
||||||
// only means policy grants would need to include the entire jar filename as they always have before.
|
|
||||||
String property = "codebase." + name;
|
|
||||||
String aliasProperty = "codebase." + name.replaceFirst("-\\d+\\.\\d+.*\\.jar", "");
|
|
||||||
if (aliasProperty.equals(property) == false) {
|
|
||||||
propertiesSet.add(aliasProperty);
|
|
||||||
String previous = System.setProperty(aliasProperty, url.toString());
|
|
||||||
if (previous != null) {
|
|
||||||
throw new IllegalStateException("codebase property already set: " + aliasProperty + " -> " + previous +
|
|
||||||
", cannot set to " + url.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
propertiesSet.add(property);
|
|
||||||
String previous = System.setProperty(property, url.toString());
|
|
||||||
if (previous != null) {
|
|
||||||
throw new IllegalStateException("codebase property already set: " + property + " -> " + previous +
|
|
||||||
", cannot set to " + url.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Policy.getInstance("JavaPolicy", new URIParameter(policyFile.toURI()));
|
|
||||||
} finally {
|
|
||||||
// clear codebase properties
|
|
||||||
for (String property : propertiesSet) {
|
|
||||||
System.clearProperty(property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (NoSuchAlgorithmException | URISyntaxException e) {
|
|
||||||
throw new IllegalArgumentException("unable to parse policy file `" + policyFile + "`", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** returns dynamic Permissions to configured paths and bind ports */
|
/** returns dynamic Permissions to configured paths and bind ports */
|
||||||
static Permissions createPermissions(Environment environment) throws IOException {
|
static Permissions createPermissions(Environment environment) throws IOException {
|
||||||
Permissions policy = new Permissions();
|
Permissions policy = new Permissions();
|
||||||
|
|
|
@ -19,24 +19,21 @@
|
||||||
|
|
||||||
package org.elasticsearch.plugins;
|
package org.elasticsearch.plugins;
|
||||||
|
|
||||||
|
import org.elasticsearch.bootstrap.PluginPolicyInfo;
|
||||||
|
import org.elasticsearch.bootstrap.PolicyUtil;
|
||||||
import org.elasticsearch.cli.ExitCodes;
|
import org.elasticsearch.cli.ExitCodes;
|
||||||
import org.elasticsearch.cli.Terminal;
|
import org.elasticsearch.cli.Terminal;
|
||||||
import org.elasticsearch.cli.Terminal.Verbosity;
|
import org.elasticsearch.cli.Terminal.Verbosity;
|
||||||
import org.elasticsearch.cli.UserException;
|
import org.elasticsearch.cli.UserException;
|
||||||
import org.elasticsearch.core.internal.io.IOUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.net.URL;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.Permission;
|
import java.security.Permission;
|
||||||
import java.security.PermissionCollection;
|
|
||||||
import java.security.Permissions;
|
|
||||||
import java.security.Policy;
|
|
||||||
import java.security.URIParameter;
|
|
||||||
import java.security.UnresolvedPermission;
|
import java.security.UnresolvedPermission;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -115,41 +112,15 @@ class PluginSecurity {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses plugin policy into a set of permissions. Each permission is formatted for output to users.
|
* Extract a unique set of permissions from the plugin's policy file. Each permission is formatted for output to users.
|
||||||
*/
|
*/
|
||||||
public static Set<String> parsePermissions(Path file, Path tmpDir) throws IOException {
|
static Set<String> getPermissionDescriptions(PluginPolicyInfo pluginPolicyInfo, Path tmpDir) throws IOException {
|
||||||
// create a zero byte file for "comparison"
|
Set<Permission> allPermissions = new HashSet<>(PolicyUtil.getPolicyPermissions(null, pluginPolicyInfo.policy, tmpDir));
|
||||||
// this is necessary because the default policy impl automatically grants two permissions:
|
for (URL jar : pluginPolicyInfo.jars) {
|
||||||
// 1. permission to exitVM (which we ignore)
|
Set<Permission> jarPermissions = PolicyUtil.getPolicyPermissions(jar, pluginPolicyInfo.policy, tmpDir);
|
||||||
// 2. read permission to the code itself (e.g. jar file of the code)
|
allPermissions.addAll(jarPermissions);
|
||||||
|
}
|
||||||
|
|
||||||
Path emptyPolicyFile = Files.createTempFile(tmpDir, "empty", "tmp");
|
return allPermissions.stream().map(PluginSecurity::formatPermission).collect(Collectors.toSet());
|
||||||
final Policy emptyPolicy;
|
|
||||||
try {
|
|
||||||
emptyPolicy = Policy.getInstance("JavaPolicy", new URIParameter(emptyPolicyFile.toUri()));
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
IOUtils.rm(emptyPolicyFile);
|
|
||||||
|
|
||||||
// parse the plugin's policy file into a set of permissions
|
|
||||||
final Policy policy;
|
|
||||||
try {
|
|
||||||
policy = Policy.getInstance("JavaPolicy", new URIParameter(file.toUri()));
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
PermissionCollection permissions = policy.getPermissions(PluginSecurity.class.getProtectionDomain());
|
|
||||||
// this method is supported with the specific implementation we use, but just check for safety.
|
|
||||||
if (permissions == Policy.UNSUPPORTED_EMPTY_COLLECTION) {
|
|
||||||
throw new UnsupportedOperationException("JavaPolicy implementation does not support retrieving permissions");
|
|
||||||
}
|
|
||||||
PermissionCollection actualPermissions = new Permissions();
|
|
||||||
for (Permission permission : Collections.list(permissions.elements())) {
|
|
||||||
if (!emptyPolicy.implies(PluginSecurity.class.getProtectionDomain(), permission)) {
|
|
||||||
actualPermissions.add(permission);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Collections.list(actualPermissions.elements()).stream().map(PluginSecurity::formatPermission).collect(Collectors.toSet());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,7 @@ public class BootstrapForTesting {
|
||||||
perms.add(new SocketPermission("localhost:1024-", "listen,resolve"));
|
perms.add(new SocketPermission("localhost:1024-", "listen,resolve"));
|
||||||
|
|
||||||
// read test-framework permissions
|
// read test-framework permissions
|
||||||
Map<String, URL> codebases = Security.getCodebaseJarMap(JarHell.parseClassPath());
|
Map<String, URL> codebases = PolicyUtil.getCodebaseJarMap(JarHell.parseClassPath());
|
||||||
// when testing server, the main elasticsearch code is not yet in a jar, so we need to manually add it
|
// when testing server, the main elasticsearch code is not yet in a jar, so we need to manually add it
|
||||||
addClassCodebase(codebases,"elasticsearch", "org.elasticsearch.plugins.PluginsService");
|
addClassCodebase(codebases,"elasticsearch", "org.elasticsearch.plugins.PluginsService");
|
||||||
if (System.getProperty("tests.gradle") == null) {
|
if (System.getProperty("tests.gradle") == null) {
|
||||||
|
@ -148,7 +148,7 @@ public class BootstrapForTesting {
|
||||||
addClassCodebase(codebases, "elasticsearch-secure-sm", "org.elasticsearch.secure_sm.SecureSM");
|
addClassCodebase(codebases, "elasticsearch-secure-sm", "org.elasticsearch.secure_sm.SecureSM");
|
||||||
addClassCodebase(codebases, "elasticsearch-rest-client", "org.elasticsearch.client.RestClient");
|
addClassCodebase(codebases, "elasticsearch-rest-client", "org.elasticsearch.client.RestClient");
|
||||||
}
|
}
|
||||||
final Policy testFramework = Security.readPolicy(Bootstrap.class.getResource("test-framework.policy"), codebases);
|
final Policy testFramework = PolicyUtil.readPolicy(Bootstrap.class.getResource("test-framework.policy"), codebases);
|
||||||
final Policy esPolicy = new ESPolicy(codebases, perms, getPluginPermissions(), true, new Permissions());
|
final Policy esPolicy = new ESPolicy(codebases, perms, getPluginPermissions(), true, new Permissions());
|
||||||
Policy.setPolicy(new Policy() {
|
Policy.setPolicy(new Policy() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -224,7 +224,7 @@ public class BootstrapForTesting {
|
||||||
// parse each policy file, with codebase substitution from the classpath
|
// parse each policy file, with codebase substitution from the classpath
|
||||||
final List<Policy> policies = new ArrayList<>(pluginPolicies.size());
|
final List<Policy> policies = new ArrayList<>(pluginPolicies.size());
|
||||||
for (URL policyFile : pluginPolicies) {
|
for (URL policyFile : pluginPolicies) {
|
||||||
policies.add(Security.readPolicy(policyFile, Security.getCodebaseJarMap(codebases)));
|
policies.add(PolicyUtil.readPolicy(policyFile, PolicyUtil.getCodebaseJarMap(codebases)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// consult each policy file for those codebases
|
// consult each policy file for those codebases
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue