Remove settings and system properties entanglement

This commit removals the usage of system properties as settings from the
command scripts and the commands themselves.

Relates elastic/elasticsearch#2206

Original commit: elastic/x-pack-elasticsearch@b0a3b895b1
This commit is contained in:
Jason Tedor 2016-05-19 14:09:49 -04:00
parent d34a20f8c8
commit ded4c2278c
20 changed files with 293 additions and 440 deletions

View File

@ -34,25 +34,5 @@ else
JAVA=`which java`
fi
# Parse any long getopt options and put them into properties before calling getopt below
# Be dash compatible to make sure running under ubuntu works
ARGCOUNT=$#
COUNT=0
while [ $COUNT -lt $ARGCOUNT ]
do
case $1 in
-D*=*)
properties="$properties $1"
shift 1; COUNT=$(($COUNT+1))
;;
-D*)
properties="$properties $1=$2"
shift ; shift; COUNT=$(($COUNT+2))
;;
*) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1))
esac
done
exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool "$@"
exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.KeyPairGeneratorTool "$@"

View File

@ -34,23 +34,4 @@ else
JAVA=`which java`
fi
# Parse any long getopt options and put them into properties before calling getopt below
# Be dash compatible to make sure running under ubuntu works
ARGCOUNT=$#
COUNT=0
while [ $COUNT -lt $ARGCOUNT ]
do
case $1 in
-D*=*)
properties="$properties $1"
shift 1; COUNT=$(($COUNT+1))
;;
-D*)
properties="$properties $1=$2"
shift ; shift; COUNT=$(($COUNT+2))
;;
*) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1))
esac
done
exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.LicenseGeneratorTool "$@"
exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.LicenseGeneratorTool "$@"

View File

@ -34,24 +34,5 @@ else
JAVA=`which java`
fi
# Parse any long getopt options and put them into properties before calling getopt below
# Be dash compatible to make sure running under ubuntu works
ARGCOUNT=$#
COUNT=0
while [ $COUNT -lt $ARGCOUNT ]
do
case $1 in
-D*=*)
properties="$properties $1"
shift 1; COUNT=$(($COUNT+1))
;;
-D*)
properties="$properties $1=$2"
shift ; shift; COUNT=$(($COUNT+2))
;;
*) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1))
esac
done
exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m $properties -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.LicenseVerificationTool "$@"
exec "$JAVA" $JAVA_OPTS -Xmx64m -Xms16m -cp "$LICENSE_CLASSPATH" -Des.path.home="`pwd`" org.elasticsearch.license.licensor.tools.LicenseVerificationTool "$@"

View File

@ -5,22 +5,21 @@
*/
package org.elasticsearch.license.licensor.tools;
import java.io.File;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.PathUtils;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.SecureRandom;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.PathUtils;
import static org.elasticsearch.license.core.CryptUtils.writeEncryptedPrivateKey;
import static org.elasticsearch.license.core.CryptUtils.writeEncryptedPublicKey;

View File

@ -112,7 +112,7 @@ def smoke_test_release(release, files, expected_hash):
print(' Starting elasticsearch daemon from [%s]' % es_dir)
try:
run('%s; %s -Ees.node.name=smoke_tester -Ees.cluster.name=prepare_release -Ees.script.inline=true -Ees.script.stored=true -Ees.repositories.url.allowed_urls=http://snapshot.test* %s -Ees.pidfile=%s -Ees.node.portsfile=true'
run('%s; %s -Enode.name=smoke_tester -Ecluster.name=prepare_release -Escript.inline=true -Escript.stored=true -Erepositories.url.allowed_urls=http://snapshot.test* %s -Epidfile=%s -Enode.portsfile=true'
% (java_exe(), es_run_path, '-d', os.path.join(es_dir, 'es-smoke.pid')))
if not wait_for_node_startup(es_dir, headers=headers):
print("elasticsearch logs:")

View File

@ -70,38 +70,6 @@ elif [ -f "/etc/default/elasticsearch" ]; then
. "/etc/default/elasticsearch"
fi
# Parse any long getopt options and put them into properties before calling getopt below
# Be dash compatible to make sure running under ubuntu works
ARGCOUNT=$#
COUNT=0
while [ $COUNT -lt $ARGCOUNT ]
do
case $1 in
--*=*) properties="$properties -Des.${1#--}"
shift 1; COUNT=$(($COUNT+1))
;;
--*) properties="$properties -Des.${1#--}=$2"
shift ; shift; COUNT=$(($COUNT+2))
;;
*) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1))
esac
done
# check if properties already has a config file or config dir
if [ -e "$CONF_DIR" ]; then
case "$properties" in
*-Des.default.path.conf=*) ;;
*)
if [ ! -d "$CONF_DIR/x-pack" ]; then
echo "ERROR: The configuration directory [$CONF_DIR/x-pack] does not exist. The extension tool expects security configuration files in that location."
echo "The plugin may not have been installed with the correct configuration path. If [$ES_HOME/config/x-pack] exists, please copy the 'x-pack' directory to [$CONF_DIR]"
exit 1
fi
properties="$properties -Des.default.path.conf=$CONF_DIR"
;;
esac
fi
export HOSTNAME=`hostname -s`
# include x-pack jars in classpath
@ -113,8 +81,14 @@ if [ ! -z "$CONF_FILE" ]; then
exit 1
fi
declare -a args=("$@")
if [ -e "$CONF_DIR" ]; then
args=("${args[@]}" -Edefault.path.conf="$CONF_DIR")
fi
cd "$ES_HOME" > /dev/null
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.xpack.extensions.XPackExtensionCli "$@"
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" org.elasticsearch.xpack.extensions.XPackExtensionCli "${args[@]}"
status=$?
cd - > /dev/null
exit $status

View File

