fix: replaces aesh with picocli (#28276)
* fix: replaces aesh with picocli closes: #28275 Signed-off-by: Steve Hawkins <shawkins@redhat.com> * fix: replaces aesh with picocli closes: #28275 Signed-off-by: Steve Hawkins <shawkins@redhat.com> --------- Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
b428e7dc81
commit
58398d1f69
31 changed files with 933 additions and 1591 deletions
|
@ -69,9 +69,9 @@ Options `cache`, `cache-stack`, and `cache-config-file` are no longer build opti
|
|||
This eliminates the need to execute the build phase and rebuild your image due to them.
|
||||
Be aware that they will not be recognized during the `build` phase, so you need to remove them.
|
||||
|
||||
= kcadm Changes
|
||||
= kcadm and kcreg changes
|
||||
|
||||
How kcadm parses and handles options and parameters has changed. Error messages from usage errors, the wrong option or parameter, may be slightly different than previous versions. Also usage errors will have an exit code of 2 instead of 1.
|
||||
How kcadm and kcreg parse and handle options and parameters has changed. Error messages from usage errors, the wrong option or parameter, may be slightly different than previous versions. Also usage errors will have an exit code of 2 instead of 1.
|
||||
|
||||
= Removing custom user attribute indexes
|
||||
|
||||
|
|
|
@ -31,8 +31,12 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.aesh</groupId>
|
||||
<artifactId>aesh</artifactId>
|
||||
<groupId>info.picocli</groupId>
|
||||
<artifactId>picocli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-admin-cli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package org.keycloak.client.registration.cli;
|
||||
|
||||
import org.keycloak.client.registration.cli.common.EndpointType;
|
||||
|
||||
import picocli.CommandLine.ITypeConverter;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class EndpointTypeConverter implements ITypeConverter<EndpointType> {
|
||||
|
||||
@Override
|
||||
public EndpointType convert(String value) throws Exception {
|
||||
return EndpointType.of(value);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package org.keycloak.client.registration.cli;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class Globals {
|
||||
|
||||
public static boolean dumpTrace = false;
|
||||
|
||||
public static boolean help = false;
|
||||
|
||||
}
|
|
@ -1,21 +1,16 @@
|
|||
package org.keycloak.client.registration.cli;
|
||||
|
||||
import org.jboss.aesh.console.AeshConsoleBuilder;
|
||||
import org.jboss.aesh.console.AeshConsoleImpl;
|
||||
import org.jboss.aesh.console.Prompt;
|
||||
import org.jboss.aesh.console.command.registry.AeshCommandRegistryBuilder;
|
||||
import org.jboss.aesh.console.command.registry.CommandRegistry;
|
||||
import org.jboss.aesh.console.settings.Settings;
|
||||
import org.jboss.aesh.console.settings.SettingsBuilder;
|
||||
import org.keycloak.client.registration.cli.aesh.AeshEnhancer;
|
||||
import org.keycloak.client.registration.cli.aesh.ValveInputStream;
|
||||
import org.keycloak.client.registration.cli.aesh.Globals;
|
||||
import org.keycloak.client.admin.cli.ExecutionExceptionHandler;
|
||||
import org.keycloak.client.admin.cli.ShortErrorMessageHandler;
|
||||
import org.keycloak.client.registration.cli.commands.KcRegCmd;
|
||||
import org.keycloak.client.registration.cli.util.ClassLoaderUtil;
|
||||
import org.keycloak.client.registration.cli.util.OsUtil;
|
||||
import org.keycloak.common.crypto.CryptoIntegration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Model.CommandSpec;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
|
@ -32,54 +27,20 @@ public class KcRegMain {
|
|||
|
||||
CryptoIntegration.init(cl);
|
||||
|
||||
Globals.stdin = new ValveInputStream();
|
||||
|
||||
Settings settings = new SettingsBuilder()
|
||||
.logging(false)
|
||||
.readInputrc(false)
|
||||
.disableCompletion(true)
|
||||
.disableHistory(true)
|
||||
.enableAlias(false)
|
||||
.enableExport(false)
|
||||
.inputStream(Globals.stdin)
|
||||
.create();
|
||||
|
||||
CommandRegistry registry = new AeshCommandRegistryBuilder()
|
||||
.command(KcRegCmd.class)
|
||||
.create();
|
||||
|
||||
AeshConsoleImpl console = (AeshConsoleImpl) new AeshConsoleBuilder()
|
||||
.settings(settings)
|
||||
.commandRegistry(registry)
|
||||
.prompt(new Prompt(""))
|
||||
.create();
|
||||
|
||||
AeshEnhancer.enhance(console);
|
||||
|
||||
// work around parser issues with quotes and brackets
|
||||
ArrayList<String> arguments = new ArrayList<>();
|
||||
arguments.add("kcreg");
|
||||
arguments.addAll(Arrays.asList(args));
|
||||
Globals.args = arguments;
|
||||
|
||||
StringBuilder b = new StringBuilder();
|
||||
for (String s : args) {
|
||||
// quote if necessary
|
||||
boolean needQuote = false;
|
||||
needQuote = s.indexOf(' ') != -1 || s.indexOf('\"') != -1 || s.indexOf('\'') != -1;
|
||||
b.append(' ');
|
||||
if (needQuote) {
|
||||
b.append('\'');
|
||||
CommandLine cli = createCommandLine();
|
||||
int exitCode = cli.execute(args);
|
||||
System.exit(exitCode);
|
||||
}
|
||||
b.append(s);
|
||||
if (needQuote) {
|
||||
b.append('\'');
|
||||
}
|
||||
}
|
||||
console.setEcho(false);
|
||||
|
||||
console.execute("kcreg" + b.toString());
|
||||
public static CommandLine createCommandLine() {
|
||||
CommandSpec spec = CommandSpec.forAnnotatedObject(new KcRegCmd()).name(OsUtil.CMD);
|
||||
|
||||
console.start();
|
||||
CommandLine cmd = new CommandLine(spec);
|
||||
|
||||
cmd.setExecutionExceptionHandler(new ExecutionExceptionHandler());
|
||||
cmd.setParameterExceptionHandler(new ShortErrorMessageHandler());
|
||||
cmd.setErr(new PrintWriter(System.err, true));
|
||||
|
||||
return cmd;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
package org.keycloak.client.registration.cli.aesh;
|
||||
|
||||
import org.jboss.aesh.cl.parser.OptionParserException;
|
||||
import org.jboss.aesh.cl.result.ResultHandler;
|
||||
import org.jboss.aesh.console.AeshConsoleCallback;
|
||||
import org.jboss.aesh.console.AeshConsoleImpl;
|
||||
import org.jboss.aesh.console.ConsoleOperation;
|
||||
import org.jboss.aesh.console.command.CommandNotFoundException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.container.CommandContainer;
|
||||
import org.jboss.aesh.console.command.container.CommandContainerResult;
|
||||
import org.jboss.aesh.console.command.invocation.AeshCommandInvocation;
|
||||
import org.jboss.aesh.console.command.invocation.AeshCommandInvocationProvider;
|
||||
import org.jboss.aesh.parser.AeshLine;
|
||||
import org.jboss.aesh.parser.ParserStatus;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
class AeshConsoleCallbackImpl extends AeshConsoleCallback {
|
||||
|
||||
private final AeshConsoleImpl console;
|
||||
private CommandResult result;
|
||||
|
||||
AeshConsoleCallbackImpl(AeshConsoleImpl aeshConsole) {
|
||||
this.console = aeshConsole;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public int execute(ConsoleOperation output) throws InterruptedException {
|
||||
if (output != null && output.getBuffer().trim().length() > 0) {
|
||||
ResultHandler resultHandler = null;
|
||||
//AeshLine aeshLine = Parser.findAllWords(output.getBuffer());
|
||||
AeshLine aeshLine = new AeshLine(output.getBuffer(), Globals.args, ParserStatus.OK, "");
|
||||
try (CommandContainer commandContainer = getCommand(output, aeshLine)) {
|
||||
resultHandler = commandContainer.getParser().getProcessedCommand().getResultHandler();
|
||||
CommandContainerResult ccResult =
|
||||
commandContainer.executeCommand(aeshLine, console.getInvocationProviders(), console.getAeshContext(),
|
||||
new AeshCommandInvocationProvider().enhanceCommandInvocation(
|
||||
new AeshCommandInvocation(console,
|
||||
output.getControlOperator(), output.getPid(), this)));
|
||||
|
||||
result = ccResult.getCommandResult();
|
||||
|
||||
if(result == CommandResult.SUCCESS && resultHandler != null)
|
||||
resultHandler.onSuccess();
|
||||
else if(resultHandler != null)
|
||||
resultHandler.onFailure(result);
|
||||
|
||||
if (result == CommandResult.FAILURE) {
|
||||
// we assume the command has already output any error messages
|
||||
System.exit(1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
console.stop();
|
||||
|
||||
if (e instanceof OptionParserException) {
|
||||
System.err.println("Unknown command: " + aeshLine.getWords().get(0));
|
||||
} else {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
if (Globals.dumpTrace) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
// empty line
|
||||
else if (output != null) {
|
||||
result = CommandResult.FAILURE;
|
||||
}
|
||||
else {
|
||||
//stop();
|
||||
result = CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
if (result == CommandResult.SUCCESS) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private CommandContainer getCommand(ConsoleOperation output, AeshLine aeshLine) throws CommandNotFoundException {
|
||||
Method m;
|
||||
try {
|
||||
m = console.getClass().getDeclaredMethod("getCommand", AeshLine.class, String.class);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException("Unexpected error: ", e);
|
||||
}
|
||||
|
||||
m.setAccessible(true);
|
||||
|
||||
try {
|
||||
return (CommandContainer) m.invoke(console, aeshLine, output.getBuffer());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unexpected error: ", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package org.keycloak.client.registration.cli.aesh;
|
||||
|
||||
import org.jboss.aesh.console.AeshConsoleImpl;
|
||||
import org.jboss.aesh.console.Console;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class AeshEnhancer {
|
||||
|
||||
public static void enhance(AeshConsoleImpl console) {
|
||||
try {
|
||||
Globals.stdin.setConsole(console);
|
||||
|
||||
Field field = AeshConsoleImpl.class.getDeclaredField("console");
|
||||
field.setAccessible(true);
|
||||
Console internalConsole = (Console) field.get(console);
|
||||
internalConsole.setConsoleCallback(new AeshConsoleCallbackImpl(console));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to install Aesh enhancement", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package org.keycloak.client.registration.cli.aesh;
|
||||
|
||||
import org.jboss.aesh.cl.converter.Converter;
|
||||
import org.jboss.aesh.cl.validator.OptionValidatorException;
|
||||
import org.jboss.aesh.console.command.converter.ConverterInvocation;
|
||||
import org.keycloak.client.registration.cli.common.EndpointType;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class EndpointTypeConverter implements Converter<EndpointType, ConverterInvocation> {
|
||||
|
||||
@Override
|
||||
public EndpointType convert(ConverterInvocation converterInvocation) throws OptionValidatorException {
|
||||
return EndpointType.of(converterInvocation.getInput());
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package org.keycloak.client.registration.cli.aesh;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public class Globals {
|
||||
|
||||
public static boolean dumpTrace = false;
|
||||
|
||||
public static ValveInputStream stdin;
|
||||
|
||||
public static List<String> args;
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
package org.keycloak.client.registration.cli.aesh;
|
||||
|
||||
import org.jboss.aesh.console.AeshConsoleImpl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InterruptedIOException;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* This stream blocks and waits, until there is some stream in the queue.
|
||||
* It reads all streams from the queue, and then blocks until it receives more.
|
||||
*/
|
||||
public class ValveInputStream extends InputStream {
|
||||
|
||||
private BlockingQueue<InputStream> queue = new LinkedBlockingQueue<>(10);
|
||||
|
||||
private InputStream current;
|
||||
|
||||
private AeshConsoleImpl console;
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
if (current == null) {
|
||||
try {
|
||||
current = queue.take();
|
||||
} catch (InterruptedException e) {
|
||||
throw new InterruptedIOException("Signalled to exit");
|
||||
}
|
||||
}
|
||||
int c = current.read();
|
||||
if (c == -1) {
|
||||
//current = null;
|
||||
if (console != null) {
|
||||
console.stop();
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* For some reason AeshInputStream wants to do blocking read of whole buffers, which for stdin
|
||||
* results in blocked input.
|
||||
*/
|
||||
@Override
|
||||
public int read(byte b[], int off, int len) throws IOException {
|
||||
int c = read();
|
||||
if (c == -1) {
|
||||
return c;
|
||||
}
|
||||
b[off] = (byte) c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
public void setInputStream(InputStream is) {
|
||||
if (queue.contains(is)) {
|
||||
return;
|
||||
}
|
||||
queue.add(is);
|
||||
}
|
||||
|
||||
public void setConsole(AeshConsoleImpl console) {
|
||||
this.console = console;
|
||||
}
|
||||
|
||||
public boolean isStdinAvailable() {
|
||||
return console.isRunning();
|
||||
}
|
||||
}
|
|
@ -1,7 +1,5 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.Option;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.client.registration.cli.config.ConfigData;
|
||||
import org.keycloak.client.registration.cli.config.ConfigHandler;
|
||||
|
@ -14,6 +12,8 @@ import org.keycloak.client.registration.cli.util.IoUtil;
|
|||
|
||||
import java.io.File;
|
||||
|
||||
import picocli.CommandLine.Option;
|
||||
|
||||
import static org.keycloak.client.registration.cli.config.FileConfigHandler.setConfigFile;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.checkAuthInfo;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.checkServerInfo;
|
||||
|
@ -26,58 +26,55 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
|
|||
|
||||
static final String DEFAULT_CLIENT = "admin-cli";
|
||||
|
||||
@Option(name = "config", description = "Path to the config file (~/.keycloak/kcreg.config by default)", hasValue = true)
|
||||
@Option(names = "--config", description = "Path to the config file (~/.keycloak/kcreg.config by default)")
|
||||
protected String config;
|
||||
|
||||
@Option(name = "no-config", description = "No configuration file should be used, no authentication info is loaded or saved", hasValue = false)
|
||||
@Option(names = "--no-config", description = "No configuration file should be used, no authentication info is loaded or saved")
|
||||
protected boolean noconfig;
|
||||
|
||||
@Option(name = "server", description = "Server endpoint url (e.g. 'http://localhost:8080')", hasValue = true)
|
||||
@Option(names = "--server", description = "Server endpoint url (e.g. 'http://localhost:8080')")
|
||||
protected String server;
|
||||
|
||||
@Option(name = "realm", description = "Realm name to authenticate against", hasValue = true)
|
||||
@Option(names = "--realm", description = "Realm name to authenticate against")
|
||||
protected String realm;
|
||||
|
||||
@Option(name = "client", description = "Realm name to authenticate against", hasValue = true)
|
||||
@Option(names = "--client", description = "Realm name to authenticate against")
|
||||
protected String clientId;
|
||||
|
||||
@Option(name = "user", description = "Username to login with", hasValue = true)
|
||||
@Option(names = "--user", description = "Username to login with")
|
||||
protected String user;
|
||||
|
||||
@Option(name = "password", description = "Password to login with (prompted for if not specified and --user is used)", hasValue = true)
|
||||
@Option(names = "--password", description = "Password to login with (prompted for if not specified and --user is used)")
|
||||
protected String password;
|
||||
|
||||
@Option(name = "secret", description = "Secret to authenticate the client (prompted for if no --user or --keystore is specified)", hasValue = true)
|
||||
@Option(names = "--secret", description = "Secret to authenticate the client (prompted for if no --user or --keystore is specified)")
|
||||
protected String secret;
|
||||
|
||||
@Option(name = "keystore", description = "Path to a keystore containing private key", hasValue = true)
|
||||
@Option(names = "--keystore", description = "Path to a keystore containing private key")
|
||||
protected String keystore;
|
||||
|
||||
@Option(name = "storepass", description = "Keystore password (prompted for if not specified and --keystore is used)", hasValue = true)
|
||||
@Option(names = "--storepass", description = "Keystore password (prompted for if not specified and --keystore is used)")
|
||||
protected String storePass;
|
||||
|
||||
@Option(name = "keypass", description = "Key password (prompted for if not specified and --keystore is used without --storepass, \n otherwise defaults to keystore password)", hasValue = true)
|
||||
@Option(names = "--keypass", description = "Key password (prompted for if not specified and --keystore is used without --storepass, \n otherwise defaults to keystore password)")
|
||||
protected String keyPass;
|
||||
|
||||
@Option(name = "alias", description = "Alias of the key inside a keystore (defaults to the value of ClientId)", hasValue = true)
|
||||
@Option(names = "--alias", description = "Alias of the key inside a keystore (defaults to the value of ClientId)")
|
||||
protected String alias;
|
||||
|
||||
@Option(name = "truststore", description = "Path to a truststore", hasValue = true)
|
||||
@Option(names = "--truststore", description = "Path to a truststore")
|
||||
protected String trustStore;
|
||||
|
||||
@Option(name = "trustpass", description = "Truststore password (prompted for if not specified and --truststore is used)", hasValue = true)
|
||||
@Option(names = "--trustpass", description = "Truststore password (prompted for if not specified and --truststore is used)")
|
||||
protected String trustPass;
|
||||
|
||||
@Option(name = "insecure", description = "Turns off TLS validation", hasValue = false)
|
||||
@Option(names = "--insecure", description = "Turns off TLS validation")
|
||||
protected boolean insecure;
|
||||
|
||||
@Option(shortName = 't', name = "token", description = "Initial / Registration access token to use)", hasValue = true)
|
||||
@Option(names = {"-t", "--token"}, description = "Initial / Registration access token to use)")
|
||||
protected String token;
|
||||
|
||||
protected void initFromParent(AbstractAuthOptionsCmd parent) {
|
||||
|
||||
super.initFromParent(parent);
|
||||
|
||||
noconfig = parent.noconfig;
|
||||
config = parent.config;
|
||||
server = parent.server;
|
||||
|
@ -110,12 +107,11 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
|
|||
token == null && config == null;
|
||||
}
|
||||
|
||||
protected void processGlobalOptions() {
|
||||
|
||||
super.processGlobalOptions();
|
||||
@Override
|
||||
protected void processOptions() {
|
||||
|
||||
if (config != null && noconfig) {
|
||||
throw new RuntimeException("Options --config and --no-config are mutually exclusive");
|
||||
throw new IllegalArgumentException("Options --config and --no-config are mutually exclusive");
|
||||
}
|
||||
|
||||
if (!noconfig) {
|
||||
|
@ -130,7 +126,7 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
|
|||
}
|
||||
}
|
||||
|
||||
protected void setupTruststore(ConfigData configData, CommandInvocation invocation ) {
|
||||
protected void setupTruststore(ConfigData configData) {
|
||||
|
||||
if (!configData.getServerUrl().startsWith("https:")) {
|
||||
return;
|
||||
|
@ -147,7 +143,7 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
|
|||
pass = configData.getTrustpass();
|
||||
}
|
||||
if (pass == null) {
|
||||
pass = IoUtil.readSecret("Enter truststore password: ", invocation);
|
||||
pass = IoUtil.readSecret("Enter truststore password: ");
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -162,7 +158,7 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
|
|||
}
|
||||
}
|
||||
|
||||
protected ConfigData ensureAuthInfo(ConfigData config, CommandInvocation commandInvocation) {
|
||||
protected ConfigData ensureAuthInfo(ConfigData config) {
|
||||
|
||||
if (requiresLogin()) {
|
||||
// make sure current handler is in-memory handler
|
||||
|
@ -178,7 +174,7 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
|
|||
ConfigCredentialsCmd login = new ConfigCredentialsCmd();
|
||||
login.initFromParent(this);
|
||||
login.init(config);
|
||||
login.process(commandInvocation);
|
||||
login.process();
|
||||
|
||||
// this must be executed before finally block which restores config handler
|
||||
return loadConfig();
|
||||
|
@ -237,6 +233,7 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
|
|||
rdata.setGrantTypeForAuthentication(grantTypeForAuthentication);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkUnsupportedOptions(String ... options) {
|
||||
if (options.length % 2 != 0) {
|
||||
throw new IllegalArgumentException("Even number of argument required");
|
||||
|
|
|
@ -1,38 +1,37 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.Option;
|
||||
import org.jboss.aesh.console.command.Command;
|
||||
import org.keycloak.client.registration.cli.aesh.Globals;
|
||||
import org.keycloak.client.registration.cli.Globals;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Option;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
public abstract class AbstractGlobalOptionsCmd implements Command {
|
||||
public abstract class AbstractGlobalOptionsCmd implements Runnable {
|
||||
|
||||
@Option(shortName = 'x', description = "Print full stack trace when exiting with error", hasValue = false)
|
||||
protected boolean dumpTrace;
|
||||
|
||||
@Option(name = "help", description = "Print command specific help", hasValue = false)
|
||||
protected boolean help;
|
||||
|
||||
protected void initFromParent(AbstractGlobalOptionsCmd parent) {
|
||||
dumpTrace = parent.dumpTrace;
|
||||
help = parent.help;
|
||||
@Option(names = "--help",
|
||||
description = "Print command specific help")
|
||||
public void setHelp(boolean help) {
|
||||
Globals.help = help;
|
||||
}
|
||||
|
||||
protected void processGlobalOptions() {
|
||||
@Option(names = "-x",
|
||||
description = "Print full stack trace when exiting with error")
|
||||
public void setDumpTrace(boolean dumpTrace) {
|
||||
Globals.dumpTrace = dumpTrace;
|
||||
}
|
||||
|
||||
protected boolean printHelp() {
|
||||
if (help || nothingToDo()) {
|
||||
protected void printHelpIfNeeded() {
|
||||
if (Globals.help) {
|
||||
printOut(help());
|
||||
return true;
|
||||
System.exit(CommandLine.ExitCode.OK);
|
||||
} else if (nothingToDo()) {
|
||||
printOut(help());
|
||||
System.exit(CommandLine.ExitCode.USAGE);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean nothingToDo() {
|
||||
|
@ -42,4 +41,47 @@ public abstract class AbstractGlobalOptionsCmd implements Command {
|
|||
protected String help() {
|
||||
return KcRegCmd.usage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
printHelpIfNeeded();
|
||||
|
||||
checkUnsupportedOptions(getUnsupportedOptions());
|
||||
|
||||
processOptions();
|
||||
|
||||
process();
|
||||
}
|
||||
|
||||
protected String[] getUnsupportedOptions() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
protected void processOptions() {
|
||||
|
||||
}
|
||||
|
||||
protected void process() {
|
||||
|
||||
}
|
||||
|
||||
protected void checkUnsupportedOptions(String ... options) {
|
||||
if (options.length % 2 != 0) {
|
||||
throw new IllegalArgumentException("Even number of argument required");
|
||||
}
|
||||
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
String name = options[i];
|
||||
String value = options[++i];
|
||||
|
||||
if (value != null) {
|
||||
throw new IllegalArgumentException("Unsupported option: " + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static String booleanOptionForCheck(boolean value) {
|
||||
return value ? "true" : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.Arguments;
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.cl.Option;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.client.registration.cli.common.AttributeKey;
|
||||
import org.keycloak.client.registration.cli.common.EndpointType;
|
||||
import org.keycloak.client.registration.cli.util.ReflectionUtil;
|
||||
|
@ -19,9 +13,13 @@ import java.lang.reflect.Field;
|
|||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
import static org.keycloak.client.registration.cli.util.ReflectionUtil.getAttributeListWithJSonTypes;
|
||||
|
@ -32,40 +30,26 @@ import static org.keycloak.client.registration.cli.util.ReflectionUtil.isMapType
|
|||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "attrs", description = "[ATTRIBUTE] [--endpoint TYPE]")
|
||||
@Command(name = "attrs", description = "[ATTRIBUTE] [--endpoint TYPE]")
|
||||
public class AttrsCmd extends AbstractGlobalOptionsCmd {
|
||||
|
||||
@Option(shortName = 'e', name = "endpoint", description = "Endpoint type to use", hasValue = true)
|
||||
CommandLine.Model.CommandSpec spec;
|
||||
|
||||
@Option(names = {"-e", "--endpoint"}, description = "Endpoint type to use")
|
||||
protected String endpoint;
|
||||
|
||||
@Arguments
|
||||
protected List<String> args;
|
||||
|
||||
@Parameters(arity = "0..1")
|
||||
protected String attr;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
processGlobalOptions();
|
||||
|
||||
if (printHelp()) {
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
protected void process() {
|
||||
EndpointType regType = EndpointType.DEFAULT;
|
||||
PrintStream out = commandInvocation.getShell().out();
|
||||
PrintStream out = System.out;
|
||||
|
||||
if (endpoint != null) {
|
||||
regType = EndpointType.of(endpoint);
|
||||
}
|
||||
|
||||
if (args != null) {
|
||||
if (args.size() > 1) {
|
||||
throw new IllegalArgumentException("Invalid option: " + args.get(1));
|
||||
}
|
||||
attr = args.get(0);
|
||||
}
|
||||
|
||||
Class type = regType == EndpointType.DEFAULT ? ClientRepresentation.class : (regType == EndpointType.OIDC ? OIDCClientRepresentation.class : null);
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Endpoint not supported: " + regType);
|
||||
|
@ -92,7 +76,7 @@ public class AttrsCmd extends AbstractGlobalOptionsCmd {
|
|||
t = ((ParameterizedType) t).getActualTypeArguments()[0];
|
||||
if (!isBasicType(t) && t instanceof Class) {
|
||||
eol = true;
|
||||
System.out.printf(", where value is:\n", ts);
|
||||
out.printf(", where value is:\n", ts);
|
||||
LinkedHashMap<String, String> items = ReflectionUtil.getAttributeListWithJSonTypes((Class) t, null);
|
||||
for (Map.Entry<String, String> item : items.entrySet()) {
|
||||
out.printf(" %-36s %s\n", item.getKey(), item.getValue());
|
||||
|
@ -115,14 +99,9 @@ public class AttrsCmd extends AbstractGlobalOptionsCmd {
|
|||
out.println();
|
||||
}
|
||||
}
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -17,80 +17,36 @@
|
|||
|
||||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.Arguments;
|
||||
import org.jboss.aesh.cl.GroupCommandDefinition;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.Command;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
|
||||
@GroupCommandDefinition(name = "config", description = "COMMAND [ARGUMENTS]", groupCommands = {ConfigCredentialsCmd.class} )
|
||||
public class ConfigCmd extends AbstractAuthOptionsCmd implements Command {
|
||||
@Command(name = "config", description = "COMMAND [ARGUMENTS]", subcommands = {
|
||||
ConfigCredentialsCmd.class,
|
||||
ConfigInitialTokenCmd.class,
|
||||
ConfigRegistrationTokenCmd.class,
|
||||
ConfigTruststoreCmd.class
|
||||
})
|
||||
public class ConfigCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Arguments
|
||||
protected List<String> args;
|
||||
@Override
|
||||
protected void process() {
|
||||
|
||||
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
if (args != null && args.size() > 0) {
|
||||
String cmd = args.get(0);
|
||||
switch (cmd) {
|
||||
case "credentials": {
|
||||
ConfigCredentialsCmd command = new ConfigCredentialsCmd();
|
||||
command.initFromParent(this);
|
||||
return command.execute(commandInvocation);
|
||||
}
|
||||
case "truststore": {
|
||||
ConfigTruststoreCmd command = new ConfigTruststoreCmd();
|
||||
command.initFromParent(this);
|
||||
return command.execute(commandInvocation);
|
||||
}
|
||||
case "initial-token": {
|
||||
ConfigInitialTokenCmd command = new ConfigInitialTokenCmd();
|
||||
command.initFromParent(this);
|
||||
return command.execute(commandInvocation);
|
||||
}
|
||||
case "registration-token": {
|
||||
ConfigRegistrationTokenCmd command = new ConfigRegistrationTokenCmd();
|
||||
command.initFromParent(this);
|
||||
return command.execute(commandInvocation);
|
||||
}
|
||||
default: {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown sub-command: " + cmd + suggestHelp());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Sub-command required by '" + CMD + " config' - one of: 'credentials', 'truststore', 'initial-token', 'registration-token'");
|
||||
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help config' for more information";
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.console.command.Command;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.client.registration.cli.config.ConfigData;
|
||||
import org.keycloak.client.registration.cli.config.RealmConfigData;
|
||||
|
@ -16,6 +11,8 @@ import java.io.PrintWriter;
|
|||
import java.io.StringWriter;
|
||||
import java.net.URL;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.AuthUtil.getAuthTokens;
|
||||
import static org.keycloak.client.registration.cli.util.AuthUtil.getAuthTokensByJWT;
|
||||
import static org.keycloak.client.registration.cli.util.AuthUtil.getAuthTokensBySecret;
|
||||
|
@ -26,15 +23,14 @@ import static org.keycloak.client.registration.cli.util.ConfigUtil.saveTokens;
|
|||
import static org.keycloak.client.registration.cli.util.IoUtil.printErr;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.readSecret;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "credentials", description = "--server SERVER_URL --realm REALM [ARGUMENTS]")
|
||||
public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Command {
|
||||
@Command(name = "credentials", description = "--server SERVER_URL --realm REALM [ARGUMENTS]")
|
||||
public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
private int sigLifetime = 600;
|
||||
|
||||
|
@ -60,24 +56,9 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
checkUnsupportedOptions("--no-config", booleanOptionForCheck(noconfig));
|
||||
|
||||
processGlobalOptions();
|
||||
|
||||
return process(commandInvocation);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
protected String[] getUnsupportedOptions() {
|
||||
return new String[] {"--no-config", booleanOptionForCheck(noconfig)};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -85,8 +66,8 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
|
|||
return noOptions();
|
||||
}
|
||||
|
||||
public CommandResult process(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
|
||||
@Override
|
||||
protected void process() {
|
||||
// check server
|
||||
if (server == null) {
|
||||
throw new IllegalArgumentException("Required option not specified: --server");
|
||||
|
@ -113,18 +94,18 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
|
|||
|
||||
// if user was set there needs to be a password so we can authenticate
|
||||
if (password == null) {
|
||||
password = readSecret("Enter password: ", commandInvocation);
|
||||
password = readSecret("Enter password: ");
|
||||
}
|
||||
// if secret was set to be read from stdin, then ask for it
|
||||
if ("-".equals(secret) && keystore == null) {
|
||||
secret = readSecret("Enter client secret: ", commandInvocation);
|
||||
secret = readSecret("Enter client secret: ");
|
||||
}
|
||||
} else if (keystore != null || secret != null || clientSet) {
|
||||
grantTypeForAuthentication = OAuth2Constants.CLIENT_CREDENTIALS;
|
||||
printErr("Logging into " + server + " as " + "service-account-" + clientId + " of realm " + realm);
|
||||
if (keystore == null) {
|
||||
if (secret == null) {
|
||||
secret = readSecret("Enter client secret: ", commandInvocation);
|
||||
secret = readSecret("Enter client secret: ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -139,8 +120,8 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
|
|||
}
|
||||
|
||||
if (storePass == null) {
|
||||
storePass = readSecret("Enter keystore password: ", commandInvocation);
|
||||
keyPass = readSecret("Enter key password: ", commandInvocation);
|
||||
storePass = readSecret("Enter keystore password: ");
|
||||
keyPass = readSecret("Enter key password: ");
|
||||
}
|
||||
|
||||
if (keyPass == null) {
|
||||
|
@ -163,10 +144,10 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
|
|||
config.setServerUrl(server);
|
||||
config.setRealm(realm);
|
||||
});
|
||||
return CommandResult.SUCCESS;
|
||||
return;
|
||||
}
|
||||
|
||||
setupTruststore(copyWithServerInfo(loadConfig()), commandInvocation);
|
||||
setupTruststore(copyWithServerInfo(loadConfig()));
|
||||
|
||||
// now use the token endpoint to retrieve access token, and refresh token
|
||||
AccessTokenResponse tokens = signedRequestToken != null ?
|
||||
|
@ -179,14 +160,9 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd implements Comm
|
|||
|
||||
// save tokens to config file
|
||||
saveTokens(tokens, server, realm, clientId, signedRequestToken, sigExpiresAt, secret, grantTypeForAuthentication);
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help config credentials' for more information";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -1,107 +1,45 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.console.command.Command;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.client.registration.cli.config.RealmConfigData;
|
||||
import org.keycloak.client.registration.cli.util.IoUtil;
|
||||
import org.keycloak.client.registration.cli.util.ParseUtil;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.saveMergeConfig;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.warnfOut;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "initial-token", description = "[--server SERVER] --realm REALM [--delete | TOKEN] [ARGUMENTS]")
|
||||
public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd implements Command {
|
||||
|
||||
private ConfigCmd parent;
|
||||
@Command(name = "initial-token", description = "[--server SERVER] --realm REALM [--delete | TOKEN] [ARGUMENTS]")
|
||||
public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Option(names = {"-d", "--delete"}, description = "Indicates that initial access token should be removed")
|
||||
private boolean delete;
|
||||
@Option(names = {"-k", "--keep-domain"}, description = "Don't overwrite default server and realm")
|
||||
private boolean keepDomain;
|
||||
|
||||
|
||||
protected void initFromParent(ConfigCmd parent) {
|
||||
this.parent = parent;
|
||||
super.initFromParent(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
return process(commandInvocation);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
@Parameters(arity = "0..1")
|
||||
private String token;
|
||||
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return noOptions() && parent.args.size() == 1;
|
||||
return noOptions() && token == null && !delete && !keepDomain;
|
||||
}
|
||||
|
||||
public CommandResult process(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
|
||||
List<String> args = new ArrayList<>();
|
||||
|
||||
Iterator<String> it = parent.args.iterator();
|
||||
// skip the first argument 'initial-token'
|
||||
it.next();
|
||||
|
||||
while (it.hasNext()) {
|
||||
String arg = it.next();
|
||||
switch (arg) {
|
||||
case "-d":
|
||||
case "--delete": {
|
||||
delete = true;
|
||||
break;
|
||||
}
|
||||
case "-k":
|
||||
case "--keep-domain": {
|
||||
keepDomain = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
args.add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.size() > 1) {
|
||||
throw new IllegalArgumentException("Invalid option: " + args.get(1));
|
||||
}
|
||||
|
||||
String token = args.size() == 1 ? args.get(0) : null;
|
||||
|
||||
if (realm == null) {
|
||||
throw new IllegalArgumentException("Realm not specified");
|
||||
}
|
||||
|
||||
if (token != null && token.startsWith("-")) {
|
||||
warnfOut(ParseUtil.TOKEN_OPTION_WARN, token);
|
||||
}
|
||||
|
||||
checkUnsupportedOptions(
|
||||
@Override
|
||||
protected String[] getUnsupportedOptions() {
|
||||
return new String[] {
|
||||
"--client", clientId,
|
||||
"--user", user,
|
||||
"--password", password,
|
||||
|
@ -112,15 +50,24 @@ public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd implements Com
|
|||
"--alias", alias,
|
||||
"--truststore", trustStore,
|
||||
"--trustpass", keyPass,
|
||||
"--no-config", booleanOptionForCheck(noconfig));
|
||||
"--no-config", booleanOptionForCheck(noconfig)};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process() {
|
||||
if (realm == null) {
|
||||
throw new IllegalArgumentException("Realm not specified");
|
||||
}
|
||||
|
||||
if (token != null && token.startsWith("-")) {
|
||||
warnfOut(ParseUtil.TOKEN_OPTION_WARN, token);
|
||||
}
|
||||
|
||||
if (!delete && token == null) {
|
||||
token = IoUtil.readSecret("Enter Initial Access Token: ", commandInvocation);
|
||||
token = IoUtil.readSecret("Enter Initial Access Token: ");
|
||||
}
|
||||
|
||||
// now update the config
|
||||
processGlobalOptions();
|
||||
|
||||
String initialToken = token;
|
||||
saveMergeConfig(config -> {
|
||||
|
@ -138,14 +85,9 @@ public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd implements Com
|
|||
rdata.setInitialToken(initialToken);
|
||||
}
|
||||
});
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help config initial-token' for more information";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -1,91 +1,40 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.console.command.Command;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.client.registration.cli.config.RealmConfigData;
|
||||
import org.keycloak.client.registration.cli.util.IoUtil;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.saveMergeConfig;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "registration-token", description = "[--server SERVER] --realm REALM --client CLIENT [--delete | TOKEN] [ARGUMENTS]")
|
||||
public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd implements Command {
|
||||
|
||||
private ConfigCmd parent;
|
||||
@Command(name = "registration-token", description = "[--server SERVER] --realm REALM --client CLIENT [--delete | TOKEN] [ARGUMENTS]")
|
||||
public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Option(names = {"-d", "--delete"}, description = "Indicates that initial access token should be removed")
|
||||
private boolean delete;
|
||||
|
||||
|
||||
protected void initFromParent(ConfigCmd parent) {
|
||||
this.parent = parent;
|
||||
super.initFromParent(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
return process(commandInvocation);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
@Parameters(arity = "0..1")
|
||||
private String token;
|
||||
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return noOptions() && parent.args.size() == 1;
|
||||
return noOptions() && token == null && !delete;
|
||||
}
|
||||
|
||||
public CommandResult process(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
|
||||
List<String> args = new ArrayList<>();
|
||||
|
||||
Iterator<String> it = parent.args.iterator();
|
||||
// skip the first argument 'registration-token'
|
||||
it.next();
|
||||
|
||||
while (it.hasNext()) {
|
||||
String arg = it.next();
|
||||
switch (arg) {
|
||||
case "-d":
|
||||
case "--delete": {
|
||||
delete = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
args.add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.size() > 1) {
|
||||
throw new IllegalArgumentException("Invalid option: " + args.get(1));
|
||||
}
|
||||
|
||||
String token = args.size() == 1 ? args.get(0) : null;
|
||||
|
||||
@Override
|
||||
protected void process() {
|
||||
if (server == null) {
|
||||
throw new IllegalArgumentException("Required option not specified: --server");
|
||||
}
|
||||
|
@ -112,11 +61,10 @@ public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd implement
|
|||
|
||||
|
||||
if (!delete && token == null) {
|
||||
token = IoUtil.readSecret("Enter Registration Access Token: ", commandInvocation);
|
||||
token = IoUtil.readSecret("Enter Registration Access Token: ");
|
||||
}
|
||||
|
||||
// now update the config
|
||||
processGlobalOptions();
|
||||
|
||||
String registrationToken = token;
|
||||
saveMergeConfig(config -> {
|
||||
|
@ -129,14 +77,9 @@ public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd implement
|
|||
config.ensureRealmConfigData(server, realm).getClients().put(clientId, registrationToken);
|
||||
}
|
||||
});
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help config registration-token' for more information";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -16,96 +16,41 @@
|
|||
*/
|
||||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.console.command.Command;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.saveMergeConfig;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.readSecret;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "truststore", description = "PATH [ARGUMENTS]")
|
||||
public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd implements Command {
|
||||
|
||||
private ConfigCmd parent;
|
||||
@Command(name = "truststore", description = "PATH [ARGUMENTS]")
|
||||
public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Option(names = {"-d", "--delete"}, description = "Indicates that initial access token should be removed")
|
||||
private boolean delete;
|
||||
|
||||
|
||||
protected void initFromParent(ConfigCmd parent) {
|
||||
this.parent = parent;
|
||||
super.initFromParent(parent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
return process(commandInvocation);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
@Parameters(arity = "0..1")
|
||||
private String truststorePath;
|
||||
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return noOptions() && parent.args.size() == 1;
|
||||
return noOptions() && truststorePath == null && !delete;
|
||||
}
|
||||
|
||||
public CommandResult process(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
|
||||
List<String> args = new ArrayList<>();
|
||||
|
||||
Iterator<String> it = parent.args.iterator();
|
||||
// skip the first argument 'truststore'
|
||||
it.next();
|
||||
|
||||
while (it.hasNext()) {
|
||||
String arg = it.next();
|
||||
switch (arg) {
|
||||
case "-d":
|
||||
case "--delete": {
|
||||
delete = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
args.add(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (args.size() > 1) {
|
||||
throw new IllegalArgumentException("Invalid option: " + args.get(1));
|
||||
}
|
||||
|
||||
String truststore = null;
|
||||
if (args.size() > 0) {
|
||||
truststore = args.get(0);
|
||||
}
|
||||
|
||||
checkUnsupportedOptions("--server", server,
|
||||
@Override
|
||||
protected String[] getUnsupportedOptions() {
|
||||
return new String[] {"--server", server,
|
||||
"--realm", realm,
|
||||
"--client", clientId,
|
||||
"--user", user,
|
||||
|
@ -115,33 +60,35 @@ public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd implements Comma
|
|||
"--keystore", keystore,
|
||||
"--keypass", keyPass,
|
||||
"--alias", alias,
|
||||
"--no-config", booleanOptionForCheck(noconfig));
|
||||
"--no-config", booleanOptionForCheck(noconfig)};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process() {
|
||||
// now update the config
|
||||
processGlobalOptions();
|
||||
|
||||
String store;
|
||||
String pass;
|
||||
|
||||
if (!delete) {
|
||||
|
||||
if (truststore == null) {
|
||||
if (truststorePath == null) {
|
||||
throw new IllegalArgumentException("No truststore specified");
|
||||
}
|
||||
|
||||
if (!new File(truststore).isFile()) {
|
||||
throw new RuntimeException("Truststore file not found: " + truststore);
|
||||
if (!new File(truststorePath).isFile()) {
|
||||
throw new RuntimeException("Truststore file not found: " + truststorePath);
|
||||
}
|
||||
|
||||
if ("-".equals(trustPass)) {
|
||||
trustPass = readSecret("Enter truststore password: ", commandInvocation);
|
||||
trustPass = readSecret("Enter truststore password: ");
|
||||
}
|
||||
|
||||
store = truststore;
|
||||
store = truststorePath;
|
||||
pass = trustPass;
|
||||
|
||||
} else {
|
||||
if (truststore != null) {
|
||||
if (truststorePath != null) {
|
||||
throw new IllegalArgumentException("Option --delete is mutually exclusive with specifying a TRUSTSTORE");
|
||||
}
|
||||
if (trustPass != null) {
|
||||
|
@ -155,14 +102,9 @@ public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd implements Comma
|
|||
config.setTruststore(store);
|
||||
config.setTrustpass(pass);
|
||||
});
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help config truststore' for more information";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -17,19 +17,11 @@
|
|||
|
||||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
|
||||
import org.jboss.aesh.cl.Arguments;
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.cl.Option;
|
||||
import org.jboss.aesh.console.command.Command;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.client.registration.cli.aesh.EndpointTypeConverter;
|
||||
import org.keycloak.client.registration.cli.EndpointTypeConverter;
|
||||
import org.keycloak.client.registration.cli.common.AttributeOperation;
|
||||
import org.keycloak.client.registration.cli.config.ConfigData;
|
||||
import org.keycloak.client.registration.cli.common.CmdStdinContext;
|
||||
import org.keycloak.client.registration.cli.common.EndpointType;
|
||||
import org.keycloak.client.registration.cli.config.ConfigData;
|
||||
import org.keycloak.client.registration.cli.util.HttpUtil;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.oidc.OIDCClientRepresentation;
|
||||
|
@ -39,95 +31,75 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
|
||||
import static org.keycloak.client.registration.cli.common.AttributeOperation.Type.SET;
|
||||
import static org.keycloak.client.registration.cli.common.EndpointType.DEFAULT;
|
||||
import static org.keycloak.client.registration.cli.common.EndpointType.OIDC;
|
||||
import static org.keycloak.client.registration.cli.common.EndpointType.SAML2;
|
||||
import static org.keycloak.client.registration.cli.util.AuthUtil.ensureToken;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.credentialsAvailable;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.loadConfig;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.saveMergeConfig;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.setRegistrationToken;
|
||||
import static org.keycloak.client.registration.cli.util.HttpUtil.doPost;
|
||||
import static org.keycloak.client.registration.cli.util.HttpUtil.getExpectedContentType;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.printErr;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.readFully;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.readSecret;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
import static org.keycloak.client.registration.cli.util.ParseUtil.mergeAttributes;
|
||||
import static org.keycloak.client.registration.cli.util.ParseUtil.parseFileOrStdin;
|
||||
import static org.keycloak.client.registration.cli.util.AuthUtil.ensureToken;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.setRegistrationToken;
|
||||
import static org.keycloak.client.registration.cli.util.HttpUtil.doPost;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
|
||||
import static org.keycloak.client.registration.cli.util.ParseUtil.parseKeyVal;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "create", description = "[ARGUMENTS]")
|
||||
public class CreateCmd extends AbstractAuthOptionsCmd implements Command {
|
||||
@Command(name = "create", description = "[ARGUMENTS]")
|
||||
public class CreateCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Option(shortName = 'i', name = "clientId", description = "After creation only print clientId to standard output", hasValue = false)
|
||||
@Option(names = {"-i", "--clientId"}, description = "After creation only print clientId to standard output")
|
||||
protected boolean returnClientId = false;
|
||||
|
||||
@Option(shortName = 'e', name = "endpoint", description = "Endpoint type / document format to use - one of: 'default', 'oidc', 'saml2'",
|
||||
hasValue = true, converter = EndpointTypeConverter.class)
|
||||
@Option(names = {"-e", "--endpoint"}, description = "Endpoint type / document format to use - one of: 'default', 'oidc', 'saml2'", converter = EndpointTypeConverter.class)
|
||||
protected EndpointType regType;
|
||||
|
||||
@Option(shortName = 'f', name = "file", description = "Read object from file or standard input if FILENAME is set to '-'", hasValue = true)
|
||||
@Option(names = {"-f", "--file"}, description = "Read object from file or standard input if FILENAME is set to '-'")
|
||||
protected String file;
|
||||
|
||||
@Option(shortName = 'o', name = "output", description = "After creation output the new client configuration to standard output", hasValue = false)
|
||||
@Option(names = {"-o", "--output"}, description = "After creation output the new client configuration to standard output")
|
||||
protected boolean outputClient = false;
|
||||
|
||||
@Option(shortName = 'c', name = "compressed", description = "Don't pretty print the output", hasValue = false)
|
||||
@Option(names = {"-c", "--compressed"}, description = "Don't pretty print the output")
|
||||
protected boolean compressed = false;
|
||||
|
||||
//@OptionGroup(shortName = 's', name = "set", description = "Set attribute to the specified value")
|
||||
//Map<String, String> attributes = new LinkedHashMap<>();
|
||||
@Option(names = {"-s", "--set"}, description = "Set a specific attribute NAME to a specified value VALUE")
|
||||
List<String> rawSets = new ArrayList<>();
|
||||
|
||||
@Arguments
|
||||
protected List<String> args;
|
||||
List<AttributeOperation> attrs = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
protected void processOptions() {
|
||||
super.processOptions();
|
||||
|
||||
List<AttributeOperation> attrs = new LinkedList<>();
|
||||
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
processGlobalOptions();
|
||||
|
||||
if (args != null) {
|
||||
Iterator<String> it = args.iterator();
|
||||
while (it.hasNext()) {
|
||||
String option = it.next();
|
||||
switch (option) {
|
||||
case "-s":
|
||||
case "--set": {
|
||||
if (!it.hasNext()) {
|
||||
throw new IllegalArgumentException("Option " + option + " requires a value");
|
||||
}
|
||||
String[] keyVal = parseKeyVal(it.next());
|
||||
for (String set : rawSets) {
|
||||
String[] keyVal = parseKeyVal(set);
|
||||
attrs.add(new AttributeOperation(SET, keyVal[0], keyVal[1]));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException("Unsupported option: " + option);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void process() {
|
||||
if (file == null && attrs.size() == 0) {
|
||||
throw new IllegalArgumentException("No file nor attribute values specified");
|
||||
}
|
||||
|
@ -138,7 +110,7 @@ public class CreateCmd extends AbstractAuthOptionsCmd implements Command {
|
|||
|
||||
// if --token is specified read it
|
||||
if ("-".equals(token)) {
|
||||
token = readSecret("Enter Initial Access Token: ", commandInvocation);
|
||||
token = readSecret("Enter Initial Access Token: ");
|
||||
}
|
||||
|
||||
CmdStdinContext ctx = new CmdStdinContext();
|
||||
|
@ -167,11 +139,11 @@ public class CreateCmd extends AbstractAuthOptionsCmd implements Command {
|
|||
token = config.sessionRealmConfigData().getInitialToken();
|
||||
}
|
||||
|
||||
setupTruststore(config, commandInvocation);
|
||||
setupTruststore(config);
|
||||
|
||||
String auth = token;
|
||||
if (auth == null) {
|
||||
config = ensureAuthInfo(config, commandInvocation);
|
||||
config = ensureAuthInfo(config);
|
||||
config = copyWithServerInfo(config);
|
||||
if (credentialsAvailable(config)) {
|
||||
auth = ensureToken(config);
|
||||
|
@ -209,14 +181,6 @@ public class CreateCmd extends AbstractAuthOptionsCmd implements Command {
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to process HTTP response", e);
|
||||
}
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void outputResult(String clientId, Object result) throws IOException {
|
||||
|
@ -235,13 +199,10 @@ public class CreateCmd extends AbstractAuthOptionsCmd implements Command {
|
|||
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return noOptions() && regType == null && file == null && (args == null || args.size() == 0);
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help create' for more information";
|
||||
return noOptions() && regType == null && file == null && rawSets.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -17,17 +17,14 @@
|
|||
|
||||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.Arguments;
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.client.registration.cli.config.ConfigData;
|
||||
import org.keycloak.client.registration.cli.util.ParseUtil;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.AuthUtil.ensureToken;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
|
||||
|
@ -39,38 +36,24 @@ import static org.keycloak.client.registration.cli.util.HttpUtil.doDelete;
|
|||
import static org.keycloak.client.registration.cli.util.HttpUtil.urlencode;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.warnfErr;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "delete", description = "CLIENT [GLOBAL_OPTIONS]")
|
||||
@Command(name = "delete", description = "CLIENT [GLOBAL_OPTIONS]")
|
||||
public class DeleteCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Arguments
|
||||
private List<String> args;
|
||||
@Parameters(arity = "0..1")
|
||||
String clientId;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
processGlobalOptions();
|
||||
|
||||
if (args == null || args.isEmpty()) {
|
||||
protected void process() {
|
||||
if (clientId == null) {
|
||||
throw new IllegalArgumentException("CLIENT not specified");
|
||||
}
|
||||
|
||||
if (args.size() > 1) {
|
||||
throw new IllegalArgumentException("Invalid option: " + args.get(1));
|
||||
}
|
||||
|
||||
String clientId = args.get(0);
|
||||
|
||||
if (clientId.startsWith("-")) {
|
||||
warnfErr(ParseUtil.CLIENT_OPTION_WARN, clientId);
|
||||
}
|
||||
|
@ -85,11 +68,11 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
|
|||
token = getRegistrationToken(config.sessionRealmConfigData(), clientId);
|
||||
}
|
||||
|
||||
setupTruststore(config, commandInvocation);
|
||||
setupTruststore(config);
|
||||
|
||||
String auth = token;
|
||||
if (auth == null) {
|
||||
config = ensureAuthInfo(config, commandInvocation);
|
||||
config = ensureAuthInfo(config);
|
||||
config = copyWithServerInfo(config);
|
||||
if (credentialsAvailable(config)) {
|
||||
auth = ensureToken(config);
|
||||
|
@ -107,24 +90,14 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
|
|||
saveMergeConfig(cfg -> {
|
||||
cfg.ensureRealmConfigData(server, realm).getClients().remove(clientId);
|
||||
});
|
||||
return CommandResult.SUCCESS;
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return noOptions() && (args == null || args.size() == 0);
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help delete' for more information";
|
||||
return noOptions() && clientId == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -17,12 +17,6 @@
|
|||
|
||||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.Arguments;
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.cl.Option;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.client.registration.cli.config.ConfigData;
|
||||
import org.keycloak.client.registration.cli.common.EndpointType;
|
||||
import org.keycloak.client.registration.cli.util.ParseUtil;
|
||||
|
@ -35,7 +29,10 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.AuthUtil.ensureToken;
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
|
||||
|
@ -51,43 +48,29 @@ import static org.keycloak.client.registration.cli.util.IoUtil.warnfErr;
|
|||
import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.readFully;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "get", description = "[ARGUMENTS]")
|
||||
@Command(name = "get", description = "[ARGUMENTS]")
|
||||
public class GetCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Option(shortName = 'c', name = "compressed", description = "Print full stack trace when exiting with error", hasValue = false)
|
||||
@Option(names = {"-c", "--compressed"}, description = "Print full stack trace when exiting with error")
|
||||
private boolean compressed = false;
|
||||
|
||||
@Option(shortName = 'e', name = "endpoint", description = "Endpoint type to use", hasValue = true)
|
||||
@Option(names = {"-e", "--endpoint"}, description = "Endpoint type to use")
|
||||
private String endpoint;
|
||||
|
||||
@Arguments
|
||||
private List<String> args;
|
||||
@Parameters(arity = "0..1")
|
||||
String clientId;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
processGlobalOptions();
|
||||
|
||||
if (args == null || args.isEmpty()) {
|
||||
protected void process() {
|
||||
if (clientId == null) {
|
||||
throw new IllegalArgumentException("CLIENT not specified");
|
||||
}
|
||||
|
||||
if (args.size() > 1) {
|
||||
throw new IllegalArgumentException("Invalid option: " + args.get(1));
|
||||
}
|
||||
|
||||
String clientId = args.get(0);
|
||||
EndpointType regType = endpoint != null ? EndpointType.of(endpoint) : EndpointType.DEFAULT;
|
||||
|
||||
|
||||
|
@ -103,11 +86,11 @@ public class GetCmd extends AbstractAuthOptionsCmd {
|
|||
token = getRegistrationToken(config.sessionRealmConfigData(), clientId);
|
||||
}
|
||||
|
||||
setupTruststore(config, commandInvocation);
|
||||
setupTruststore(config);
|
||||
|
||||
String auth = token;
|
||||
if (auth == null) {
|
||||
config = ensureAuthInfo(config, commandInvocation);
|
||||
config = ensureAuthInfo(config);
|
||||
config = copyWithServerInfo(config);
|
||||
if (credentialsAvailable(config)) {
|
||||
auth = ensureToken(config);
|
||||
|
@ -169,24 +152,14 @@ public class GetCmd extends AbstractAuthOptionsCmd {
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to process HTTP response", e);
|
||||
}
|
||||
return CommandResult.SUCCESS;
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return noOptions() && endpoint == null && (args == null || args.size() == 0);
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help get' for more information";
|
||||
return noOptions() && endpoint == null && clientId == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.Arguments;
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.console.command.Command;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "help", description = "This help")
|
||||
public class HelpCmd implements Command {
|
||||
@Command(name = "help", description = "This help")
|
||||
public class HelpCmd implements Runnable {
|
||||
|
||||
@Arguments
|
||||
@Parameters
|
||||
private List<String> args;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
public void run() {
|
||||
if (args == null || args.size() == 0) {
|
||||
printOut(KcRegCmd.usage());
|
||||
} else {
|
||||
|
@ -77,14 +72,9 @@ public class HelpCmd implements Command {
|
|||
break;
|
||||
}
|
||||
default: {
|
||||
throw new RuntimeException("Unknown command: " + args.get(0));
|
||||
throw new IllegalArgumentException("Unknown command: " + args.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,11 @@
|
|||
*/
|
||||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import org.jboss.aesh.cl.GroupCommandDefinition;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
|
||||
import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
|
@ -33,27 +30,30 @@ import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
|||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
|
||||
@GroupCommandDefinition(name = "kcreg", description = "COMMAND [ARGUMENTS]", groupCommands = {
|
||||
HelpCmd.class, ConfigCmd.class, CreateCmd.class, UpdateCmd.class, GetCmd.class, DeleteCmd.class, AttrsCmd.class, UpdateTokenCmd.class} )
|
||||
@Command(name = "kcreg",
|
||||
header = {
|
||||
"Keycloak - Open Source Identity and Access Management",
|
||||
"",
|
||||
"Find more information at: https://www.keycloak.org/docs/latest"
|
||||
},
|
||||
description = {
|
||||
"%nCOMMAND [ARGUMENTS]"
|
||||
},
|
||||
subcommands = {
|
||||
HelpCmd.class,
|
||||
ConfigCmd.class,
|
||||
CreateCmd.class,
|
||||
GetCmd.class,
|
||||
UpdateCmd.class,
|
||||
DeleteCmd.class,
|
||||
AttrsCmd.class,
|
||||
UpdateTokenCmd.class
|
||||
})
|
||||
public class KcRegCmd extends AbstractGlobalOptionsCmd {
|
||||
|
||||
//@Arguments
|
||||
//private List<String> args;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
try {
|
||||
// if --help was requested then status is SUCCESS
|
||||
// if not we print help anyway, but status is FAILURE
|
||||
if (printHelp()) {
|
||||
return CommandResult.SUCCESS;
|
||||
} else {
|
||||
printOut(usage());
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
protected boolean nothingToDo() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static String usage() {
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import org.jboss.aesh.cl.Arguments;
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.cl.Option;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.client.registration.cli.aesh.EndpointTypeConverter;
|
||||
|
||||
import picocli.CommandLine.ArgGroup;
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Option;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import org.keycloak.client.registration.cli.EndpointTypeConverter;
|
||||
import org.keycloak.client.registration.cli.common.AttributeOperation;
|
||||
import org.keycloak.client.registration.cli.config.ConfigData;
|
||||
import org.keycloak.client.registration.cli.common.CmdStdinContext;
|
||||
|
@ -39,7 +39,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -62,7 +62,6 @@ import static org.keycloak.client.registration.cli.util.IoUtil.warnfErr;
|
|||
import static org.keycloak.client.registration.cli.util.IoUtil.readFully;
|
||||
import static org.keycloak.client.registration.cli.util.HttpUtil.APPLICATION_JSON;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
import static org.keycloak.client.registration.cli.util.ParseUtil.mergeAttributes;
|
||||
import static org.keycloak.client.registration.cli.util.ParseUtil.parseFileOrStdin;
|
||||
|
@ -71,81 +70,62 @@ import static org.keycloak.client.registration.cli.util.ParseUtil.parseKeyVal;
|
|||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "update", description = "CLIENT_ID [ARGUMENTS]")
|
||||
@Command(name = "update", description = "CLIENT_ID [ARGUMENTS]")
|
||||
public class UpdateCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Option(shortName = 'e', name = "endpoint", description = "Endpoint type to use - one of: 'default', 'oidc'", hasValue = true, converter = EndpointTypeConverter.class)
|
||||
@Option(names = {"-e", "--endpoint"}, description = "Endpoint type to use - one of: 'default', 'oidc'", converter = EndpointTypeConverter.class)
|
||||
private EndpointType regType = null;
|
||||
|
||||
//@GroupOption(shortName = 's', name = "set", description = "Set specific attribute to a specified value", hasValue = true)
|
||||
//private List<String> attributes = new ArrayList<>();
|
||||
|
||||
@Option(shortName = 'f', name = "file", description = "Use the file or standard input if '-' is specified", hasValue = true)
|
||||
@Option(names = {"-f", "--file"}, description = "Use the file or standard input if '-' is specified")
|
||||
private String file = null;
|
||||
|
||||
@Option(shortName = 'm', name = "merge", description = "Merge new values with existing configuration on the server", hasValue = false)
|
||||
private boolean mergeMode = true;
|
||||
@Option(names = {"-m", "--merge"}, description = "Merge new values with existing configuration on the server")
|
||||
private boolean mergeMode = false;
|
||||
|
||||
@Option(shortName = 'o', name = "output", description = "After update output the new client configuration", hasValue = false)
|
||||
@Option(names = {"-o", "--output"}, description = "After update output the new client configuration")
|
||||
private boolean outputClient = false;
|
||||
|
||||
@Option(shortName = 'c', name = "compressed", description = "Don't pretty print the output", hasValue = false)
|
||||
@Option(names = {"-c", "--compressed"}, description = "Don't pretty print the output")
|
||||
private boolean compressed = false;
|
||||
|
||||
@Arguments
|
||||
private List<String> args;
|
||||
@Parameters(arity = "0..1")
|
||||
String clientId;
|
||||
|
||||
// to maintain relative positions of set and delete operations
|
||||
static class AttributeOperations {
|
||||
@Option(names = {"-s", "--set"}, required = true) String set;
|
||||
@Option(names = {"-d", "--delete"}, required = true) String delete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
@ArgGroup(exclusive = true, multiplicity = "0..*")
|
||||
List<AttributeOperations> rawAttributeOperations = new ArrayList<>();
|
||||
|
||||
List<AttributeOperation> attrs = new LinkedList<>();
|
||||
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
@Override
|
||||
protected void processOptions() {
|
||||
super.processOptions();
|
||||
|
||||
for (AttributeOperations entry : rawAttributeOperations) {
|
||||
if (entry.delete != null) {
|
||||
attrs.add(new AttributeOperation(DELETE, entry.delete));
|
||||
} else {
|
||||
String[] keyVal = parseKeyVal(entry.set);
|
||||
attrs.add(new AttributeOperation(SET, keyVal[0], keyVal[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
processGlobalOptions();
|
||||
|
||||
String clientId = null;
|
||||
|
||||
if (args != null) {
|
||||
Iterator<String> it = args.iterator();
|
||||
if (!it.hasNext()) {
|
||||
@Override
|
||||
protected void process() {
|
||||
if (clientId == null) {
|
||||
throw new IllegalArgumentException("CLIENT_ID not specified");
|
||||
}
|
||||
|
||||
clientId = it.next();
|
||||
|
||||
if (clientId.startsWith("-")) {
|
||||
warnfErr(ParseUtil.CLIENT_OPTION_WARN, clientId);
|
||||
}
|
||||
|
||||
while (it.hasNext()) {
|
||||
String option = it.next();
|
||||
switch (option) {
|
||||
case "-s":
|
||||
case "--set": {
|
||||
if (!it.hasNext()) {
|
||||
throw new IllegalArgumentException("Option " + option + " requires a value");
|
||||
}
|
||||
String[] keyVal = parseKeyVal(it.next());
|
||||
attrs.add(new AttributeOperation(SET, keyVal[0], keyVal[1]));
|
||||
break;
|
||||
}
|
||||
case "-d":
|
||||
case "--delete": {
|
||||
attrs.add(new AttributeOperation(DELETE, it.next()));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
throw new IllegalArgumentException("Unsupported option: " + option);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (file == null && attrs.size() == 0) {
|
||||
throw new IllegalArgumentException("No file nor attribute values specified");
|
||||
}
|
||||
|
@ -229,11 +209,11 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
|
|||
token = getRegistrationToken(config.sessionRealmConfigData(), clientId);
|
||||
}
|
||||
|
||||
setupTruststore(config, commandInvocation);
|
||||
setupTruststore(config);
|
||||
|
||||
String auth = token;
|
||||
if (auth == null) {
|
||||
config = ensureAuthInfo(config, commandInvocation);
|
||||
config = ensureAuthInfo(config);
|
||||
config = copyWithServerInfo(config);
|
||||
if (credentialsAvailable(config)) {
|
||||
auth = ensureToken(config);
|
||||
|
@ -316,14 +296,6 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to process HTTP response", e);
|
||||
}
|
||||
|
||||
return CommandResult.SUCCESS;
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private void outputResult(Object result) throws IOException {
|
||||
|
@ -338,13 +310,10 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
|
|||
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return noOptions() && regType == null && file == null && (args == null || args.size() == 0);
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help update' for more information";
|
||||
return noOptions() && regType == null && file == null && rawAttributeOperations.isEmpty() && clientId == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -18,11 +18,10 @@
|
|||
package org.keycloak.client.registration.cli.commands;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import org.jboss.aesh.cl.Arguments;
|
||||
import org.jboss.aesh.cl.CommandDefinition;
|
||||
import org.jboss.aesh.console.command.CommandException;
|
||||
import org.jboss.aesh.console.command.CommandResult;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
|
||||
import picocli.CommandLine.Command;
|
||||
import picocli.CommandLine.Parameters;
|
||||
|
||||
import org.keycloak.client.registration.cli.config.ConfigData;
|
||||
import org.keycloak.client.registration.cli.util.ParseUtil;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
|
@ -45,43 +44,32 @@ import static org.keycloak.client.registration.cli.util.HttpUtil.doPost;
|
|||
import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
|
||||
import static org.keycloak.client.registration.cli.util.IoUtil.warnfOut;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.EOL;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
*/
|
||||
@CommandDefinition(name = "update-token", description = "CLIENT [ARGUMENTS]")
|
||||
@Command(name = "update-token", description = "CLIENT [ARGUMENTS]")
|
||||
public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
|
||||
|
||||
@Arguments
|
||||
private List<String> args;
|
||||
@Parameters(arity = "0..1")
|
||||
String clientId;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandInvocation commandInvocation) throws CommandException, InterruptedException {
|
||||
|
||||
try {
|
||||
if (printHelp()) {
|
||||
return help ? CommandResult.SUCCESS : CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
processGlobalOptions();
|
||||
|
||||
if (args == null || args.isEmpty()) {
|
||||
protected void process() {
|
||||
if (clientId == null) {
|
||||
throw new IllegalArgumentException("CLIENT not specified");
|
||||
}
|
||||
|
||||
String clientId = args.get(0);
|
||||
|
||||
if (clientId.startsWith("-")) {
|
||||
warnfOut(ParseUtil.CLIENT_OPTION_WARN, clientId);
|
||||
}
|
||||
|
||||
ConfigData config = loadConfig();
|
||||
config = copyWithServerInfo(config);
|
||||
setupTruststore(config, commandInvocation);
|
||||
setupTruststore(config);
|
||||
|
||||
config = ensureAuthInfo(config, commandInvocation);
|
||||
config = ensureAuthInfo(config);
|
||||
String auth = ensureToken(config);
|
||||
|
||||
String cid = null;
|
||||
|
@ -124,26 +112,14 @@ public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
|
|||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to process response from server", e);
|
||||
}
|
||||
|
||||
//System.out.println("Token updated for client " + clientId);
|
||||
return CommandResult.SUCCESS;
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException(e.getMessage() + suggestHelp(), e);
|
||||
} finally {
|
||||
commandInvocation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean nothingToDo() {
|
||||
return noOptions() && (args == null || args.size() == 0);
|
||||
}
|
||||
|
||||
protected String suggestHelp() {
|
||||
return EOL + "Try '" + CMD + " help update-token' for more information";
|
||||
return noOptions() && clientId == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String help() {
|
||||
return usage();
|
||||
}
|
||||
|
|
|
@ -17,14 +17,7 @@
|
|||
|
||||
package org.keycloak.client.registration.cli.util;
|
||||
|
||||
import org.jboss.aesh.console.AeshConsoleBufferBuilder;
|
||||
import org.jboss.aesh.console.AeshInputProcessorBuilder;
|
||||
import org.jboss.aesh.console.ConsoleBuffer;
|
||||
import org.jboss.aesh.console.InputProcessor;
|
||||
import org.jboss.aesh.console.Prompt;
|
||||
import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||
import org.keycloak.client.registration.cli.aesh.Globals;
|
||||
|
||||
import java.io.Console;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
@ -50,7 +43,6 @@ import static java.nio.file.Files.createDirectories;
|
|||
import static java.nio.file.Files.createFile;
|
||||
import static java.nio.file.Files.isDirectory;
|
||||
import static java.nio.file.Files.isRegularFile;
|
||||
import static org.keycloak.client.registration.cli.util.OsUtil.OS_ARCH;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
|
@ -81,43 +73,14 @@ public class IoUtil {
|
|||
}
|
||||
}
|
||||
|
||||
public static String readSecret(String prompt, CommandInvocation invocation) {
|
||||
|
||||
// TODO Windows hack - masking not working on Windows
|
||||
char maskChar = OS_ARCH.isWindows() ? 0 : '*';
|
||||
ConsoleBuffer consoleBuffer = new AeshConsoleBufferBuilder()
|
||||
.shell(invocation.getShell())
|
||||
.prompt(new Prompt(prompt, maskChar))
|
||||
.create();
|
||||
InputProcessor inputProcessor = new AeshInputProcessorBuilder()
|
||||
.consoleBuffer(consoleBuffer)
|
||||
.create();
|
||||
|
||||
consoleBuffer.displayPrompt();
|
||||
|
||||
// activate stdin
|
||||
Globals.stdin.setInputStream(System.in);
|
||||
|
||||
String result;
|
||||
try {
|
||||
do {
|
||||
result = inputProcessor.parseOperation(invocation.getInput());
|
||||
} while (result == null);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("^C", e);
|
||||
public static String readSecret(String prompt) {
|
||||
Console cons;
|
||||
char[] passwd;
|
||||
if ((cons = System.console()) != null &&
|
||||
(passwd = cons.readPassword("%s", prompt)) != null) {
|
||||
return new String(passwd);
|
||||
}
|
||||
/*
|
||||
if (!Globals.stdin.isStdinAvailable()) {
|
||||
try {
|
||||
return readLine(new InputStreamReader(System.in));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Standard input not available");
|
||||
}
|
||||
}
|
||||
*/
|
||||
// Windows hack - get rid of any \n
|
||||
result = result.replaceAll("\\n", "");
|
||||
return result;
|
||||
throw new RuntimeException("Console is not active, or no password provided");
|
||||
}
|
||||
|
||||
public static String readFully(InputStream is) {
|
||||
|
|
6
pom.xml
6
pom.xml
|
@ -80,7 +80,6 @@
|
|||
<jboss.as.subsystem.test.version>7.5.22.Final-redhat-1</jboss.as.subsystem.test.version>
|
||||
|
||||
<!-- Versions used mostly for Undertow server, aligned with WildFly -->
|
||||
<jboss.aesh.version>0.66.19</jboss.aesh.version>
|
||||
<apache.httpcomponents.version>4.5.14</apache.httpcomponents.version>
|
||||
<jboss.dmr.version>1.5.1.Final</jboss.dmr.version>
|
||||
|
||||
|
@ -948,11 +947,6 @@
|
|||
<artifactId>pax-web-spi</artifactId>
|
||||
<version>${pax.web.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.aesh</groupId>
|
||||
<artifactId>aesh</artifactId>
|
||||
<version>${jboss.aesh.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- keycloak -->
|
||||
<dependency>
|
||||
|
|
|
@ -20,27 +20,27 @@ public class KcRegConfigTest extends AbstractRegCliTest {
|
|||
@Test
|
||||
public void testRegistrationToken() throws IOException {
|
||||
|
||||
FileConfigHandler handler = initCustomConfigFile();
|
||||
initCustomConfigFile();
|
||||
|
||||
try (TempFileResource configFile = new TempFileResource(handler.getConfigFile())) {
|
||||
try (TempFileResource configFile = new TempFileResource(FileConfigHandler.getConfigFile())) {
|
||||
|
||||
// without --server
|
||||
KcRegExec exe = execute("config registration-token --config '" + configFile.getName() + "' ");
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("error message", "Required option not specified: --server", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config registration-token' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config registration-token --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
|
||||
// without --realm
|
||||
exe = execute("config registration-token --config '" + configFile.getName() + "' --server http://localhost:8080/auth");
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("error message", "Required option not specified: --realm", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config registration-token' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config registration-token --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
|
||||
// without --client
|
||||
exe = execute("config registration-token --config '" + configFile.getName() + "' --server http://localhost:8080/auth --realm test");
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("error message", "Required option not specified: --client", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config registration-token' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config registration-token --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
|
||||
// specify token on cmdline
|
||||
exe = execute("config registration-token --config '" + configFile.getName() + "' --server http://localhost:8080/auth --realm test --client my_client NEWTOKEN");
|
||||
|
@ -75,14 +75,14 @@ public class KcRegConfigTest extends AbstractRegCliTest {
|
|||
public void testNoConfigOption() throws IOException {
|
||||
|
||||
KcRegExec exe = execute("config registration-token --no-config --server http://localhost:8080/auth --realm test --client my_client --delete");
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("stderr first line", "Unsupported option: --no-config", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config registration-token' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config registration-token --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
|
||||
exe = execute("config initial-token --no-config --server http://localhost:8080/auth --realm test --delete");
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("stderr first line", "Unsupported option: --no-config", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config initial-token' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config initial-token --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
*/
|
||||
KcRegExec exe = execute("");
|
||||
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
|
||||
List<String> lines = exe.stdoutLines();
|
||||
Assert.assertTrue("stdout output not empty", lines.size() > 0);
|
||||
|
@ -49,51 +49,51 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
* Test commands without arguments
|
||||
*/
|
||||
exe = execute("config");
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 1);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 8, 0);
|
||||
Assert.assertEquals("error message",
|
||||
"Sub-command required by '" + CMD + " config' - one of: 'credentials', 'truststore', 'initial-token', 'registration-token'",
|
||||
exe.stderrLines().get(0));
|
||||
"Usage: kcreg.sh config SUB_COMMAND [ARGUMENTS]",
|
||||
exe.stdoutLines().get(0));
|
||||
|
||||
exe = execute("config credentials");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " config credentials --server SERVER_URL --realm REALM [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
|
||||
exe = execute("config initial-token");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " config initial-token --server SERVER --realm REALM [--delete | TOKEN] [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
|
||||
exe = execute("config registration-token");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " config registration-token --server SERVER --realm REALM --client CLIENT [--delete | TOKEN] [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
|
||||
exe = execute("config truststore");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " config truststore [TRUSTSTORE | --delete] [--trustpass PASSWORD] [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
|
||||
exe = execute("create");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " create [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
//Assert.assertEquals("error message", "No file nor attribute values specified", exe.stderrLines().get(0));
|
||||
|
||||
exe = execute("get");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " get CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
//Assert.assertEquals("error message", "CLIENT not specified", exe.stderrLines().get(0));
|
||||
|
||||
exe = execute("update");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " update CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
//Assert.assertEquals("error message", "No file nor attribute values specified", exe.stderrLines().get(0));
|
||||
|
||||
exe = execute("delete");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " delete CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
//Assert.assertEquals("error message", "CLIENT not specified", exe.stderrLines().get(0));
|
||||
|
@ -104,7 +104,7 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
Assert.assertEquals("first line", "Attributes for default format:", exe.stdoutLines().get(0));
|
||||
|
||||
exe = execute("update-token");
|
||||
assertExitCodeAndStdErrSize(exe, 1, 0);
|
||||
assertExitCodeAndStdErrSize(exe, 2, 0);
|
||||
Assert.assertTrue("help message returned", exe.stdoutLines().size() > 10);
|
||||
Assert.assertEquals("help message", "Usage: " + CMD + " update-token CLIENT [ARGUMENTS]", exe.stdoutLines().get(0));
|
||||
//Assert.assertEquals("error message", "CLIENT not specified", exe.stderrLines().get(0));
|
||||
|
@ -188,8 +188,8 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
*/
|
||||
KcRegExec exe = execute("nonexistent");
|
||||
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 1);
|
||||
Assert.assertEquals("stderr first line", "Unknown command: nonexistent", exe.stderrLines().get(0));
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 3);
|
||||
Assert.assertEquals("stderr first line", "Unmatched argument at index 0: 'nonexistent'", exe.stderrLines().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -199,8 +199,8 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
*/
|
||||
KcRegExec exe = execute("--nonexistent");
|
||||
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 1);
|
||||
Assert.assertEquals("stderr first line", "Unknown command: --nonexistent", exe.stderrLines().get(0));
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("stderr first line", "Unknown option: '--nonexistent'", exe.stderrLines().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -211,9 +211,9 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
|
||||
KcRegExec exe = execute("get my_client --nonexistent");
|
||||
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
Assert.assertEquals("stderr first line", "Invalid option: --nonexistent", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help get' for more information", exe.stderrLines().get(1));
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 3);
|
||||
Assert.assertEquals("stderr first line", "Unknown option: '--nonexistent'", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " get --help' for more information on the available options.", exe.stderrLines().get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -233,9 +233,9 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
*/
|
||||
KcRegExec exe = execute("config credentials --realm master --user admin --password admin");
|
||||
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("stderr first line", "Required option not specified: --server", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config credentials' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config credentials --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -245,9 +245,9 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
*/
|
||||
KcRegExec exe = execute("config credentials --server " + serverUrl + " --user admin --password admin");
|
||||
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("stderr first line", "Required option not specified: --realm", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config credentials' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config credentials --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -257,9 +257,9 @@ public class KcRegTest extends AbstractRegCliTest {
|
|||
*/
|
||||
KcRegExec exe = KcRegExec.execute("config credentials --no-config --server " + serverUrl + " --realm master --user admin --password admin");
|
||||
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("stderr first line", "Unsupported option: --no-config", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config credentials' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config credentials --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.keycloak.client.registration.cli.config.ConfigData;
|
|||
import org.keycloak.client.registration.cli.config.FileConfigHandler;
|
||||
import org.keycloak.client.registration.cli.util.OsUtil;
|
||||
import org.keycloak.testsuite.cli.KcRegExec;
|
||||
import org.keycloak.testsuite.util.OAuthClient;
|
||||
import org.keycloak.testsuite.util.TempFileResource;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -29,9 +30,9 @@ public class KcRegTruststoreTest extends AbstractRegCliTest {
|
|||
|
||||
KcRegExec exe = execute("config truststore --no-config '" + truststore.getAbsolutePath() + "'");
|
||||
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("stderr first line", "Unsupported option: --no-config", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + OsUtil.CMD + " help config truststore' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + OsUtil.CMD + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
|
||||
// only run the rest of this test if ssl protected keycloak server is available
|
||||
if (!AUTH_SERVER_SSL_REQUIRED) {
|
||||
|
@ -39,9 +40,9 @@ public class KcRegTruststoreTest extends AbstractRegCliTest {
|
|||
return;
|
||||
}
|
||||
|
||||
FileConfigHandler handler = initCustomConfigFile();
|
||||
initCustomConfigFile();
|
||||
|
||||
try (TempFileResource configFile = new TempFileResource(handler.getConfigFile())) {
|
||||
try (TempFileResource configFile = new TempFileResource(FileConfigHandler.getConfigFile())) {
|
||||
|
||||
if (runIntermittentlyFailingTests()) {
|
||||
// configure truststore
|
||||
|
@ -52,7 +53,7 @@ public class KcRegTruststoreTest extends AbstractRegCliTest {
|
|||
|
||||
// perform authentication against server - asks for password, then for truststore password
|
||||
exe = KcRegExec.newBuilder()
|
||||
.argsLine("config credentials --server " + oauth.AUTH_SERVER_ROOT + " --realm test --user user1" +
|
||||
.argsLine("config credentials --server " + OAuthClient.AUTH_SERVER_ROOT + " --realm test --user user1" +
|
||||
" --config '" + configFile.getName() + "'")
|
||||
.executeAsync();
|
||||
|
||||
|
@ -72,7 +73,7 @@ public class KcRegTruststoreTest extends AbstractRegCliTest {
|
|||
|
||||
// perform authentication against server - asks for password, then for truststore password
|
||||
exe = KcRegExec.newBuilder()
|
||||
.argsLine("config credentials --server " + oauth.AUTH_SERVER_ROOT + " --realm test --user user1" +
|
||||
.argsLine("config credentials --server " + OAuthClient.AUTH_SERVER_ROOT + " --realm test --user user1" +
|
||||
" --config '" + configFile.getName() + "'")
|
||||
.executeAsync();
|
||||
|
||||
|
@ -99,17 +100,17 @@ public class KcRegTruststoreTest extends AbstractRegCliTest {
|
|||
assertExitCodeAndStreamSizes(exe, 0, 0, 0);
|
||||
|
||||
exe = execute("config truststore --delete '" + truststore.getAbsolutePath() + "'");
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("incompatible", "Option --delete is mutually exclusive with specifying a TRUSTSTORE", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config truststore' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
|
||||
exe = execute("config truststore --delete --trustpass secret");
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 2);
|
||||
Assert.assertEquals("no truststore error", "Options --trustpass and --delete are mutually exclusive", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help config truststore' for more information", exe.stderrLines().get(1));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
|
||||
|
||||
FileConfigHandler cfghandler = new FileConfigHandler();
|
||||
cfghandler.setConfigFile(DEFAULT_CONFIG_FILE_PATH);
|
||||
FileConfigHandler.setConfigFile(DEFAULT_CONFIG_FILE_PATH);
|
||||
ConfigData config = cfghandler.loadConfig();
|
||||
Assert.assertNull("truststore null", config.getTruststore());
|
||||
Assert.assertNull("trustpass null", config.getTrustpass());
|
||||
|
|
|
@ -26,7 +26,7 @@ public class KcRegUpdateTest extends AbstractRegCliTest {
|
|||
|
||||
FileConfigHandler handler = initCustomConfigFile();
|
||||
|
||||
try (TempFileResource configFile = new TempFileResource(handler.getConfigFile())) {
|
||||
try (TempFileResource configFile = new TempFileResource(FileConfigHandler.getConfigFile())) {
|
||||
|
||||
final String realm = "test";
|
||||
|
||||
|
@ -91,9 +91,9 @@ public class KcRegUpdateTest extends AbstractRegCliTest {
|
|||
// check that using an invalid attribute key is not ignored
|
||||
exe = execute("update my_client --nonexisting --config '" + configFile.getName() + "'");
|
||||
|
||||
assertExitCodeAndStreamSizes(exe, 1, 0, 2);
|
||||
Assert.assertEquals("error message", "Unsupported option: --nonexisting", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " help update' for more information", exe.stderrLines().get(1));
|
||||
assertExitCodeAndStreamSizes(exe, 2, 0, 3);
|
||||
Assert.assertEquals("error message", "Unknown option: '--nonexisting'", exe.stderrLines().get(0));
|
||||
Assert.assertEquals("try help", "Try '" + CMD + " update --help' for more information on the available options.", exe.stderrLines().get(2));
|
||||
|
||||
|
||||
// try use incompatible endpoint
|
||||
|
|
Loading…
Reference in a new issue