Moved ESUsersTool to cores cli tool infra
Also removed the cli tool infra from this repo (as it was moved to core) Original commit: elastic/x-pack-elasticsearch@0bf7f84ab6
This commit is contained in:
parent
86546e80ad
commit
605aee5a54
|
@ -5,16 +5,16 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.authc.esusers.tool;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.cli.CliTool;
|
||||
import org.elasticsearch.common.cli.CliToolConfig;
|
||||
import org.elasticsearch.common.cli.Terminal;
|
||||
import org.elasticsearch.common.cli.commons.CommandLine;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.shield.authc.esusers.FileUserPasswdStore;
|
||||
import org.elasticsearch.shield.authc.esusers.FileUserRolesStore;
|
||||
import org.elasticsearch.shield.authc.support.Hasher;
|
||||
import org.elasticsearch.shield.support.cli.CliTool;
|
||||
import org.elasticsearch.shield.support.cli.CliToolConfig;
|
||||
import org.elasticsearch.shield.support.cli.Terminal;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
|
@ -22,8 +22,8 @@ import java.util.HashMap;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.shield.support.cli.CliToolConfig.Builder.cmd;
|
||||
import static org.elasticsearch.shield.support.cli.CliToolConfig.Builder.option;
|
||||
import static org.elasticsearch.common.cli.CliToolConfig.Builder.cmd;
|
||||
import static org.elasticsearch.common.cli.CliToolConfig.Builder.option;
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.shield.support.cli;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.CommandLineParser;
|
||||
import org.apache.commons.cli.GnuParser;
|
||||
import org.elasticsearch.common.base.Preconditions;
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.node.internal.InternalSettingsPreparer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.elasticsearch.common.settings.ImmutableSettings.Builder.EMPTY_SETTINGS;
|
||||
|
||||
/**
|
||||
* A base class for command-line interface tool.
|
||||
*
|
||||
* Two modes are supported:
|
||||
*
|
||||
* - Singe command mode. The tool exposes a single command that can potentially accept arguments (eg. CLI options).
|
||||
* - Multi command mode. The tool support multiple command, each for different tasks, each potentially accepts arguments.
|
||||
*
|
||||
* In a multi-command mode. The first argument must be the command name. For example, the plugin manager
|
||||
* can be seen as a multi-command tool with two possible commands: install and uninstall
|
||||
*
|
||||
* The tool is configured using a {@link CliToolConfig} which encapsulates the tool's commands and their
|
||||
* potential options. The tool also comes with out of the box simple help support (the -h/--help option is
|
||||
* automatically handled) where the help text is configured in a dedicated *.help files located in the same package
|
||||
* as the tool.
|
||||
*/
|
||||
public abstract class CliTool {
|
||||
|
||||
// based on sysexits.h
|
||||
public static enum ExitStatus {
|
||||
OK(0),
|
||||
USAGE(64), /* command line usage error */
|
||||
DATA_ERROR(65), /* data format error */
|
||||
NO_INPUT(66), /* cannot open input */
|
||||
NO_USER(67), /* addressee unknown */
|
||||
NO_HOST(68), /* host name unknown */
|
||||
UNAVAILABLE(69), /* service unavailable */
|
||||
CODE_ERROR(70), /* internal software error */
|
||||
CANT_CREATE(73), /* can't create (user) output file */
|
||||
IO_ERROR(74), /* input/output error */
|
||||
TEMP_FAILURE(75), /* temp failure; user is invited to retry */
|
||||
PROTOCOL(76), /* remote error in protocol */
|
||||
NOPERM(77), /* permission denied */
|
||||
CONFIG(78); /* configuration error */
|
||||
|
||||
final int status;
|
||||
|
||||
private ExitStatus(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int status() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
protected final Terminal terminal;
|
||||
protected final Environment env;
|
||||
protected final Settings settings;
|
||||
|
||||
private final CliToolConfig config;
|
||||
|
||||
protected CliTool(CliToolConfig config) {
|
||||
this(config, Terminal.INSTANCE);
|
||||
}
|
||||
|
||||
protected CliTool(CliToolConfig config, Terminal terminal) {
|
||||
Preconditions.checkArgument(config.cmds().size() != 0, "At least one command must be configured");
|
||||
this.config = config;
|
||||
this.terminal = terminal;
|
||||
Tuple<Settings, Environment> tuple = InternalSettingsPreparer.prepareSettings(EMPTY_SETTINGS, true);
|
||||
settings = tuple.v1();
|
||||
env = tuple.v2();
|
||||
}
|
||||
|
||||
public final int execute(String... args) {
|
||||
|
||||
// first lets see if the user requests tool help. We're doing it only if
|
||||
// this is a multi-command tool. If it's a single command tool, the -h/--help
|
||||
// option will be taken care of on the command level
|
||||
if (!config.isSingle() && args.length > 0 && (args[0].equals("-h") || args[0].equals("--help"))) {
|
||||
config.printUsage(terminal);
|
||||
return ExitStatus.OK.status;
|
||||
}
|
||||
|
||||
CliToolConfig.Cmd cmd = null;
|
||||
if (config.isSingle()) {
|
||||
cmd = config.single();
|
||||
} else {
|
||||
|
||||
if (args.length == 0) {
|
||||
terminal.println("Error: command not specified");
|
||||
config.printUsage(terminal);
|
||||
return ExitStatus.USAGE.status;
|
||||
}
|
||||
|
||||
String cmdName = args[0];
|
||||
cmd = config.cmd(cmdName);
|
||||
if (cmd == null) {
|
||||
terminal.println("Error: unknown command [%s]. Use [-h] option to list available commands", cmdName);
|
||||
return ExitStatus.USAGE.status;
|
||||
}
|
||||
|
||||
// we now remove the command name from the args
|
||||
if (args.length == 1) {
|
||||
args = new String[0];
|
||||
} else {
|
||||
String[] cmdArgs = new String[args.length - 1];
|
||||
System.arraycopy(args, 1, cmdArgs, 0, cmdArgs.length);
|
||||
args = cmdArgs;
|
||||
}
|
||||
}
|
||||
|
||||
Command command = null;
|
||||
try {
|
||||
command = parse(cmd, args);
|
||||
return command.execute(settings, env).status;
|
||||
} catch (IOException ioe) {
|
||||
terminal.println(ioe.getMessage());
|
||||
return ExitStatus.IO_ERROR.status;
|
||||
} catch (Exception e) {
|
||||
terminal.println(e.getMessage());
|
||||
if (command == null) {
|
||||
return ExitStatus.USAGE.status;
|
||||
}
|
||||
return ExitStatus.CODE_ERROR.status;
|
||||
}
|
||||
}
|
||||
|
||||
public Command parse(String cmdName, String[] args) throws Exception {
|
||||
CliToolConfig.Cmd cmd = config.cmd(cmdName);
|
||||
return parse(cmd, args);
|
||||
}
|
||||
|
||||
public Command parse(CliToolConfig.Cmd cmd, String[] args) throws Exception {
|
||||
CommandLineParser parser = new GnuParser();
|
||||
CommandLine cli = parser.parse(cmd.options(), args);
|
||||
if (cli.hasOption("h")) {
|
||||
return helpCmd(cmd);
|
||||
}
|
||||
return parse(cmd.name(), cli);
|
||||
}
|
||||
|
||||
protected Command.Help helpCmd(CliToolConfig.Cmd cmd) {
|
||||
return new Command.Help(cmd, terminal);
|
||||
}
|
||||
|
||||
protected static Command.Exit exitCmd(ExitStatus status) {
|
||||
return new Command.Exit(null, status, null);
|
||||
}
|
||||
|
||||
protected static Command.Exit exitCmd(ExitStatus status, Terminal terminal, String msg, Object... args) {
|
||||
return new Command.Exit(String.format(Locale.ROOT, msg, args), status, terminal);
|
||||
}
|
||||
|
||||
protected abstract Command parse(String cmdName, CommandLine cli) throws Exception;
|
||||
|
||||
public static abstract class Command {
|
||||
|
||||
protected final Terminal terminal;
|
||||
|
||||
protected Command(Terminal terminal) {
|
||||
this.terminal = terminal;
|
||||
}
|
||||
|
||||
public abstract ExitStatus execute(Settings settings, Environment env) throws Exception;
|
||||
|
||||
public static class Help extends Command {
|
||||
|
||||
private final CliToolConfig.Cmd cmd;
|
||||
|
||||
private Help(CliToolConfig.Cmd cmd, Terminal terminal) {
|
||||
super(terminal);
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
cmd.printUsage(terminal);
|
||||
return ExitStatus.OK;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Exit extends Command {
|
||||
private final String msg;
|
||||
private final ExitStatus status;
|
||||
|
||||
private Exit(String msg, ExitStatus status, Terminal terminal) {
|
||||
super(terminal);
|
||||
this.msg = msg;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
if (msg != null) {
|
||||
terminal.println(msg);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
public ExitStatus status() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.shield.support.cli;
|
||||
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.elasticsearch.common.collect.ImmutableMap;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class CliToolConfig {
|
||||
|
||||
public static Builder config(String name, Class<? extends CliTool> toolType) {
|
||||
return new Builder(name, toolType);
|
||||
}
|
||||
|
||||
private final Class<? extends CliTool> toolType;
|
||||
private final String name;
|
||||
private final ImmutableMap<String, Cmd> cmds;
|
||||
|
||||
private static final HelpPrinter helpPrinter = new HelpPrinter();
|
||||
|
||||
private CliToolConfig(String name, Class<? extends CliTool> toolType, Cmd[] cmds) {
|
||||
this.name = name;
|
||||
this.toolType = toolType;
|
||||
ImmutableMap.Builder<String, Cmd> cmdsBuilder = ImmutableMap.builder();
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
cmdsBuilder.put(cmds[i].name, cmds[i]);
|
||||
}
|
||||
this.cmds = cmdsBuilder.build();
|
||||
}
|
||||
|
||||
public boolean isSingle() {
|
||||
return cmds.size() == 1;
|
||||
}
|
||||
|
||||
public Cmd single() {
|
||||
assert isSingle() : "Requesting single command on a multi-command tool";
|
||||
return cmds.values().iterator().next();
|
||||
}
|
||||
|
||||
public Class<? extends CliTool> toolType() {
|
||||
return toolType;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Collection<Cmd> cmds() {
|
||||
return cmds.values();
|
||||
}
|
||||
|
||||
public Cmd cmd(String name) {
|
||||
return cmds.get(name);
|
||||
}
|
||||
|
||||
public void printUsage(Terminal terminal) {
|
||||
helpPrinter.print(this, terminal);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
public static Cmd.Builder cmd(String name, Class<? extends CliTool.Command> cmdType) {
|
||||
return new Cmd.Builder(name, cmdType);
|
||||
}
|
||||
|
||||
public static OptionBuilder option(String shortName, String longName) {
|
||||
return new OptionBuilder(shortName, longName);
|
||||
}
|
||||
|
||||
private final Class<? extends CliTool> toolType;
|
||||
private final String name;
|
||||
private Cmd[] cmds;
|
||||
|
||||
private Builder(String name, Class<? extends CliTool> toolType) {
|
||||
this.name = name;
|
||||
this.toolType = toolType;
|
||||
}
|
||||
|
||||
public Builder cmds(Cmd.Builder... cmds) {
|
||||
this.cmds = new Cmd[cmds.length];
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
this.cmds[i] = cmds[i].build();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder cmds(Cmd... cmds) {
|
||||
this.cmds = cmds;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CliToolConfig build() {
|
||||
return new CliToolConfig(name, toolType, cmds);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Cmd {
|
||||
|
||||
private final String name;
|
||||
private final Class<? extends CliTool.Command> cmdType;
|
||||
private final Options options;
|
||||
|
||||
private Cmd(String name, Class<? extends CliTool.Command> cmdType, Options options) {
|
||||
this.name = name;
|
||||
this.cmdType = cmdType;
|
||||
this.options = options;
|
||||
this.options.addOption(new OptionBuilder("h", "help").required(false).build());
|
||||
}
|
||||
|
||||
public Class<? extends CliTool.Command> cmdType() {
|
||||
return cmdType;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Options options() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public void printUsage(Terminal terminal) {
|
||||
helpPrinter.print(this, terminal);
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
|
||||
private final String name;
|
||||
private final Class<? extends CliTool.Command> cmdType;
|
||||
private Options options = new Options();
|
||||
|
||||
private Builder(String name, Class<? extends CliTool.Command> cmdType) {
|
||||
this.name = name;
|
||||
this.cmdType = cmdType;
|
||||
}
|
||||
|
||||
public Builder options(OptionBuilder... optionBuilder) {
|
||||
for (int i = 0; i < optionBuilder.length; i++) {
|
||||
options.addOption(optionBuilder[i].build());
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Cmd build() {
|
||||
return new Cmd(name, cmdType, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class OptionBuilder {
|
||||
|
||||
private final Option option;
|
||||
|
||||
private OptionBuilder(String shortName, String longName) {
|
||||
option = new Option(shortName, "");
|
||||
option.setLongOpt(longName);
|
||||
option.setArgName(longName);
|
||||
}
|
||||
|
||||
public OptionBuilder required(boolean required) {
|
||||
option.setRequired(required);
|
||||
return this;
|
||||
}
|
||||
|
||||
public OptionBuilder hasArg(boolean optional) {
|
||||
option.setOptionalArg(optional);
|
||||
option.setArgs(1);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Option build() {
|
||||
return option;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.shield.support.cli;
|
||||
|
||||
import org.elasticsearch.common.base.Charsets;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class HelpPrinter {
|
||||
|
||||
public void print(CliToolConfig config, Terminal terminal) {
|
||||
URL url = config.toolType().getResource(config.name() + ".help");
|
||||
print(url, terminal);
|
||||
}
|
||||
|
||||
public void print(CliToolConfig.Cmd cmd, Terminal terminal) {
|
||||
URL url = cmd.cmdType().getResource(cmd.name() + ".help");
|
||||
print(url, terminal);
|
||||
}
|
||||
|
||||
private static void print(URL url, Terminal terminal) {
|
||||
terminal.println();
|
||||
try {
|
||||
Path helpFile = Paths.get(url.toURI());
|
||||
for (String line : Files.readAllLines(helpFile, Charsets.UTF_8)) {
|
||||
terminal.println(line);
|
||||
}
|
||||
} catch (IOException | URISyntaxException e) {
|
||||
e.printStackTrace(terminal.writer());
|
||||
}
|
||||
terminal.println();
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.shield.support.cli;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public abstract class Terminal {
|
||||
|
||||
public static final Terminal INSTANCE = ConsoleTerminal.supported() ? new ConsoleTerminal() : new SystemTerminal();
|
||||
|
||||
public abstract String readText(String text, Object... args);
|
||||
|
||||
public abstract char[] readSecret(String text, Object... args);
|
||||
|
||||
public abstract void println();
|
||||
|
||||
public abstract void println(String msg, Object... args);
|
||||
|
||||
public abstract void print(String msg, Object... args);
|
||||
|
||||
public abstract PrintWriter writer();
|
||||
|
||||
public static abstract class Base extends Terminal {
|
||||
|
||||
@Override
|
||||
public void println() {
|
||||
println("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(String msg, Object... args) {
|
||||
print(msg + System.lineSeparator(), args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class ConsoleTerminal extends Base {
|
||||
|
||||
final Console console = System.console();
|
||||
|
||||
static boolean supported() {
|
||||
return System.console() != null;
|
||||
}
|
||||
|
||||
private ConsoleTerminal() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg, Object... args) {
|
||||
console.printf(msg, args);
|
||||
console.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readText(String text, Object... args) {
|
||||
return console.readLine(text, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] readSecret(String text, Object... args) {
|
||||
return console.readPassword(text, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintWriter writer() {
|
||||
return console.writer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class SystemTerminal extends Base {
|
||||
|
||||
private final PrintWriter printWriter = new PrintWriter(System.out);
|
||||
|
||||
@Override
|
||||
public void print(String msg, Object... args) {
|
||||
System.out.print(String.format(Locale.ROOT, msg, args));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readText(String text, Object... args) {
|
||||
print(text, args);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
|
||||
try {
|
||||
return reader.readLine();
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] readSecret(String text, Object... args) {
|
||||
return readText(text, args).toCharArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintWriter writer() {
|
||||
return printWriter;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
NAME
|
||||
|
||||
passwd - Changes the password of an existing native user
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
esusers passwd <username> [-p <password>]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
The passwd command changes passwords for native user accounts. The tool
|
||||
prompts twice for a replacement password. The second entry is compared
|
||||
against the first and both are required to match in order for the
|
||||
password to be changed. If non-default users file is used (a different
|
||||
file location is configured in elasticsearch.yml) the appropriate file
|
||||
will be resolved from the settings.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h,--help Shows this message
|
||||
|
||||
-p,--password <password> The new password for the user
|
|
@ -0,0 +1,28 @@
|
|||
NAME
|
||||
|
||||
useradd - Adds a native user
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
esusers useradd <username> [-p <password>] [-r <roles>]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Adds a native user to elasticsearch (via internal realm). The user will
|
||||
be added to the users file and its roles will be added to the
|
||||
users_roles file. If non-default files are used (different file
|
||||
locations are configured in elasticsearch.yml) the appropriate files
|
||||
will be resolved from the settings and the user and its roles will be
|
||||
added to them.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h,--help Shows this message
|
||||
|
||||
-p,--password <password> The user password
|
||||
|
||||
-r,--roles <roles> Comma-separated list of the roles of the user
|
||||
|
||||
SEE ALSO
|
||||
|
||||
[1] esusers userdel
|
|
@ -0,0 +1,24 @@
|
|||
NAME
|
||||
|
||||
userdel - Delete an existing native user
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
esusers userdel <username>
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Removes an existing native user from elasticsearch. The user will be
|
||||
removed from the users file and its roles will be removed to the
|
||||
users_roles file. If non-default files are used (different file
|
||||
locations are configured in elasticsearch.yml) the appropriate files
|
||||
will be resolved from the settings and the user and its roles will be
|
||||
removed to them.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-h,--help Shows this message
|
||||
|
||||
SEE ALSO
|
||||
|
||||
[1] esusers useradd
|
|
@ -1,22 +1,26 @@
|
|||
SYNTAX:
|
||||
NAME
|
||||
|
||||
esusers <command>
|
||||
esusers - Manages elasticsearch native users
|
||||
|
||||
DESCRIPTION:
|
||||
SYNOPSIS
|
||||
|
||||
This tool manages all native security aspects in elasticsearch, saving
|
||||
the administratorfrom needing to modify security related fiels manually.
|
||||
This tool provides several commands for different security management
|
||||
tasks
|
||||
esusers <command>
|
||||
|
||||
COMMANDS:
|
||||
DESCRIPTION
|
||||
|
||||
passwd Changes passwords for a native user
|
||||
This tool manages all native security aspects in elasticsearch, saving
|
||||
the administratorfrom needing to modify security related fiels manually.
|
||||
This tool provides several commands for different security management
|
||||
tasks
|
||||
|
||||
useradd Adds a new native user to the system
|
||||
COMMANDS
|
||||
|
||||
userdel Removes an existing native user from the system
|
||||
passwd Changes passwords for a native user
|
||||
|
||||
NOTES:
|
||||
useradd Adds a new native user to the system
|
||||
|
||||
[1] For usage help on specific commands please type "security <command> -h"
|
||||
userdel Removes an existing native user from the system
|
||||
|
||||
NOTES
|
||||
|
||||
[*] For usage help on specific commands please type "security <command> -h"
|
|
@ -1,18 +0,0 @@
|
|||
USAGE:
|
||||
|
||||
esusers passwd <username> [-p <password>]
|
||||
|
||||
DESCRIPTION:
|
||||
|
||||
The passwd command changes passwords for native user accounts. The tool
|
||||
prompts twice for a replacement password. The second entry is compared
|
||||
against the first and both are required to match in order for the
|
||||
password to be changed. If non-default users file is used (a different
|
||||
file location is configured in elasticsearch.yml) the appropriate file
|
||||
will be resolved from the settings.
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-h,--help Shows this message
|
||||
|
||||
-p,--password <password> The new password for the user
|
|
@ -1,21 +0,0 @@
|
|||
USAGE:
|
||||
|
||||
esusers useradd <username> [-p <password>] [-r <roles>]
|
||||
|
||||
DESCRIPTION:
|
||||
|
||||
Adds a native user to elasticsearch (via internal realm). The user will
|
||||
be added to the users file and its roles will be added to the
|
||||
users_roles file. If non-default files are used (different file
|
||||
locations are configured in elasticsearch.yml) the appropriate files
|
||||
will be resolved from the settings and the user and its roles will be
|
||||
added to them.
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-h,--help Shows this message
|
||||
|
||||
-p,--password <password> The user password
|
||||
|
||||
-r,--roles <roles> Comma-separated list of the roles of the
|
||||
user
|
|
@ -1,16 +0,0 @@
|
|||
USAGE:
|
||||
|
||||
esusers userdel <username>
|
||||
|
||||
DESCRIPTION:
|
||||
|
||||
Removes an existing native user from elasticsearch. The user will be
|
||||
removed from the users file and its roles will be removed to the
|
||||
users_roles file. If non-default files are used (different file
|
||||
locations are configured in elasticsearch.yml) the appropriate files
|
||||
will be resolved from the settings and the user and its roles will be
|
||||
removed to them.
|
||||
|
||||
OPTIONS:
|
||||
|
||||
-h,--help Shows this message
|
|
@ -6,13 +6,13 @@
|
|||
package org.elasticsearch.shield.authc.esusers.tool;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import org.elasticsearch.common.cli.CliTool;
|
||||
import org.elasticsearch.common.cli.CliToolTestCase;
|
||||
import org.elasticsearch.common.cli.Terminal;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.shield.authc.support.Hasher;
|
||||
import org.elasticsearch.shield.support.cli.CliToolTestCase;
|
||||
import org.elasticsearch.shield.support.cli.CliTool;
|
||||
import org.elasticsearch.shield.support.cli.Terminal;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
|
@ -365,4 +365,5 @@ public class ESUsersToolTests extends CliToolTestCase {
|
|||
CliTool.ExitStatus status = cmd.execute(settings, env);
|
||||
assertThat(status, is(CliTool.ExitStatus.NO_USER));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.shield.support.cli;
|
||||
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.test.ElasticsearchTestCase;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class CliToolTestCase extends ElasticsearchTestCase {
|
||||
|
||||
protected static String[] args(String command) {
|
||||
if (!Strings.hasLength(command)) {
|
||||
return Strings.EMPTY_ARRAY;
|
||||
}
|
||||
return command.split("\\s+");
|
||||
}
|
||||
|
||||
public static class TerminalMock extends Terminal {
|
||||
|
||||
@Override
|
||||
public void println() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void println(String msg, Object... args) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readText(String text, Object... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] readSecret(String text, Object... args) {
|
||||
return new char[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void print(String msg, Object... args) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PrintWriter writer() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,285 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.shield.support.cli;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.elasticsearch.shield.support.cli.CliToolConfig.Builder.cmd;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class CliToolTests extends CliToolTestCase {
|
||||
|
||||
@Test
|
||||
public void testOK() throws Exception {
|
||||
Terminal terminal = new TerminalMock();
|
||||
final AtomicReference<Boolean> executed = new AtomicReference<>(false);
|
||||
final NamedCommand cmd = new NamedCommand("cmd", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) {
|
||||
executed.set(true);
|
||||
return CliTool.ExitStatus.OK;
|
||||
}
|
||||
};
|
||||
SingleCmdTool tool = new SingleCmdTool("tool", terminal, cmd);
|
||||
int status = tool.execute();
|
||||
assertThat(executed.get(), is(true));
|
||||
assertThat(status, is(CliTool.ExitStatus.OK.status()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsageError() throws Exception {
|
||||
Terminal terminal = new TerminalMock();
|
||||
final AtomicReference<Boolean> executed = new AtomicReference<>(false);
|
||||
final NamedCommand cmd = new NamedCommand("cmd", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) {
|
||||
executed.set(true);
|
||||
return CliTool.ExitStatus.USAGE;
|
||||
}
|
||||
};
|
||||
SingleCmdTool tool = new SingleCmdTool("tool", terminal, cmd);
|
||||
int status = tool.execute();
|
||||
assertThat(executed.get(), is(true));
|
||||
assertThat(status, is(CliTool.ExitStatus.USAGE.status()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIOError() throws Exception {
|
||||
Terminal terminal = new TerminalMock();
|
||||
final AtomicReference<Boolean> executed = new AtomicReference<>(false);
|
||||
final NamedCommand cmd = new NamedCommand("cmd", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
executed.set(true);
|
||||
throw new IOException("io error");
|
||||
}
|
||||
};
|
||||
SingleCmdTool tool = new SingleCmdTool("tool", terminal, cmd);
|
||||
int status = tool.execute();
|
||||
assertThat(executed.get(), is(true));
|
||||
assertThat(status, is(CliTool.ExitStatus.IO_ERROR.status()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCodeError() throws Exception {
|
||||
Terminal terminal = new TerminalMock();
|
||||
final AtomicReference<Boolean> executed = new AtomicReference<>(false);
|
||||
final NamedCommand cmd = new NamedCommand("cmd", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
executed.set(true);
|
||||
throw new Exception("random error");
|
||||
}
|
||||
};
|
||||
SingleCmdTool tool = new SingleCmdTool("tool", terminal, cmd);
|
||||
int status = tool.execute();
|
||||
assertThat(executed.get(), is(true));
|
||||
assertThat(status, is(CliTool.ExitStatus.CODE_ERROR.status()));
|
||||
}
|
||||
|
||||
public void testMultiCommand() {
|
||||
Terminal terminal = new TerminalMock();
|
||||
int count = randomIntBetween(2, 7);
|
||||
final AtomicReference<Boolean>[] executed = new AtomicReference[count];
|
||||
for (int i = 0; i < executed.length; i++) {
|
||||
executed[i] = new AtomicReference<>(false);
|
||||
}
|
||||
NamedCommand[] cmds = new NamedCommand[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
final int index = i;
|
||||
cmds[i] = new NamedCommand("cmd" + index, terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
executed[index].set(true);
|
||||
return CliTool.ExitStatus.OK;
|
||||
}
|
||||
};
|
||||
}
|
||||
MultiCmdTool tool = new MultiCmdTool("tool", terminal, cmds);
|
||||
int cmdIndex = randomIntBetween(0, count-1);
|
||||
int status = tool.execute("cmd" + cmdIndex);
|
||||
assertThat(status, is(CliTool.ExitStatus.OK.status()));
|
||||
for (int i = 0; i < executed.length; i++) {
|
||||
assertThat(executed[i].get(), is(i == cmdIndex));
|
||||
}
|
||||
}
|
||||
|
||||
public void testMultiCommand_UnknownCommand() {
|
||||
Terminal terminal = new TerminalMock();
|
||||
int count = randomIntBetween(2, 7);
|
||||
final AtomicReference<Boolean>[] executed = new AtomicReference[count];
|
||||
for (int i = 0; i < executed.length; i++) {
|
||||
executed[i] = new AtomicReference<>(false);
|
||||
}
|
||||
NamedCommand[] cmds = new NamedCommand[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
final int index = i;
|
||||
cmds[i] = new NamedCommand("cmd" + index, terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
executed[index].set(true);
|
||||
return CliTool.ExitStatus.OK;
|
||||
}
|
||||
};
|
||||
}
|
||||
MultiCmdTool tool = new MultiCmdTool("tool", terminal, cmds);
|
||||
int status = tool.execute("cmd" + count); // "cmd" + count doesn't exist
|
||||
assertThat(status, is(CliTool.ExitStatus.USAGE.status()));
|
||||
for (int i = 0; i < executed.length; i++) {
|
||||
assertThat(executed[i].get(), is(false));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleCommand_ToolHelp() throws Exception {
|
||||
final AtomicReference<Boolean> helpWritten = new AtomicReference<>(false);
|
||||
Terminal terminal = new TerminalMock() {
|
||||
@Override
|
||||
public void println(String msg, Object... args) {
|
||||
assertThat(msg, equalTo("cmd1 help"));
|
||||
helpWritten.set(true);
|
||||
}
|
||||
};
|
||||
final AtomicReference<Boolean> executed = new AtomicReference<>(false);
|
||||
final NamedCommand cmd = new NamedCommand("cmd1", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
executed.set(true);
|
||||
throw new IOException("io error");
|
||||
}
|
||||
};
|
||||
SingleCmdTool tool = new SingleCmdTool("tool", terminal, cmd);
|
||||
int status = tool.execute(args("-h"));
|
||||
assertThat(status, is(CliTool.ExitStatus.OK.status()));
|
||||
assertThat(helpWritten.get(), is(true));
|
||||
}
|
||||
|
||||
public void testMultiCommand_ToolHelp() {
|
||||
final AtomicReference<Boolean> helpWritten = new AtomicReference<>(false);
|
||||
Terminal terminal = new TerminalMock() {
|
||||
@Override
|
||||
public void println(String msg, Object... args) {
|
||||
assertThat(msg, equalTo("tool help"));
|
||||
helpWritten.set(true);
|
||||
}
|
||||
};
|
||||
NamedCommand[] cmds = new NamedCommand[2];
|
||||
cmds[0] = new NamedCommand("cmd0", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
return CliTool.ExitStatus.OK;
|
||||
}
|
||||
};
|
||||
cmds[1] = new NamedCommand("cmd1", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
return CliTool.ExitStatus.OK;
|
||||
}
|
||||
};
|
||||
MultiCmdTool tool = new MultiCmdTool("tool", terminal, cmds);
|
||||
int status = tool.execute(args("-h"));
|
||||
assertThat(status, is(CliTool.ExitStatus.OK.status()));
|
||||
assertThat(helpWritten.get(), is(true));
|
||||
}
|
||||
|
||||
public void testMultiCommand_CmdHelp() {
|
||||
final AtomicReference<Boolean> helpWritten = new AtomicReference<>(false);
|
||||
Terminal terminal = new TerminalMock() {
|
||||
@Override
|
||||
public void println(String msg, Object... args) {
|
||||
assertThat(msg, equalTo("cmd1 help"));
|
||||
helpWritten.set(true);
|
||||
}
|
||||
};
|
||||
NamedCommand[] cmds = new NamedCommand[2];
|
||||
cmds[0] = new NamedCommand("cmd0", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
return CliTool.ExitStatus.OK;
|
||||
}
|
||||
};
|
||||
cmds[1] = new NamedCommand("cmd1", terminal) {
|
||||
@Override
|
||||
public CliTool.ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
return CliTool.ExitStatus.OK;
|
||||
}
|
||||
};
|
||||
MultiCmdTool tool = new MultiCmdTool("tool", terminal, cmds);
|
||||
int status = tool.execute(args("cmd1 -h"));
|
||||
assertThat(status, is(CliTool.ExitStatus.OK.status()));
|
||||
assertThat(helpWritten.get(), is(true));
|
||||
}
|
||||
|
||||
private static class SingleCmdTool extends CliTool {
|
||||
|
||||
private final Command command;
|
||||
|
||||
private SingleCmdTool(String name, Terminal terminal, NamedCommand command) {
|
||||
super(CliToolConfig.config(name, SingleCmdTool.class)
|
||||
.cmds(cmd(command.name, command.getClass()))
|
||||
.build(), terminal);
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command parse(String cmdName, CommandLine cli) throws Exception {
|
||||
return command;
|
||||
}
|
||||
}
|
||||
|
||||
private static class MultiCmdTool extends CliTool {
|
||||
|
||||
private final Map<String, Command> commands;
|
||||
|
||||
private MultiCmdTool(String name, Terminal terminal, NamedCommand... commands) {
|
||||
super(CliToolConfig.config(name, MultiCmdTool.class)
|
||||
.cmds(cmds(commands))
|
||||
.build(), terminal);
|
||||
ImmutableMap.Builder<String, Command> commandByName = ImmutableMap.builder();
|
||||
for (int i = 0; i < commands.length; i++) {
|
||||
commandByName.put(commands[i].name, commands[i]);
|
||||
}
|
||||
this.commands = commandByName.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command parse(String cmdName, CommandLine cli) throws Exception {
|
||||
return commands.get(cmdName);
|
||||
}
|
||||
|
||||
private static CliToolConfig.Cmd[] cmds(NamedCommand... commands) {
|
||||
CliToolConfig.Cmd[] cmds = new CliToolConfig.Cmd[commands.length];
|
||||
for (int i = 0; i < commands.length; i++) {
|
||||
cmds[i] = cmd(commands[i].name, commands[i].getClass()).build();
|
||||
}
|
||||
return cmds;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class NamedCommand extends CliTool.Command {
|
||||
|
||||
private final String name;
|
||||
|
||||
private NamedCommand(String name, Terminal terminal) {
|
||||
super(terminal);
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
cmd1 help
|
|
@ -1 +0,0 @@
|
|||
tool help
|
Loading…
Reference in New Issue