@ -70,38 +70,6 @@ elif [ -f "/etc/default/elasticsearch" ]; then
. "/etc/default/elasticsearch"
fi
# Parse any long getopt options and put them into properties before calling getopt below
# Be dash compatible to make sure running under ubuntu works
ARGCOUNT=$#
COUNT=0
while [ $COUNT -lt $ARGCOUNT ]
do
case $1 in
--*=*) properties="$properties -Des.${1#--}"
shift 1; COUNT=$(($COUNT+1))
;;
--*) properties="$properties -Des.${1#--}=$2"
shift ; shift; COUNT=$(($COUNT+2))
;;
*) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1))
esac
done
# check if properties already has a config file or config dir
if [ -e "$CONF_DIR" ]; then
case "$properties" in
*-Des.default.path.conf=*) ;;
*)
if [ ! -d "$CONF_DIR/x-pack" ]; then
echo "ERROR: The configuration directory [$CONF_DIR/x-pack] does not exist. The syskeygen tool expects security configuration files in that location."
echo "The plugin may not have been installed with the correct configuration path. If [$ES_HOME/config/x-pack] exists, please copy the 'x-pack' directory to [$CONF_DIR]"
exit 1
fi
properties="$properties -Des.default.path.conf=$CONF_DIR"
;;
esac
fi
export HOSTNAME=`hostname -s`
# include shield jars in classpath
@ -121,8 +89,14 @@ if [ ! -z "$CONF_FILE" ]; then
exit 1
fi
declare -a args=("$@")
if [ -e "$CONF_DIR" ]; then
args=("${args[@]}" -Edefault.path.conf="$CONF_DIR")
fi
cd "$ES_HOME" > /dev/null
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.shield.crypto.tool.SystemKeyTool "$@"
"$JAVA" $ES_JAVA_OPTS -Des.path.home="$ES_HOME" -cp "$ES_CLASSPATH" org.elasticsearch.shield.crypto.tool.SystemKeyTool $properties "{args[@]}"
status=$?
cd - > /dev/null
exit $status

View File

@ -70,38 +70,6 @@ elif [ -f "/etc/default/elasticsearch" ]; then
. "/etc/default/elasticsearch"
fi
# Parse any long getopt options and put them into properties before calling getopt below
# Be dash compatible to make sure running under ubuntu works
ARGCOUNT=$#
COUNT=0
while [ $COUNT -lt $ARGCOUNT ]
do
case $1 in
--*=*) properties="$properties -Des.${1#--}"
shift 1; COUNT=$(($COUNT+1))
;;
--*) properties="$properties -Des.${1#--}=$2"
shift ; shift; COUNT=$(($COUNT+2))
;;
*) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1))
esac
done
# check if properties already has a config file or config dir
if [ -e "$CONF_DIR" ]; then
case "$properties" in
*-Des.default.path.conf=*) ;;
*)
if [ ! -d "$CONF_DIR/x-pack" ]; then
echo "ERROR: The configuration directory [$CONF_DIR/x-pack] does not exist. The users tool expects security configuration files in that location."
echo "The plugin may not have been installed with the correct configuration path. If [$ES_HOME/config/x-pack] exists, please copy the 'x-pack' directory to [$CONF_DIR]"
exit 1
fi
properties="$properties -Des.default.path.conf=$CONF_DIR"
;;
esac
fi
export HOSTNAME=`hostname -s`
# include shield jars in classpath
@ -121,8 +89,14 @@ if [ ! -z "$CONF_FILE" ]; then
exit 1
fi
declare -a args=("$@")
if [ -e "$CONF_DIR" ]; then
args=("${args[@]}" -Edefault.path.conf="$CONF_DIR")
fi
cd "$ES_HOME" > /dev/null
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" $properties org.elasticsearch.shield.authc.file.tool.UsersTool "$@"
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" org.elasticsearch.shield.authc.file.tool.UsersTool "${args[@]}"
status=$?
cd - > /dev/null
exit $status

View File

