2015-10-14 14:46:45 -04:00
|
|
|
/*
|
|
|
|
* 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.plugins;
|
|
|
|
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
import org.apache.lucene.util.IOUtils;
|
2016-03-08 14:13:55 -08:00
|
|
|
import org.elasticsearch.cli.Terminal;
|
|
|
|
import org.elasticsearch.cli.Terminal.Verbosity;
|
2015-10-14 14:46:45 -04:00
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.nio.file.Files;
|
|
|
|
import java.nio.file.Path;
|
|
|
|
import java.security.NoSuchAlgorithmException;
|
|
|
|
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.util.Collections;
|
|
|
|
import java.util.Comparator;
|
|
|
|
import java.util.List;
|
2017-03-27 15:52:45 -04:00
|
|
|
import java.util.function.Supplier;
|
2015-10-14 14:46:45 -04:00
|
|
|
|
|
|
|
class PluginSecurity {
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
|
2015-10-14 14:46:45 -04:00
|
|
|
/**
|
|
|
|
* Reads plugin policy, prints/confirms exceptions
|
|
|
|
*/
|
2017-03-27 15:52:45 -04:00
|
|
|
static void readPolicy(PluginInfo info, Path file, Terminal terminal, Supplier<Path> tmpFile, boolean batch) throws IOException {
|
|
|
|
PermissionCollection permissions = parsePermissions(terminal, file, tmpFile.get());
|
2015-10-14 14:46:45 -04:00
|
|
|
List<Permission> requested = Collections.list(permissions.elements());
|
|
|
|
if (requested.isEmpty()) {
|
2016-02-03 22:22:56 -08:00
|
|
|
terminal.println(Verbosity.VERBOSE, "plugin has a policy file with no additional permissions");
|
2017-03-27 15:52:45 -04:00
|
|
|
} else {
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
|
2017-03-27 15:52:45 -04:00
|
|
|
// sort permissions in a reasonable order
|
|
|
|
Collections.sort(requested, new Comparator<Permission>() {
|
|
|
|
@Override
|
|
|
|
public int compare(Permission o1, Permission o2) {
|
|
|
|
int cmp = o1.getClass().getName().compareTo(o2.getClass().getName());
|
2015-10-14 14:46:45 -04:00
|
|
|
if (cmp == 0) {
|
2017-03-27 15:52:45 -04:00
|
|
|
String name1 = o1.getName();
|
|
|
|
String name2 = o2.getName();
|
|
|
|
if (name1 == null) {
|
|
|
|
name1 = "";
|
|
|
|
}
|
|
|
|
if (name2 == null) {
|
|
|
|
name2 = "";
|
2015-10-14 14:46:45 -04:00
|
|
|
}
|
2017-03-27 15:52:45 -04:00
|
|
|
cmp = name1.compareTo(name2);
|
|
|
|
if (cmp == 0) {
|
|
|
|
String actions1 = o1.getActions();
|
|
|
|
String actions2 = o2.getActions();
|
|
|
|
if (actions1 == null) {
|
|
|
|
actions1 = "";
|
|
|
|
}
|
|
|
|
if (actions2 == null) {
|
|
|
|
actions2 = "";
|
|
|
|
}
|
|
|
|
cmp = actions1.compareTo(actions2);
|
2015-10-14 14:46:45 -04:00
|
|
|
}
|
|
|
|
}
|
2017-03-27 15:52:45 -04:00
|
|
|
return cmp;
|
2015-10-14 14:46:45 -04:00
|
|
|
}
|
2017-03-27 15:52:45 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
terminal.println(Verbosity.NORMAL, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
|
|
|
terminal.println(Verbosity.NORMAL, "@ WARNING: plugin requires additional permissions @");
|
|
|
|
terminal.println(Verbosity.NORMAL, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
|
|
|
// print all permissions:
|
|
|
|
for (Permission permission : requested) {
|
|
|
|
terminal.println(Verbosity.NORMAL, "* " + formatPermission(permission));
|
2015-10-14 14:46:45 -04:00
|
|
|
}
|
2017-03-27 15:52:45 -04:00
|
|
|
terminal.println(Verbosity.NORMAL, "See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html");
|
|
|
|
terminal.println(Verbosity.NORMAL, "for descriptions of what these permissions allow and the associated risks.");
|
|
|
|
prompt(terminal, batch);
|
|
|
|
}
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
|
2017-03-27 15:52:45 -04:00
|
|
|
if (info.hasNativeController()) {
|
|
|
|
terminal.println(Verbosity.NORMAL, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
|
|
|
terminal.println(Verbosity.NORMAL, "@ WARNING: plugin forks a native controller @");
|
|
|
|
terminal.println(Verbosity.NORMAL, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
|
|
|
terminal.println(Verbosity.NORMAL, "This plugin launches a native controller that is not subject to the Java");
|
|
|
|
terminal.println(Verbosity.NORMAL, "security manager nor to system call filters.");
|
|
|
|
prompt(terminal, batch);
|
2015-10-14 14:46:45 -04:00
|
|
|
}
|
2017-03-27 15:52:45 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
private static void prompt(final Terminal terminal, final boolean batch) {
|
2015-10-14 14:46:45 -04:00
|
|
|
if (!batch) {
|
2016-02-03 22:22:56 -08:00
|
|
|
terminal.println(Verbosity.NORMAL, "");
|
2015-10-14 14:46:45 -04:00
|
|
|
String text = terminal.readText("Continue with installation? [y/N]");
|
|
|
|
if (!text.equalsIgnoreCase("y")) {
|
|
|
|
throw new RuntimeException("installation aborted by user");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
|
2015-10-14 14:46:45 -04:00
|
|
|
/** Format permission type, name, and actions into a string */
|
|
|
|
static String formatPermission(Permission permission) {
|
|
|
|
StringBuilder sb = new StringBuilder();
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
|
2015-10-14 14:46:45 -04:00
|
|
|
String clazz = null;
|
|
|
|
if (permission instanceof UnresolvedPermission) {
|
|
|
|
clazz = ((UnresolvedPermission) permission).getUnresolvedType();
|
|
|
|
} else {
|
|
|
|
clazz = permission.getClass().getName();
|
|
|
|
}
|
|
|
|
sb.append(clazz);
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
|
2015-10-14 14:46:45 -04:00
|
|
|
String name = null;
|
|
|
|
if (permission instanceof UnresolvedPermission) {
|
|
|
|
name = ((UnresolvedPermission) permission).getUnresolvedName();
|
|
|
|
} else {
|
|
|
|
name = permission.getName();
|
|
|
|
}
|
|
|
|
if (name != null && name.length() > 0) {
|
|
|
|
sb.append(' ');
|
|
|
|
sb.append(name);
|
|
|
|
}
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
|
2015-10-14 14:46:45 -04:00
|
|
|
String actions = null;
|
|
|
|
if (permission instanceof UnresolvedPermission) {
|
|
|
|
actions = ((UnresolvedPermission) permission).getUnresolvedActions();
|
|
|
|
} else {
|
|
|
|
actions = permission.getActions();
|
|
|
|
}
|
|
|
|
if (actions != null && actions.length() > 0) {
|
|
|
|
sb.append(' ');
|
|
|
|
sb.append(actions);
|
|
|
|
}
|
|
|
|
return sb.toString();
|
|
|
|
}
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
|
2015-10-14 14:46:45 -04:00
|
|
|
/**
|
|
|
|
* Parses plugin policy into a set of permissions
|
|
|
|
*/
|
|
|
|
static PermissionCollection parsePermissions(Terminal terminal, Path file, 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);
|
|
|
|
}
|
Plugins: Reduce complexity of plugin cli
The plugin cli currently is extremely lenient, allowing most errors to
simply be logged. This can lead to either corrupt installations (eg
partially installed plugins), or confused users.
This change rewrites the plugin cli to have almost no leniency.
Unfortunately it was not possible to remove all leniency, due in
particular to how config files are handled.
The following functionality was simplified:
* The format of the name argument to install a plugin is now an official
plugin name, maven coordinates, or a URL.
* Checksum files are required, and only checked, for official plugins
and maven plugins. Checksums are also only SHA1.
* Downloading no longer uses a separate thread, and no longer has a timeout.
* Installation, and removal, attempts to be atomic. This only truly works
when no config or bin files exist.
* config and bin directories are verified before copying is attempted.
* Permissions and user/group are no longer set on config and bin files.
We rely on the users umask.
* config and bin directories must only contain files, no subdirectories.
* The code is reorganized so each command is a separate class. These
classes already existed, but were embedded in the plugin cli class, as
an extra layer between the cli code and the code running for each command.
2016-01-31 17:22:56 -08:00
|
|
|
IOUtils.rm(emptyPolicyFile);
|
|
|
|
|
2015-10-14 14:46:45 -04:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
actualPermissions.setReadOnly();
|
|
|
|
return actualPermissions;
|
|
|
|
}
|
|
|
|
}
|