@ -5,26 +5,14 @@
*/
package org.elasticsearch.shield.authc.file.tool;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.MultiCommand;
import org.elasticsearch.cli.SettingCommand;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.Strings;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.env.Environment;
@ -40,32 +28,41 @@ import org.elasticsearch.shield.support.FileAttributesChecker;
import org.elasticsearch.shield.support.Validation;
import org.elasticsearch.shield.support.Validation.Users;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class UsersTool extends MultiCommand {
public static void main(String[] args) throws Exception {
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, Terminal.DEFAULT);
exit(new UsersTool(env).main(args, Terminal.DEFAULT));
exit(new UsersTool().main(args, Terminal.DEFAULT));
}
UsersTool(Environment env) {
UsersTool() {
super("Manages elasticsearch native users");
subcommands.put("useradd", new AddUserCommand(env));
subcommands.put("userdel", new DeleteUserCommand(env));
subcommands.put("passwd", new PasswordCommand(env));
subcommands.put("roles", new RolesCommand(env));
subcommands.put("list", new ListCommand(env));
subcommands.put("useradd", new AddUserCommand());
subcommands.put("userdel", new DeleteUserCommand());
subcommands.put("passwd", new PasswordCommand());
subcommands.put("roles", new RolesCommand());
subcommands.put("list", new ListCommand());
}
static class AddUserCommand extends Command {
static class AddUserCommand extends SettingCommand {
private final Environment env;
private final OptionSpec<String> passwordOption;
private final OptionSpec<String> rolesOption;
private final OptionSpec<String> arguments;
AddUserCommand(Environment env) {
AddUserCommand() {
super("Adds a native user");
this.env = env;
this.passwordOption = parser.acceptsAll(Arrays.asList("p", "password"),
"The user password")
.withRequiredArg();
@ -87,7 +84,7 @@ public class UsersTool extends MultiCommand {
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
String username = parseUsername(arguments.values(options));
Validation.Error validationError = Users.validateUsername(username);
if (validationError != null) {
@ -95,6 +92,7 @@ public class UsersTool extends MultiCommand {
}
char[] password = parsePassword(terminal, passwordOption.value(options));
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
String[] roles = parseRoles(terminal, env, rolesOption.value(options));
Settings fileSettings = Realms.fileRealmSettings(env.settings());
@ -120,14 +118,12 @@ public class UsersTool extends MultiCommand {
}
}
static class DeleteUserCommand extends Command {
static class DeleteUserCommand extends SettingCommand {
private final Environment env;
private final OptionSpec<String> arguments;
DeleteUserCommand(Environment env) {
DeleteUserCommand() {
super("Deletes a file based user");
this.env = env;
this.arguments = parser.nonOptions("username");
}
@ -143,8 +139,9 @@ public class UsersTool extends MultiCommand {
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
String username = parseUsername(arguments.values(options));
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
Settings fileSettings = Realms.fileRealmSettings(env.settings());
Path passwordFile = FileUserPasswdStore.resolveFile(fileSettings, env);
Path rolesFile = FileUserRolesStore.resolveFile(fileSettings, env);
@ -173,15 +170,13 @@ public class UsersTool extends MultiCommand {
}
}
static class PasswordCommand extends Command {
static class PasswordCommand extends SettingCommand {
private final Environment env;
private final OptionSpec<String> passwordOption;
private final OptionSpec<String> arguments;
PasswordCommand(Environment env) {
PasswordCommand() {
super("Changes the password of an existing file based user");
this.env = env;
this.passwordOption = parser.acceptsAll(Arrays.asList("p", "password"),
"The user password")
.withRequiredArg();
@ -200,10 +195,11 @@ public class UsersTool extends MultiCommand {
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
String username = parseUsername(arguments.values(options));
char[] password = parsePassword(terminal, passwordOption.value(options));
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
Settings fileSettings = Realms.fileRealmSettings(env.settings());
Path file = FileUserPasswdStore.resolveFile(fileSettings, env);
FileAttributesChecker attributesChecker = new FileAttributesChecker(file);
@ -218,16 +214,14 @@ public class UsersTool extends MultiCommand {
}
}
static class RolesCommand extends Command {
static class RolesCommand extends SettingCommand {
private final Environment env;
private final OptionSpec<String> addOption;
private final OptionSpec<String> removeOption;
private final OptionSpec<String> arguments;
RolesCommand(Environment env) {
RolesCommand() {
super("Edit roles of an existing user");
this.env = env;
this.addOption = parser.acceptsAll(Arrays.asList("a", "add"),
"Adds supplied roles to the specified user")
.withRequiredArg().defaultsTo("");
@ -246,8 +240,9 @@ public class UsersTool extends MultiCommand {
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
String username = parseUsername(arguments.values(options));
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
String[] addRoles = parseRoles(terminal, env, addOption.value(options));
String[] removeRoles = parseRoles(terminal, env, removeOption.value(options));
@ -290,14 +285,12 @@ public class UsersTool extends MultiCommand {
}
}
static class ListCommand extends Command {
static class ListCommand extends SettingCommand {
private final Environment env;
private final OptionSpec<String> arguments;
ListCommand(Environment env) {
ListCommand() {
super("List existing file based users and their corresponding roles");
this.env = env;
this.arguments = parser.nonOptions("username");
}
@ -308,11 +301,12 @@ public class UsersTool extends MultiCommand {
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
String username = null;
if (options.has(arguments)) {
username = arguments.value(options);
}
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
listUsersAndRoles(terminal, env, username);
}
}

View File

@ -5,21 +5,14 @@
*/
package org.elasticsearch.shield.crypto.tool;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import joptsimple.util.KeyValuePair;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.cli.SettingCommand;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.settings.Settings;
@ -28,28 +21,47 @@ import org.elasticsearch.env.Environment;
import org.elasticsearch.node.internal.InternalSettingsPreparer;
import org.elasticsearch.shield.crypto.InternalCryptoService;
public class SystemKeyTool extends Command {
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public class SystemKeyTool extends SettingCommand {
private final OptionSpec<String> arguments;
SystemKeyTool() {
super("system key tool");
arguments = parser.nonOptions("key path");
}
public static final Set<PosixFilePermission> PERMISSION_OWNER_READ_WRITE = Sets.newHashSet(PosixFilePermission.OWNER_READ,
PosixFilePermission.OWNER_WRITE);
public static void main(String[] args) throws Exception {
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, Terminal.DEFAULT);
exit(new SystemKeyTool(env).main(args, Terminal.DEFAULT));
final SystemKeyTool tool = new SystemKeyTool();
int status = main(tool, args, Terminal.DEFAULT);
if (status != ExitCodes.OK) {
exit(status);
}
}
private final Environment env;
private final OptionSpec<String> arguments;
public SystemKeyTool(Environment env) {
super("Generates the system key");
this.env = env;
this.arguments = parser.nonOptions("key path");
static int main(SystemKeyTool tool, String[] args, Terminal terminal) throws Exception {
return tool.main(args, terminal);
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
final Path keyPath;
final Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
if (options.hasArgument(arguments)) {
List<String> args = arguments.values(options);
if (args.size() > 1) {
@ -79,4 +91,5 @@ public class SystemKeyTool extends Command {
private static Path parsePath(String path) {
return PathUtils.get(path);
}
}

View File

@ -5,16 +5,6 @@
*/
package org.elasticsearch.shield.authc.file.tool;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import org.apache.lucene.util.IOUtils;
@ -35,17 +25,28 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class UsersToolTests extends CommandTestCase {
// the mock filesystem we use so permissions/users/groups can be modified
static FileSystem jimfs;
String pathHomeParameter;
String fileTypeParameter;
// the config dir for each test to use
Path confDir;
// settings used to create an Environment for tools
Settings.Builder settingsBuilder;
Settings settings;
@BeforeClass
public static void setupJimfs() throws IOException {
@ -78,9 +79,13 @@ public class UsersToolTests extends CommandTestCase {
"test_r2:",
" cluster: all"
), StandardCharsets.UTF_8);
settingsBuilder = Settings.builder()
.put("path.home", homeDir)
.put("xpack.security.authc.realms.file.type", "file");
settings =
Settings.builder()
.put("path.home", homeDir)
.put("xpack.security.authc.realms.file.type", "file")
.build();
pathHomeParameter = "-Epath.home=" + homeDir;
fileTypeParameter = "-Expack.security.authc.realms.file.type=file";
}
@AfterClass
@ -92,7 +97,7 @@ public class UsersToolTests extends CommandTestCase {
@Override
protected Command newCommand() {
return new UsersTool(new Environment(settingsBuilder.build()));
return new UsersTool();
}
/** checks the user exists with the given password */
@ -219,7 +224,7 @@ public class UsersToolTests extends CommandTestCase {
}
public void testParseUnknownRole() throws Exception {
UsersTool.parseRoles(terminal, new Environment(settingsBuilder.build()), "test_r1,r2,r3");
UsersTool.parseRoles(terminal, new Environment(settings), "test_r1,r2,r3");
String output = terminal.getOutput();
assertTrue(output, output.contains("The following roles [r2,r3] are not in the ["));
}
@ -227,21 +232,21 @@ public class UsersToolTests extends CommandTestCase {
public void testParseReservedRole() throws Exception {
final String reservedRoleName = randomFrom(ReservedRolesStore.names().toArray(Strings.EMPTY_ARRAY));
String rolesArg = randomBoolean() ? "test_r1," + reservedRoleName : reservedRoleName;
UsersTool.parseRoles(terminal, new Environment(settingsBuilder.build()), rolesArg);
UsersTool.parseRoles(terminal, new Environment(settings), rolesArg);
String output = terminal.getOutput();
assertTrue(output, output.isEmpty());
}
public void testParseInvalidRole() throws Exception {
UserError e = expectThrows(UserError.class, () -> {
UsersTool.parseRoles(terminal, new Environment(settingsBuilder.build()), "$345");
UsersTool.parseRoles(terminal, new Environment(settings), "$345");
});
assertEquals(ExitCodes.DATA_ERROR, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().contains("Invalid role [$345]"));
}
public void testParseMultipleRoles() throws Exception {
String[] roles = UsersTool.parseRoles(terminal, new Environment(settingsBuilder.build()), "test_r1,test_r2");
String[] roles = UsersTool.parseRoles(terminal, new Environment(settings), "test_r1,test_r2");
assertEquals(Objects.toString(roles), 2, roles.length);
assertEquals("test_r1", roles[0]);
assertEquals("test_r2", roles[1]);
@ -250,18 +255,18 @@ public class UsersToolTests extends CommandTestCase {
public void testUseraddNoPassword() throws Exception {
terminal.addSecretInput("changeme");
terminal.addSecretInput("changeme");
execute("useradd", "username");
execute("useradd", pathHomeParameter, fileTypeParameter, "username");
assertUser("username", "changeme");
}
public void testUseraddPasswordOption() throws Exception {
execute("useradd", "username", "-p", "changeme");
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", "changeme");
assertUser("username", "changeme");
}
public void testUseraddUserExists() throws Exception {
UserError e = expectThrows(UserError.class, () -> {
execute("useradd", "existing_user", "-p", "changeme");
execute("useradd", pathHomeParameter, fileTypeParameter, "existing_user", "-p", "changeme");
});
assertEquals(ExitCodes.CODE_ERROR, e.exitCode);
assertEquals("User [existing_user] already exists", e.getMessage());
@ -270,27 +275,27 @@ public class UsersToolTests extends CommandTestCase {
public void testUseraddNoRoles() throws Exception {
Files.delete(confDir.resolve("users_roles"));
Files.createFile(confDir.resolve("users_roles"));
execute("useradd", "username", "-p", "changeme");
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", "changeme");
List<String> lines = Files.readAllLines(confDir.resolve("users_roles"), StandardCharsets.UTF_8);
assertTrue(lines.toString(), lines.isEmpty());
}
public void testUserdelUnknownUser() throws Exception {
UserError e = expectThrows(UserError.class, () -> {
execute("userdel", "unknown");
execute("userdel", pathHomeParameter, fileTypeParameter, "unknown");
});
assertEquals(ExitCodes.NO_USER, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().contains("User [unknown] doesn't exist"));
}
public void testUserdel() throws Exception {
execute("userdel", "existing_user");
execute("userdel", pathHomeParameter, fileTypeParameter, "existing_user");
assertNoUser("existing_user");
}
public void testPasswdUnknownUser() throws Exception {
UserError e = expectThrows(UserError.class, () -> {
execute("passwd", "unknown", "-p", "changeme");
execute("passwd", pathHomeParameter, fileTypeParameter, "unknown", "-p", "changeme");
});
assertEquals(ExitCodes.NO_USER, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().contains("User [unknown] doesn't exist"));
@ -299,64 +304,64 @@ public class UsersToolTests extends CommandTestCase {
public void testPasswdNoPasswordOption() throws Exception {
terminal.addSecretInput("newpassword");
terminal.addSecretInput("newpassword");
execute("passwd", "existing_user");
execute("passwd", pathHomeParameter, fileTypeParameter, "existing_user");
assertUser("existing_user", "newpassword");
assertRole("test_admin", "existing_user", "existing_user2"); // roles unchanged
}
public void testPasswd() throws Exception {
execute("passwd", "existing_user", "-p", "newpassword");
execute("passwd", pathHomeParameter, fileTypeParameter, "existing_user", "-p", "newpassword");
assertUser("existing_user", "newpassword");
assertRole("test_admin", "existing_user"); // roles unchanged
}
public void testRolesUnknownUser() throws Exception {
UserError e = expectThrows(UserError.class, () -> {
execute("roles", "unknown");
execute("roles", pathHomeParameter, fileTypeParameter, "unknown");
});
assertEquals(ExitCodes.NO_USER, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().contains("User [unknown] doesn't exist"));
}
public void testRolesAdd() throws Exception {
execute("roles", "existing_user", "-a", "test_r1");
execute("roles", pathHomeParameter, fileTypeParameter, "existing_user", "-a", "test_r1");
assertRole("test_admin", "existing_user");
assertRole("test_r1", "existing_user");
}
public void testRolesRemove() throws Exception {
execute("roles", "existing_user", "-r", "test_admin");
execute("roles", pathHomeParameter, fileTypeParameter, "existing_user", "-r", "test_admin");
assertRole("test_admin", "existing_user2");
}
public void testRolesAddAndRemove() throws Exception {
execute("roles", "existing_user", "-a", "test_r1", "-r", "test_admin");
execute("roles", pathHomeParameter, fileTypeParameter, "existing_user", "-a", "test_r1", "-r", "test_admin");
assertRole("test_admin", "existing_user2");
assertRole("test_r1", "existing_user");
}
public void testRolesRemoveLeavesExisting() throws Exception {
execute("useradd", "username", "-p", "changeme", "-r", "test_admin");
execute("roles", "existing_user", "-r", "test_admin");
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", "changeme", "-r", "test_admin");
execute("roles", pathHomeParameter, fileTypeParameter, "existing_user", "-r", "test_admin");
assertRole("test_admin", "username");
}
public void testRolesNoAddOrRemove() throws Exception {
String output = execute("roles", "existing_user");
String output = execute("roles", pathHomeParameter, fileTypeParameter, "existing_user");
assertTrue(output, output.contains("existing_user"));
assertTrue(output, output.contains("test_admin"));
}
public void testListUnknownUser() throws Exception {
UserError e = expectThrows(UserError.class, () -> {
execute("list", "unknown");
execute("list", pathHomeParameter, fileTypeParameter, "unknown");
});
assertEquals(ExitCodes.NO_USER, e.exitCode);
assertTrue(e.getMessage(), e.getMessage().contains("User [unknown] doesn't exist"));
}
public void testListAllUsers() throws Exception {
String output = execute("list");
String output = execute("list", pathHomeParameter, fileTypeParameter);
assertTrue(output, output.contains("existing_user"));
assertTrue(output, output.contains("test_admin"));
assertTrue(output, output.contains("existing_user2"));
@ -367,7 +372,7 @@ public class UsersToolTests extends CommandTestCase {
}
public void testListSingleUser() throws Exception {
String output = execute("list", "existing_user");
String output = execute("list", pathHomeParameter, fileTypeParameter, "existing_user");
assertTrue(output, output.contains("existing_user"));
assertTrue(output, output.contains("test_admin"));
assertFalse(output, output.contains("existing_user2"));
@ -378,8 +383,8 @@ public class UsersToolTests extends CommandTestCase {
}
public void testListUnknownRoles() throws Exception {
execute("useradd", "username", "-p", "changeme", "-r", "test_r1,r2,r3");
String output = execute("list", "username");
execute("useradd", pathHomeParameter, fileTypeParameter, "username", "-p", "changeme", "-r", "test_r1,r2,r3");
String output = execute("list", pathHomeParameter, fileTypeParameter, "username");
assertTrue(output, output.contains("username"));
assertTrue(output, output.contains("r2*,r3*,test_r1"));
}
@ -389,14 +394,14 @@ public class UsersToolTests extends CommandTestCase {
Files.createFile(confDir.resolve("users"));
Files.delete(confDir.resolve("users_roles"));
Files.createFile(confDir.resolve("users_roles"));
String output = execute("list");
String output = execute("list", pathHomeParameter, fileTypeParameter);
assertTrue(output, output.contains("No users found"));
}
public void testListUserWithoutRoles() throws Exception {
String output = execute("list", "existing_user3");
String output = execute("list", pathHomeParameter, fileTypeParameter, "existing_user3");
assertTrue(output, output.contains("existing_user3"));
output = execute("list");
output = execute("list", pathHomeParameter, fileTypeParameter);
assertTrue(output, output.contains("existing_user3"));
// output should not contain '*' which indicates unknown role

View File

@ -7,12 +7,12 @@ package org.elasticsearch.shield.crypto.tool;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.CommandTestCase;
import org.elasticsearch.common.io.PathUtilsForTesting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.shield.crypto.InternalCryptoService;
import org.junit.After;
import java.nio.file.FileSystem;
import java.nio.file.Files;
@ -23,32 +23,33 @@ import java.util.Set;
public class SystemKeyToolTests extends CommandTestCase {
private FileSystem jimfs;
private Settings.Builder settingsBuilder;
private Path homeDir;
private void initFileSystem(boolean needsPosix) throws Exception {
private Path initFileSystem(boolean needsPosix) throws Exception {
String view = needsPosix ? "posix" : randomFrom("basic", "posix");
Configuration conf = Configuration.unix().toBuilder().setAttributeViews(view).build();
jimfs = Jimfs.newFileSystem(conf);
PathUtilsForTesting.installMock(jimfs);
homeDir = jimfs.getPath("eshome");
return jimfs.getPath("eshome");
}
settingsBuilder = Settings.builder()
.put(Environment.PATH_HOME_SETTING.getKey(), homeDir);
@After
public void tearDown() throws Exception {
IOUtils.close(jimfs);
super.tearDown();
}
@Override
protected Command newCommand() {
return new SystemKeyTool(new Environment(settingsBuilder.build()));
return new SystemKeyTool();
}
public void testGenerate() throws Exception {
initFileSystem(true);
final Path homeDir = initFileSystem(true);
Path path = jimfs.getPath(randomAsciiOfLength(10)).resolve("key");
Files.createDirectory(path.getParent());
execute(path.toString());
execute("-Epath.home=" + homeDir, path.toString());
byte[] bytes = Files.readAllBytes(path);
// TODO: maybe we should actually check the key is...i dunno...valid?
assertEquals(InternalCryptoService.KEY_SIZE / 8, bytes.length);
@ -60,35 +61,35 @@ public class SystemKeyToolTests extends CommandTestCase {
}
public void testGeneratePathInSettings() throws Exception {
initFileSystem(false);
final Path homeDir = initFileSystem(false);
Path path = jimfs.getPath(randomAsciiOfLength(10)).resolve("key");
Files.createDirectories(path.getParent());
settingsBuilder.put(InternalCryptoService.FILE_SETTING.getKey(), path.toAbsolutePath().toString());
execute();
execute("-Epath.home=" + homeDir.toString(), "-Expack.security.system_key.file=" + path.toAbsolutePath().toString());
byte[] bytes = Files.readAllBytes(path);
assertEquals(InternalCryptoService.KEY_SIZE / 8, bytes.length);
}
public void testGenerateDefaultPath() throws Exception {
initFileSystem(false);
final Path homeDir = initFileSystem(false);
Path keyPath = homeDir.resolve("config/x-pack/system_key");
Files.createDirectories(keyPath.getParent());
execute();
execute("-Epath.home=" + homeDir.toString());
byte[] bytes = Files.readAllBytes(keyPath);
assertEquals(InternalCryptoService.KEY_SIZE / 8, bytes.length);
}
public void testThatSystemKeyMayOnlyBeReadByOwner() throws Exception {
initFileSystem(true);
final Path homeDir = initFileSystem(true);
Path path = jimfs.getPath(randomAsciiOfLength(10)).resolve("key");
Files.createDirectories(path.getParent());
execute(path.toString());
execute("-Epath.home=" + homeDir, path.toString());
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(path);
assertTrue(perms.toString(), perms.contains(PosixFilePermission.OWNER_READ));
assertTrue(perms.toString(), perms.contains(PosixFilePermission.OWNER_WRITE));
assertEquals(perms.toString(), 2, perms.size());
}
}

View File

@ -8,17 +8,18 @@ package org.elasticsearch.xpack.extensions;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.bootstrap.JarHell;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.SettingCommand;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.io.FileSystemUtils;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.node.internal.InternalSettingsPreparer;
import java.io.InputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLDecoder;
@ -26,13 +27,14 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static org.elasticsearch.xpack.XPackPlugin.resolveXPackExtensionsFile;
import static org.elasticsearch.cli.Terminal.Verbosity.VERBOSE;
import static org.elasticsearch.xpack.XPackPlugin.resolveXPackExtensionsFile;
/**
* A command for the extension cli to install an extension into x-pack.
@ -49,22 +51,20 @@ import static org.elasticsearch.cli.Terminal.Verbosity.VERBOSE;
* <li>Jar hell does not exist, either between the extension's own jars or with the parent classloader (elasticsearch + x-pack)</li>
* </ul>
*/
class InstallXPackExtensionCommand extends Command {
class InstallXPackExtensionCommand extends SettingCommand {
private final Environment env;
private final OptionSpec<Void> batchOption;
private final OptionSpec<String> arguments;
InstallXPackExtensionCommand(Environment env) {
InstallXPackExtensionCommand() {
super("Install a plugin");
this.env = env;
this.batchOption = parser.acceptsAll(Arrays.asList("b", "batch"),
"Enable batch mode explicitly, automatic confirmation of security permission");
this.arguments = parser.nonOptions("plugin id");
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
// TODO: in jopt-simple 5.0 we can enforce a min/max number of positional args
List<String> args = arguments.values(options);
if (args.size() != 1) {
@ -72,12 +72,13 @@ class InstallXPackExtensionCommand extends Command {
}
String extensionURL = args.get(0);
boolean isBatch = options.has(batchOption) || System.console() == null;
execute(terminal, extensionURL, isBatch);
execute(terminal, extensionURL, isBatch, settings);
}
// pkg private for testing
void execute(Terminal terminal, String extensionId, boolean isBatch) throws Exception {
void execute(Terminal terminal, String extensionId, boolean isBatch, Map<String, String> properties) throws Exception {
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, properties);
if (Files.exists(resolveXPackExtensionsFile(env)) == false) {
terminal.println("xpack extensions directory [" + resolveXPackExtensionsFile(env) + "] does not exist. Creating...");
Files.createDirectories(resolveXPackExtensionsFile(env));

View File

@ -6,32 +6,33 @@
package org.elasticsearch.xpack.extensions;
import joptsimple.OptionSet;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.SettingCommand;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.node.internal.InternalSettingsPreparer;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import static org.elasticsearch.xpack.XPackPlugin.resolveXPackExtensionsFile;
import static org.elasticsearch.cli.Terminal.Verbosity.VERBOSE;
import static org.elasticsearch.xpack.XPackPlugin.resolveXPackExtensionsFile;
/**
* A command for the extension cli to list extensions installed in x-pack.
*/
class ListXPackExtensionCommand extends Command {
private final Environment env;
class ListXPackExtensionCommand extends SettingCommand {
ListXPackExtensionCommand(Environment env) {
ListXPackExtensionCommand() {
super("Lists installed x-pack extensions");
this.env = env;
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
if (Files.exists(resolveXPackExtensionsFile(env)) == false) {
throw new IOException("Extensions directory missing: " + resolveXPackExtensionsFile(env));
}
@ -43,4 +44,5 @@ class ListXPackExtensionCommand extends Command {
}
}
}
}

View File

@ -7,51 +7,53 @@ package org.elasticsearch.xpack.extensions;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.apache.lucene.util.IOUtils;
import org.elasticsearch.cli.Command;
import org.elasticsearch.cli.ExitCodes;
import org.elasticsearch.cli.SettingCommand;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.node.internal.InternalSettingsPreparer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.xpack.XPackPlugin.resolveXPackExtensionsFile;
import static org.elasticsearch.cli.Terminal.Verbosity.VERBOSE;
import static org.elasticsearch.xpack.XPackPlugin.resolveXPackExtensionsFile;
/**
* A command for the extension cli to remove an extension from x-pack.
*/
class RemoveXPackExtensionCommand extends Command {
private final Environment env;
class RemoveXPackExtensionCommand extends SettingCommand {
private final OptionSpec<String> arguments;
RemoveXPackExtensionCommand(Environment env) {
RemoveXPackExtensionCommand() {
super("Removes an extension from x-pack");
this.env = env;
this.arguments = parser.nonOptions("extension name");
}
@Override
protected void execute(Terminal terminal, OptionSet options) throws Exception {
protected void execute(Terminal terminal, OptionSet options, Map<String, String> settings) throws Exception {
// TODO: in jopt-simple 5.0 we can enforce a min/max number of positional args
List<String> args = arguments.values(options);
if (args.size() != 1) {
throw new UserError(ExitCodes.USAGE, "Must supply a single extension id argument");
}
execute(terminal, args.get(0));
execute(terminal, args.get(0), settings);
}
// pkg private for testing
void execute(Terminal terminal, String extensionName) throws Exception {
void execute(Terminal terminal, String extensionName, Map<String, String> settings) throws Exception {
terminal.println("-> Removing " + Strings.coalesceToEmpty(extensionName) + "...");
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, terminal, settings);
Path extensionDir = resolveXPackExtensionsFile(env).resolve(extensionName);
if (Files.exists(extensionDir) == false) {
throw new UserError(ExitCodes.USAGE,

View File

@ -9,25 +9,22 @@ import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.varia.NullAppender;
import org.elasticsearch.cli.MultiCommand;
import org.elasticsearch.cli.Terminal;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.node.internal.InternalSettingsPreparer;
/**
* A cli tool for adding, removing and listing extensions for x-pack.
*/
public class XPackExtensionCli extends MultiCommand {
public XPackExtensionCli(Environment env) {
public XPackExtensionCli() {
super("A tool for managing installed x-pack extensions");
subcommands.put("list", new ListXPackExtensionCommand(env));
subcommands.put("install", new InstallXPackExtensionCommand(env));
subcommands.put("remove", new RemoveXPackExtensionCommand(env));
subcommands.put("list", new ListXPackExtensionCommand());
subcommands.put("install", new InstallXPackExtensionCommand());
subcommands.put("remove", new RemoveXPackExtensionCommand());
}
public static void main(String[] args) throws Exception {
BasicConfigurator.configure(new NullAppender());
Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, Terminal.DEFAULT);
exit(new XPackExtensionCli(env).main(args, Terminal.DEFAULT));
exit(new XPackExtensionCli().main(args, Terminal.DEFAULT));
}
}

View File

@ -12,34 +12,37 @@ import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.DirectoryStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.FileVisitResult;
import java.nio.file.NoSuchFileException;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@LuceneTestCase.SuppressFileSystems("*")
public class InstallXPackExtensionCommandTests extends ESTestCase {
/**
* Creates a test environment with plugins and xpack extensions directories.
*/
static Environment createEnv() throws IOException {
Path home = createTempDir();
Path home;
Environment env;
@Before
public void setUp() throws Exception {
super.setUp();
home = createTempDir();
Files.createDirectories(home.resolve("org/elasticsearch/xpack/extensions").resolve("xpack").resolve("extensions"));
Settings settings = Settings.builder()
.put("path.home", home)
.build();
return new Environment(settings);
env = new Environment(Settings.builder().put("path.home", home.toString()).build());
}
/**
@ -84,9 +87,11 @@ public class InstallXPackExtensionCommandTests extends ESTestCase {
return writeZip(structure);
}
static MockTerminal installExtension(String extensionUrl, Environment env) throws Exception {
static MockTerminal installExtension(String extensionUrl, Path home) throws Exception {
Map<String, String> settings = new HashMap<>();
settings.put("path.home", home.toString());
MockTerminal terminal = new MockTerminal();
new InstallXPackExtensionCommand(env).execute(terminal, extensionUrl, true);
new InstallXPackExtensionCommand().execute(terminal, extensionUrl, true, settings);
return terminal;
}
@ -108,77 +113,65 @@ public class InstallXPackExtensionCommandTests extends ESTestCase {
}
public void testSomethingWorks() throws Exception {
Environment env = createEnv();
Path extDir = createTempDir();
String extZip = createExtension("fake", extDir);
installExtension(extZip, env);
installExtension(extZip, home);
assertExtension("fake", extDir, env);
}
public void testSpaceInUrl() throws Exception {
Environment env = createEnv();
Path extDir = createTempDir();
String extZip = createExtension("fake", extDir);
Path extZipWithSpaces = createTempFile("foo bar", ".zip");
try (InputStream in = new URL(extZip).openStream()) {
Files.copy(in, extZipWithSpaces, StandardCopyOption.REPLACE_EXISTING);
}
installExtension(extZipWithSpaces.toUri().toURL().toString(), env);
installExtension(extZipWithSpaces.toUri().toURL().toString(), home);
assertExtension("fake", extDir, env);
}
public void testMalformedUrlNotMaven() throws Exception {
// has two colons, so it appears similar to maven coordinates
MalformedURLException e = expectThrows(MalformedURLException.class, () -> {
installExtension("://host:1234", createEnv());
installExtension("://host:1234", home);
});
assertTrue(e.getMessage(), e.getMessage().contains("no protocol"));
}
public void testJarHell() throws Exception {
Environment env = createEnv();
Path extDir = createTempDir();
writeJar(extDir.resolve("other.jar"), "FakeExtension");
String extZip = createExtension("fake", extDir); // adds extension.jar with FakeExtension
IllegalStateException e = expectThrows(IllegalStateException.class, () -> {
installExtension(extZip, env);
});
IllegalStateException e = expectThrows(IllegalStateException.class, () -> installExtension(extZip, home));
assertTrue(e.getMessage(), e.getMessage().contains("jar hell"));
assertInstallCleaned(env);
}
public void testIsolatedExtension() throws Exception {
Environment env = createEnv();
// these both share the same FakeExtension class
Path extDir1 = createTempDir();
String extZip1 = createExtension("fake1", extDir1);
installExtension(extZip1, env);
installExtension(extZip1, home);
Path extDir2 = createTempDir();
String extZip2 = createExtension("fake2", extDir2);
installExtension(extZip2, env);
installExtension(extZip2, home);
assertExtension("fake1", extDir1, env);
assertExtension("fake2", extDir2, env);
}
public void testExistingExtension() throws Exception {
Environment env = createEnv();
String extZip = createExtension("fake", createTempDir());
installExtension(extZip, env);
UserError e = expectThrows(UserError.class, () -> {
installExtension(extZip, env);
});
installExtension(extZip, home);
UserError e = expectThrows(UserError.class, () -> installExtension(extZip, home));
assertTrue(e.getMessage(), e.getMessage().contains("already exists"));
assertInstallCleaned(env);
}
public void testMissingDescriptor() throws Exception {
Environment env = createEnv();
Path extDir = createTempDir();
Files.createFile(extDir.resolve("fake.yml"));
String extZip = writeZip(extDir);
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> {
installExtension(extZip, env);
});
NoSuchFileException e = expectThrows(NoSuchFileException.class, () -> installExtension(extZip, home));
assertTrue(e.getMessage(), e.getMessage().contains("x-pack-extension-descriptor.properties"));
assertInstallCleaned(env);
}

View File

@ -11,6 +11,7 @@ import org.elasticsearch.cli.MockTerminal;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
import java.io.IOException;
import java.nio.file.Files;
@ -19,60 +20,55 @@ import java.nio.file.Path;
@LuceneTestCase.SuppressFileSystems("*")
public class ListXPackExtensionCommandTests extends ESTestCase {
Environment createEnv() throws IOException {
Path home = createTempDir();
Settings settings = Settings.builder()
.put("path.home", home)
.build();
return new Environment(settings);
private Path home;
@Before
public void setUp() throws Exception {
super.setUp();
home = createTempDir();
}
Path createExtensionDir(Environment env) throws IOException {
Path path = env.pluginsFile().resolve("x-pack").resolve("extensions");
private static Path createExtensionDir(final Path home) throws IOException {
final Environment env = new Environment(Settings.builder().put("path.home", home.toString()).build());
final Path path = env.pluginsFile().resolve("x-pack").resolve("extensions");
return Files.createDirectories(path);
}
static MockTerminal listExtensions(Environment env) throws Exception {
static MockTerminal listExtensions(Path home) throws Exception {
MockTerminal terminal = new MockTerminal();
String[] args = {};
int status = new ListXPackExtensionCommand(env).main(args, terminal);
int status = new ListXPackExtensionCommand().main(new String[] { "-Epath.home=" + home }, terminal);
assertEquals(ExitCodes.OK, status);
return terminal;
}
public void testExtensionsDirMissing() throws Exception {
Environment env = createEnv();
Path extDir = createExtensionDir(env);
Path extDir = createExtensionDir(home);
Files.delete(extDir);
IOException e = expectThrows(IOException.class, () -> {
listExtensions(env);
});
IOException e = expectThrows(IOException.class, () -> listExtensions(home));
assertTrue(e.getMessage(), e.getMessage().contains("Extensions directory missing"));
}
public void testNoExtensions() throws Exception {
Environment env = createEnv();
createExtensionDir(env);
MockTerminal terminal = listExtensions(env);
createExtensionDir(home);
MockTerminal terminal = listExtensions(home);
assertTrue(terminal.getOutput(), terminal.getOutput().isEmpty());
}
public void testOneExtension() throws Exception {
Environment env = createEnv();
Path extDir = createExtensionDir(env);
Path extDir = createExtensionDir(home);
Files.createDirectory(extDir.resolve("fake"));
MockTerminal terminal = listExtensions(env);
MockTerminal terminal = listExtensions(home);
assertTrue(terminal.getOutput(), terminal.getOutput().contains("fake"));
}
public void testTwoExtensions() throws Exception {
Environment env = createEnv();
Path extDir = createExtensionDir(env);
Path extDir = createExtensionDir(home);
Files.createDirectory(extDir.resolve("fake1"));
Files.createDirectory(extDir.resolve("fake2"));
MockTerminal terminal = listExtensions(env);
MockTerminal terminal = listExtensions(home);
String output = terminal.getOutput();
assertTrue(output, output.contains("fake1"));
assertTrue(output, output.contains("fake2"));
}
}

View File

@ -11,22 +11,26 @@ import org.elasticsearch.cli.UserError;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
@LuceneTestCase.SuppressFileSystems("*")
public class RemoveXPackExtensionCommandTests extends ESTestCase {
/** Creates a test environment with bin, config and plugins directories. */
static Environment createEnv() throws IOException {
Path home = createTempDir();
Settings settings = Settings.builder()
.put("path.home", home)
.build();
return new Environment(settings);
private Path home;
private Environment env;
@Before
public void setUp() throws Exception {
super.setUp();
home = createTempDir();
env = new Environment(Settings.builder().put("path.home", home.toString()).build());
}
Path createExtensionDir(Environment env) throws IOException {
@ -34,9 +38,11 @@ public class RemoveXPackExtensionCommandTests extends ESTestCase {
return Files.createDirectories(path);
}
static MockTerminal removeExtension(String name, Environment env) throws Exception {
static MockTerminal removeExtension(String name, Path home) throws Exception {
Map<String, String> settings = new HashMap<>();
settings.put("path.home", home.toString());
MockTerminal terminal = new MockTerminal();
new RemoveXPackExtensionCommand(env).execute(terminal, name);
new RemoveXPackExtensionCommand().execute(terminal, name, settings);
return terminal;
}
@ -51,25 +57,22 @@ public class RemoveXPackExtensionCommandTests extends ESTestCase {
}
public void testMissing() throws Exception {
Environment env = createEnv();
Path extDir = createExtensionDir(env);
UserError e = expectThrows(UserError.class, () -> {
removeExtension("dne", env);
});
UserError e = expectThrows(UserError.class, () -> removeExtension("dne", home));
assertTrue(e.getMessage(), e.getMessage().contains("Extension dne not found"));
assertRemoveCleaned(extDir);
}
public void testBasic() throws Exception {
Environment env = createEnv();
Path extDir = createExtensionDir(env);
Files.createDirectory(extDir.resolve("fake"));
Files.createFile(extDir.resolve("fake").resolve("extension.jar"));
Files.createDirectory(extDir.resolve("fake").resolve("subdir"));
Files.createDirectory(extDir.resolve("other"));
removeExtension("fake", env);
removeExtension("fake", home);
assertFalse(Files.exists(extDir.resolve("fake")));
assertTrue(Files.exists(extDir.resolve("other")));
assertRemoveCleaned(extDir);
}
}

View File

@ -70,29 +70,6 @@ elif [ -f "/etc/default/elasticsearch" ]; then
. "/etc/default/elasticsearch"
fi
# Parse any long getopt options and put them into properties
ARGCOUNT=$#
COUNT=0
while [ $COUNT -lt $ARGCOUNT ]
do
case $1 in
--*) properties="$properties $1 $2"
shift ; shift; COUNT=$(($COUNT+2))
;;
*) set -- "$@" "$1"; shift; COUNT=$(($COUNT+1))
esac
done
# check if properties already has a config file or config dir
if [ -e "$CONF_DIR" ]; then
case "$properties" in
*-Des.default.path.conf=*) ;;
*)
properties="$properties -Des.default.path.conf=$CONF_DIR"
;;
esac
fi
export HOSTNAME=`hostname -s`
# include watcher jars in classpath
@ -112,8 +89,14 @@ if [ ! -z "$CONF_FILE" ]; then
exit 1
fi
declare -a args=("$@")
if [ -e "$CONF_DIR" ]; then
args=("${args[@]}" -Edefault.path.conf="$CONF_DIR")
fi
cd "$ES_HOME" > /dev/null
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" org.elasticsearch.xpack.watcher.trigger.schedule.tool.CronEvalTool "$@" $properties
"$JAVA" $ES_JAVA_OPTS -cp "$ES_CLASSPATH" -Des.path.home="$ES_HOME" org.elasticsearch.xpack.watcher.trigger.schedule.tool.CronEvalTool "${args[@]}"
status=$?
cd - > /dev/null
exit $status