diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ParseUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/CmdStdinContext.java
similarity index 80%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ParseUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/CmdStdinContext.java
index 7d7399ec01..525a436888 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ParseUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/CmdStdinContext.java
@@ -14,49 +14,57 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.admin.cli;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.keycloak.client.admin.cli.common.AttributeOperation;
-import org.keycloak.client.admin.cli.common.CmdStdinContext;
+import org.keycloak.client.cli.common.AttributeOperation;
+import org.keycloak.client.cli.util.AttributeException;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.util.List;
-import static org.keycloak.client.admin.cli.util.IoUtil.readFileOrStdin;
-import static org.keycloak.client.admin.cli.util.ReflectionUtil.setAttributes;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.keycloak.client.admin.cli.ReflectionUtil.setAttributes;
+import static org.keycloak.client.cli.util.IoUtil.readFileOrStdin;
/**
* @author Marko Strukelj
*/
-public class ParseUtil {
+public class CmdStdinContext {
- public static String[] parseKeyVal(String keyval) {
- // we expect = as a separator
- int pos = keyval.indexOf("=");
- if (pos <= 0) {
- throw new IllegalArgumentException("Invalid key=value parameter: [" + keyval + "]");
- }
+ private T result;
+ private String content;
- String [] parsed = new String[2];
- parsed[0] = keyval.substring(0, pos);
- parsed[1] = keyval.substring(pos+1);
+ public CmdStdinContext() {}
- return parsed;
+ public T getResult() {
+ return result;
+ }
+
+ public void setResult(T result) {
+ this.result = result;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
}
public static CmdStdinContext parseFileOrStdin(String file) {
-
+
String content = readFileOrStdin(file).trim();
JsonNode result = null;
-
+
if (content.length() == 0) {
throw new RuntimeException("Document provided by --file option is empty");
}
-
+
try {
result = JsonSerialization.readValue(content, JsonNode.class);
} catch (JsonParseException e) {
@@ -66,7 +74,7 @@ public class ParseUtil {
} catch (Exception e) {
throw new RuntimeException("Not a valid JSON document", e);
}
-
+
CmdStdinContext ctx = new CmdStdinContext<>();
ctx.setContent(content);
ctx.setResult(result);
@@ -74,33 +82,33 @@ public class ParseUtil {
}
public static CmdStdinContext mergeAttributes(CmdStdinContext ctx, ObjectNode newObject, List attrs) {
-
+
JsonNode node = ctx.getResult();
if (node != null && !node.isObject()) {
throw new RuntimeException("Not a JSON object: " + node);
}
ObjectNode result = (ObjectNode) node;
try {
-
+
if (result == null) {
result = newObject;
}
-
+
if (result == null) {
throw new RuntimeException("Failed to set attribute(s) - no target object");
}
-
+
try {
setAttributes(result, attrs);
} catch (AttributeException e) {
throw new RuntimeException("Failed to set attribute '" + e.getAttributeName() + "' on document type '" + result.getClass().getName() + "'", e);
}
ctx.setContent(JsonSerialization.writeValueAsString(result));
-
+
} catch (IOException e) {
throw new RuntimeException("Failed to merge attributes with configuration from file", e);
}
-
+
ctx.setResult(result);
return ctx;
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/KcAdmMain.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/KcAdmMain.java
index cc913235e0..50e35ee2b8 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/KcAdmMain.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/KcAdmMain.java
@@ -17,45 +17,37 @@
package org.keycloak.client.admin.cli;
import org.keycloak.client.admin.cli.commands.KcAdmCmd;
-import org.keycloak.client.admin.cli.util.ClassLoaderUtil;
-import org.keycloak.client.admin.cli.util.OsUtil;
-import org.keycloak.common.crypto.CryptoIntegration;
-
-import java.io.PrintWriter;
-
-import picocli.CommandLine;
-import picocli.CommandLine.Model.CommandSpec;
+import org.keycloak.client.cli.common.CommandState;
+import org.keycloak.client.cli.common.Globals;
+import org.keycloak.client.cli.util.OsUtil;
/**
* @author Marko Strukelj
*/
public class KcAdmMain {
- public static void main(String [] args) {
- String libDir = System.getProperty("kc.lib.dir");
- if (libDir == null) {
- throw new RuntimeException("System property kc.lib.dir needs to be set");
+ public static final String DEFAULT_CONFIG_FILE_PATH = System.getProperty("user.home") + "/.keycloak/kcadm.config";
+
+ public static final String DEFAULT_CONFIG_FILE_STRING = OsUtil.OS_ARCH.isWindows() ? "%HOMEDRIVE%%HOMEPATH%\\.keycloak\\kcadm.config" : "~/.keycloak/kcadm.config";
+
+ public static final String CMD = OsUtil.OS_ARCH.isWindows() ? "kcadm.bat" : "kcadm.sh";
+
+ public static final CommandState COMMAND_STATE = new CommandState() {
+
+ @Override
+ public String getCommand() {
+ return CMD;
}
- ClassLoader cl = ClassLoaderUtil.resolveClassLoader(libDir);
- Thread.currentThread().setContextClassLoader(cl);
- CryptoIntegration.init(cl);
+ @Override
+ public String getDefaultConfigFilePath() {
+ return DEFAULT_CONFIG_FILE_PATH;
+ }
- CommandLine cli = createCommandLine();
- int exitCode = cli.execute(args);
- System.exit(exitCode);
- }
+ };
- public static CommandLine createCommandLine() {
- CommandSpec spec = CommandSpec.forAnnotatedObject(new KcAdmCmd()).name(OsUtil.CMD);
-
- CommandLine cmd = new CommandLine(spec);
-
- cmd.setExecutionExceptionHandler(new ExecutionExceptionHandler());
- cmd.setParameterExceptionHandler(new ShortErrorMessageHandler());
- cmd.setErr(new PrintWriter(System.err, true));
-
- return cmd;
+ public static void main(String [] args) {
+ Globals.main(args, new KcAdmCmd(), CMD, DEFAULT_CONFIG_FILE_STRING);
}
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ReflectionUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ReflectionUtil.java
similarity index 95%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ReflectionUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ReflectionUtil.java
index 4a0774502a..3a7cede5e8 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ReflectionUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ReflectionUtil.java
@@ -14,22 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.admin.cli;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.NullNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
-import org.keycloak.client.admin.cli.common.AttributeKey;
-import org.keycloak.client.admin.cli.common.AttributeOperation;
+
+import org.keycloak.client.cli.common.AttributeKey;
+import org.keycloak.client.cli.common.AttributeOperation;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import static org.keycloak.client.admin.cli.common.AttributeOperation.Type.SET;
-import static org.keycloak.client.admin.cli.util.OutputUtil.MAPPER;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.SET;
+import static org.keycloak.client.cli.util.OutputUtil.MAPPER;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractAuthOptionsCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractAuthOptionsCmd.java
index c17bb19e91..88234618d2 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractAuthOptionsCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractAuthOptionsCmd.java
@@ -16,252 +16,35 @@
*/
package org.keycloak.client.admin.cli.commands;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.client.admin.cli.config.ConfigData;
-import org.keycloak.client.admin.cli.config.ConfigHandler;
-import org.keycloak.client.admin.cli.config.FileConfigHandler;
-import org.keycloak.client.admin.cli.config.InMemoryConfigHandler;
-import org.keycloak.client.admin.cli.config.RealmConfigData;
-import org.keycloak.client.admin.cli.util.ConfigUtil;
-import org.keycloak.client.admin.cli.util.HttpUtil;
-import org.keycloak.client.admin.cli.util.IoUtil;
-
-import java.io.File;
+import org.keycloak.client.admin.cli.KcAdmMain;
+import org.keycloak.client.cli.common.BaseAuthOptionsCmd;
+import org.keycloak.client.cli.config.ConfigData;
import picocli.CommandLine.Option;
-import static org.keycloak.client.admin.cli.config.FileConfigHandler.setConfigFile;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CLIENT;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.checkAuthInfo;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.checkServerInfo;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.loadConfig;
-
/**
* @author Marko Strukelj
*/
-public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
+public abstract class AbstractAuthOptionsCmd extends BaseAuthOptionsCmd implements GlobalOptionsCmdHelper {
@Option(names = {"-a", "--admin-root"}, description = "URL of Admin REST endpoint root if not default - e.g. http://localhost:8080/admin")
String adminRestRoot;
- @Option(names = "--config", description = "Path to the config file (~/.keycloak/kcadm.config by default)")
- String config;
-
- @Option(names = "--no-config", description = "Don't use config file - no authentication info is loaded or saved")
- boolean noconfig;
-
- @Option(names = "--server", description = "Server endpoint url (e.g. 'http://localhost:8080')")
- String server;
-
@Option(names = {"-r", "--target-realm"}, description = "Realm to target - when it's different than the realm we authenticate against")
String targetRealm;
- @Option(names = "--realm", description = "Realm name to authenticate against")
- String realm;
-
- @Option(names = "--client", description = "Realm name to authenticate against")
- String clientId;
-
- @Option(names = "--user", description = "Username to login with")
- String user;
-
- @Option(names = "--password", description = "Password to login with (prompted for if not specified and --user is used)")
- String password;
-
- @Option(names = "--secret", description = "Secret to authenticate the client (prompted for if no --user or --keystore is specified)")
- String secret;
-
- @Option(names = "--keystore", description = "Path to a keystore containing private key")
- String keystore;
-
- @Option(names = "--storepass", description = "Keystore password (prompted for if not specified and --keystore is used)")
- String storePass;
-
- @Option(names = "--keypass", description = "Key password (prompted for if not specified and --keystore is used without --storepass, \n otherwise defaults to keystore password)")
- String keyPass;
-
- @Option(names = "--alias", description = "Alias of the key inside a keystore (defaults to the value of ClientId)")
- String alias;
-
- @Option(names = "--truststore", description = "Path to a truststore")
- String trustStore;
-
- @Option(names = "--trustpass", description = "Truststore password (prompted for if not specified and --truststore is used)")
- String trustPass;
-
- @Option(names = "--insecure", description = "Turns off TLS validation")
- boolean insecure;
-
@Option(names = "--token", description = "Token to use for invocations. With this option set, every other authentication option is ignored")
- String externalToken;
-
- protected void initFromParent(AbstractAuthOptionsCmd parent) {
- noconfig = parent.noconfig;
- config = parent.config;
- server = parent.server;
- realm = parent.realm;
- clientId = parent.clientId;
- user = parent.user;
- password = parent.password;
- secret = parent.secret;
- keystore = parent.keystore;
- storePass = parent.storePass;
- keyPass = parent.keyPass;
- alias = parent.alias;
- trustStore = parent.trustStore;
- trustPass = parent.trustPass;
- externalToken = parent.externalToken;
+ public void setToken(String token) {
+ this.externalToken = token;
}
- protected void applyDefaultOptionValues() {
- if (clientId == null) {
- clientId = DEFAULT_CLIENT;
- }
+ public AbstractAuthOptionsCmd() {
+ super(KcAdmMain.COMMAND_STATE);
}
- @Override
- protected boolean nothingToDo() {
- return externalToken == null && server == null && realm == null && clientId == null && secret == null &&
- user == null && password == null &&
- keystore == null && storePass == null && keyPass == null && alias == null &&
- trustStore == null && trustPass == null && config == null;
- }
-
-
protected String getTargetRealm(ConfigData config) {
return targetRealm != null ? targetRealm : config.getRealm();
}
- @Override
- protected void processOptions() {
- if (config != null && noconfig) {
- throw new IllegalArgumentException("Options --config and --no-config are mutually exclusive");
- }
-
- if (!noconfig) {
- setConfigFile(config != null ? config : ConfigUtil.DEFAULT_CONFIG_FILE_PATH);
- ConfigUtil.setHandler(new FileConfigHandler());
- } else {
- InMemoryConfigHandler handler = new InMemoryConfigHandler();
- ConfigData data = new ConfigData();
- initConfigData(data);
- handler.setConfigData(data);
- ConfigUtil.setHandler(handler);
- }
- }
-
- protected void setupTruststore(ConfigData configData) {
-
- if (!configData.getServerUrl().startsWith("https:")) {
- return;
- }
-
- String truststore = trustStore;
- if (truststore == null) {
- truststore = configData.getTruststore();
- }
-
- if (truststore != null) {
- String pass = trustPass;
- if (pass == null) {
- pass = configData.getTrustpass();
- }
- if (pass == null) {
- pass = IoUtil.readSecret("Enter truststore password: ");
- }
-
- try {
- HttpUtil.setTruststore(new File(truststore), pass);
- } catch (Exception e) {
- throw new RuntimeException("Failed to load truststore: " + truststore, e);
- }
- }
-
- if (insecure) {
- HttpUtil.setSkipCertificateValidation();
- }
- }
-
- protected ConfigData ensureAuthInfo(ConfigData config) {
-
- if (requiresLogin()) {
- // make sure current handler is in-memory handler
- // restore it at the end
- ConfigHandler old = ConfigUtil.getHandler();
- try {
- // make sure all defaults are initialized after this point
- applyDefaultOptionValues();
-
- initConfigData(config);
- ConfigUtil.setupInMemoryHandler(config);
-
- ConfigCredentialsCmd login = new ConfigCredentialsCmd();
- login.initFromParent(this);
- login.init(config);
- login.process();
-
- // this must be executed before finally block which restores config handler
- return loadConfig();
-
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new RuntimeException(e);
- } finally {
- ConfigUtil.setHandler(old);
- }
-
- } else {
- checkAuthInfo(config);
-
- // make sure all defaults are initialized after this point
- applyDefaultOptionValues();
- return loadConfig();
- }
- }
-
- protected boolean requiresLogin() {
- return externalToken == null && (user != null || password != null || secret != null || keystore != null
- || keyPass != null || storePass != null || alias != null);
- }
-
- protected ConfigData copyWithServerInfo(ConfigData config) {
-
- ConfigData result = config.deepcopy();
-
- if (server != null) {
- result.setServerUrl(server);
- }
- if (realm != null) {
- result.setRealm(realm);
- }
- if (externalToken != null) {
- result.setExternalToken(externalToken);
- }
-
- checkServerInfo(result);
- return result;
- }
-
- private void initConfigData(ConfigData data) {
- if (server != null)
- data.setServerUrl(server);
- if (realm != null)
- data.setRealm(realm);
- if (trustStore != null)
- data.setTruststore(trustStore);
- if (externalToken != null) {
- data.setExternalToken(externalToken);
- }
-
- RealmConfigData rdata = data.sessionRealmConfigData();
- if (clientId != null)
- rdata.setClientId(clientId);
- if (secret != null)
- rdata.setSecret(secret);
- String grantTypeForAuthentication = user == null ? OAuth2Constants.CLIENT_CREDENTIALS : OAuth2Constants.PASSWORD;
- rdata.setGrantTypeForAuthentication(grantTypeForAuthentication);
- }
-
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractGlobalOptionsCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractGlobalOptionsCmd.java
deleted file mode 100644
index 7190595021..0000000000
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractGlobalOptionsCmd.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.keycloak.client.admin.cli.commands;
-
-import org.keycloak.client.admin.cli.Globals;
-import org.keycloak.client.admin.cli.util.FilterUtil;
-import org.keycloak.client.admin.cli.util.ReturnFields;
-
-import java.io.IOException;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import picocli.CommandLine;
-import picocli.CommandLine.Option;
-
-import static org.keycloak.client.admin.cli.util.HttpUtil.normalize;
-import static org.keycloak.client.admin.cli.util.IoUtil.printOut;
-
-public abstract class AbstractGlobalOptionsCmd implements Runnable {
-
- @Option(names = "--help",
- description = "Print command specific help")
- public void setHelp(boolean help) {
- Globals.help = help;
- }
-
- @Option(names = "-x",
- description = "Print full stack trace when exiting with error")
- public void setDumpTrace(boolean dumpTrace) {
- Globals.dumpTrace = dumpTrace;
- }
-
- protected void printHelpIfNeeded() {
- if (Globals.help) {
- printOut(help());
- System.exit(CommandLine.ExitCode.OK);
- } else if (nothingToDo()) {
- printOut(help());
- System.exit(CommandLine.ExitCode.USAGE);
- }
- }
-
- protected boolean nothingToDo() {
- return false;
- }
-
- protected String help() {
- return KcAdmCmd.usage();
- }
-
- protected String composeAdminRoot(String server) {
- return normalize(server) + "admin";
- }
-
- protected String extractTypeNameFromUri(String resourceUrl) {
- String type = extractLastComponentOfUri(resourceUrl);
- if (type.endsWith("s")) {
- type = type.substring(0, type.length()-1);
- }
- return type;
- }
-
- protected String extractLastComponentOfUri(String resourceUrl) {
- int endPos = resourceUrl.endsWith("/") ? resourceUrl.length()-2 : resourceUrl.length()-1;
- int pos = resourceUrl.lastIndexOf("/", endPos);
- pos = pos == -1 ? 0 : pos;
- return resourceUrl.substring(pos+1, endPos+1);
- }
-
- protected JsonNode applyFieldFilter(ObjectMapper mapper, JsonNode rootNode, ReturnFields returnFields) {
- // construct new JsonNode that satisfies filtering specified by returnFields
- try {
- return FilterUtil.copyFilteredObject(rootNode, returnFields);
- } catch (IOException e) {
- throw new RuntimeException("Failed to apply fields filter", e);
- }
- }
-
- @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;
- }
-
-}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractRequestCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractRequestCmd.java
index 882a37b6ba..69e4cf9be0 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractRequestCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractRequestCmd.java
@@ -17,18 +17,18 @@
package org.keycloak.client.admin.cli.commands;
import org.apache.http.entity.ContentType;
-import org.keycloak.client.admin.cli.common.AttributeOperation;
-import org.keycloak.client.admin.cli.common.CmdStdinContext;
-import org.keycloak.client.admin.cli.config.ConfigData;
-import org.keycloak.client.admin.cli.util.AccessibleBufferOutputStream;
-import org.keycloak.client.admin.cli.util.Header;
-import org.keycloak.client.admin.cli.util.Headers;
-import org.keycloak.client.admin.cli.util.HeadersBody;
-import org.keycloak.client.admin.cli.util.HeadersBodyStatus;
-import org.keycloak.client.admin.cli.util.HttpUtil;
-import org.keycloak.client.admin.cli.util.OutputFormat;
-import org.keycloak.client.admin.cli.util.ReflectionUtil;
-import org.keycloak.client.admin.cli.util.ReturnFields;
+import org.keycloak.client.admin.cli.CmdStdinContext;
+import org.keycloak.client.admin.cli.ReflectionUtil;
+import org.keycloak.client.cli.common.AttributeOperation;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.util.AccessibleBufferOutputStream;
+import org.keycloak.client.cli.util.Header;
+import org.keycloak.client.cli.util.Headers;
+import org.keycloak.client.cli.util.HeadersBody;
+import org.keycloak.client.cli.util.HeadersBodyStatus;
+import org.keycloak.client.cli.util.HttpUtil;
+import org.keycloak.client.cli.util.OutputFormat;
+import org.keycloak.client.cli.util.ReturnFields;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
@@ -52,22 +52,19 @@ import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
-import static org.keycloak.client.admin.cli.common.AttributeOperation.Type.DELETE;
-import static org.keycloak.client.admin.cli.common.AttributeOperation.Type.SET;
-import static org.keycloak.client.admin.cli.util.AuthUtil.ensureToken;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.credentialsAvailable;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.loadConfig;
-import static org.keycloak.client.admin.cli.util.HttpUtil.checkSuccess;
-import static org.keycloak.client.admin.cli.util.HttpUtil.composeResourceUrl;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doGet;
-import static org.keycloak.client.admin.cli.util.IoUtil.copyStream;
-import static org.keycloak.client.admin.cli.util.IoUtil.printErr;
-import static org.keycloak.client.admin.cli.util.IoUtil.printOut;
-import static org.keycloak.client.admin.cli.util.OutputUtil.MAPPER;
-import static org.keycloak.client.admin.cli.util.OutputUtil.printAsCsv;
-import static org.keycloak.client.admin.cli.util.ParseUtil.mergeAttributes;
-import static org.keycloak.client.admin.cli.util.ParseUtil.parseFileOrStdin;
-import static org.keycloak.client.admin.cli.util.ParseUtil.parseKeyVal;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.DELETE;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.SET;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.HttpUtil.checkSuccess;
+import static org.keycloak.client.cli.util.HttpUtil.composeResourceUrl;
+import static org.keycloak.client.cli.util.HttpUtil.doGet;
+import static org.keycloak.client.cli.util.IoUtil.copyStream;
+import static org.keycloak.client.cli.util.IoUtil.printErr;
+import static org.keycloak.client.cli.util.IoUtil.printOut;
+import static org.keycloak.client.cli.util.OutputUtil.MAPPER;
+import static org.keycloak.client.cli.util.OutputUtil.printAsCsv;
+import static org.keycloak.client.cli.util.ParseUtil.parseKeyVal;
/**
* @author Marko Strukelj
@@ -208,7 +205,7 @@ public abstract class AbstractRequestCmd extends AbstractAuthOptionsCmd {
}
}
} else {
- ctx = parseFileOrStdin(file);
+ ctx = CmdStdinContext.parseFileOrStdin(file);
}
} else if (body != null) {
content = new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8));
@@ -280,7 +277,7 @@ public abstract class AbstractRequestCmd extends AbstractAuthOptionsCmd {
throw new RuntimeException("Can't set attributes on content of type other than application/json");
}
- ctx = mergeAttributes(ctx, MAPPER.createObjectNode(), attrs);
+ ctx = CmdStdinContext.mergeAttributes(ctx, MAPPER.createObjectNode(), attrs);
}
if (content == null && ctx.getContent() != null) {
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AddRolesCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AddRolesCmd.java
index a4ef642df3..9f4c8e3d95 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AddRolesCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AddRolesCmd.java
@@ -21,12 +21,13 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import org.keycloak.client.admin.cli.config.ConfigData;
+import org.keycloak.client.admin.cli.KcAdmMain;
import org.keycloak.client.admin.cli.operations.ClientOperations;
import org.keycloak.client.admin.cli.operations.GroupOperations;
import org.keycloak.client.admin.cli.operations.RoleOperations;
import org.keycloak.client.admin.cli.operations.LocalSearch;
import org.keycloak.client.admin.cli.operations.UserOperations;
+import org.keycloak.client.cli.config.ConfigData;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -35,12 +36,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import static org.keycloak.client.admin.cli.util.AuthUtil.ensureToken;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.credentialsAvailable;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.loadConfig;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
/**
* @author Marko Strukelj
@@ -290,7 +289,7 @@ public class AddRolesCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigCmd.java
index 9bc0c346e5..4479de9847 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigCmd.java
@@ -21,7 +21,7 @@ import java.io.StringWriter;
import picocli.CommandLine.Command;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
/**
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigCredentialsCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigCredentialsCmd.java
index f62b448c1c..a89a4f32ee 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigCredentialsCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigCredentialsCmd.java
@@ -16,237 +16,20 @@
*/
package org.keycloak.client.admin.cli.commands;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.client.admin.cli.config.ConfigData;
-import org.keycloak.client.admin.cli.config.RealmConfigData;
-import org.keycloak.client.admin.cli.util.AuthUtil;
-import org.keycloak.representations.AccessTokenResponse;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.net.URL;
+import org.keycloak.client.admin.cli.KcAdmMain;
+import org.keycloak.client.cli.common.BaseConfigCredentialsCmd;
import picocli.CommandLine.Command;
-import static org.keycloak.client.admin.cli.util.AuthUtil.getAuthTokens;
-import static org.keycloak.client.admin.cli.util.AuthUtil.getAuthTokensByJWT;
-import static org.keycloak.client.admin.cli.util.AuthUtil.getAuthTokensBySecret;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.getHandler;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.loadConfig;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.saveTokens;
-import static org.keycloak.client.admin.cli.util.IoUtil.printErr;
-import static org.keycloak.client.admin.cli.util.IoUtil.readSecret;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.OS_ARCH;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
-
/**
* @author Marko Strukelj
*/
@Command(name = "credentials", description = "--server SERVER_URL --realm REALM [ARGUMENTS]")
-public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd {
+public class ConfigCredentialsCmd extends BaseConfigCredentialsCmd {
- private int sigLifetime = 600;
-
- public void init(ConfigData configData) {
- if (server == null) {
- server = configData.getServerUrl();
- }
- if (realm == null) {
- realm = configData.getRealm();
- }
- if (trustStore == null) {
- trustStore = configData.getTruststore();
- }
-
- RealmConfigData rdata = configData.getRealmConfigData(server, realm);
- if (rdata == null) {
- return;
- }
-
- if (clientId == null) {
- clientId = rdata.getClientId();
- }
+ public ConfigCredentialsCmd() {
+ super(KcAdmMain.COMMAND_STATE);
}
- @Override
- protected String[] getUnsupportedOptions() {
- return new String[] {"--no-config", booleanOptionForCheck(noconfig)};
- }
-
- @Override
- public void process() {
- // check server
- if (server == null) {
- throw new IllegalArgumentException("Required option not specified: --server");
- }
-
- try {
- new URL(server);
- } catch (Exception e) {
- throw new RuntimeException("Invalid server endpoint url: " + server, e);
- }
-
- if (realm == null)
- throw new IllegalArgumentException("Required option not specified: --realm");
-
- String signedRequestToken = null;
- boolean clientSet = clientId != null;
-
- applyDefaultOptionValues();
- String grantTypeForAuthentication = null;
-
- if (user != null) {
- grantTypeForAuthentication = OAuth2Constants.PASSWORD;
- printErr("Logging into " + server + " as user " + user + " of realm " + realm);
-
- // if user was set there needs to be a password so we can authenticate
- if (password == null) {
- 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: ");
- }
- } 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: ");
- }
- }
- }
-
- if (keystore != null) {
- if (secret != null) {
- throw new IllegalArgumentException("Can't use both --keystore and --secret");
- }
-
- if (!new File(keystore).isFile()) {
- throw new RuntimeException("No such keystore file: " + keystore);
- }
-
- if (storePass == null) {
- storePass = readSecret("Enter keystore password: ");
- keyPass = readSecret("Enter key password: ");
- }
-
- if (keyPass == null) {
- keyPass = storePass;
- }
-
- if (alias == null) {
- alias = clientId;
- }
-
- String realmInfoUrl = server + "/realms/" + realm;
-
- signedRequestToken = AuthUtil.getSignedRequestToken(keystore, storePass, keyPass,
- alias, sigLifetime, clientId, realmInfoUrl);
- }
-
- // if only server and realm are set, just save config and be done
- if (user == null && secret == null && keystore == null) {
- getHandler().saveMergeConfig(config -> {
- config.setServerUrl(server);
- config.setRealm(realm);
- });
- return;
- }
-
- setupTruststore(copyWithServerInfo(loadConfig()));
-
- // now use the token endpoint to retrieve access token, and refresh token
- AccessTokenResponse tokens = signedRequestToken != null ?
- getAuthTokensByJWT(server, realm, user, password, clientId, signedRequestToken) :
- secret != null ?
- getAuthTokensBySecret(server, realm, user, password, clientId, secret) :
- getAuthTokens(server, realm, user, password, clientId);
-
- Long sigExpiresAt = signedRequestToken == null ? null : System.currentTimeMillis() + sigLifetime * 1000;
-
- // save tokens to config file
- saveTokens(tokens, server, realm, clientId, signedRequestToken, sigExpiresAt, secret, grantTypeForAuthentication);
- }
-
- @Override
- protected String help() {
- return usage();
- }
-
- public static String usage() {
- StringWriter sb = new StringWriter();
- PrintWriter out = new PrintWriter(sb);
- out.println("Usage: " + CMD + " config credentials --server SERVER_URL --realm REALM --user USER [--password PASSWORD] [ARGUMENTS]");
- out.println(" " + CMD + " config credentials --server SERVER_URL --realm REALM --client CLIENT_ID [--secret SECRET] [ARGUMENTS]");
- out.println(" " + CMD + " config credentials --server SERVER_URL --realm REALM --client CLIENT_ID [--keystore KEYSTORE] [ARGUMENTS]");
- out.println();
- out.println("Command to establish an authenticated client session with the server. There are many authentication");
- out.println("options available, and it depends on server side client authentication configuration how client can or should authenticate.");
- out.println("The information always required includes --server, and --realm. Then, --user and / or --client need to be used to authenticate.");
- out.println("If --client is not provided it defaults to 'admin-cli'. The authentication options / requirements depend on how this client is configured.");
- out.println();
- out.println("If confidential client authentication is also configured, you may have to specify a client id, and client credentials in addition to");
- out.println("user credentials. Client credentials are either a client secret, or a keystore information to use Signed JWT mechanism.");
- out.println("If only client credentials are provided, and no user credentials, then the service account is used for login.");
- out.println();
- out.println("Arguments:");
- out.println();
- out.println(" Global options:");
- out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to a config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
- out.println(" --truststore PATH Path to a truststore containing trusted certificates");
- out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
- out.println();
- out.println(" Command specific options:");
- out.println(" --server SERVER_URL Server endpoint url (e.g. 'http://localhost:8080')");
- out.println(" --realm REALM Realm name to use");
- out.println(" --user USER Username to login with");
- out.println(" --password PASSWORD Password to login with (prompted for if not specified and --user is used)");
- out.println(" --client CLIENT_ID ClientId used by this client tool ('admin-cli' by default)");
- out.println(" --secret SECRET Secret to authenticate the client (prompted for if --client is specified, and no --keystore is specified)");
- out.println(" --keystore PATH Path to a keystore containing private key");
- out.println(" --storepass PASSWORD Keystore password (prompted for if not specified and --keystore is used)");
- out.println(" --keypass PASSWORD Key password (prompted for if not specified and --keystore is used without --storepass,");
- out.println(" otherwise defaults to keystore password)");
- out.println(" --alias ALIAS Alias of the key inside a keystore (defaults to the value of ClientId)");
- out.println();
- out.println();
- out.println("Examples:");
- out.println();
- out.println("Login as 'admin' user of 'master' realm to a local Keycloak server running on default port.");
- out.println("You will be prompted for a password:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:8080 --realm master --user admin");
- out.println();
- out.println("Login to Keycloak server at non-default endpoint passing the password via standard input:");
- if (OS_ARCH.isWindows()) {
- out.println(" " + PROMPT + " echo mypassword | " + CMD + " config credentials --server http://localhost:9080 --realm master --user admin");
- } else {
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --user admin << EOF");
- out.println(" mypassword");
- out.println(" EOF");
- }
- out.println();
- out.println("Login specifying a password through command line:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --user admin --password " + OS_ARCH.envVar("PASSWORD"));
- out.println();
- out.println("Login using a client service account of a custom client. You will be prompted for a client secret:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --client reg-cli");
- out.println();
- out.println("Login using a client service account of a custom client, authenticating with signed JWT.");
- out.println("You will be prompted for a keystore password, and a key password:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --client reg-cli --keystore " + OS_ARCH.path("~/.keycloak/keystore.jks"));
- out.println();
- out.println("Login as 'user' while also authenticating a custom client with signed JWT.");
- out.println("You will be prompted for a user password, a keystore password, and a key password:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --user user --client reg-cli --keystore " + OS_ARCH.path("~/.keycloak/keystore.jks"));
- out.println();
- out.println();
- out.println("Use '" + CMD + " help' for general information and a list of commands");
- return sb.toString();
- }
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigTruststoreCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigTruststoreCmd.java
index 2b86df05f6..36abec0ad9 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigTruststoreCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/ConfigTruststoreCmd.java
@@ -16,126 +16,19 @@
*/
package org.keycloak.client.admin.cli.commands;
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import org.keycloak.client.admin.cli.KcAdmMain;
+import org.keycloak.client.cli.common.BaseConfigTruststoreCmd;
import picocli.CommandLine.Command;
-import picocli.CommandLine.Option;
-import picocli.CommandLine.Parameters;
-
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.saveMergeConfig;
-import static org.keycloak.client.admin.cli.util.IoUtil.readSecret;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.OS_ARCH;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
/**
* @author Marko Strukelj
*/
@Command(name = "truststore", description = "PATH [ARGUMENTS]")
-public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd {
+public class ConfigTruststoreCmd extends BaseConfigTruststoreCmd {
- @Parameters(arity = "0..1")
- private String store;
-
- @Option(names = {"-d", "--delete"}, description = "Remove truststore configuration")
- private boolean delete;
-
- @Override
- protected boolean nothingToDo() {
- return super.nothingToDo() && store == null && !delete;
+ public ConfigTruststoreCmd() {
+ super(KcAdmMain.COMMAND_STATE);
}
- @Override
- protected String[] getUnsupportedOptions() {
- return new String[] {"--server", server,
- "--realm", realm,
- "--client", clientId,
- "--user", user,
- "--password", password,
- "--secret", secret,
- "--truststore", trustStore,
- "--keystore", keystore,
- "--keypass", keyPass,
- "--alias", alias,
- "--no-config", booleanOptionForCheck(noconfig)};
- }
-
- @Override
- protected void process() {
- String pass;
-
- if (!delete) {
-
- if (store == null) {
- throw new IllegalArgumentException("No truststore specified");
- }
-
- if (!new File(store).isFile()) {
- throw new RuntimeException("Truststore file not found: " + store);
- }
-
- if ("-".equals(trustPass)) {
- trustPass = readSecret("Enter truststore password: ");
- }
-
- pass = trustPass;
-
- } else {
- if (store != null) {
- throw new IllegalArgumentException("Option --delete is mutually exclusive with specifying a TRUSTSTORE");
- }
- if (trustPass != null) {
- throw new IllegalArgumentException("Options --trustpass and --delete are mutually exclusive");
- }
- pass = null;
- }
-
- saveMergeConfig(config -> {
- config.setTruststore(store);
- config.setTrustpass(pass);
- });
- }
-
- @Override
- protected String help() {
- return usage();
- }
-
- public static String usage() {
- StringWriter sb = new StringWriter();
- PrintWriter out = new PrintWriter(sb);
- out.println("Usage: " + CMD + " config truststore [TRUSTSTORE | --delete] [--trustpass PASSWORD] [ARGUMENTS]");
- out.println();
- out.println("Command to configure a global truststore to use when using https to connect to Keycloak server.");
- out.println();
- out.println("Arguments:");
- out.println();
- out.println(" Global options:");
- out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
- out.println();
- out.println(" Command specific options:");
- out.println(" TRUSTSTORE Path to truststore file");
- out.println(" --trustpass PASSWORD Truststore password to unlock truststore (prompted for if set to '-')");
- out.println(" -d, --delete Remove truststore configuration");
- out.println();
- out.println();
- out.println("Examples:");
- out.println();
- out.println("Specify a truststore - you will be prompted for truststore password every time it is used:");
- out.println(" " + PROMPT + " " + CMD + " config truststore " + OS_ARCH.path("~/.keycloak/truststore.jks"));
- out.println();
- out.println("Specify a truststore, and password - truststore will automatically be used without prompting for password:");
- out.println(" " + PROMPT + " " + CMD + " config truststore --trustpass " + OS_ARCH.envVar("PASSWORD") + " " + OS_ARCH.path("~/.keycloak/truststore.jks"));
- out.println();
- out.println("Remove truststore configuration:");
- out.println(" " + PROMPT + " " + CMD + " config truststore --delete");
- out.println();
- out.println();
- out.println("Use '" + CMD + " help' for general information and a list of commands");
- return sb.toString();
- }
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/CreateCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/CreateCmd.java
index a74ea74463..3240589186 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/CreateCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/CreateCmd.java
@@ -16,16 +16,17 @@
*/
package org.keycloak.client.admin.cli.commands;
+import org.keycloak.client.admin.cli.KcAdmMain;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.OS_ARCH;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.OsUtil.OS_ARCH;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
/**
* @author Marko Strukelj
@@ -91,7 +92,7 @@ public class CreateCmd extends AbstractRequestCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/DeleteCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/DeleteCmd.java
index a8ba2c27fc..829cfd9301 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/DeleteCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/DeleteCmd.java
@@ -16,14 +16,15 @@
*/
package org.keycloak.client.admin.cli.commands;
+import org.keycloak.client.admin.cli.KcAdmMain;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import picocli.CommandLine.Command;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
/**
@@ -55,7 +56,7 @@ public class DeleteCmd extends CreateCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GetCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GetCmd.java
index 367fb2cdd8..17ddb090b5 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GetCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GetCmd.java
@@ -16,15 +16,16 @@
*/
package org.keycloak.client.admin.cli.commands;
+import org.keycloak.client.admin.cli.KcAdmMain;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
/**
* @author Marko Strukelj
@@ -91,7 +92,7 @@ public class GetCmd extends AbstractRequestCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GetRolesCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GetRolesCmd.java
index 92088fa9b2..3568d45869 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GetRolesCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GetRolesCmd.java
@@ -16,11 +16,12 @@
*/
package org.keycloak.client.admin.cli.commands;
-import org.keycloak.client.admin.cli.config.ConfigData;
+import org.keycloak.client.admin.cli.KcAdmMain;
import org.keycloak.client.admin.cli.operations.ClientOperations;
import org.keycloak.client.admin.cli.operations.GroupOperations;
import org.keycloak.client.admin.cli.operations.RoleOperations;
import org.keycloak.client.admin.cli.operations.UserOperations;
+import org.keycloak.client.cli.config.ConfigData;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -28,13 +29,11 @@ import java.io.StringWriter;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import static org.keycloak.client.admin.cli.util.AuthUtil.ensureToken;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.credentialsAvailable;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.loadConfig;
-import static org.keycloak.client.admin.cli.util.HttpUtil.composeResourceUrl;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.HttpUtil.composeResourceUrl;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
/**
* @author Marko Strukelj
@@ -325,7 +324,7 @@ public class GetRolesCmd extends GetCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GlobalOptionsCmdHelper.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GlobalOptionsCmdHelper.java
new file mode 100644
index 0000000000..9ee04b41c3
--- /dev/null
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/GlobalOptionsCmdHelper.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.client.admin.cli.commands;
+
+import org.keycloak.client.cli.util.FilterUtil;
+import org.keycloak.client.cli.util.ReturnFields;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import static org.keycloak.client.cli.util.HttpUtil.normalize;
+
+public interface GlobalOptionsCmdHelper {
+
+ default String composeAdminRoot(String server) {
+ return normalize(server) + "admin";
+ }
+
+ default String extractTypeNameFromUri(String resourceUrl) {
+ String type = extractLastComponentOfUri(resourceUrl);
+ if (type.endsWith("s")) {
+ type = type.substring(0, type.length()-1);
+ }
+ return type;
+ }
+
+ default String extractLastComponentOfUri(String resourceUrl) {
+ int endPos = resourceUrl.endsWith("/") ? resourceUrl.length()-2 : resourceUrl.length()-1;
+ int pos = resourceUrl.lastIndexOf("/", endPos);
+ pos = pos == -1 ? 0 : pos;
+ return resourceUrl.substring(pos+1, endPos+1);
+ }
+
+ default JsonNode applyFieldFilter(ObjectMapper mapper, JsonNode rootNode, ReturnFields returnFields) {
+ // construct new JsonNode that satisfies filtering specified by returnFields
+ try {
+ return FilterUtil.copyFilteredObject(rootNode, returnFields);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to apply fields filter", e);
+ }
+ }
+
+}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/HelpCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/HelpCmd.java
index ff675ab4e2..3a3ca05a1e 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/HelpCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/HelpCmd.java
@@ -21,7 +21,7 @@ import java.util.List;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
-import static org.keycloak.client.admin.cli.util.IoUtil.printOut;
+import static org.keycloak.client.cli.util.IoUtil.printOut;
@Command(name = "help", description = "This Help")
public class HelpCmd implements Runnable {
@@ -39,11 +39,11 @@ public class HelpCmd implements Runnable {
if (args.size() > 1) {
switch (args.get(1)) {
case "credentials": {
- printOut(ConfigCredentialsCmd.usage());
+ printOut(new ConfigCredentialsCmd().help());
break outer;
}
case "truststore": {
- printOut(ConfigTruststoreCmd.usage());
+ printOut(new ConfigTruststoreCmd().help());
break outer;
}
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/KcAdmCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/KcAdmCmd.java
index 904c4e9209..3e3cdcfc29 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/KcAdmCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/KcAdmCmd.java
@@ -16,14 +16,16 @@
*/
package org.keycloak.client.admin.cli.commands;
+import org.keycloak.client.admin.cli.KcAdmMain;
+import org.keycloak.client.cli.common.BaseGlobalOptionsCmd;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import picocli.CommandLine.Command;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
@Command(name = "kcadm",
header = {
@@ -47,13 +49,18 @@ subcommands = {
GetRolesCmd.class,
SetPasswordCmd.class
})
-public class KcAdmCmd extends AbstractGlobalOptionsCmd {
+public class KcAdmCmd extends BaseGlobalOptionsCmd {
@Override
protected boolean nothingToDo() {
return true;
}
+ @Override
+ protected String help() {
+ return usage();
+ }
+
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
@@ -76,7 +83,7 @@ public class KcAdmCmd extends AbstractGlobalOptionsCmd {
out.println("Global options:");
out.println(" -x Print full stack trace when exiting with error");
out.println(" --help Print help for specific command");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println();
out.println("Commands: ");
out.println(" config Set up credentials, and other configuration settings using the config file");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/NewObjectCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/NewObjectCmd.java
index 47bc1e884e..2ca8f0d040 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/NewObjectCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/NewObjectCmd.java
@@ -21,9 +21,10 @@ import com.fasterxml.jackson.databind.JsonNode;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import org.keycloak.client.admin.cli.common.AttributeOperation;
-import org.keycloak.client.admin.cli.common.CmdStdinContext;
-import org.keycloak.client.admin.cli.util.AccessibleBufferOutputStream;
+import org.keycloak.client.admin.cli.CmdStdinContext;
+import org.keycloak.client.cli.common.AttributeOperation;
+import org.keycloak.client.cli.common.BaseGlobalOptionsCmd;
+import org.keycloak.client.cli.util.AccessibleBufferOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -35,22 +36,20 @@ import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
-import static org.keycloak.client.admin.cli.common.AttributeOperation.Type.SET;
-import static org.keycloak.client.admin.cli.util.IoUtil.copyStream;
-import static org.keycloak.client.admin.cli.util.IoUtil.printErr;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.OS_ARCH;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
-import static org.keycloak.client.admin.cli.util.OutputUtil.MAPPER;
-import static org.keycloak.client.admin.cli.util.ParseUtil.mergeAttributes;
-import static org.keycloak.client.admin.cli.util.ParseUtil.parseFileOrStdin;
-import static org.keycloak.client.admin.cli.util.ParseUtil.parseKeyVal;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.SET;
+import static org.keycloak.client.cli.util.IoUtil.copyStream;
+import static org.keycloak.client.cli.util.IoUtil.printErr;
+import static org.keycloak.client.cli.util.OsUtil.OS_ARCH;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.cli.util.OutputUtil.MAPPER;
+import static org.keycloak.client.cli.util.ParseUtil.parseKeyVal;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
/**
* @author Marko Strukelj
*/
@Command(name = "new-object", description = "Command to create new JSON objects locally")
-public class NewObjectCmd extends AbstractGlobalOptionsCmd {
+public class NewObjectCmd extends BaseGlobalOptionsCmd implements GlobalOptionsCmdHelper {
@Option(names = {"-f", "--file"}, description = "Read object from file or standard input if FILENAME is set to '-'")
String file;
@@ -73,11 +72,11 @@ public class NewObjectCmd extends AbstractGlobalOptionsCmd {
CmdStdinContext ctx = new CmdStdinContext<>();
if (file != null) {
- ctx = parseFileOrStdin(file);
+ ctx = CmdStdinContext.parseFileOrStdin(file);
}
if (attrs.size() > 0) {
- ctx = mergeAttributes(ctx, MAPPER.createObjectNode(), attrs);
+ ctx = CmdStdinContext.mergeAttributes(ctx, MAPPER.createObjectNode(), attrs);
}
if (body == null && ctx.getContent() != null) {
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/RemoveRolesCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/RemoveRolesCmd.java
index 959833f8a0..b07b5de404 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/RemoveRolesCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/RemoveRolesCmd.java
@@ -16,12 +16,13 @@
*/
package org.keycloak.client.admin.cli.commands;
-import org.keycloak.client.admin.cli.config.ConfigData;
+import org.keycloak.client.admin.cli.KcAdmMain;
import org.keycloak.client.admin.cli.operations.ClientOperations;
import org.keycloak.client.admin.cli.operations.GroupOperations;
import org.keycloak.client.admin.cli.operations.LocalSearch;
import org.keycloak.client.admin.cli.operations.RoleOperations;
import org.keycloak.client.admin.cli.operations.UserOperations;
+import org.keycloak.client.cli.config.ConfigData;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -35,12 +36,10 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import static org.keycloak.client.admin.cli.util.AuthUtil.ensureToken;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.credentialsAvailable;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.loadConfig;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
/**
* @author Marko Strukelj
@@ -297,7 +296,7 @@ public class RemoveRolesCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/SetPasswordCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/SetPasswordCmd.java
index 038b305f9f..baa99fc828 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/SetPasswordCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/SetPasswordCmd.java
@@ -16,7 +16,8 @@
*/
package org.keycloak.client.admin.cli.commands;
-import org.keycloak.client.admin.cli.config.ConfigData;
+import org.keycloak.client.admin.cli.KcAdmMain;
+import org.keycloak.client.cli.config.ConfigData;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -26,13 +27,11 @@ import picocli.CommandLine.Option;
import static org.keycloak.client.admin.cli.operations.UserOperations.getIdFromUsername;
import static org.keycloak.client.admin.cli.operations.UserOperations.resetUserPassword;
-import static org.keycloak.client.admin.cli.util.AuthUtil.ensureToken;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.credentialsAvailable;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.loadConfig;
-import static org.keycloak.client.admin.cli.util.IoUtil.readSecret;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.IoUtil.readSecret;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
/**
* @author Marko Strukelj
@@ -117,7 +116,7 @@ public class SetPasswordCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/UpdateCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/UpdateCmd.java
index c503ab9b21..11ccc18693 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/UpdateCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/UpdateCmd.java
@@ -17,16 +17,17 @@
package org.keycloak.client.admin.cli.commands;
+import org.keycloak.client.admin.cli.KcAdmMain;
+
import java.io.PrintWriter;
import java.io.StringWriter;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.OS_ARCH;
-import static org.keycloak.client.admin.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.OsUtil.OS_ARCH;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
/**
* @author Marko Strukelj
@@ -97,7 +98,7 @@ public class UpdateCmd extends AbstractRequestCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcAdmMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --token Token to use to invoke on Keycloak. Other credential may be ignored if this flag is set.");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/RealmConfigData.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/RealmConfigData.java
deleted file mode 100644
index ac6fe64527..0000000000
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/RealmConfigData.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.keycloak.client.admin.cli.config;
-
-import org.keycloak.util.JsonSerialization;
-
-import java.io.IOException;
-
-/**
- * @author Marko Strukelj
- */
-public class RealmConfigData {
-
- private String serverUrl;
-
- private String realm;
-
- private String clientId;
-
- private String token;
-
- private String refreshToken;
-
- private String signingToken;
-
- private String secret;
-
- private String grantTypeForAuthentication;
-
- private Long expiresAt;
-
- private Long refreshExpiresAt;
-
- private Long sigExpiresAt;
-
-
- public String serverUrl() {
- return serverUrl;
- }
-
- public void serverUrl(String serverUrl) {
- this.serverUrl = serverUrl;
- }
-
- public String realm() {
- return realm;
- }
-
- public void realm(String realm) {
- this.realm = realm;
- }
-
- public String getClientId() {
- return clientId;
- }
-
- public void setClientId(String clientId) {
- this.clientId = clientId;
- }
-
- public String getToken() {
- return token;
- }
-
- public void setToken(String token) {
- this.token = token;
- }
-
- public String getRefreshToken() {
- return refreshToken;
- }
-
- public void setRefreshToken(String refreshToken) {
- this.refreshToken = refreshToken;
- }
-
- public String getSigningToken() {
- return signingToken;
- }
-
- public void setSigningToken(String signingToken) {
- this.signingToken = signingToken;
- }
-
- public String getSecret() {
- return secret;
- }
-
- public void setSecret(String secret) {
- this.secret = secret;
- }
-
- public String getGrantTypeForAuthentication() {
- return grantTypeForAuthentication;
- }
-
- public void setGrantTypeForAuthentication(String grantTypeForAuthentication) {
- this.grantTypeForAuthentication = grantTypeForAuthentication;
- }
-
- public Long getExpiresAt() {
- return expiresAt;
- }
-
- public void setExpiresAt(Long expiresAt) {
- this.expiresAt = expiresAt;
- }
-
- public Long getRefreshExpiresAt() {
- return refreshExpiresAt;
- }
-
- public void setRefreshExpiresAt(Long refreshExpiresAt) {
- this.refreshExpiresAt = refreshExpiresAt;
- }
-
- public Long getSigExpiresAt() {
- return sigExpiresAt;
- }
-
- public void setSigExpiresAt(Long sigExpiresAt) {
- this.sigExpiresAt = sigExpiresAt;
- }
-
- public void merge(RealmConfigData source) {
- serverUrl = source.serverUrl;
- realm = source.realm;
- clientId = source.clientId;
- token = source.token;
- refreshToken = source.refreshToken;
- signingToken = source.signingToken;
- secret = source.secret;
- grantTypeForAuthentication = source.grantTypeForAuthentication;
- expiresAt = source.expiresAt;
- refreshExpiresAt = source.refreshExpiresAt;
- sigExpiresAt = source.sigExpiresAt;
- }
-
- public void mergeRefreshTokens(RealmConfigData source) {
- token = source.token;
- refreshToken = source.refreshToken;
- expiresAt = source.expiresAt;
- refreshExpiresAt = source.refreshExpiresAt;
- }
-
- @Override
- public String toString() {
- try {
- return JsonSerialization.writeValueAsPrettyString(this);
- } catch (IOException e) {
- return super.toString() + " - Error: " + e.toString();
- }
- }
-
- public RealmConfigData deepcopy() {
- RealmConfigData data = new RealmConfigData();
- data.serverUrl = serverUrl;
- data.realm = realm;
- data.clientId = clientId;
- data.token = token;
- data.refreshToken = refreshToken;
- data.signingToken = signingToken;
- data.secret = secret;
- data.grantTypeForAuthentication = grantTypeForAuthentication;
- data.expiresAt = expiresAt;
- data.refreshExpiresAt = refreshExpiresAt;
- data.sigExpiresAt = sigExpiresAt;
- return data;
- }
-}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/ClientOperations.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/ClientOperations.java
index 7106668241..4ffba3709b 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/ClientOperations.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/ClientOperations.java
@@ -16,14 +16,12 @@
*/
package org.keycloak.client.admin.cli.operations;
-import static org.keycloak.client.admin.cli.util.HttpUtil.getIdForType;
-
/**
* @author Marko Strukelj
*/
public class ClientOperations {
public static String getIdFromClientId(String rootUrl, String realm, String auth, String clientId) {
- return getIdForType(rootUrl, realm, auth, "clients", "clientId", clientId, "clientId");
+ return OperationUtils.getIdForType(rootUrl, realm, auth, "clients", "clientId", clientId, "clientId");
}
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/GroupOperations.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/GroupOperations.java
index 144dd0b9a4..1235230949 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/GroupOperations.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/GroupOperations.java
@@ -18,10 +18,9 @@ package org.keycloak.client.admin.cli.operations;
import java.util.List;
-import static org.keycloak.client.admin.cli.util.HttpUtil.composeResourceUrl;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doDeleteJSON;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doPostJSON;
-import static org.keycloak.client.admin.cli.util.HttpUtil.getIdForType;
+import static org.keycloak.client.cli.util.HttpUtil.composeResourceUrl;
+import static org.keycloak.client.cli.util.HttpUtil.doDeleteJSON;
+import static org.keycloak.client.cli.util.HttpUtil.doPostJSON;
/**
* @author Marko Strukelj
@@ -29,11 +28,11 @@ import static org.keycloak.client.admin.cli.util.HttpUtil.getIdForType;
public class GroupOperations {
public static String getIdFromName(String rootUrl, String realm, String auth, String groupname) {
- return getIdForType(rootUrl, realm, auth, "groups", "search", groupname, "name", () -> new String[] { "exact", "true" });
+ return OperationUtils.getIdForType(rootUrl, realm, auth, "groups", "search", groupname, "name", () -> new String[] { "exact", "true" });
}
public static String getIdFromPath(String rootUrl, String realm, String auth, String path) {
- return getIdForType(rootUrl, realm, auth, "groups", "path", path, "path");
+ return OperationUtils.getIdForType(rootUrl, realm, auth, "groups", "path", path, "path");
}
public static void addRealmRoles(String rootUrl, String realm, String auth, String groupid, List> roles) {
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/OperationUtils.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/OperationUtils.java
new file mode 100644
index 0000000000..15245c565b
--- /dev/null
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/OperationUtils.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2024 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.keycloak.client.admin.cli.operations;
+
+import org.keycloak.client.cli.util.HttpUtil;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.keycloak.common.util.ObjectUtil.capitalize;
+
+public class OperationUtils {
+
+ private static final String[] DEFAULT_QUERY_PARAMS = { "first", "0", "max", "2" };
+
+ public static String getIdForType(String rootUrl, String realm, String auth, String resourceEndpoint, String attrName, String attrValue, String inputAttrName) {
+
+ return getAttrForType(rootUrl, realm, auth, resourceEndpoint, attrName, attrValue, inputAttrName, "id", null);
+ }
+
+ public static String getIdForType(String rootUrl, String realm, String auth, String resourceEndpoint, String attrName, String attrValue, String inputAttrName, Supplier endpointParams) {
+ return getAttrForType(rootUrl, realm, auth, resourceEndpoint, attrName, attrValue, inputAttrName, "id", endpointParams);
+ }
+
+ public static String getAttrForType(String rootUrl, String realm, String auth, String resourceEndpoint, String attrName, String attrValue, String inputAttrName, String returnAttrName) {
+ return getAttrForType(rootUrl, realm, auth, resourceEndpoint, attrName, attrValue, inputAttrName, returnAttrName, null);
+ }
+
+ public static String getAttrForType(String rootUrl, String realm, String auth, String resourceEndpoint, String attrName, String attrValue, String inputAttrName, String returnAttrName, Supplier endpointParams) {
+ String resourceUrl = HttpUtil.composeResourceUrl(rootUrl, realm, resourceEndpoint);
+ String[] defaultParams;
+
+ if (endpointParams == null) {
+ defaultParams = DEFAULT_QUERY_PARAMS;
+ } else {
+ defaultParams = endpointParams.get();
+ }
+
+ resourceUrl = HttpUtil.addQueryParamsToUri(resourceUrl, attrName, attrValue);
+ resourceUrl = HttpUtil.addQueryParamsToUri(resourceUrl, defaultParams);
+
+ List results = HttpUtil.doGetJSON(RoleOperations.LIST_OF_NODES.class, resourceUrl, auth);
+
+ ObjectNode match;
+ try {
+ match = new LocalSearch(results).exactMatchOne(attrValue, inputAttrName);
+ } catch (Exception e) {
+ throw new RuntimeException("Multiple " + resourceEndpoint + " found for " + inputAttrName + ": " + attrValue, e);
+ }
+
+ String typeName = HttpUtil.singularize(resourceEndpoint);
+ if (match == null) {
+ if (results.size() > 1) {
+ throw new RuntimeException("Some matches, but not an exact match, found for " + capitalize(typeName) + " with " + inputAttrName + ": " + attrValue + ". Try using a more unique search, such as an id.");
+ }
+ throw new RuntimeException(capitalize(typeName) + " not found for " + inputAttrName + ": " + attrValue);
+ }
+
+ JsonNode attr = match.get(returnAttrName);
+ if (attr == null) {
+ throw new RuntimeException("Returned " + typeName + " info has no '" + returnAttrName + "' attribute");
+ }
+ return attr.asText();
+ }
+
+}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/RoleOperations.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/RoleOperations.java
index 3dbbcf7bad..c49e361e29 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/RoleOperations.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/RoleOperations.java
@@ -17,18 +17,17 @@
package org.keycloak.client.admin.cli.operations;
import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.keycloak.client.cli.util.HttpUtil.composeResourceUrl;
+import static org.keycloak.client.cli.util.HttpUtil.doDeleteJSON;
+import static org.keycloak.client.cli.util.HttpUtil.doGetJSON;
+import static org.keycloak.client.cli.util.HttpUtil.doPostJSON;
+
import org.keycloak.representations.idm.RoleRepresentation;
import java.util.ArrayList;
import java.util.List;
-import static org.keycloak.client.admin.cli.util.HttpUtil.composeResourceUrl;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doDeleteJSON;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doGetJSON;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doPostJSON;
-import static org.keycloak.client.admin.cli.util.HttpUtil.getAttrForType;
-import static org.keycloak.client.admin.cli.util.HttpUtil.getIdForType;
-
/**
* @author Marko Strukelj
*/
@@ -38,7 +37,7 @@ public class RoleOperations {
public static class LIST_OF_NODES extends ArrayList{};
public static String getIdFromRoleName(String adminRoot, String realm, String auth, String rname) {
- return getIdForType(adminRoot, realm, auth, "roles", "search", rname, "name");
+ return OperationUtils.getIdForType(adminRoot, realm, auth, "roles", "search", rname, "name");
}
public static void addRealmRoles(String rootUrl, String realm, String auth, String roleid, List> roles) {
@@ -60,11 +59,11 @@ public class RoleOperations {
}
public static String getRoleNameFromId(String adminRoot, String realm, String auth, String rid) {
- return getAttrForType(adminRoot, realm, auth, "roles", "id", rid, "id","name");
+ return OperationUtils.getAttrForType(adminRoot, realm, auth, "roles", "id", rid, "id","name");
}
public static String getClientRoleNameFromId(String adminRoot, String realm, String auth, String cid, String rid) {
- return getAttrForType(adminRoot, realm, auth, "clients/" + cid + "/roles", "id", rid, "id", "name");
+ return OperationUtils.getAttrForType(adminRoot, realm, auth, "clients/" + cid + "/roles", "id", rid, "id", "name");
}
public static List getRealmRoles(String rootUrl, String realm, String auth) {
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/UserOperations.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/UserOperations.java
index a0d3f6c2c3..1e9c8fbd07 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/UserOperations.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/operations/UserOperations.java
@@ -16,10 +16,10 @@
*/
package org.keycloak.client.admin.cli.operations;
-import org.keycloak.client.admin.cli.util.Headers;
-import org.keycloak.client.admin.cli.util.HeadersBody;
-import org.keycloak.client.admin.cli.util.HeadersBodyStatus;
-import org.keycloak.client.admin.cli.util.HttpUtil;
+import org.keycloak.client.cli.util.Headers;
+import org.keycloak.client.cli.util.HeadersBody;
+import org.keycloak.client.cli.util.HeadersBodyStatus;
+import org.keycloak.client.cli.util.HttpUtil;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.util.JsonSerialization;
@@ -27,10 +27,9 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
-import static org.keycloak.client.admin.cli.util.HttpUtil.composeResourceUrl;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doDeleteJSON;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doPostJSON;
-import static org.keycloak.client.admin.cli.util.HttpUtil.getIdForType;
+import static org.keycloak.client.cli.util.HttpUtil.composeResourceUrl;
+import static org.keycloak.client.cli.util.HttpUtil.doDeleteJSON;
+import static org.keycloak.client.cli.util.HttpUtil.doPostJSON;
/**
* @author Marko Strukelj
@@ -91,7 +90,7 @@ public class UserOperations {
}
public static String getIdFromUsername(String rootUrl, String realm, String auth, String username) {
- return getIdForType(rootUrl, realm, auth, "users", "username", username, "username",
+ return OperationUtils.getIdForType(rootUrl, realm, auth, "users", "username", username, "username",
() -> new String[] {"exact", "true"});
}
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/AttributeKey.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/AttributeKey.java
similarity index 99%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/AttributeKey.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/AttributeKey.java
index 7cb0dc885f..51f394f3bf 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/AttributeKey.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/AttributeKey.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.common;
+package org.keycloak.client.cli.common;
import java.util.Collections;
import java.util.LinkedList;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/AttributeOperation.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/AttributeOperation.java
similarity index 97%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/AttributeOperation.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/AttributeOperation.java
index 4db483e81f..bd0db9cf4e 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/AttributeOperation.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/AttributeOperation.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.common;
+package org.keycloak.client.cli.common;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseAuthOptionsCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseAuthOptionsCmd.java
new file mode 100644
index 0000000000..6393e3bacf
--- /dev/null
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseAuthOptionsCmd.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.client.cli.common;
+
+import org.keycloak.OAuth2Constants;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.ConfigHandler;
+import org.keycloak.client.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.InMemoryConfigHandler;
+import org.keycloak.client.cli.config.RealmConfigData;
+import org.keycloak.client.cli.util.AuthUtil;
+import org.keycloak.client.cli.util.ConfigUtil;
+import org.keycloak.client.cli.util.HttpUtil;
+import org.keycloak.client.cli.util.IoUtil;
+
+import java.io.File;
+
+import picocli.CommandLine.Option;
+
+import static org.keycloak.client.cli.config.FileConfigHandler.setConfigFile;
+import static org.keycloak.client.cli.util.ConfigUtil.DEFAULT_CLIENT;
+import static org.keycloak.client.cli.util.ConfigUtil.checkServerInfo;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+
+
+/**
+ * @author Marko Strukelj
+ */
+public abstract class BaseAuthOptionsCmd extends BaseGlobalOptionsCmd {
+
+ public static final String DEFAULT_CONFIG_PATH_STRING_KEY = "default.config.path.string";
+
+ @Option(names = "--config", description = "Path to the config file (${sys:"+DEFAULT_CONFIG_PATH_STRING_KEY+"} by default)")
+ protected String config;
+
+ @Option(names = "--no-config", description = "Don't use config file - no authentication info is loaded or saved")
+ protected boolean noconfig;
+
+ @Option(names = "--server", description = "Server endpoint url (e.g. 'http://localhost:8080')")
+ protected String server;
+
+ @Option(names = "--realm", description = "Realm name to authenticate against")
+ protected String realm;
+
+ @Option(names = "--client", description = "Realm name to authenticate against")
+ protected String clientId;
+
+ @Option(names = "--user", description = "Username to login with")
+ protected String user;
+
+ @Option(names = "--password", description = "Password to login with (prompted for if not specified and --user is used)")
+ protected String password;
+
+ @Option(names = "--secret", description = "Secret to authenticate the client (prompted for if no --user or --keystore is specified)")
+ protected String secret;
+
+ @Option(names = "--keystore", description = "Path to a keystore containing private key")
+ protected String keystore;
+
+ @Option(names = "--storepass", description = "Keystore password (prompted for if not specified and --keystore is used)")
+ protected String storePass;
+
+ @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(names = "--alias", description = "Alias of the key inside a keystore (defaults to the value of ClientId)")
+ protected String alias;
+
+ @Option(names = "--truststore", description = "Path to a truststore")
+ protected String trustStore;
+
+ @Option(names = "--trustpass", description = "Truststore password (prompted for if not specified and --truststore is used)")
+ protected String trustPass;
+
+ @Option(names = "--insecure", description = "Turns off TLS validation")
+ protected boolean insecure;
+
+ // subclasses unfortunately use different options for this, so they must be declared elsewhere
+ protected String externalToken;
+
+ protected CommandState commandState;
+
+ public BaseAuthOptionsCmd(CommandState state) {
+ this.commandState = state;
+ }
+
+ protected String getCommand() {
+ return commandState.getCommand();
+ }
+
+ protected String getDefaultConfigFilePath() {
+ return commandState.getDefaultConfigFilePath();
+ }
+
+ protected void initFromParent(BaseAuthOptionsCmd parent) {
+ noconfig = parent.noconfig;
+ config = parent.config;
+ server = parent.server;
+ realm = parent.realm;
+ clientId = parent.clientId;
+ user = parent.user;
+ password = parent.password;
+ secret = parent.secret;
+ keystore = parent.keystore;
+ storePass = parent.storePass;
+ keyPass = parent.keyPass;
+ alias = parent.alias;
+ trustStore = parent.trustStore;
+ trustPass = parent.trustPass;
+ externalToken = parent.externalToken;
+ }
+
+ protected void applyDefaultOptionValues() {
+ if (clientId == null) {
+ clientId = DEFAULT_CLIENT;
+ }
+ }
+
+ @Override
+ protected boolean nothingToDo() {
+ return externalToken == null && server == null && realm == null && clientId == null && secret == null &&
+ user == null && password == null &&
+ keystore == null && storePass == null && keyPass == null && alias == null &&
+ trustStore == null && trustPass == null && config == null;
+ }
+
+ @Override
+ protected void processOptions() {
+ if (config != null && noconfig) {
+ throw new IllegalArgumentException("Options --config and --no-config are mutually exclusive");
+ }
+
+ if (!noconfig) {
+ setConfigFile(config != null ? config : getDefaultConfigFilePath());
+ ConfigUtil.setHandler(new FileConfigHandler());
+ } else {
+ InMemoryConfigHandler handler = new InMemoryConfigHandler();
+ ConfigData data = new ConfigData();
+ initConfigData(data);
+ handler.setConfigData(data);
+ ConfigUtil.setHandler(handler);
+ }
+ }
+
+ protected void setupTruststore(ConfigData configData) {
+
+ if (!configData.getServerUrl().startsWith("https:")) {
+ return;
+ }
+
+ String truststore = trustStore;
+ if (truststore == null) {
+ truststore = configData.getTruststore();
+ }
+
+ if (truststore != null) {
+ String pass = trustPass;
+ if (pass == null) {
+ pass = configData.getTrustpass();
+ }
+ if (pass == null) {
+ pass = IoUtil.readSecret("Enter truststore password: ");
+ }
+
+ try {
+ HttpUtil.setTruststore(new File(truststore), pass);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to load truststore: " + truststore, e);
+ }
+ }
+
+ if (insecure) {
+ HttpUtil.setSkipCertificateValidation();
+ }
+ }
+
+ protected ConfigData ensureAuthInfo(ConfigData config) {
+
+ if (requiresLogin()) {
+ // make sure current handler is in-memory handler
+ // restore it at the end
+ ConfigHandler old = ConfigUtil.getHandler();
+ try {
+ // make sure all defaults are initialized after this point
+ applyDefaultOptionValues();
+
+ initConfigData(config);
+ ConfigUtil.setupInMemoryHandler(config);
+
+ BaseConfigCredentialsCmd login = new BaseConfigCredentialsCmd(commandState);
+ login.initFromParent(this);
+ login.init(config);
+ login.process();
+
+ // this must be executed before finally block which restores config handler
+ return loadConfig();
+
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ ConfigUtil.setHandler(old);
+ }
+
+ } else {
+ checkServerInfo(config, getCommand());
+
+ // make sure all defaults are initialized after this point
+ applyDefaultOptionValues();
+ return loadConfig();
+ }
+ }
+
+ protected boolean requiresLogin() {
+ return externalToken == null && (user != null || password != null || secret != null || keystore != null
+ || keyPass != null || storePass != null || alias != null);
+ }
+
+ protected ConfigData copyWithServerInfo(ConfigData config) {
+
+ ConfigData result = config.deepcopy();
+
+ if (server != null) {
+ result.setServerUrl(server);
+ }
+ if (realm != null) {
+ result.setRealm(realm);
+ }
+ if (externalToken != null) {
+ result.setExternalToken(externalToken);
+ }
+
+ checkServerInfo(result, getCommand());
+ return result;
+ }
+
+ private void initConfigData(ConfigData data) {
+ if (server != null)
+ data.setServerUrl(server);
+ if (realm != null)
+ data.setRealm(realm);
+ if (trustStore != null)
+ data.setTruststore(trustStore);
+ if (externalToken != null) {
+ data.setExternalToken(externalToken);
+ }
+
+ RealmConfigData rdata = data.sessionRealmConfigData();
+ if (clientId != null)
+ rdata.setClientId(clientId);
+ if (secret != null)
+ rdata.setSecret(secret);
+ String grantTypeForAuthentication = user == null ? OAuth2Constants.CLIENT_CREDENTIALS : OAuth2Constants.PASSWORD;
+ rdata.setGrantTypeForAuthentication(grantTypeForAuthentication);
+ }
+
+ protected String ensureToken(ConfigData config) {
+ return AuthUtil.ensureToken(config, getCommand());
+ }
+
+}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseConfigCredentialsCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseConfigCredentialsCmd.java
new file mode 100644
index 0000000000..66cff02731
--- /dev/null
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseConfigCredentialsCmd.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.client.cli.common;
+
+import org.keycloak.OAuth2Constants;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.RealmConfigData;
+import org.keycloak.client.cli.util.AuthUtil;
+import org.keycloak.representations.AccessTokenResponse;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+
+import static org.keycloak.client.cli.util.AuthUtil.getAuthTokens;
+import static org.keycloak.client.cli.util.AuthUtil.getAuthTokensByJWT;
+import static org.keycloak.client.cli.util.AuthUtil.getAuthTokensBySecret;
+import static org.keycloak.client.cli.util.ConfigUtil.getHandler;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.saveTokens;
+import static org.keycloak.client.cli.util.IoUtil.printErr;
+import static org.keycloak.client.cli.util.IoUtil.readSecret;
+import static org.keycloak.client.cli.util.OsUtil.OS_ARCH;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+
+
+/**
+ * @author Marko Strukelj
+ */
+public class BaseConfigCredentialsCmd extends BaseAuthOptionsCmd {
+
+ private int sigLifetime = 600;
+
+ public BaseConfigCredentialsCmd(CommandState commandState) {
+ super(commandState);
+ }
+
+ public void init(ConfigData configData) {
+ if (server == null) {
+ server = configData.getServerUrl();
+ }
+ if (realm == null) {
+ realm = configData.getRealm();
+ }
+ if (trustStore == null) {
+ trustStore = configData.getTruststore();
+ }
+
+ RealmConfigData rdata = configData.getRealmConfigData(server, realm);
+ if (rdata == null) {
+ return;
+ }
+
+ if (clientId == null) {
+ clientId = rdata.getClientId();
+ }
+ }
+
+ @Override
+ protected String[] getUnsupportedOptions() {
+ return new String[] {"--no-config", booleanOptionForCheck(noconfig)};
+ }
+
+ @Override
+ public void process() {
+ // check server
+ if (server == null) {
+ throw new IllegalArgumentException("Required option not specified: --server");
+ }
+
+ try {
+ new URL(server);
+ } catch (Exception e) {
+ throw new RuntimeException("Invalid server endpoint url: " + server, e);
+ }
+
+ if (realm == null)
+ throw new IllegalArgumentException("Required option not specified: --realm");
+
+ String signedRequestToken = null;
+ boolean clientSet = clientId != null;
+
+ applyDefaultOptionValues();
+ String grantTypeForAuthentication = null;
+
+ if (user != null) {
+ grantTypeForAuthentication = OAuth2Constants.PASSWORD;
+ printErr("Logging into " + server + " as user " + user + " of realm " + realm);
+
+ // if user was set there needs to be a password so we can authenticate
+ if (password == null) {
+ 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: ");
+ }
+ } 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: ");
+ }
+ }
+ }
+
+ if (keystore != null) {
+ if (secret != null) {
+ throw new IllegalArgumentException("Can't use both --keystore and --secret");
+ }
+
+ if (!new File(keystore).isFile()) {
+ throw new RuntimeException("No such keystore file: " + keystore);
+ }
+
+ if (storePass == null) {
+ storePass = readSecret("Enter keystore password: ");
+ keyPass = readSecret("Enter key password: ");
+ }
+
+ if (keyPass == null) {
+ keyPass = storePass;
+ }
+
+ if (alias == null) {
+ alias = clientId;
+ }
+
+ String realmInfoUrl = server + "/realms/" + realm;
+
+ signedRequestToken = AuthUtil.getSignedRequestToken(keystore, storePass, keyPass,
+ alias, sigLifetime, clientId, realmInfoUrl);
+ }
+
+ // if only server and realm are set, just save config and be done
+ if (user == null && secret == null && keystore == null) {
+ getHandler().saveMergeConfig(config -> {
+ config.setServerUrl(server);
+ config.setRealm(realm);
+ });
+ return;
+ }
+
+ setupTruststore(copyWithServerInfo(loadConfig()));
+
+ // now use the token endpoint to retrieve access token, and refresh token
+ AccessTokenResponse tokens = signedRequestToken != null ?
+ getAuthTokensByJWT(server, realm, user, password, clientId, signedRequestToken) :
+ secret != null ?
+ getAuthTokensBySecret(server, realm, user, password, clientId, secret) :
+ getAuthTokens(server, realm, user, password, clientId);
+
+ Long sigExpiresAt = signedRequestToken == null ? null : System.currentTimeMillis() + sigLifetime * 1000;
+
+ // save tokens to config file
+ saveTokens(tokens, server, realm, clientId, signedRequestToken, sigExpiresAt, secret, grantTypeForAuthentication);
+ }
+
+ @Override
+ public String help() {
+ StringWriter sb = new StringWriter();
+ PrintWriter out = new PrintWriter(sb);
+ out.println("Usage: " + getCommand() + " config credentials --server SERVER_URL --realm REALM [ARGUMENTS]");
+ out.println(" " + getCommand() + " config credentials --server SERVER_URL --realm REALM --user USER [--password PASSWORD] [ARGUMENTS]");
+ out.println(" " + getCommand() + " config credentials --server SERVER_URL --realm REALM --client CLIENT_ID [--secret SECRET] [ARGUMENTS]");
+ out.println(" " + getCommand() + " config credentials --server SERVER_URL --realm REALM --client CLIENT_ID [--keystore KEYSTORE] [ARGUMENTS]");
+ out.println();
+ out.println("Command to establish an authenticated client session with the server. There are many authentication");
+ out.println("options available, and it depends on server side client authentication configuration how client can or should authenticate.");
+ out.println("The information always required includes --server, and --realm. Then, --user and / or --client need to be used to authenticate.");
+ out.println("If --client is not provided it defaults to 'admin-cli'. The authentication options / requirements depend on how this client is configured.");
+ out.println();
+ out.println("If confidential client authentication is also configured, you may have to specify a client id, and client credentials in addition to");
+ out.println("user credentials. Client credentials are either a client secret, or a keystore information to use Signed JWT mechanism.");
+ out.println("If only client credentials are provided, and no user credentials, then the service account is used for login.");
+ out.println();
+ out.println("Arguments:");
+ out.println();
+ out.println(" Global options:");
+ out.println(" -x Print full stack trace when exiting with error");
+ out.println(" --config Path to a config file (" + getDefaultConfigFilePath() + " by default)");
+ out.println(" --truststore PATH Path to a truststore containing trusted certificates");
+ out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
+ out.println();
+ out.println(" Command specific options:");
+ out.println(" --server SERVER_URL Server endpoint url (e.g. 'http://localhost:8080')");
+ out.println(" --realm REALM Realm name to use");
+ out.println(" --user USER Username to login with");
+ out.println(" --password PASSWORD Password to login with (prompted for if not specified and --user is used)");
+ out.println(" --client CLIENT_ID ClientId used by this client tool ('admin-cli' by default)");
+ out.println(" --secret SECRET Secret to authenticate the client (prompted for if --client is specified, and no --keystore is specified)");
+ out.println(" --keystore PATH Path to a keystore containing private key");
+ out.println(" --storepass PASSWORD Keystore password (prompted for if not specified and --keystore is used)");
+ out.println(" --keypass PASSWORD Key password (prompted for if not specified and --keystore is used without --storepass,");
+ out.println(" otherwise defaults to keystore password)");
+ out.println(" --alias ALIAS Alias of the key inside a keystore (defaults to the value of ClientId)");
+ out.println();
+ out.println();
+ out.println("Examples:");
+ out.println();
+ out.println("Login as 'admin' user of 'master' realm to a local Keycloak server running on default port.");
+ out.println("You will be prompted for a password:");
+ out.println(" " + PROMPT + " " + getCommand() + " config credentials --server http://localhost:8080 --realm master --user admin");
+ out.println();
+ out.println("Login to Keycloak server at non-default endpoint passing the password via standard input:");
+ if (OS_ARCH.isWindows()) {
+ out.println(" " + PROMPT + " echo mypassword | " + getCommand() + " config credentials --server http://localhost:9080 --realm master --user admin");
+ } else {
+ out.println(" " + PROMPT + " " + getCommand() + " config credentials --server http://localhost:9080 --realm master --user admin << EOF");
+ out.println(" mypassword");
+ out.println(" EOF");
+ }
+ out.println();
+ out.println("Login specifying a password through command line:");
+ out.println(" " + PROMPT + " " + getCommand() + " config credentials --server http://localhost:9080 --realm master --user admin --password " + OS_ARCH.envVar("PASSWORD"));
+ out.println();
+ out.println("Login using a client service account of a custom client. You will be prompted for a client secret:");
+ out.println(" " + PROMPT + " " + getCommand() + " config credentials --server http://localhost:9080 --realm master --client reg-cli");
+ out.println();
+ out.println("Login using a client service account of a custom client, authenticating with signed JWT.");
+ out.println("You will be prompted for a keystore password, and a key password:");
+ out.println(" " + PROMPT + " " + getCommand() + " config credentials --server http://localhost:9080 --realm master --client reg-cli --keystore " + OS_ARCH.path("~/.keycloak/keystore.jks"));
+ out.println();
+ out.println("Login as 'user' while also authenticating a custom client with signed JWT.");
+ out.println("You will be prompted for a user password, a keystore password, and a key password:");
+ out.println(" " + PROMPT + " " + getCommand() + " config credentials --server http://localhost:9080 --realm master --user user --client reg-cli --keystore " + OS_ARCH.path("~/.keycloak/keystore.jks"));
+ out.println();
+ out.println();
+ out.println("Use '" + getCommand() + " help' for general information and a list of commands");
+ return sb.toString();
+ }
+}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseConfigTruststoreCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseConfigTruststoreCmd.java
new file mode 100644
index 0000000000..bc289fc31f
--- /dev/null
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseConfigTruststoreCmd.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.client.cli.common;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import picocli.CommandLine.Option;
+import picocli.CommandLine.Parameters;
+
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.IoUtil.readSecret;
+import static org.keycloak.client.cli.util.OsUtil.OS_ARCH;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+
+/**
+ * @author Marko Strukelj
+ */
+public class BaseConfigTruststoreCmd extends BaseAuthOptionsCmd {
+
+ @Parameters(arity = "0..1")
+ private String store;
+
+ @Option(names = {"-d", "--delete"}, description = "Remove truststore configuration")
+ private boolean delete;
+
+ public BaseConfigTruststoreCmd(CommandState commandState) {
+ super(commandState);
+ }
+
+ @Override
+ protected boolean nothingToDo() {
+ return super.nothingToDo() && store == null && !delete;
+ }
+
+ @Override
+ protected String[] getUnsupportedOptions() {
+ return new String[] {"--server", server,
+ "--realm", realm,
+ "--client", clientId,
+ "--user", user,
+ "--password", password,
+ "--secret", secret,
+ "--truststore", trustStore,
+ "--keystore", keystore,
+ "--keypass", keyPass,
+ "--alias", alias,
+ "--no-config", booleanOptionForCheck(noconfig)};
+ }
+
+ @Override
+ protected void process() {
+ String pass;
+
+ if (!delete) {
+
+ if (store == null) {
+ throw new IllegalArgumentException("No truststore specified");
+ }
+
+ if (!new File(store).isFile()) {
+ throw new RuntimeException("Truststore file not found: " + store);
+ }
+
+ if ("-".equals(trustPass)) {
+ trustPass = readSecret("Enter truststore password: ");
+ }
+
+ pass = trustPass;
+
+ } else {
+ if (store != null) {
+ throw new IllegalArgumentException("Option --delete is mutually exclusive with specifying a TRUSTSTORE");
+ }
+ if (trustPass != null) {
+ throw new IllegalArgumentException("Options --trustpass and --delete are mutually exclusive");
+ }
+ pass = null;
+ }
+
+ saveMergeConfig(config -> {
+ config.setTruststore(store);
+ config.setTrustpass(pass);
+ });
+ }
+
+ @Override
+ public String help() {
+ StringWriter sb = new StringWriter();
+ PrintWriter out = new PrintWriter(sb);
+ out.println("Usage: " + getCommand() + " config truststore [TRUSTSTORE | --delete] [--trustpass PASSWORD] [ARGUMENTS]");
+ out.println();
+ out.println("Command to configure a global truststore to use when using https to connect to Keycloak server.");
+ out.println();
+ out.println("Arguments:");
+ out.println();
+ out.println(" Global options:");
+ out.println(" -x Print full stack trace when exiting with error");
+ out.println(" --config Path to the config file (" + getDefaultConfigFilePath() + " by default)");
+ out.println();
+ out.println(" Command specific options:");
+ out.println(" TRUSTSTORE Path to truststore file");
+ out.println(" --trustpass PASSWORD Truststore password to unlock truststore (prompted for if set to '-')");
+ out.println(" -d, --delete Remove truststore configuration");
+ out.println();
+ out.println();
+ out.println("Examples:");
+ out.println();
+ out.println("Specify a truststore - you will be prompted for truststore password every time it is used:");
+ out.println(" " + PROMPT + " " + getCommand() + " config truststore " + OS_ARCH.path("~/.keycloak/truststore.jks"));
+ out.println();
+ out.println("Specify a truststore, and password - truststore will automatically be used without prompting for password:");
+ out.println(" " + PROMPT + " " + getCommand() + " config truststore --trustpass " + OS_ARCH.envVar("PASSWORD") + " " + OS_ARCH.path("~/.keycloak/truststore.jks"));
+ out.println();
+ out.println("Remove truststore configuration:");
+ out.println(" " + PROMPT + " " + getCommand() + " config truststore --delete");
+ out.println();
+ out.println();
+ out.println("Use '" + getCommand() + " help' for general information and a list of commands");
+ return sb.toString();
+ }
+}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AbstractGlobalOptionsCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseGlobalOptionsCmd.java
similarity index 66%
rename from integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AbstractGlobalOptionsCmd.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseGlobalOptionsCmd.java
index 5c9c7a7094..a120ea4307 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AbstractGlobalOptionsCmd.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/BaseGlobalOptionsCmd.java
@@ -1,16 +1,27 @@
-package org.keycloak.client.registration.cli.commands;
-
-import org.keycloak.client.registration.cli.Globals;
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.client.cli.common;
import picocli.CommandLine;
import picocli.CommandLine.Option;
-import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
+import static org.keycloak.client.cli.util.IoUtil.printOut;
-/**
- * @author Marko Strukelj
- */
-public abstract class AbstractGlobalOptionsCmd implements Runnable {
+public abstract class BaseGlobalOptionsCmd implements Runnable {
@Option(names = "--help",
description = "Print command specific help")
@@ -38,9 +49,7 @@ public abstract class AbstractGlobalOptionsCmd implements Runnable {
return false;
}
- protected String help() {
- return KcRegCmd.usage();
- }
+ protected abstract String help();
@Override
public void run() {
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/Globals.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/CommandState.java
similarity index 69%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/Globals.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/CommandState.java
index d35d4a0a96..da6f6d7184 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/Globals.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/CommandState.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * Copyright 2024 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,15 +14,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli;
-/**
- * @author Marko Strukelj
- */
-public class Globals {
+package org.keycloak.client.cli.common;
- public static boolean dumpTrace = false;
+public interface CommandState {
- public static boolean help = false;
+ String getCommand();
+
+ String getDefaultConfigFilePath();
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ExecutionExceptionHandler.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/ExecutionExceptionHandler.java
similarity index 96%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ExecutionExceptionHandler.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/ExecutionExceptionHandler.java
index 352c5f4f89..d777177a22 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ExecutionExceptionHandler.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/ExecutionExceptionHandler.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.keycloak.client.admin.cli;
+package org.keycloak.client.cli.common;
import picocli.CommandLine;
import picocli.CommandLine.ParseResult;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/Globals.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/Globals.java
new file mode 100644
index 0000000000..3afda5763a
--- /dev/null
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/Globals.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.client.cli.common;
+
+import org.keycloak.client.cli.util.ClassLoaderUtil;
+import org.keycloak.common.crypto.CryptoIntegration;
+
+import java.io.PrintWriter;
+
+import picocli.CommandLine;
+import picocli.CommandLine.Model.CommandSpec;
+
+/**
+ * @author Marko Strukelj
+ */
+public class Globals {
+
+ public static boolean dumpTrace = false;
+
+ public static boolean help = false;
+
+ public static void main(String [] args, BaseGlobalOptionsCmd rootCommand, String command, String defaultConfigFile) {
+ String libDir = System.getProperty("kc.lib.dir");
+ if (libDir == null) {
+ throw new RuntimeException("System property kc.lib.dir needs to be set");
+ }
+ ClassLoader cl = ClassLoaderUtil.resolveClassLoader(libDir);
+ Thread.currentThread().setContextClassLoader(cl);
+
+ CryptoIntegration.init(cl);
+
+ System.setProperty(BaseAuthOptionsCmd.DEFAULT_CONFIG_PATH_STRING_KEY, defaultConfigFile);
+ CommandLine cli = createCommandLine(rootCommand, command);
+ int exitCode = cli.execute(args);
+ System.exit(exitCode);
+ }
+
+ public static CommandLine createCommandLine(BaseGlobalOptionsCmd rootCommand, String command) {
+ CommandSpec spec = CommandSpec.forAnnotatedObject(rootCommand).name(command);
+
+ CommandLine cmd = new CommandLine(spec);
+
+ cmd.setExecutionExceptionHandler(new ExecutionExceptionHandler());
+ cmd.setParameterExceptionHandler(new ShortErrorMessageHandler());
+ cmd.setErr(new PrintWriter(System.err, true));
+
+ return cmd;
+ }
+
+
+}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ShortErrorMessageHandler.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/ShortErrorMessageHandler.java
similarity index 98%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ShortErrorMessageHandler.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/ShortErrorMessageHandler.java
index b0c6d9bc16..e76cda5fb1 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/ShortErrorMessageHandler.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/common/ShortErrorMessageHandler.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.keycloak.client.admin.cli;
+package org.keycloak.client.cli.common;
import java.io.PrintWriter;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigData.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigData.java
similarity index 99%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigData.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigData.java
index 9cdec9f129..f67c7fcc84 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigData.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigData.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.config;
+package org.keycloak.client.cli.config;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.keycloak.util.JsonSerialization;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigHandler.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigHandler.java
similarity index 94%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigHandler.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigHandler.java
index fd318c569b..710bb2168b 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigHandler.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigHandler.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.config;
+package org.keycloak.client.cli.config;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigUpdateOperation.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigUpdateOperation.java
similarity index 94%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigUpdateOperation.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigUpdateOperation.java
index 15276a051f..b7b7c5e529 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/ConfigUpdateOperation.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/ConfigUpdateOperation.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.config;
+package org.keycloak.client.cli.config;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/FileConfigHandler.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/FileConfigHandler.java
similarity index 96%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/FileConfigHandler.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/FileConfigHandler.java
index cb76dfeec9..a7eb461984 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/FileConfigHandler.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/FileConfigHandler.java
@@ -14,9 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.config;
+package org.keycloak.client.cli.config;
-import org.keycloak.client.admin.cli.util.IoUtil;
+import org.keycloak.client.cli.util.IoUtil;
import org.keycloak.util.JsonSerialization;
import java.io.ByteArrayInputStream;
@@ -30,7 +30,7 @@ import java.nio.channels.OverlappingFileLockException;
import java.nio.file.Path;
import java.nio.file.Paths;
-import static org.keycloak.client.admin.cli.util.IoUtil.printErr;
+import static org.keycloak.client.cli.util.IoUtil.printErr;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/InMemoryConfigHandler.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/InMemoryConfigHandler.java
similarity index 96%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/InMemoryConfigHandler.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/InMemoryConfigHandler.java
index 7ac43775e7..3c6f9fdb1e 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/config/InMemoryConfigHandler.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/InMemoryConfigHandler.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.config;
+package org.keycloak.client.cli.config;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/RealmConfigData.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/RealmConfigData.java
similarity index 96%
rename from integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/RealmConfigData.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/RealmConfigData.java
index 6eade23434..6e1a73d018 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/RealmConfigData.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/config/RealmConfigData.java
@@ -14,8 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-package org.keycloak.client.registration.cli.config;
+package org.keycloak.client.cli.config;
import org.keycloak.util.JsonSerialization;
@@ -23,6 +22,8 @@ import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
/**
* @author Marko Strukelj
*/
@@ -50,11 +51,12 @@ public class RealmConfigData {
private Long sigExpiresAt;
+ @JsonInclude(JsonInclude.Include.NON_NULL)
private String initialToken;
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
private Map clients = new LinkedHashMap();
-
public String serverUrl() {
return serverUrl;
}
@@ -111,6 +113,14 @@ public class RealmConfigData {
this.secret = secret;
}
+ public String getGrantTypeForAuthentication() {
+ return grantTypeForAuthentication;
+ }
+
+ public void setGrantTypeForAuthentication(String grantTypeForAuthentication) {
+ this.grantTypeForAuthentication = grantTypeForAuthentication;
+ }
+
public Long getExpiresAt() {
return expiresAt;
}
@@ -127,14 +137,6 @@ public class RealmConfigData {
this.refreshExpiresAt = refreshExpiresAt;
}
- public String getGrantTypeForAuthentication() {
- return grantTypeForAuthentication;
- }
-
- public void setGrantTypeForAuthentication(String grantTypeForAuthentication) {
- this.grantTypeForAuthentication = grantTypeForAuthentication;
- }
-
public Long getSigExpiresAt() {
return sigExpiresAt;
}
@@ -194,13 +196,6 @@ public class RealmConfigData {
refreshToken = source.refreshToken;
expiresAt = source.expiresAt;
refreshExpiresAt = source.refreshExpiresAt;
-
- mergeClients(source);
- }
-
- public void mergeRegistrationTokens(RealmConfigData source) {
- initialToken = source.initialToken;
- mergeClients(source);
}
@Override
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AccessibleBufferOutputStream.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AccessibleBufferOutputStream.java
similarity index 97%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AccessibleBufferOutputStream.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AccessibleBufferOutputStream.java
index 984784eb34..8afce36c70 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AccessibleBufferOutputStream.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AccessibleBufferOutputStream.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import java.io.FilterOutputStream;
import java.io.IOException;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AttributeException.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AttributeException.java
similarity index 96%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AttributeException.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AttributeException.java
index 721baf260e..7e310f54b5 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AttributeException.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AttributeException.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AuthUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AuthUtil.java
similarity index 91%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AuthUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AuthUtil.java
index 125913fbe2..ea0b6eec33 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/AuthUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/AuthUtil.java
@@ -14,10 +14,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
-import org.keycloak.client.admin.cli.config.ConfigData;
-import org.keycloak.client.admin.cli.config.RealmConfigData;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.RealmConfigData;
import org.keycloak.common.util.KeystoreUtil;
import org.keycloak.common.util.Time;
import org.keycloak.jose.jws.JWSBuilder;
@@ -33,24 +33,24 @@ import java.security.KeyPair;
import java.util.UUID;
import static java.lang.System.currentTimeMillis;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.checkAuthInfo;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.saveMergeConfig;
-import static org.keycloak.client.admin.cli.util.HttpUtil.APPLICATION_FORM_URL_ENCODED;
-import static org.keycloak.client.admin.cli.util.HttpUtil.APPLICATION_JSON;
-import static org.keycloak.client.admin.cli.util.HttpUtil.doPost;
-import static org.keycloak.client.admin.cli.util.HttpUtil.urlencode;
+import static org.keycloak.client.cli.util.ConfigUtil.checkServerInfo;
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.HttpUtil.APPLICATION_FORM_URL_ENCODED;
+import static org.keycloak.client.cli.util.HttpUtil.APPLICATION_JSON;
+import static org.keycloak.client.cli.util.HttpUtil.doPost;
+import static org.keycloak.client.cli.util.HttpUtil.urlencode;
/**
* @author Marko Strukelj
*/
public class AuthUtil {
- public static String ensureToken(ConfigData config) {
+ public static String ensureToken(ConfigData config, String cmd) {
if (config.getExternalToken() != null) {
return config.getExternalToken();
}
- checkAuthInfo(config);
+ checkServerInfo(config, cmd);
RealmConfigData realmConfig = config.sessionRealmConfigData();
@@ -63,11 +63,11 @@ public class AuthUtil {
// check refresh_token against expiry time
// if it's less than 5s to expiry, fail with credentials expired
if (realmConfig.getRefreshExpiresAt() != null && realmConfig.getRefreshExpiresAt() - now < 5000) {
- throw new RuntimeException("Session has expired. Login again with '" + OsUtil.CMD + " config credentials'");
+ throw new RuntimeException("Session has expired. Login again with '" + cmd + " config credentials'");
}
if (realmConfig.getSigExpiresAt() != null && realmConfig.getSigExpiresAt() - now < 5000) {
- throw new RuntimeException("Session has expired. Login again with '" + OsUtil.CMD + " config credentials'");
+ throw new RuntimeException("Session has expired. Login again with '" + cmd + " config credentials'");
}
try {
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ClassLoaderUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ClassLoaderUtil.java
similarity index 98%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ClassLoaderUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ClassLoaderUtil.java
index 990cf8182e..3ce4afaa08 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ClassLoaderUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ClassLoaderUtil.java
@@ -17,7 +17,7 @@
*
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import java.io.File;
import java.net.MalformedURLException;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ConfigUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ConfigUtil.java
similarity index 82%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ConfigUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ConfigUtil.java
index 9d6033cb38..ece5dbf26c 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ConfigUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ConfigUtil.java
@@ -14,14 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import org.keycloak.OAuth2Constants;
-import org.keycloak.client.admin.cli.config.ConfigData;
-import org.keycloak.client.admin.cli.config.ConfigHandler;
-import org.keycloak.client.admin.cli.config.ConfigUpdateOperation;
-import org.keycloak.client.admin.cli.config.InMemoryConfigHandler;
-import org.keycloak.client.admin.cli.config.RealmConfigData;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.ConfigHandler;
+import org.keycloak.client.cli.config.ConfigUpdateOperation;
+import org.keycloak.client.cli.config.InMemoryConfigHandler;
+import org.keycloak.client.cli.config.RealmConfigData;
import org.keycloak.representations.AccessTokenResponse;
/**
@@ -31,10 +31,6 @@ public class ConfigUtil {
public static final String DEFAULT_CLIENT = "admin-cli";
- public static final String DEFAULT_CONFIG_FILE_STRING = OsUtil.OS_ARCH.isWindows() ? "%HOMEDRIVE%%HOMEPATH%\\.keycloak\\kcadm.config" : "~/.keycloak/kcadm.config";
-
- public static final String DEFAULT_CONFIG_FILE_PATH = System.getProperty("user.home") + "/.keycloak/kcadm.config";
-
private static ConfigHandler handler;
public static ConfigHandler getHandler() {
@@ -45,6 +41,15 @@ public class ConfigUtil {
ConfigUtil.handler = handler;
}
+ public static String getRegistrationToken(RealmConfigData data, String clientId) {
+ String token = data.getClients().get(clientId);
+ return token == null || token.length() == 0 ? null : token;
+ }
+
+ public static void setRegistrationToken(RealmConfigData data, String clientId, String token) {
+ data.getClients().put(clientId, token == null ? "" : token);
+ }
+
public static void saveTokens(AccessTokenResponse tokens, String endpoint, String realm, String clientId, String signKey, Long sigExpiresAt, String secret,
String grantTypeForAuthentication) {
handler.saveMergeConfig(config -> {
@@ -67,19 +72,15 @@ public class ConfigUtil {
});
}
- public static void checkServerInfo(ConfigData config) {
+ public static void checkServerInfo(ConfigData config, String cmd) {
if (config.getServerUrl() == null) {
- throw new RuntimeException("No server specified. Use --server, or '" + OsUtil.CMD + " config credentials'.");
+ throw new RuntimeException("No server specified. Use --server, or '" + cmd + " config credentials'.");
}
if (config.getRealm() == null && config.getExternalToken() == null) {
- throw new RuntimeException("No realm or token specified. Use --realm, --token, or '" + OsUtil.CMD + " config credentials'.");
+ throw new RuntimeException("No realm or token specified. Use --realm, --token, or '" + cmd + " config credentials'.");
}
}
- public static void checkAuthInfo(ConfigData config) {
- checkServerInfo(config);
- }
-
public static boolean credentialsAvailable(ConfigData config) {
// Just supporting "client_credentials" grant type for the case when refresh token is missing
boolean credsAvailable = config.getServerUrl() != null && (config.getExternalToken() != null || (config.getRealm() != null
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/FilterUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/FilterUtil.java
similarity index 90%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/FilterUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/FilterUtil.java
index 6a68f85d29..6dcf85ae1d 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/FilterUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/FilterUtil.java
@@ -14,18 +14,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import static org.keycloak.client.cli.util.OutputUtil.MAPPER;
+import static org.keycloak.client.cli.util.OutputUtil.convertToJsonNode;
+
import java.io.IOException;
import java.util.Iterator;
-import static org.keycloak.client.admin.cli.util.OutputUtil.MAPPER;
-import static org.keycloak.client.admin.cli.util.OutputUtil.convertToJsonNode;
-
/**
* @author Marko Strukelj
*/
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/Header.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/Header.java
similarity index 95%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/Header.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/Header.java
index 6ba4a600cc..a90491a9a4 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/Header.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/Header.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/Headers.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/Headers.java
similarity index 97%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/Headers.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/Headers.java
index 57fc034e5a..7a9b16ed28 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/Headers.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/Headers.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import org.apache.http.entity.ContentType;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HeadersBody.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HeadersBody.java
similarity index 94%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HeadersBody.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HeadersBody.java
index eba553b0f8..e11417de3d 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HeadersBody.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HeadersBody.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import org.apache.http.entity.ContentType;
@@ -22,7 +22,7 @@ import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.Charset;
-import static org.keycloak.client.admin.cli.util.IoUtil.copyStream;
+import static org.keycloak.client.cli.util.IoUtil.copyStream;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HeadersBodyStatus.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HeadersBodyStatus.java
similarity index 98%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HeadersBodyStatus.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HeadersBodyStatus.java
index 9ce89651f5..8e82aac079 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HeadersBodyStatus.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HeadersBodyStatus.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import org.keycloak.util.JsonSerialization;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/httpcomponents/HttpDelete.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpDelete.java
similarity index 95%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/httpcomponents/HttpDelete.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpDelete.java
index 51c1bcaa38..fd9a65a371 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/httpcomponents/HttpDelete.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpDelete.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.httpcomponents;
+package org.keycloak.client.cli.util;
import org.apache.http.annotation.Contract;
import org.apache.http.annotation.ThreadingBehavior;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HttpResponseException.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpResponseException.java
similarity index 96%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HttpResponseException.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpResponseException.java
index 692b38467a..f7ea7b383a 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HttpResponseException.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpResponseException.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HttpUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpUtil.java
similarity index 83%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HttpUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpUtil.java
index 30eb9e9b7f..5af609f5a0 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/HttpUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/HttpUtil.java
@@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.http.HeaderIterator;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
@@ -36,9 +34,6 @@ import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
-import org.keycloak.client.admin.cli.httpcomponents.HttpDelete;
-import org.keycloak.client.admin.cli.operations.LocalSearch;
-import org.keycloak.client.admin.cli.operations.RoleOperations;
import org.keycloak.util.JsonSerialization;
import javax.net.ssl.SSLContext;
@@ -53,12 +48,8 @@ import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.LinkedHashMap;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Supplier;
-
-import static org.keycloak.common.util.ObjectUtil.capitalize;
/**
* @author Marko Strukelj
@@ -69,7 +60,6 @@ public class HttpUtil {
public static final String APPLICATION_JSON = "application/json";
public static final String APPLICATION_FORM_URL_ENCODED = "application/x-www-form-urlencoded";
public static final String UTF_8 = "utf-8";
- private static final String[] DEFAULT_QUERY_PARAMS = { "first", "0", "max", "2" };
private static HttpClient httpClient;
private static SSLConnectionSocketFactory sslsf;
@@ -436,57 +426,6 @@ public class HttpUtil {
checkSuccess(resourceUrl, response);
}
- public static String getIdForType(String rootUrl, String realm, String auth, String resourceEndpoint, String attrName, String attrValue, String inputAttrName) {
-
- return getAttrForType(rootUrl, realm, auth, resourceEndpoint, attrName, attrValue, inputAttrName, "id", null);
- }
-
- public static String getIdForType(String rootUrl, String realm, String auth, String resourceEndpoint, String attrName, String attrValue, String inputAttrName, Supplier endpointParams) {
- return getAttrForType(rootUrl, realm, auth, resourceEndpoint, attrName, attrValue, inputAttrName, "id", endpointParams);
- }
-
- public static String getAttrForType(String rootUrl, String realm, String auth, String resourceEndpoint, String attrName, String attrValue, String inputAttrName, String returnAttrName) {
- return getAttrForType(rootUrl, realm, auth, resourceEndpoint, attrName, attrValue, inputAttrName, returnAttrName, null);
- }
-
- public static String getAttrForType(String rootUrl, String realm, String auth, String resourceEndpoint, String attrName, String attrValue, String inputAttrName, String returnAttrName, Supplier endpointParams) {
- String resourceUrl = composeResourceUrl(rootUrl, realm, resourceEndpoint);
- String[] defaultParams;
-
- if (endpointParams == null) {
- defaultParams = DEFAULT_QUERY_PARAMS;
- } else {
- defaultParams = endpointParams.get();
- }
-
- resourceUrl = HttpUtil.addQueryParamsToUri(resourceUrl, attrName, attrValue);
- resourceUrl = HttpUtil.addQueryParamsToUri(resourceUrl, defaultParams);
-
- List results = doGetJSON(RoleOperations.LIST_OF_NODES.class, resourceUrl, auth);
-
- ObjectNode match;
- try {
- match = new LocalSearch(results).exactMatchOne(attrValue, inputAttrName);
- } catch (Exception e) {
- throw new RuntimeException("Multiple " + resourceEndpoint + " found for " + inputAttrName + ": " + attrValue, e);
- }
-
- String typeName = singularize(resourceEndpoint);
- if (match == null) {
- if (results.size() > 1) {
- throw new RuntimeException("Some matches, but not an exact match, found for " + capitalize(typeName) + " with " + inputAttrName + ": " + attrValue + ". Try using a more unique search, such as an id.");
- }
- throw new RuntimeException(capitalize(typeName) + " not found for " + inputAttrName + ": " + attrValue);
- }
-
- JsonNode attr = match.get(returnAttrName);
- if (attr == null) {
- throw new RuntimeException("Returned " + typeName + " info has no '" + returnAttrName + "' attribute");
- }
- return attr.asText();
- }
-
-
public static String singularize(String value) {
return value.substring(0, value.length()-1);
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/IoUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/IoUtil.java
similarity index 99%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/IoUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/IoUtil.java
index c2e49870b8..f2ececae02 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/IoUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/IoUtil.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import java.io.Console;
import java.io.FileInputStream;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OsArch.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OsArch.java
similarity index 97%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OsArch.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OsArch.java
index 13cf424d87..6b63a8fa7b 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OsArch.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OsArch.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OsUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OsUtil.java
similarity index 93%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OsUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OsUtil.java
index 3b70f47ad6..5398c7e2a2 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OsUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OsUtil.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
/**
* @author Marko Strukelj
@@ -22,8 +22,6 @@ package org.keycloak.client.admin.cli.util;
public class OsUtil {
public static final OsArch OS_ARCH = determineOSAndArch();
- // TODO: move CMD out of this class
- public static final String CMD = OS_ARCH.isWindows() ? "kcadm.bat" : "kcadm.sh";
public static final String PROMPT = OS_ARCH.isWindows() ? "c:\\>" : "$";
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OutputFormat.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OutputFormat.java
similarity index 94%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OutputFormat.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OutputFormat.java
index 31181cc296..64955f6c16 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OutputFormat.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OutputFormat.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OutputUtil.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OutputUtil.java
similarity index 98%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OutputUtil.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OutputUtil.java
index 8e3c083e58..50a9c0740a 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/OutputUtil.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/OutputUtil.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/CmdStdinContext.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ParseUtil.java
similarity index 61%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/CmdStdinContext.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ParseUtil.java
index 1c6752666a..2920ee8726 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/common/CmdStdinContext.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ParseUtil.java
@@ -14,31 +14,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.common;
+package org.keycloak.client.cli.util;
/**
* @author Marko Strukelj
*/
-public class CmdStdinContext {
+public class ParseUtil {
- private T result;
- private String content;
+ public static String[] parseKeyVal(String keyval) {
+ // we expect = as a separator
+ int pos = keyval.indexOf("=");
+ if (pos <= 0) {
+ throw new IllegalArgumentException("Invalid key=value parameter: [" + keyval + "]");
+ }
- public CmdStdinContext() {}
+ String [] parsed = new String[2];
+ parsed[0] = keyval.substring(0, pos);
+ parsed[1] = keyval.substring(pos+1);
- public T getResult() {
- return result;
- }
-
- public void setResult(T result) {
- this.result = result;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
+ return parsed;
}
}
diff --git a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ReturnFields.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ReturnFields.java
similarity index 99%
rename from integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ReturnFields.java
rename to integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ReturnFields.java
index a185471457..0de307a24c 100644
--- a/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/util/ReturnFields.java
+++ b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/cli/util/ReturnFields.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import java.util.Collections;
import java.util.HashMap;
diff --git a/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/ReflectionUtilTest.java b/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/ReflectionUtilTest.java
similarity index 97%
rename from integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/ReflectionUtilTest.java
rename to integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/ReflectionUtilTest.java
index 76adcebe78..0ffd561db3 100644
--- a/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/ReflectionUtilTest.java
+++ b/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/ReflectionUtilTest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.admin.cli;
import org.junit.Test;
diff --git a/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/MergeAttributesTest.java b/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/MergeAttributesTest.java
similarity index 88%
rename from integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/MergeAttributesTest.java
rename to integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/MergeAttributesTest.java
index bb518e39f5..ab36853228 100644
--- a/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/MergeAttributesTest.java
+++ b/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/MergeAttributesTest.java
@@ -14,22 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Test;
-import org.keycloak.client.admin.cli.common.AttributeOperation;
-import org.keycloak.client.admin.cli.common.CmdStdinContext;
+import org.keycloak.client.admin.cli.CmdStdinContext;
+import org.keycloak.client.admin.cli.ReflectionUtil;
+import org.keycloak.client.cli.common.AttributeOperation;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
-import static org.keycloak.client.admin.cli.common.AttributeOperation.Type.DELETE;
-import static org.keycloak.client.admin.cli.common.AttributeOperation.Type.SET;
-import static org.keycloak.client.admin.cli.util.OutputUtil.MAPPER;
-import static org.keycloak.client.admin.cli.util.ParseUtil.mergeAttributes;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.DELETE;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.SET;
+import static org.keycloak.client.cli.util.OutputUtil.MAPPER;
/**
* @author Marko Strukelj
@@ -71,7 +71,7 @@ public class MergeAttributesTest {
CmdStdinContext ctx = new CmdStdinContext<>();
ctx.setResult(localNode);
- ctx = mergeAttributes(ctx, MAPPER.createObjectNode(), attrs);
+ ctx = CmdStdinContext.mergeAttributes(ctx, MAPPER.createObjectNode(), attrs);
System.out.println(ctx);
String remoteJSON = "{\n" +
diff --git a/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/OuputUtilTest.java b/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/OuputUtilTest.java
similarity index 91%
rename from integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/OuputUtilTest.java
rename to integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/OuputUtilTest.java
index d91b0b8e1a..6151018d5b 100644
--- a/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/OuputUtilTest.java
+++ b/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/OuputUtilTest.java
@@ -15,9 +15,11 @@
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import org.junit.Test;
+import org.keycloak.client.cli.util.OutputUtil;
+import org.keycloak.client.cli.util.ReturnFields;
import java.io.IOException;
import java.util.ArrayList;
diff --git a/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/ReturnFieldsTest.java b/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/ReturnFieldsTest.java
similarity index 98%
rename from integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/ReturnFieldsTest.java
rename to integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/ReturnFieldsTest.java
index bd2105be8f..218f6f120f 100644
--- a/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/admin/cli/util/ReturnFieldsTest.java
+++ b/integration/client-cli/admin-cli/src/test/java/org/keycloak/client/cli/util/ReturnFieldsTest.java
@@ -14,10 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.keycloak.client.admin.cli.util;
+package org.keycloak.client.cli.util;
import org.junit.Assert;
import org.junit.Test;
+import org.keycloak.client.cli.util.ReturnFields;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ParseUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/CmdStdinContext.java
similarity index 80%
rename from integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ParseUtil.java
rename to integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/CmdStdinContext.java
index 8d237dd987..4ed3b4cd2a 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ParseUtil.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/CmdStdinContext.java
@@ -15,13 +15,10 @@
* limitations under the License.
*/
-package org.keycloak.client.registration.cli.util;
+package org.keycloak.client.registration.cli;
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
-import org.keycloak.client.registration.cli.common.AttributeOperation;
-import org.keycloak.client.registration.cli.common.CmdStdinContext;
-import org.keycloak.client.registration.cli.common.EndpointType;
+import org.keycloak.client.cli.common.AttributeOperation;
+import org.keycloak.client.cli.util.AttributeException;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
import org.keycloak.util.JsonSerialization;
@@ -29,46 +26,73 @@ import org.keycloak.util.JsonSerialization;
import java.io.IOException;
import java.util.List;
-import static java.lang.System.arraycopy;
-import static org.keycloak.client.registration.cli.util.IoUtil.readFileOrStdin;
-import static org.keycloak.client.registration.cli.util.ReflectionUtil.setAttributes;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
+
+import static org.keycloak.client.cli.util.IoUtil.readFileOrStdin;
+import static org.keycloak.client.registration.cli.ReflectionUtil.setAttributes;
/**
* @author Marko Strukelj
*/
-public class ParseUtil {
+public class CmdStdinContext {
+ private EndpointType regType;
+ private ClientRepresentation client;
+ private OIDCClientRepresentation oidcClient;
+ private String content;
public static final String CLIENT_OPTION_WARN = "You're using what looks like an OPTION as CLIENT: %s";
public static final String TOKEN_OPTION_WARN = "You're using what looks like an OPTION as TOKEN: %s";
- public static String[] shift(String[] args) {
- if (args.length == 1)
- return new String[0];
- String [] nu = new String [args.length-1];
- arraycopy(args, 1, nu, 0, args.length-1);
- return nu;
+ public CmdStdinContext() {}
+
+ public EndpointType getEndpointType() {
+ return regType;
}
- public static String[] parseKeyVal(String keyval) {
- // we expect = as a separator
- int pos = keyval.indexOf("=");
- if (pos <= 0) {
- throw new RuntimeException("Invalid key=value parameter: [" + keyval + "]");
+ public void setEndpointType(EndpointType regType) {
+ this.regType = regType;
+ }
+
+ public ClientRepresentation getClient() {
+ return client;
+ }
+
+ public void setClient(ClientRepresentation client) {
+ this.client = client;
+ }
+
+ public OIDCClientRepresentation getOidcClient() {
+ return oidcClient;
+ }
+
+ public void setOidcClient(OIDCClientRepresentation oidcClient) {
+ this.oidcClient = oidcClient;
+ }
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public String getRegistrationAccessToken() {
+ if (client != null) {
+ return client.getRegistrationAccessToken();
+ } else if (oidcClient != null) {
+ return oidcClient.getRegistrationAccessToken();
}
-
- String [] parsed = new String[2];
- parsed[0] = keyval.substring(0, pos);
- parsed[1] = keyval.substring(pos+1);
-
- return parsed;
+ return null;
}
public static CmdStdinContext parseFileOrStdin(String file, EndpointType type) {
-
+
String content = readFileOrStdin(file).trim();
ClientRepresentation client = null;
OIDCClientRepresentation oidcClient = null;
-
+
if (type == null) {
// guess the correct endpoint from content of the file
if (content.startsWith("<")) {
@@ -80,13 +104,13 @@ public class ParseUtil {
try {
client = JsonSerialization.readValue(content, ClientRepresentation.class);
type = EndpointType.DEFAULT;
-
+
} catch (JsonParseException e) {
throw new RuntimeException("Failed to read the input document as JSON: " + e.getMessage(), e);
} catch (Exception ignored) {
// deliberately not logged
}
-
+
if (client == null) {
// try parse as OIDCClientRepresentation
try {
@@ -98,14 +122,14 @@ public class ParseUtil {
throw new RuntimeException("Failed to read the input document as JSON", e);
}
}
-
+
} else if (content.length() == 0) {
throw new RuntimeException("Document provided by --file option is empty");
} else {
throw new RuntimeException("Unable to determine input document type. Use -e TYPE to specify the registration endpoint to use");
}
}
-
+
// check content type, making sure it can be parsed into .json if it's not saml xml
if (content != null) {
try {
@@ -122,7 +146,7 @@ public class ParseUtil {
throw new RuntimeException("Not a valid JSON document", e);
}
}
-
+
CmdStdinContext ctx = new CmdStdinContext();
ctx.setEndpointType(type);
ctx.setContent(content);
@@ -158,7 +182,7 @@ public class ParseUtil {
} catch (IOException e) {
throw new RuntimeException("Failed to merge set attributes with configuration from file", e);
}
-
+
ctx.setContent(content);
ctx.setClient(client);
ctx.setOidcClient(oidcClient);
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/EndpointType.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/EndpointType.java
similarity index 81%
rename from integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/EndpointType.java
rename to integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/EndpointType.java
index 5114adacb0..698777f8db 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/EndpointType.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/EndpointType.java
@@ -15,7 +15,9 @@
* limitations under the License.
*/
-package org.keycloak.client.registration.cli.common;
+package org.keycloak.client.registration.cli;
+
+import org.keycloak.client.cli.util.HttpUtil;
import java.util.Arrays;
import java.util.HashSet;
@@ -60,4 +62,16 @@ public enum EndpointType {
public String getName() {
return preferredName;
}
+
+ public static String getExpectedContentType(EndpointType type) {
+ switch (type) {
+ case DEFAULT:
+ case OIDC:
+ return HttpUtil.APPLICATION_JSON;
+ case SAML2:
+ return HttpUtil.APPLICATION_XML;
+ default:
+ throw new RuntimeException("Unsupported endpoint type: " + type);
+ }
+ }
}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/EndpointTypeConverter.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/EndpointTypeConverter.java
index 80015edd23..276b2b2361 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/EndpointTypeConverter.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/EndpointTypeConverter.java
@@ -1,7 +1,5 @@
package org.keycloak.client.registration.cli;
-import org.keycloak.client.registration.cli.common.EndpointType;
-
import picocli.CommandLine.ITypeConverter;
/**
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/Globals.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/Globals.java
deleted file mode 100644
index d266c7a953..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/Globals.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.client.registration.cli;
-
-/**
- * @author Marko Strukelj
- */
-public class Globals {
-
- public static boolean dumpTrace = false;
-
- public static boolean help = false;
-
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/KcRegMain.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/KcRegMain.java
index 90330bf596..94b2a03905 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/KcRegMain.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/KcRegMain.java
@@ -1,46 +1,36 @@
package org.keycloak.client.registration.cli;
-import org.keycloak.client.admin.cli.ExecutionExceptionHandler;
-import org.keycloak.client.admin.cli.ShortErrorMessageHandler;
+import org.keycloak.client.cli.common.CommandState;
+import org.keycloak.client.cli.common.Globals;
+import org.keycloak.client.cli.util.OsUtil;
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.io.PrintWriter;
-
-import picocli.CommandLine;
-import picocli.CommandLine.Model.CommandSpec;
/**
* @author Marko Strukelj
*/
public class KcRegMain {
- public static void main(String [] args) {
- String libDir = System.getProperty("kc.lib.dir");
- if (libDir == null) {
- throw new RuntimeException("System property kc.lib.dir needs to be set");
+ public static final String DEFAULT_CONFIG_FILE_PATH = System.getProperty("user.home") + "/.keycloak/kcreg.config";
+
+ public static final String DEFAULT_CONFIG_FILE_STRING = OsUtil.OS_ARCH.isWindows() ? "%HOMEDRIVE%%HOMEPATH%\\.keycloak\\kcreg.config" : "~/.keycloak/kcreg.config";
+
+ public static final String CMD = OsUtil.OS_ARCH.isWindows() ? "kcreg.bat" : "kcreg.sh";
+
+ public static final CommandState COMMAND_STATE = new CommandState() {
+
+ @Override
+ public String getCommand() {
+ return CMD;
}
- ClassLoader cl = ClassLoaderUtil.resolveClassLoader(libDir);
- Thread.currentThread().setContextClassLoader(cl);
- CryptoIntegration.init(cl);
+ @Override
+ public String getDefaultConfigFilePath() {
+ return DEFAULT_CONFIG_FILE_PATH;
+ }
- CommandLine cli = createCommandLine();
- int exitCode = cli.execute(args);
- System.exit(exitCode);
- }
+ };
- public static CommandLine createCommandLine() {
- CommandSpec spec = CommandSpec.forAnnotatedObject(new KcRegCmd()).name(OsUtil.CMD);
-
- CommandLine cmd = new CommandLine(spec);
-
- cmd.setExecutionExceptionHandler(new ExecutionExceptionHandler());
- cmd.setParameterExceptionHandler(new ShortErrorMessageHandler());
- cmd.setErr(new PrintWriter(System.err, true));
-
- return cmd;
+ public static void main(String [] args) {
+ Globals.main(args, new KcRegCmd(), CMD, DEFAULT_CONFIG_FILE_STRING);
}
}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ReflectionUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/ReflectionUtil.java
similarity index 99%
rename from integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ReflectionUtil.java
rename to integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/ReflectionUtil.java
index 1fe500b82b..1e884884d0 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ReflectionUtil.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/ReflectionUtil.java
@@ -15,11 +15,13 @@
* limitations under the License.
*/
-package org.keycloak.client.registration.cli.util;
+package org.keycloak.client.registration.cli;
import com.fasterxml.jackson.core.JsonParseException;
-import org.keycloak.client.registration.cli.common.AttributeKey;
-import org.keycloak.client.registration.cli.common.AttributeOperation;
+
+import org.keycloak.client.cli.common.AttributeKey;
+import org.keycloak.client.cli.common.AttributeOperation;
+import org.keycloak.client.cli.util.AttributeException;
import org.keycloak.util.JsonSerialization;
import java.io.IOException;
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AbstractAuthOptionsCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AbstractAuthOptionsCmd.java
index 436b2f2270..e6ceb00b0b 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AbstractAuthOptionsCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AbstractAuthOptionsCmd.java
@@ -1,255 +1,22 @@
package org.keycloak.client.registration.cli.commands;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.config.ConfigHandler;
-import org.keycloak.client.registration.cli.config.FileConfigHandler;
-import org.keycloak.client.registration.cli.config.InMemoryConfigHandler;
-import org.keycloak.client.registration.cli.config.RealmConfigData;
-import org.keycloak.client.registration.cli.util.ConfigUtil;
-import org.keycloak.client.registration.cli.util.HttpUtil;
-import org.keycloak.client.registration.cli.util.IoUtil;
-
-import java.io.File;
+import org.keycloak.client.cli.common.BaseAuthOptionsCmd;
+import org.keycloak.client.registration.cli.KcRegMain;
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;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.loadConfig;
-
/**
* @author Marko Strukelj
*/
-public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd {
-
- static final String DEFAULT_CLIENT = "admin-cli";
-
- @Option(names = "--config", description = "Path to the config file (~/.keycloak/kcreg.config by default)")
- protected String config;
-
- @Option(names = "--no-config", description = "No configuration file should be used, no authentication info is loaded or saved")
- protected boolean noconfig;
-
- @Option(names = "--server", description = "Server endpoint url (e.g. 'http://localhost:8080')")
- protected String server;
-
- @Option(names = "--realm", description = "Realm name to authenticate against")
- protected String realm;
-
- @Option(names = "--client", description = "Realm name to authenticate against")
- protected String clientId;
-
- @Option(names = "--user", description = "Username to login with")
- protected String user;
-
- @Option(names = "--password", description = "Password to login with (prompted for if not specified and --user is used)")
- protected String password;
-
- @Option(names = "--secret", description = "Secret to authenticate the client (prompted for if no --user or --keystore is specified)")
- protected String secret;
-
- @Option(names = "--keystore", description = "Path to a keystore containing private key")
- protected String keystore;
-
- @Option(names = "--storepass", description = "Keystore password (prompted for if not specified and --keystore is used)")
- protected String storePass;
-
- @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(names = "--alias", description = "Alias of the key inside a keystore (defaults to the value of ClientId)")
- protected String alias;
-
- @Option(names = "--truststore", description = "Path to a truststore")
- protected String trustStore;
-
- @Option(names = "--trustpass", description = "Truststore password (prompted for if not specified and --truststore is used)")
- protected String trustPass;
-
- @Option(names = "--insecure", description = "Turns off TLS validation")
- protected boolean insecure;
+public abstract class AbstractAuthOptionsCmd extends BaseAuthOptionsCmd {
@Option(names = {"-t", "--token"}, description = "Initial / Registration access token to use)")
- protected String token;
-
- protected void initFromParent(AbstractAuthOptionsCmd parent) {
- noconfig = parent.noconfig;
- config = parent.config;
- server = parent.server;
- realm = parent.realm;
- clientId = parent.clientId;
- user = parent.user;
- password = parent.password;
- secret = parent.secret;
- keystore = parent.keystore;
- storePass = parent.storePass;
- keyPass = parent.keyPass;
- alias = parent.alias;
- trustStore = parent.trustStore;
- trustPass = parent.trustPass;
- token = parent.token;
- insecure = parent.insecure;
+ public void setToken(String token) {
+ this.externalToken = token;
}
- protected void applyDefaultOptionValues() {
- if (clientId == null) {
- clientId = DEFAULT_CLIENT;
- }
+ public AbstractAuthOptionsCmd() {
+ super(KcRegMain.COMMAND_STATE);
}
- protected boolean noOptions() {
- return server == null && realm == null && clientId == null && secret == null &&
- user == null && password == null &&
- keystore == null && storePass == null && keyPass == null && alias == null &&
- trustStore == null && trustPass == null &&
- token == null && config == null;
- }
-
- @Override
- protected void processOptions() {
-
- if (config != null && noconfig) {
- throw new IllegalArgumentException("Options --config and --no-config are mutually exclusive");
- }
-
- if (!noconfig) {
- setConfigFile(config != null ? config : ConfigUtil.DEFAULT_CONFIG_FILE_PATH);
- ConfigUtil.setHandler(new FileConfigHandler());
- } else {
- InMemoryConfigHandler handler = new InMemoryConfigHandler();
- ConfigData data = new ConfigData();
- initConfigData(data);
- handler.setConfigData(data);
- ConfigUtil.setHandler(handler);
- }
- }
-
- protected void setupTruststore(ConfigData configData) {
-
- if (!configData.getServerUrl().startsWith("https:")) {
- return;
- }
-
- String truststore = trustStore;
- if (truststore == null) {
- truststore = configData.getTruststore();
- }
-
- if (truststore != null) {
- String pass = trustPass;
- if (pass == null) {
- pass = configData.getTrustpass();
- }
- if (pass == null) {
- pass = IoUtil.readSecret("Enter truststore password: ");
- }
-
- try {
- HttpUtil.setTruststore(new File(truststore), pass);
- } catch (Exception e) {
- throw new RuntimeException("Failed to load truststore: " + truststore, e);
- }
- }
-
- if (insecure) {
- HttpUtil.setSkipCertificateValidation();
- }
- }
-
- protected ConfigData ensureAuthInfo(ConfigData config) {
-
- if (requiresLogin()) {
- // make sure current handler is in-memory handler
- // restore it at the end
- ConfigHandler old = ConfigUtil.getHandler();
- try {
- // make sure all defaults are initialized after this point
- applyDefaultOptionValues();
-
- initConfigData(config);
- ConfigUtil.setupInMemoryHandler(config);
-
- ConfigCredentialsCmd login = new ConfigCredentialsCmd();
- login.initFromParent(this);
- login.init(config);
- login.process();
-
- // this must be executed before finally block which restores config handler
- return loadConfig();
-
- } catch (RuntimeException e) {
- throw e;
- } catch (Exception e) {
- throw new RuntimeException(e);
- } finally {
- ConfigUtil.setHandler(old);
- }
-
- } else {
- checkAuthInfo(config);
-
- // make sure all defaults are initialized after this point
- applyDefaultOptionValues();
- return loadConfig();
- }
- }
-
- protected boolean requiresLogin() {
- return user != null || password != null || secret != null || keystore != null
- || keyPass != null || storePass != null || alias != null;
- }
-
- protected ConfigData copyWithServerInfo(ConfigData config) {
-
- ConfigData result = config.deepcopy();
-
- if (server != null) {
- result.setServerUrl(server);
- }
- if (realm != null) {
- result.setRealm(realm);
- }
-
- checkServerInfo(result);
- return result;
- }
-
- private void initConfigData(ConfigData data) {
- if (server != null)
- data.setServerUrl(server);
- if (realm != null)
- data.setRealm(realm);
- if (trustStore != null)
- data.setTruststore(trustStore);
-
- RealmConfigData rdata = data.sessionRealmConfigData();
- if (clientId != null)
- rdata.setClientId(clientId);
- if (secret != null)
- rdata.setSecret(secret);
- String grantTypeForAuthentication = user == null ? OAuth2Constants.CLIENT_CREDENTIALS : OAuth2Constants.PASSWORD;
- rdata.setGrantTypeForAuthentication(grantTypeForAuthentication);
- }
-
- @Override
- 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;
- }
}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AttrsCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AttrsCmd.java
index 9f3a036aef..5362a1ba16 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AttrsCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/AttrsCmd.java
@@ -1,8 +1,9 @@
package org.keycloak.client.registration.cli.commands;
-import org.keycloak.client.registration.cli.common.AttributeKey;
-import org.keycloak.client.registration.cli.common.EndpointType;
-import org.keycloak.client.registration.cli.util.ReflectionUtil;
+import org.keycloak.client.cli.common.AttributeKey;
+import org.keycloak.client.cli.common.BaseGlobalOptionsCmd;
+import org.keycloak.client.registration.cli.EndpointType;
+import org.keycloak.client.registration.cli.ReflectionUtil;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
@@ -20,18 +21,18 @@ 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;
-import static org.keycloak.client.registration.cli.util.ReflectionUtil.isBasicType;
-import static org.keycloak.client.registration.cli.util.ReflectionUtil.isListType;
-import static org.keycloak.client.registration.cli.util.ReflectionUtil.isMapType;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
+import static org.keycloak.client.registration.cli.ReflectionUtil.getAttributeListWithJSonTypes;
+import static org.keycloak.client.registration.cli.ReflectionUtil.isBasicType;
+import static org.keycloak.client.registration.cli.ReflectionUtil.isListType;
+import static org.keycloak.client.registration.cli.ReflectionUtil.isMapType;
/**
* @author Marko Strukelj
*/
@Command(name = "attrs", description = "[ATTRIBUTE] [--endpoint TYPE]")
-public class AttrsCmd extends AbstractGlobalOptionsCmd {
+public class AttrsCmd extends BaseGlobalOptionsCmd {
CommandLine.Model.CommandSpec spec;
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCmd.java
index 22dbd3e1fe..3d127a144e 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCmd.java
@@ -22,7 +22,7 @@ import java.io.StringWriter;
import picocli.CommandLine.Command;
-import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
* @author Marko Strukelj
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCredentialsCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCredentialsCmd.java
index a0f16c9409..a9678f8d45 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCredentialsCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigCredentialsCmd.java
@@ -1,243 +1,18 @@
package org.keycloak.client.registration.cli.commands;
-import org.keycloak.OAuth2Constants;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.config.RealmConfigData;
-import org.keycloak.client.registration.cli.util.AuthUtil;
-import org.keycloak.representations.AccessTokenResponse;
-
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.net.URL;
+import org.keycloak.client.cli.common.BaseConfigCredentialsCmd;
+import org.keycloak.client.registration.cli.KcRegMain;
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;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_STRING;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.getHandler;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.loadConfig;
-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.OS_ARCH;
-import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
-
/**
* @author Marko Strukelj
*/
@Command(name = "credentials", description = "--server SERVER_URL --realm REALM [ARGUMENTS]")
-public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd {
+public class ConfigCredentialsCmd extends BaseConfigCredentialsCmd {
- private int sigLifetime = 600;
-
-
- public void init(ConfigData configData) {
- if (server == null) {
- server = configData.getServerUrl();
- }
- if (realm == null) {
- realm = configData.getRealm();
- }
- if (trustStore == null) {
- trustStore = configData.getTruststore();
- }
-
- RealmConfigData rdata = configData.getRealmConfigData(server, realm);
- if (rdata == null) {
- return;
- }
-
- if (clientId == null) {
- clientId = rdata.getClientId();
- }
+ public ConfigCredentialsCmd() {
+ super(KcRegMain.COMMAND_STATE);
}
- @Override
- protected String[] getUnsupportedOptions() {
- return new String[] {"--no-config", booleanOptionForCheck(noconfig)};
- }
-
- @Override
- protected boolean nothingToDo() {
- return noOptions();
- }
-
- @Override
- protected void process() {
- // check server
- if (server == null) {
- throw new IllegalArgumentException("Required option not specified: --server");
- }
-
- try {
- new URL(server);
- } catch (Exception e) {
- throw new RuntimeException("Invalid server endpoint url: " + server, e);
- }
-
- if (realm == null)
- throw new IllegalArgumentException("Required option not specified: --realm");
-
- String signedRequestToken = null;
- boolean clientSet = clientId != null;
-
- applyDefaultOptionValues();
- String grantTypeForAuthentication = null;
-
- if (user != null) {
- grantTypeForAuthentication = OAuth2Constants.PASSWORD;
- printErr("Logging into " + server + " as user " + user + " of realm " + realm);
-
- // if user was set there needs to be a password so we can authenticate
- if (password == null) {
- 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: ");
- }
- } 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: ");
- }
- }
- }
-
- if (keystore != null) {
- if (secret != null) {
- throw new IllegalArgumentException("Can't use both --keystore and --secret");
- }
-
- if (!new File(keystore).isFile()) {
- throw new RuntimeException("No such keystore file: " + keystore);
- }
-
- if (storePass == null) {
- storePass = readSecret("Enter keystore password: ");
- keyPass = readSecret("Enter key password: ");
- }
-
- if (keyPass == null) {
- keyPass = storePass;
- }
-
- if (alias == null) {
- alias = clientId;
- }
-
- String realmInfoUrl = server + "/realms/" + realm;
-
- signedRequestToken = AuthUtil.getSignedRequestToken(keystore, storePass, keyPass,
- alias, sigLifetime, clientId, realmInfoUrl);
- }
-
- // if only server and realm are set, just save config and be done
- if (user == null && secret == null && keystore == null) {
- getHandler().saveMergeConfig(config -> {
- config.setServerUrl(server);
- config.setRealm(realm);
- });
- return;
- }
-
- setupTruststore(copyWithServerInfo(loadConfig()));
-
- // now use the token endpoint to retrieve access token, and refresh token
- AccessTokenResponse tokens = signedRequestToken != null ?
- getAuthTokensByJWT(server, realm, user, password, clientId, signedRequestToken) :
- secret != null ?
- getAuthTokensBySecret(server, realm, user, password, clientId, secret) :
- getAuthTokens(server, realm, user, password, clientId);
-
- Long sigExpiresAt = signedRequestToken == null ? null : System.currentTimeMillis() + sigLifetime * 1000;
-
- // save tokens to config file
- saveTokens(tokens, server, realm, clientId, signedRequestToken, sigExpiresAt, secret, grantTypeForAuthentication);
- }
-
- @Override
- protected String help() {
- return usage();
- }
-
- public static String usage() {
- StringWriter sb = new StringWriter();
- PrintWriter out = new PrintWriter(sb);
- out.println("Usage: " + CMD + " config credentials --server SERVER_URL --realm REALM [ARGUMENTS]");
- out.println(" " + CMD + " config credentials --server SERVER_URL --realm REALM --user USER [--password PASSWORD] [ARGUMENTS]");
- out.println(" " + CMD + " config credentials --server SERVER_URL --realm REALM --client CLIENT_ID [--secret SECRET] [ARGUMENTS]");
- out.println(" " + CMD + " config credentials --server SERVER_URL --realm REALM --client CLIENT_ID [--keystore KEYSTORE] [ARGUMENTS]");
- out.println();
- out.println("Command to establish an authenticated client session with the server. There are many authentication");
- out.println("options available, and it depends on server side client authentication configuration how client can or should authenticate.");
- out.println("The information always required includes --server, and --realm. That is enough to establish unauthenticated session.");
- out.println("If --client is not provided it defaults to 'admin-cli'. The authantication options / requirements depend on how this client is configured.");
- out.println();
- out.println("If you have an account configured with the rights to manage clients then you can use username, and password to authenticate.");
- out.println("If confidential client authentication is also configured, you may have to specify a client id, and client credentials in addition to");
- out.println("user credentials. Client credentials are either a client secret, or a keystore information to use Signed JWT mechanism.");
- out.println("If only client credentials are provided, and no user credentials, then the service account is used for login.");
- out.println();
- out.println("Arguments:");
- out.println();
- out.println(" Global options:");
- out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to a config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
- out.println(" --truststore PATH Path to a truststore containing trusted certificates");
- out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
- out.println();
- out.println(" Command specific options:");
- out.println(" --server SERVER_URL Server endpoint url (e.g. 'http://localhost:8080')");
- out.println(" --realm REALM Realm name to use");
- out.println(" --user USER Username to login with");
- out.println(" --password PASSWORD Password to login with (prompted for if not specified and --user is used)");
- out.println(" --client CLIENT_ID ClientId used by this client tool ('admin-cli' by default)");
- out.println(" --secret SECRET Secret to authenticate the client (prompted for if --client is specified, and no --keystore is specified)");
- out.println(" --keystore PATH Path to a keystore containing private key");
- out.println(" --storepass PASSWORD Keystore password (prompted for if not specified and --keystore is used)");
- out.println(" --keypass PASSWORD Key password (prompted for if not specified and --keystore is used without --storepass,");
- out.println(" otherwise defaults to keystore password)");
- out.println(" --alias ALIAS Alias of the key inside a keystore (defaults to the value of ClientId)");
- out.println();
- out.println();
- out.println("Examples:");
- out.println();
- out.println("Login as 'admin' user of 'master' realm to a local Keycloak server running on default port.");
- out.println("You will be prompted for a password:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:8080 --realm master --user admin");
- out.println();
- out.println("Login to Keycloak server at non-default endpoint passing the password via standard input:");
- if (OS_ARCH.isWindows()) {
- out.println(" " + PROMPT + " echo mypassword | " + CMD + " config credentials --server http://localhost:9080 --realm master --user admin");
- } else {
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --user admin << EOF");
- out.println(" mypassword");
- out.println(" EOF");
- }
- out.println();
- out.println("Login specifying a password through command line:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --user admin --password " + OS_ARCH.envVar("PASSWORD"));
- out.println();
- out.println("Login using a client service account of a custom client. You will be prompted for a client secret:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --client reg-cli");
- out.println();
- out.println("Login using a client service account of a custom client, authenticating with signed JWT.");
- out.println("You will be prompted for a keystore password, and a key password:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --client reg-cli --keystore " + OS_ARCH.path("~/.keycloak/keystore.jks"));
- out.println();
- out.println("Login as 'user' while also authenticating a custom client with signed JWT.");
- out.println("You will be prompted for a user password, a keystore password, and a key password:");
- out.println(" " + PROMPT + " " + CMD + " config credentials --server http://localhost:9080 --realm master --user user --client reg-cli --keystore " + OS_ARCH.path("~/.keycloak/keystore.jks"));
- out.println();
- out.println();
- out.println("Use '" + CMD + " help' for general information and a list of commands");
- return sb.toString();
- }
}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigInitialTokenCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigInitialTokenCmd.java
index 9bd9e72718..31fdcb0b3f 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigInitialTokenCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigInitialTokenCmd.java
@@ -1,8 +1,9 @@
package org.keycloak.client.registration.cli.commands;
-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 org.keycloak.client.cli.config.RealmConfigData;
+import org.keycloak.client.cli.util.IoUtil;
+import org.keycloak.client.registration.cli.CmdStdinContext;
+import org.keycloak.client.registration.cli.KcRegMain;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -11,12 +12,11 @@ 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.OS_ARCH;
-import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.IoUtil.warnfOut;
+import static org.keycloak.client.cli.util.OsUtil.OS_ARCH;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
* @author Marko Strukelj
@@ -34,7 +34,7 @@ public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd {
@Override
protected boolean nothingToDo() {
- return noOptions() && token == null && !delete && !keepDomain;
+ return super.nothingToDo() && token == null && !delete && !keepDomain;
}
@Override
@@ -60,7 +60,7 @@ public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd {
}
if (token != null && token.startsWith("-")) {
- warnfOut(ParseUtil.TOKEN_OPTION_WARN, token);
+ warnfOut(CmdStdinContext.TOKEN_OPTION_WARN, token);
}
if (!delete && token == null) {
@@ -106,7 +106,7 @@ public class ConfigInitialTokenCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcRegMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println();
out.println(" Command specific options:");
out.println(" --server SERVER Server endpoint url (e.g. 'http://localhost:8080')");
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigRegistrationTokenCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigRegistrationTokenCmd.java
index 8d11b0a588..d78ddf56fc 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigRegistrationTokenCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigRegistrationTokenCmd.java
@@ -1,7 +1,8 @@
package org.keycloak.client.registration.cli.commands;
-import org.keycloak.client.registration.cli.config.RealmConfigData;
-import org.keycloak.client.registration.cli.util.IoUtil;
+import org.keycloak.client.registration.cli.KcRegMain;
+import org.keycloak.client.cli.config.RealmConfigData;
+import org.keycloak.client.cli.util.IoUtil;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -10,11 +11,10 @@ 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.OS_ARCH;
-import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.OsUtil.OS_ARCH;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
* @author Marko Strukelj
@@ -30,7 +30,7 @@ public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd {
@Override
protected boolean nothingToDo() {
- return noOptions() && token == null && !delete;
+ return super.nothingToDo() && token == null && !delete;
}
@Override
@@ -97,7 +97,7 @@ public class ConfigRegistrationTokenCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcRegMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println();
out.println(" Command specific options:");
out.println(" --server SERVER Server endpoint url (e.g. 'http://localhost:8080')");
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigTruststoreCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigTruststoreCmd.java
index 3e032515e7..2e199a9d99 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigTruststoreCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/ConfigTruststoreCmd.java
@@ -16,131 +16,19 @@
*/
package org.keycloak.client.registration.cli.commands;
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
+import org.keycloak.client.cli.common.BaseConfigTruststoreCmd;
+import org.keycloak.client.registration.cli.KcRegMain;
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.OS_ARCH;
-import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
/**
* @author Marko Strukelj
*/
@Command(name = "truststore", description = "PATH [ARGUMENTS]")
-public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd {
+public class ConfigTruststoreCmd extends BaseConfigTruststoreCmd {
- @Option(names = {"-d", "--delete"}, description = "Indicates that initial access token should be removed")
- private boolean delete;
-
- @Parameters(arity = "0..1")
- private String truststorePath;
-
- @Override
- protected boolean nothingToDo() {
- return noOptions() && truststorePath == null && !delete;
+ public ConfigTruststoreCmd() {
+ super(KcRegMain.COMMAND_STATE);
}
- @Override
- protected String[] getUnsupportedOptions() {
- return new String[] {"--server", server,
- "--realm", realm,
- "--client", clientId,
- "--user", user,
- "--password", password,
- "--secret", secret,
- "--truststore", trustStore,
- "--keystore", keystore,
- "--keypass", keyPass,
- "--alias", alias,
- "--no-config", booleanOptionForCheck(noconfig)};
- }
-
- @Override
- protected void process() {
- // now update the config
-
- String store;
- String pass;
-
- if (!delete) {
-
- if (truststorePath == null) {
- throw new IllegalArgumentException("No truststore specified");
- }
-
- if (!new File(truststorePath).isFile()) {
- throw new RuntimeException("Truststore file not found: " + truststorePath);
- }
-
- if ("-".equals(trustPass)) {
- trustPass = readSecret("Enter truststore password: ");
- }
-
- store = truststorePath;
- pass = trustPass;
-
- } else {
- if (truststorePath != null) {
- throw new IllegalArgumentException("Option --delete is mutually exclusive with specifying a TRUSTSTORE");
- }
- if (trustPass != null) {
- throw new IllegalArgumentException("Options --trustpass and --delete are mutually exclusive");
- }
- store = null;
- pass = null;
- }
-
- saveMergeConfig(config -> {
- config.setTruststore(store);
- config.setTrustpass(pass);
- });
- }
-
- @Override
- protected String help() {
- return usage();
- }
-
- public static String usage() {
- StringWriter sb = new StringWriter();
- PrintWriter out = new PrintWriter(sb);
- out.println("Usage: " + CMD + " config truststore [TRUSTSTORE | --delete] [--trustpass PASSWORD] [ARGUMENTS]");
- out.println();
- out.println("Command to configure a global truststore to use when using https to connect to Keycloak server.");
- out.println();
- out.println("Arguments:");
- out.println();
- out.println(" Global options:");
- out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
- out.println();
- out.println(" Command specific options:");
- out.println(" TRUSTSTORE Path to truststore file");
- out.println(" --trustpass PASSWORD Truststore password to unlock truststore (prompted for if set to '-')");
- out.println(" -d, --delete Remove truststore configuration");
- out.println();
- out.println();
- out.println("Examples:");
- out.println();
- out.println("Specify a truststore - you will be prompted for truststore password every time it is used:");
- out.println(" " + PROMPT + " " + CMD + " config truststore " + OS_ARCH.path("~/.keycloak/truststore.jks"));
- out.println();
- out.println("Specify a truststore, and password - truststore will automatically be used without prompting for password:");
- out.println(" " + PROMPT + " " + CMD + " config truststore --storepass " + OS_ARCH.envVar("PASSWORD") + " " + OS_ARCH.path("~/.keycloak/truststore.jks"));
- out.println();
- out.println("Remove truststore configuration:");
- out.println(" " + PROMPT + " " + CMD + " config truststore --delete");
- out.println();
- out.println();
- out.println("Use '" + CMD + " help' for general information and a list of commands");
- return sb.toString();
- }
}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/CreateCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/CreateCmd.java
index 605b88a1e9..fda405f3cf 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/CreateCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/CreateCmd.java
@@ -17,12 +17,13 @@
package org.keycloak.client.registration.cli.commands;
+import org.keycloak.client.registration.cli.CmdStdinContext;
+import org.keycloak.client.registration.cli.EndpointType;
import org.keycloak.client.registration.cli.EndpointTypeConverter;
-import org.keycloak.client.registration.cli.common.AttributeOperation;
-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.client.registration.cli.KcRegMain;
+import org.keycloak.client.cli.common.AttributeOperation;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.util.HttpUtil;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
import org.keycloak.util.JsonSerialization;
@@ -39,28 +40,23 @@ 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.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.ParseUtil.parseKeyVal;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.SET;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.setRegistrationToken;
+import static org.keycloak.client.cli.util.HttpUtil.doPost;
+import static org.keycloak.client.cli.util.IoUtil.printErr;
+import static org.keycloak.client.cli.util.IoUtil.printOut;
+import static org.keycloak.client.cli.util.IoUtil.readFully;
+import static org.keycloak.client.cli.util.IoUtil.readSecret;
+import static org.keycloak.client.cli.util.OsUtil.OS_ARCH;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.cli.util.ParseUtil.parseKeyVal;
+import static org.keycloak.client.registration.cli.EndpointType.DEFAULT;
+import static org.keycloak.client.registration.cli.EndpointType.OIDC;
+import static org.keycloak.client.registration.cli.EndpointType.SAML2;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
* @author Marko Strukelj
@@ -109,13 +105,13 @@ public class CreateCmd extends AbstractAuthOptionsCmd {
}
// if --token is specified read it
- if ("-".equals(token)) {
- token = readSecret("Enter Initial Access Token: ");
+ if ("-".equals(externalToken)) {
+ externalToken = readSecret("Enter Initial Access Token: ");
}
CmdStdinContext ctx = new CmdStdinContext();
if (file != null) {
- ctx = parseFileOrStdin(file, regType);
+ ctx = CmdStdinContext.parseFileOrStdin(file, regType);
}
if (ctx.getEndpointType() == null) {
@@ -126,22 +122,22 @@ public class CreateCmd extends AbstractAuthOptionsCmd {
}
if (attrs.size() > 0) {
- ctx = mergeAttributes(ctx, attrs);
+ ctx = CmdStdinContext.mergeAttributes(ctx, attrs);
}
- String contentType = getExpectedContentType(ctx.getEndpointType());
+ String contentType = EndpointType.getExpectedContentType(ctx.getEndpointType());
ConfigData config = loadConfig();
config = copyWithServerInfo(config);
- if (token == null) {
+ if (externalToken == null) {
// if initial token is not set, try use the one from configuration
- token = config.sessionRealmConfigData().getInitialToken();
+ externalToken = config.sessionRealmConfigData().getInitialToken();
}
setupTruststore(config);
- String auth = token;
+ String auth = externalToken;
if (auth == null) {
config = ensureAuthInfo(config);
config = copyWithServerInfo(config);
@@ -199,7 +195,7 @@ public class CreateCmd extends AbstractAuthOptionsCmd {
@Override
protected boolean nothingToDo() {
- return noOptions() && regType == null && file == null && rawSets.isEmpty();
+ return super.nothingToDo() && regType == null && file == null && rawSets.isEmpty();
}
@Override
@@ -220,7 +216,7 @@ public class CreateCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcRegMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/DeleteCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/DeleteCmd.java
index 3337cbb843..8011513ed1 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/DeleteCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/DeleteCmd.java
@@ -17,8 +17,9 @@
package org.keycloak.client.registration.cli.commands;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.util.ParseUtil;
+import org.keycloak.client.registration.cli.KcRegMain;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.registration.cli.CmdStdinContext;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -26,17 +27,15 @@ import java.io.StringWriter;
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;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.credentialsAvailable;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.getRegistrationToken;
-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.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.PROMPT;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.getRegistrationToken;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.HttpUtil.doDelete;
+import static org.keycloak.client.cli.util.HttpUtil.urlencode;
+import static org.keycloak.client.cli.util.IoUtil.warnfErr;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
@@ -55,7 +54,7 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
}
if (clientId.startsWith("-")) {
- warnfErr(ParseUtil.CLIENT_OPTION_WARN, clientId);
+ warnfErr(CmdStdinContext.CLIENT_OPTION_WARN, clientId);
}
String regType = "default";
@@ -63,14 +62,14 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
ConfigData config = loadConfig();
config = copyWithServerInfo(config);
- if (token == null) {
+ if (externalToken == null) {
// if registration access token is not set via -t, try use the one from configuration
- token = getRegistrationToken(config.sessionRealmConfigData(), clientId);
+ externalToken = getRegistrationToken(config.sessionRealmConfigData(), clientId);
}
setupTruststore(config);
- String auth = token;
+ String auth = externalToken;
if (auth == null) {
config = ensureAuthInfo(config);
config = copyWithServerInfo(config);
@@ -94,7 +93,7 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
@Override
protected boolean nothingToDo() {
- return noOptions() && clientId == null;
+ return super.nothingToDo() && clientId == null;
}
@Override
@@ -114,7 +113,7 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcRegMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/GetCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/GetCmd.java
index fd8ba9b5df..92dae5791d 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/GetCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/GetCmd.java
@@ -17,9 +17,10 @@
package org.keycloak.client.registration.cli.commands;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.common.EndpointType;
-import org.keycloak.client.registration.cli.util.ParseUtil;
+import org.keycloak.client.registration.cli.KcRegMain;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.registration.cli.CmdStdinContext;
+import org.keycloak.client.registration.cli.EndpointType;
import org.keycloak.representations.adapters.config.AdapterConfig;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
@@ -34,21 +35,19 @@ 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;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.credentialsAvailable;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.getRegistrationToken;
-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.APPLICATION_JSON;
-import static org.keycloak.client.registration.cli.util.HttpUtil.doGet;
-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.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.PROMPT;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.getRegistrationToken;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.setRegistrationToken;
+import static org.keycloak.client.cli.util.HttpUtil.APPLICATION_JSON;
+import static org.keycloak.client.cli.util.HttpUtil.doGet;
+import static org.keycloak.client.cli.util.HttpUtil.urlencode;
+import static org.keycloak.client.cli.util.IoUtil.printOut;
+import static org.keycloak.client.cli.util.IoUtil.readFully;
+import static org.keycloak.client.cli.util.IoUtil.warnfErr;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
* @author Marko Strukelj
@@ -75,20 +74,20 @@ public class GetCmd extends AbstractAuthOptionsCmd {
if (clientId.startsWith("-")) {
- warnfErr(ParseUtil.CLIENT_OPTION_WARN, clientId);
+ warnfErr(CmdStdinContext.CLIENT_OPTION_WARN, clientId);
}
ConfigData config = loadConfig();
config = copyWithServerInfo(config);
- if (token == null) {
+ if (externalToken == null) {
// if registration access token is not set via -t, try use the one from configuration
- token = getRegistrationToken(config.sessionRealmConfigData(), clientId);
+ externalToken = getRegistrationToken(config.sessionRealmConfigData(), clientId);
}
setupTruststore(config);
- String auth = token;
+ String auth = externalToken;
if (auth == null) {
config = ensureAuthInfo(config);
config = copyWithServerInfo(config);
@@ -156,7 +155,7 @@ public class GetCmd extends AbstractAuthOptionsCmd {
@Override
protected boolean nothingToDo() {
- return noOptions() && endpoint == null && clientId == null;
+ return super.nothingToDo() && endpoint == null && clientId == null;
}
@Override
@@ -176,7 +175,7 @@ public class GetCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcRegMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/HelpCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/HelpCmd.java
index ca8cc7e748..510c79302b 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/HelpCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/HelpCmd.java
@@ -5,7 +5,7 @@ import java.util.List;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
-import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
+import static org.keycloak.client.cli.util.IoUtil.printOut;
/**
* @author Marko Strukelj
@@ -27,7 +27,7 @@ public class HelpCmd implements Runnable {
if (args.size() > 1) {
switch (args.get(1)) {
case "credentials": {
- printOut(ConfigCredentialsCmd.usage());
+ printOut(new ConfigCredentialsCmd().help());
break outer;
}
case "initial-token": {
@@ -39,7 +39,7 @@ public class HelpCmd implements Runnable {
break outer;
}
case "truststore": {
- printOut(ConfigTruststoreCmd.usage());
+ printOut(new ConfigTruststoreCmd().help());
break outer;
}
}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/KcRegCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/KcRegCmd.java
index d2d2245abd..8e43fbc479 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/KcRegCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/KcRegCmd.java
@@ -16,15 +16,16 @@
*/
package org.keycloak.client.registration.cli.commands;
+import org.keycloak.client.cli.common.BaseGlobalOptionsCmd;
+import org.keycloak.client.registration.cli.KcRegMain;
+
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;
-import static org.keycloak.client.registration.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
* @author Marko Strukelj
@@ -49,13 +50,18 @@ subcommands = {
AttrsCmd.class,
UpdateTokenCmd.class
})
-public class KcRegCmd extends AbstractGlobalOptionsCmd {
-
+public class KcRegCmd extends BaseGlobalOptionsCmd {
+
@Override
protected boolean nothingToDo() {
return true;
}
+ @Override
+ protected String help() {
+ return usage();
+ }
+
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
@@ -93,7 +99,7 @@ public class KcRegCmd extends AbstractGlobalOptionsCmd {
out.println("Global options:");
out.println(" -x Print full stack trace when exiting with error");
out.println(" --help Print help for specific command");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcRegMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println();
out.println("Commands: ");
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateCmd.java
index c5e3c9e480..f623692f28 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateCmd.java
@@ -24,13 +24,13 @@ import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
+import org.keycloak.client.registration.cli.CmdStdinContext;
+import org.keycloak.client.registration.cli.EndpointType;
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.util.ParseUtil;
-import org.keycloak.client.registration.cli.util.ReflectionUtil;
+import org.keycloak.client.registration.cli.ReflectionUtil;
+import org.keycloak.client.registration.cli.KcRegMain;
+import org.keycloak.client.cli.common.AttributeOperation;
+import org.keycloak.client.cli.config.ConfigData;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.oidc.OIDCClientRepresentation;
import org.keycloak.util.JsonSerialization;
@@ -43,29 +43,25 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
-import static org.keycloak.client.registration.cli.common.AttributeOperation.Type.DELETE;
-import static org.keycloak.client.registration.cli.common.AttributeOperation.Type.SET;
-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.getRegistrationToken;
-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.common.EndpointType.DEFAULT;
-import static org.keycloak.client.registration.cli.common.EndpointType.OIDC;
-import static org.keycloak.client.registration.cli.util.HttpUtil.doGet;
-import static org.keycloak.client.registration.cli.util.HttpUtil.doPut;
-import static org.keycloak.client.registration.cli.util.HttpUtil.urlencode;
-import static org.keycloak.client.registration.cli.util.IoUtil.printOut;
-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.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.ParseUtil.parseKeyVal;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.DELETE;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.SET;
+import static org.keycloak.client.cli.util.ConfigUtil.credentialsAvailable;
+import static org.keycloak.client.cli.util.ConfigUtil.getRegistrationToken;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.setRegistrationToken;
+import static org.keycloak.client.cli.util.HttpUtil.APPLICATION_JSON;
+import static org.keycloak.client.cli.util.HttpUtil.doGet;
+import static org.keycloak.client.cli.util.HttpUtil.doPut;
+import static org.keycloak.client.cli.util.HttpUtil.urlencode;
+import static org.keycloak.client.cli.util.IoUtil.printOut;
+import static org.keycloak.client.cli.util.IoUtil.readFully;
+import static org.keycloak.client.cli.util.IoUtil.warnfErr;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.cli.util.ParseUtil.parseKeyVal;
+import static org.keycloak.client.registration.cli.EndpointType.DEFAULT;
+import static org.keycloak.client.registration.cli.EndpointType.OIDC;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
* @author Marko Strukelj
@@ -123,7 +119,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
}
if (clientId.startsWith("-")) {
- warnfErr(ParseUtil.CLIENT_OPTION_WARN, clientId);
+ warnfErr(CmdStdinContext.CLIENT_OPTION_WARN, clientId);
}
if (file == null && attrs.size() == 0) {
@@ -165,7 +161,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
CmdStdinContext ctx = new CmdStdinContext();
if (file != null) {
- ctx = parseFileOrStdin(file, regType);
+ ctx = CmdStdinContext.parseFileOrStdin(file, regType);
regType = ctx.getEndpointType();
}
@@ -185,7 +181,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
final String server = config.getServerUrl();
final String realm = config.getRealm();
- if (token == null) {
+ if (externalToken == null) {
// if registration access token is not set via --token, see if it's in the body of any input file
// but first see if it's overridden by --set, or maybe deliberately muted via -d registrationAccessToken
boolean processed = false;
@@ -193,25 +189,25 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
if ("registrationAccessToken".equals(op.getKey().toString())) {
processed = true;
if (op.getType() == AttributeOperation.Type.SET) {
- token = op.getValue();
+ externalToken = op.getValue();
}
// otherwise it's delete - meaning it should stay null
break;
}
}
if (!processed) {
- token = ctx.getRegistrationAccessToken();
+ externalToken = ctx.getRegistrationAccessToken();
}
}
- if (token == null) {
+ if (externalToken == null) {
// if registration access token is not set, try use the one from configuration
- token = getRegistrationToken(config.sessionRealmConfigData(), clientId);
+ externalToken = getRegistrationToken(config.sessionRealmConfigData(), clientId);
}
setupTruststore(config);
- String auth = token;
+ String auth = externalToken;
if (auth == null) {
config = ensureAuthInfo(config);
config = copyWithServerInfo(config);
@@ -236,10 +232,10 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
if (regType == DEFAULT) {
ctxremote.setClient(JsonSerialization.readValue(json, ClientRepresentation.class));
- token = ctxremote.getClient().getRegistrationAccessToken();
+ externalToken = ctxremote.getClient().getRegistrationAccessToken();
} else if (regType == OIDC) {
ctxremote.setOidcClient(JsonSerialization.readValue(json, OIDCClientRepresentation.class));
- token = ctxremote.getOidcClient().getRegistrationAccessToken();
+ externalToken = ctxremote.getOidcClient().getRegistrationAccessToken();
}
} catch (JsonParseException e) {
throw new RuntimeException("Not a valid JSON document. " + e.getMessage(), e);
@@ -249,11 +245,11 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
// we have to use registration access token retrieved from previous operation
// that ensures optimistic locking semantics
- if (token != null) {
+ if (externalToken != null) {
// we use auth with doPost later
- auth = "Bearer " + token;
+ auth = "Bearer " + externalToken;
- String newToken = token;
+ String newToken = externalToken;
String clientToUpdate = clientId;
saveMergeConfig(cfg -> {
setRegistrationToken(cfg.ensureRealmConfigData(server, realm), clientToUpdate, newToken);
@@ -270,7 +266,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
}
if (attrs.size() > 0) {
- ctx = mergeAttributes(ctx, attrs);
+ ctx = CmdStdinContext.mergeAttributes(ctx, attrs);
}
// now update
@@ -280,14 +276,14 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
if (regType == DEFAULT) {
ClientRepresentation clirep = JsonSerialization.readValue(response, ClientRepresentation.class);
outputResult(clirep);
- token = clirep.getRegistrationAccessToken();
+ externalToken = clirep.getRegistrationAccessToken();
} else if (regType == OIDC) {
OIDCClientRepresentation clirep = JsonSerialization.readValue(response, OIDCClientRepresentation.class);
outputResult(clirep);
- token = clirep.getRegistrationAccessToken();
+ externalToken = clirep.getRegistrationAccessToken();
}
- String newToken = token;
+ String newToken = externalToken;
String clientToUpdate = clientId;
saveMergeConfig(cfg -> {
setRegistrationToken(cfg.ensureRealmConfigData(server, realm), clientToUpdate, newToken);
@@ -310,7 +306,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
@Override
protected boolean nothingToDo() {
- return noOptions() && regType == null && file == null && rawAttributeOperations.isEmpty() && clientId == null;
+ return super.nothingToDo() && regType == null && file == null && rawAttributeOperations.isEmpty() && clientId == null;
}
@Override
@@ -332,7 +328,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcRegMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateTokenCmd.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateTokenCmd.java
index 85f35054b2..219ae8fad6 100644
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateTokenCmd.java
+++ b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/commands/UpdateTokenCmd.java
@@ -22,8 +22,9 @@ import com.fasterxml.jackson.core.type.TypeReference;
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.client.registration.cli.KcRegMain;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.registration.cli.CmdStdinContext;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.util.JsonSerialization;
@@ -33,18 +34,16 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
-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.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.APPLICATION_JSON;
-import static org.keycloak.client.registration.cli.util.HttpUtil.doGet;
-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.PROMPT;
+import static org.keycloak.client.cli.util.ConfigUtil.loadConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.saveMergeConfig;
+import static org.keycloak.client.cli.util.ConfigUtil.setRegistrationToken;
+import static org.keycloak.client.cli.util.HttpUtil.APPLICATION_JSON;
+import static org.keycloak.client.cli.util.HttpUtil.doGet;
+import static org.keycloak.client.cli.util.HttpUtil.doPost;
+import static org.keycloak.client.cli.util.IoUtil.printOut;
+import static org.keycloak.client.cli.util.IoUtil.warnfOut;
+import static org.keycloak.client.cli.util.OsUtil.PROMPT;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
/**
* @author Marko Strukelj
@@ -62,7 +61,7 @@ public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
}
if (clientId.startsWith("-")) {
- warnfOut(ParseUtil.CLIENT_OPTION_WARN, clientId);
+ warnfOut(CmdStdinContext.CLIENT_OPTION_WARN, clientId);
}
ConfigData config = loadConfig();
@@ -116,7 +115,7 @@ public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
@Override
protected boolean nothingToDo() {
- return noOptions() && clientId == null;
+ return super.nothingToDo() && clientId == null;
}
@Override
@@ -136,7 +135,7 @@ public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
out.println();
out.println(" Global options:");
out.println(" -x Print full stack trace when exiting with error");
- out.println(" --config Path to the config file (" + DEFAULT_CONFIG_FILE_STRING + " by default)");
+ out.println(" --config Path to the config file (" + KcRegMain.DEFAULT_CONFIG_FILE_STRING + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
out.println(" --truststore PATH Path to a truststore containing trusted certificates");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/AttributeKey.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/AttributeKey.java
deleted file mode 100644
index 49e3ab4470..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/AttributeKey.java
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.keycloak.client.registration.cli.common;
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-/**
- * @author Marko Strukelj
- */
-public class AttributeKey {
-
- private static final int START = 0;
- private static final int QUOTED = 1;
- private static final int UNQUOTED = 2;
- private static final int END = 3;
-
- private List components;
- private boolean append;
-
- public AttributeKey() {
- components = Collections.emptyList();
- }
-
- public AttributeKey(String key) {
- if (key.endsWith("+")) {
- append = true;
- key = key.substring(0, key.length() - 1);
- }
- components = parse(key);
- }
-
- static List parse(String key) {
-
- if (key == null || "".equals(key)) {
- return Collections.emptyList();
- }
-
- List cs = new LinkedList<>();
- StringBuilder sb = new StringBuilder();
- int state = START;
-
- char[] buf = key.toCharArray();
-
- for (int pos = 0; pos < buf.length; pos++) {
- char c = buf[pos];
-
- if (state == START) {
- if ('\"' == c) {
- state = QUOTED;
- } else if ('.' == c) {
- throw new RuntimeException("Invalid attribute key: " + key + " (at position " + (pos + 1) + ")");
- } else {
- state = UNQUOTED;
- sb.append(c);
- }
- } else if (state == QUOTED) {
- if ('\"' == c) {
- state = END;
- } else {
- sb.append(c);
- }
- } else if (state == UNQUOTED || state == END) {
- if ('.' == c) {
- state = START;
- cs.add(new Component(sb.toString()));
- sb.setLength(0);
- } else if (state == END || '\"' == c) {
- throw new RuntimeException("Invalid attribute key: " + key + " (at position " + (pos + 1) + ")");
- } else {
- sb.append(c);
- }
- }
- }
-
- boolean ok = false;
- if (sb.length() > 0) {
- if (state == UNQUOTED || state == END) {
- cs.add(new Component(sb.toString()));
- ok = true;
- }
- } else if (state == END) {
- ok = true;
- }
-
- if (!ok) {
- throw new RuntimeException("Invalid attribute key: " + key + " (at position " + (buf.length) + ")");
- }
-
- return Collections.unmodifiableList(cs);
- }
-
- public List getComponents() {
- return components;
- }
-
- public boolean isAppend() {
- return append;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- for (Component c: components) {
- if (sb.length() > 0) {
- sb.append(".");
- }
- sb.append(c.toString());
- }
- return sb.toString();
- }
-
-
-
- public static class Component {
-
- private int index = -1;
- private String name;
-
- Component(String name) {
- if (name.endsWith("]")) {
- int pos = name.lastIndexOf("[", name.length() - 1);
- if (pos == -1) {
- throw new RuntimeException("Invalid attribute key: " + name + " (']' not allowed here)");
- }
- String idx = name.substring(pos + 1, name.length() - 1);
- try {
- index = Integer.parseInt(idx);
- } catch (Exception e) {
- throw new RuntimeException("Invalid attribute key: " + name + " (Invalid array index: '[" + idx + "]')");
- }
- this.name = name.substring(0, pos);
- } else {
- this.name = name;
- }
- }
-
- public boolean isArray() {
- return index >= 0;
- }
-
- public int getIndex() {
- return index;
- }
-
- public String getName() {
- return name;
- }
-
- @Override
- public String toString() {
- return name + (index != -1 ? "[" + index + "]" : "");
- }
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/AttributeOperation.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/AttributeOperation.java
deleted file mode 100644
index cfc3a87d02..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/AttributeOperation.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.keycloak.client.registration.cli.common;
-
-/**
- * @author Marko Strukelj
- */
-public class AttributeOperation {
-
- private Type type;
- private AttributeKey key;
- private String value;
-
- public AttributeOperation(Type type, String key) {
- this(type, key, null);
- }
-
- public AttributeOperation(Type type, String key, String value) {
- if (type == Type.DELETE && value != null) {
- throw new IllegalArgumentException("When type is DELETE, value has to be null");
- }
- this.type = type;
- this.key = new AttributeKey(key);
- this.value = value;
- }
-
- public Type getType() {
- return type;
- }
-
- public AttributeKey getKey() {
- return key;
- }
-
- public String getValue() {
- return value;
- }
-
-
- public enum Type {
- SET,
- DELETE
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/CmdStdinContext.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/CmdStdinContext.java
deleted file mode 100644
index b3b31a91cf..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/CmdStdinContext.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.client.registration.cli.common;
-
-import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.representations.oidc.OIDCClientRepresentation;
-
-/**
- * @author Marko Strukelj
- */
-public class CmdStdinContext {
-
- private EndpointType regType;
- private ClientRepresentation client;
- private OIDCClientRepresentation oidcClient;
- private String content;
-
- public CmdStdinContext() {}
-
- public EndpointType getEndpointType() {
- return regType;
- }
-
- public void setEndpointType(EndpointType regType) {
- this.regType = regType;
- }
-
- public ClientRepresentation getClient() {
- return client;
- }
-
- public void setClient(ClientRepresentation client) {
- this.client = client;
- }
-
- public OIDCClientRepresentation getOidcClient() {
- return oidcClient;
- }
-
- public void setOidcClient(OIDCClientRepresentation oidcClient) {
- this.oidcClient = oidcClient;
- }
-
- public String getContent() {
- return content;
- }
-
- public void setContent(String content) {
- this.content = content;
- }
-
- public String getRegistrationAccessToken() {
- if (client != null) {
- return client.getRegistrationAccessToken();
- } else if (oidcClient != null) {
- return oidcClient.getRegistrationAccessToken();
- }
- return null;
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/ParsingContext.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/ParsingContext.java
deleted file mode 100644
index f5fbb78044..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/common/ParsingContext.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.keycloak.client.registration.cli.common;
-
-
-/**
- * An iterator wrapping command line
- *
- * @author Marko Strukelj
- */
-public class ParsingContext {
-
- private int offset;
- private int pos = -1;
- private String [] args;
-
- public ParsingContext(String [] args) {
- this(args, 0, -1);
- }
-
- public ParsingContext(String [] args, int offset) {
- this(args, offset, -1);
- }
-
- public ParsingContext(String [] args, int offset, int pos) {
- this.args = args.clone();
- this.offset = offset;
- this.pos = pos;
- }
-
- public boolean hasNext() {
- return pos < args.length-1;
- }
-
-
- public boolean hasNext(int count) {
- return pos < args.length - count;
- }
-
- public boolean hasPrevious() {
- return pos > 0;
- }
-
- /**
- * Get next argument
- *
- * @return Next argument or null if beyond the end of arguments
- */
- public String next() {
- if (hasNext()) {
- return args[++pos];
- } else {
- pos = args.length;
- return null;
- }
- }
-
- /**
- * Check that a next argument is available
- *
- * @return Next argument or RuntimeException if next argument is not available
- */
- public String nextRequired() {
- if (!hasNext()) {
- throw new RuntimeException("Option " + current() + " requires a value");
- }
- return next();
- }
-
- /**
- * Get next n-th argument
- *
- * @return Next n-th argument or null if beyond the end of arguments
- */
- public String next(int n) {
- if (hasNext(n)) {
- pos += n;
- return args[pos];
- } else {
- pos = args.length;
- return null;
- }
- }
-
- /**
- * Get previous argument
- *
- * @return Previous argument or null if previous call was at the beginning of the arguments (pos == 0)
- */
- public String previous() {
- if (hasPrevious()) {
- return args[--pos];
- } else {
- pos = -1;
- return null;
- }
- }
-
- /**
- * Get current argument
- *
- * @return Current argument or null if current parsing position is beyond end, or before start
- */
- public String current() {
- if (pos < 0 || pos >= args.length) {
- return null;
- } else {
- return args[pos];
- }
- }
-
- public String [] getArgs() {
- return args;
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigData.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigData.java
deleted file mode 100644
index 0ae56e0441..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigData.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.client.registration.cli.config;
-
-import org.keycloak.util.JsonSerialization;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author Marko Strukelj
- */
-public class ConfigData {
-
- private String serverUrl;
-
- private String realm;
-
- private String truststore;
-
- private String trustpass;
-
- private Map> endpoints = new HashMap<>();
-
-
- public String getServerUrl() {
- return serverUrl;
- }
-
- public void setServerUrl(String serverUrl) {
- this.serverUrl = serverUrl;
- }
-
- public String getRealm() {
- return realm;
- }
-
- public void setRealm(String realm) {
- this.realm = realm;
- }
-
- public String getTruststore() {
- return truststore;
- }
-
- public void setTruststore(String truststore) {
- this.truststore = truststore;
- }
-
- public String getTrustpass() {
- return trustpass;
- }
-
- public void setTrustpass(String trustpass) {
- this.trustpass = trustpass;
- }
-
- public Map> getEndpoints() {
- return endpoints;
- }
-
- public void setEndpoints(Map> endpoints) {
- for (Map.Entry> entry: endpoints.entrySet()) {
- String endpoint = entry.getKey();
- for (Map.Entry sub: entry.getValue().entrySet()) {
- RealmConfigData rdata = sub.getValue();
- rdata.serverUrl(endpoint);
- rdata.realm(sub.getKey());
- }
- }
- this.endpoints = endpoints;
- }
-
- public RealmConfigData sessionRealmConfigData() {
- if (serverUrl == null)
- throw new RuntimeException("Illegal state - no current endpoint in config data");
- if (realm == null)
- throw new RuntimeException("Illegal state - no current realm in config data");
- return ensureRealmConfigData(serverUrl, realm);
- }
-
- public RealmConfigData getRealmConfigData(String endpoint, String realm) {
- Map realmData = endpoints.get(endpoint);
- if (realmData == null) {
- return null;
- }
- return realmData.get(realm);
- }
-
- public RealmConfigData ensureRealmConfigData(String endpoint, String realm) {
- RealmConfigData result = getRealmConfigData(endpoint, realm);
- if (result == null) {
- result = new RealmConfigData();
- result.serverUrl(endpoint);
- result.realm(realm);
- setRealmConfigData(result);
- }
- return result;
- }
-
-
- public void setRealmConfigData(RealmConfigData data) {
- Map realm = endpoints.get(data.serverUrl());
- if (realm == null) {
- realm = new HashMap<>();
- endpoints.put(data.serverUrl(), realm);
- }
- realm.put(data.realm(), data);
- }
-
- public void merge(ConfigData source) {
- serverUrl = source.serverUrl;
- realm = source.realm;
- truststore = source.truststore;
- trustpass = source.trustpass;
-
- RealmConfigData current = getRealmConfigData(serverUrl, realm);
- RealmConfigData sourceRealm = source.getRealmConfigData(serverUrl, realm);
-
- if (current == null) {
- setRealmConfigData(sourceRealm);
- } else {
- current.merge(sourceRealm);
- }
- }
-
- public ConfigData deepcopy() {
- ConfigData data = new ConfigData();
- data.serverUrl = serverUrl;
- data.realm = realm;
- data.truststore = truststore;
- data.trustpass = trustpass;
- data.endpoints = new HashMap<>();
-
- for (Map.Entry> item: endpoints.entrySet()) {
-
- Map nuitems = new HashMap<>();
- Map curitems = item.getValue();
-
- if (curitems != null) {
- for (Map.Entry ditem : curitems.entrySet()) {
- RealmConfigData nudata = ditem.getValue();
- if (nudata != null) {
- nuitems.put(ditem.getKey(), nudata.deepcopy());
- }
- }
- data.endpoints.put(item.getKey(), nuitems);
- }
- }
- return data;
- }
-
- @Override
- public String toString() {
- try {
- return JsonSerialization.writeValueAsPrettyString(this);
- } catch (IOException e) {
- return super.toString() + " - Error: " + e.toString();
- }
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigHandler.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigHandler.java
deleted file mode 100644
index 2b33c04560..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigHandler.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package org.keycloak.client.registration.cli.config;
-
-/**
- * @author Marko Strukelj
- */
-public interface ConfigHandler {
-
- void saveMergeConfig(ConfigUpdateOperation op);
-
- ConfigData loadConfig();
-
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigUpdateOperation.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigUpdateOperation.java
deleted file mode 100644
index 98b0c85e33..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/ConfigUpdateOperation.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package org.keycloak.client.registration.cli.config;
-
-/**
- * @author Marko Strukelj
- */
-public interface ConfigUpdateOperation {
-
- void update(ConfigData data);
-
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/FileConfigHandler.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/FileConfigHandler.java
deleted file mode 100644
index 46e7a002ac..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/FileConfigHandler.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.keycloak.client.registration.cli.config;
-
-import org.keycloak.client.registration.cli.util.IoUtil;
-import org.keycloak.util.JsonSerialization;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.nio.channels.OverlappingFileLockException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import static org.keycloak.client.registration.cli.util.IoUtil.printErr;
-
-/**
- * @author Marko Strukelj
- */
-public class FileConfigHandler implements ConfigHandler {
-
- private static final long MAX_SIZE = 10 * 1024 * 1024;
- private static String configFile;
-
- public static void setConfigFile(String filename) {
- configFile = filename;
- }
-
- public static String getConfigFile() {
- return configFile;
- }
-
- public ConfigData loadConfig() {
- // for now just dumb impl ignoring file locks for read
- File file = new File(configFile);
- if (!file.isFile() || file.length() == 0) {
- return new ConfigData();
- }
-
- try {
- try (FileInputStream is = new FileInputStream(configFile)) {
- return JsonSerialization.readValue(is, ConfigData.class);
- }
- } catch (IOException e) {
- throw new RuntimeException("Failed to load " + configFile, e);
- }
- }
-
- public static void ensureFile() {
- Path path = null;
- try {
- path = Paths.get(new File(configFile).getAbsolutePath());
- IoUtil.ensureFile(path);
- } catch (Exception e) {
- throw new RuntimeException("Failed to create config file: " + path, e);
- }
- }
-
- public void saveMergeConfig(ConfigUpdateOperation op) {
- try {
- ensureFile();
-
- try (RandomAccessFile file = new RandomAccessFile(new File(configFile), "rw")) {
- FileChannel fileChannel = file.getChannel();
-
- FileLock fileLock = null;
-
- // lock file for write
- int tryCount = 0;
- do try {
- fileLock = fileChannel.tryLock();
- break;
- } catch (OverlappingFileLockException e) {
- // sleep a little, and try again
- try {
- Thread.sleep(100);
- continue;
- } catch (InterruptedException e1) {
- throw new RuntimeException("Interrupted");
- }
- } while (tryCount++ < 10);
-
- if (fileLock != null) {
- try {
- // load config from file
- ConfigData config = new ConfigData();
- long size = file.length();
- if (size > MAX_SIZE) {
- printErr("Config file " + configFile + " is too big. It will be overwritten.");
- file.setLength(0);
- } else if (size > 0){
- byte[] buf = new byte[(int) size];
- file.readFully(buf);
- config = JsonSerialization.readValue(new ByteArrayInputStream(buf), ConfigData.class);
- }
-
- // update loaded config
- op.update(config);
-
- // save config to file
- byte [] content = JsonSerialization.writeValueAsPrettyString(config).getBytes("utf-8");
- file.seek(0);
- file.write(content);
- file.setLength(content.length);
-
- } finally {
- fileLock.release();
- }
- } else {
- throw new RuntimeException("Failed to get lock on " + configFile);
- }
- }
- } catch (IOException e) {
- throw new RuntimeException("Failed to save " + configFile, e);
- }
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/InMemoryConfigHandler.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/InMemoryConfigHandler.java
deleted file mode 100644
index 1d572b2005..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/config/InMemoryConfigHandler.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.keycloak.client.registration.cli.config;
-
-
-/**
- * @author Marko Strukelj
- */
-public class InMemoryConfigHandler implements ConfigHandler {
-
- private ConfigData cached;
-
- @Override
- public void saveMergeConfig(ConfigUpdateOperation config) {
- config.update(cached);
- }
-
- @Override
- public ConfigData loadConfig() {
- return cached;
- }
-
- public void setConfigData(ConfigData data) {
- this.cached = data;
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AttributeException.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AttributeException.java
deleted file mode 100644
index 30f3caa775..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AttributeException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.keycloak.client.registration.cli.util;
-
-/**
- * @author Marko Strukelj
- */
-public class AttributeException extends RuntimeException {
-
- private final String attrName;
-
- public AttributeException(String attrName, String message) {
- super(message);
- this.attrName = attrName;
- }
-
- public AttributeException(String attrName, String message, Throwable th) {
- super(message, th);
- this.attrName = attrName;
- }
-
- public String getAttributeName() {
- return attrName;
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AuthUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AuthUtil.java
deleted file mode 100644
index be0107b2da..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/AuthUtil.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.client.registration.cli.util;
-
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.config.RealmConfigData;
-import org.keycloak.common.util.KeystoreUtil;
-import org.keycloak.common.util.Time;
-import org.keycloak.jose.jws.JWSBuilder;
-import org.keycloak.representations.AccessTokenResponse;
-import org.keycloak.representations.JsonWebToken;
-import org.keycloak.util.BasicAuthHelper;
-import org.keycloak.util.JsonSerialization;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.security.KeyPair;
-import java.util.UUID;
-
-import static java.lang.System.currentTimeMillis;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.checkAuthInfo;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.saveMergeConfig;
-import static org.keycloak.client.registration.cli.util.HttpUtil.APPLICATION_FORM_URL_ENCODED;
-import static org.keycloak.client.registration.cli.util.HttpUtil.APPLICATION_JSON;
-import static org.keycloak.client.registration.cli.util.HttpUtil.doPost;
-import static org.keycloak.client.registration.cli.util.HttpUtil.urlencode;
-
-/**
- * @author Marko Strukelj
- */
-public class AuthUtil {
-
- public static String ensureToken(ConfigData config) {
-
- checkAuthInfo(config);
-
- RealmConfigData realmConfig = config.sessionRealmConfigData();
-
- long now = currentTimeMillis();
-
- // check expires of access_token against time
- // if it's less than 5s to expiry, renew it
- if (realmConfig.getExpiresAt() - now < 5000) {
-
- // check refresh_token against expiry time
- // if it's less than 5s to expiry, fail with credentials expired
- if (realmConfig.getRefreshExpiresAt() != null && realmConfig.getRefreshExpiresAt() - now < 5000) {
- throw new RuntimeException("Session has expired. Login again with '" + OsUtil.CMD + " config credentials'");
- }
-
- if (realmConfig.getSigExpiresAt() != null && realmConfig.getSigExpiresAt() - now < 5000) {
- throw new RuntimeException("Session has expired. Login again with '" + OsUtil.CMD + " config credentials'");
- }
-
- try {
- String authorization = null;
-
- StringBuilder body = new StringBuilder();
- if (realmConfig.getRefreshToken() != null) {
- body.append("grant_type=refresh_token")
- .append("&refresh_token=").append(realmConfig.getRefreshToken());
- } else {
- body.append("grant_type=").append(realmConfig.getGrantTypeForAuthentication());
- }
-
- body.append("&client_id=").append(urlencode(realmConfig.getClientId()));
-
- if (realmConfig.getSigningToken() != null) {
- body.append("&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
- .append("&client_assertion=").append(realmConfig.getSigningToken());
- } else if (realmConfig.getSecret() != null) {
- authorization = BasicAuthHelper.createHeader(realmConfig.getClientId(), realmConfig.getSecret());
- }
-
- InputStream result = doPost(realmConfig.serverUrl() + "/realms/" + realmConfig.realm() + "/protocol/openid-connect/token",
- APPLICATION_FORM_URL_ENCODED, APPLICATION_JSON, body.toString(), authorization);
-
- AccessTokenResponse token = JsonSerialization.readValue(result, AccessTokenResponse.class);
-
- saveMergeConfig(cfg -> {
- RealmConfigData realmData = cfg.sessionRealmConfigData();
- realmData.setToken(token.getToken());
- realmData.setRefreshToken(token.getRefreshToken());
- realmData.setExpiresAt(currentTimeMillis() + token.getExpiresIn() * 1000);
- if (token.getRefreshToken() != null) {
- realmData.setRefreshExpiresAt(currentTimeMillis() + token.getRefreshExpiresIn() * 1000);
- }
- });
- return token.getToken();
-
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("Unexpected error", e);
- } catch (IOException e) {
- throw new RuntimeException("Failed to read Refresh Token response", e);
- }
- }
-
- return realmConfig.getToken();
- }
-
- public static AccessTokenResponse getAuthTokens(String server, String realm, String user, String password, String clientId) {
- StringBuilder body = new StringBuilder();
- try {
- body.append("grant_type=password")
- .append("&username=").append(urlencode(user))
- .append("&password=").append(urlencode(password))
- .append("&client_id=").append(urlencode(clientId));
-
- InputStream result = doPost(server + "/realms/" + realm + "/protocol/openid-connect/token",
- APPLICATION_FORM_URL_ENCODED, APPLICATION_JSON, body.toString(), null);
- return JsonSerialization.readValue(result, AccessTokenResponse.class);
-
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("Unexpected error: ", e);
- } catch (IOException e) {
- throw new RuntimeException("Error receiving response: ", e);
- }
- }
-
- public static AccessTokenResponse getAuthTokensByJWT(String server, String realm, String user, String password, String clientId, String signedRequestToken) {
- StringBuilder body = new StringBuilder();
- try {
- body.append("client_id=").append(urlencode(clientId))
- .append("&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
- .append("&client_assertion=").append(signedRequestToken);
-
- if (user != null) {
- if (password == null) {
- throw new RuntimeException("No password specified");
- }
- body.append("&grant_type=password")
- .append("&username=").append(urlencode(user))
- .append("&password=").append(urlencode(password));
- } else {
- body.append("&grant_type=client_credentials");
- }
-
- InputStream result = doPost(server + "/realms/" + realm + "/protocol/openid-connect/token",
- APPLICATION_FORM_URL_ENCODED, APPLICATION_JSON, body.toString(), null);
- return JsonSerialization.readValue(result, AccessTokenResponse.class);
-
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("Unexpected error: ", e);
- } catch (IOException e) {
- throw new RuntimeException("Error receiving response: ", e);
- }
- }
-
- public static AccessTokenResponse getAuthTokensBySecret(String server, String realm, String user, String password, String clientId, String secret) {
-
- StringBuilder body = new StringBuilder();
- try {
- if (user != null) {
- if (password == null) {
- throw new RuntimeException("No password specified");
- }
-
- body.append("client_id=").append(urlencode(clientId))
- .append("&grant_type=password")
- .append("&username=").append(urlencode(user))
- .append("&password=").append(urlencode(password));
- } else {
- body.append("grant_type=client_credentials");
- }
-
- InputStream result = doPost(server + "/realms/" + realm + "/protocol/openid-connect/token",
- APPLICATION_FORM_URL_ENCODED, APPLICATION_JSON, body.toString(), BasicAuthHelper.createHeader(clientId, secret));
- return JsonSerialization.readValue(result, AccessTokenResponse.class);
-
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("Unexpected error: ", e);
- } catch (IOException e) {
- throw new RuntimeException("Error receiving response: ", e);
- }
- }
-
- public static String getSignedRequestToken(String keystore, String storePass, String keyPass, String alias, int sigLifetime, String clientId, String realmInfoUrl) {
-
- KeystoreUtil.KeystoreFormat keystoreType = Enum.valueOf(KeystoreUtil.KeystoreFormat.class, KeystoreUtil.getKeystoreType(null, keystore, KeystoreUtil.KeystoreFormat.JKS.toString()));
- KeyPair keypair = KeystoreUtil.loadKeyPairFromKeystore(keystore, storePass, keyPass, alias, keystoreType);
-
- JsonWebToken reqToken = new JsonWebToken();
- reqToken.id(UUID.randomUUID().toString());
- reqToken.issuer(clientId);
- reqToken.subject(clientId);
- reqToken.audience(realmInfoUrl);
-
- int now = Time.currentTime();
- reqToken.issuedAt(now);
- reqToken.expiration(now + sigLifetime);
- reqToken.notBefore(now);
-
- String signedRequestToken = new JWSBuilder()
- .jsonContent(reqToken)
- .rsa256(keypair.getPrivate());
- return signedRequestToken;
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ClassLoaderUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ClassLoaderUtil.java
deleted file mode 100644
index 72e2b2f5f2..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ClassLoaderUtil.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2022 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-package org.keycloak.client.registration.cli.util;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.stream.Stream;
-
-/**
- * @author Marek Posolda
- */
-public class ClassLoaderUtil {
-
- /**
- * Detect if BC FIPS jars are present in the given directory. Return classloader with appropriate JARS based on that
- */
- public static ClassLoader resolveClassLoader(String libDir) {
- File[] jarsInDir = new File(libDir).listFiles(file -> file.getName().endsWith(".jar"));
-
- // Detect if BC FIPS jars are present in the "client/lib" directory
- boolean bcFipsJarPresent = Stream.of(jarsInDir).anyMatch(file -> file.getName().startsWith("bc-fips"));
- String[] validJarPrefixes = bcFipsJarPresent ? new String[] {"keycloak-crypto-fips1402", "bc-fips", "bctls-fips"} : new String[] {"keycloak-crypto-default", "bcprov-jdk18on"};
- URL[] usedJars = Stream.of(jarsInDir)
- .filter(file -> {
- for (String prefix : validJarPrefixes) {
- if (file.getName().startsWith(prefix + "-")) return true;
- }
- return false;
- })
- .map(file -> {
- try {
- return file.toURI().toURL();
- } catch (MalformedURLException ex) {
- throw new IllegalStateException("Error when converting file into URL. Please check the files in the directory " + jarsInDir, ex);
- }
- }).toArray(URL[]::new);
-
- return new URLClassLoader(usedJars, ClassLoaderUtil.class.getClassLoader());
- }
-
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ConfigUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ConfigUtil.java
deleted file mode 100644
index 8d1050f2f8..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/ConfigUtil.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.client.registration.cli.util;
-
-import org.keycloak.OAuth2Constants;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.config.ConfigHandler;
-import org.keycloak.client.registration.cli.config.ConfigUpdateOperation;
-import org.keycloak.client.registration.cli.config.InMemoryConfigHandler;
-import org.keycloak.client.registration.cli.config.RealmConfigData;
-import org.keycloak.representations.AccessTokenResponse;
-
-/**
- * @author Marko Strukelj
- */
-public class ConfigUtil {
-
- public static final String DEFAULT_CONFIG_FILE_STRING = OsUtil.OS_ARCH.isWindows() ? "%HOMEDRIVE%%HOMEPATH%\\.keycloak\\kcreg.config" : "~/.keycloak/kcreg.config";
-
- public static final String DEFAULT_CONFIG_FILE_PATH = System.getProperty("user.home") + "/.keycloak/kcreg.config";
-
- private static ConfigHandler handler;
-
- public static ConfigHandler getHandler() {
- return handler;
- }
-
- public static void setHandler(ConfigHandler handler) {
- ConfigUtil.handler = handler;
- }
-
- public static String getRegistrationToken(RealmConfigData data, String clientId) {
- String token = data.getClients().get(clientId);
- return token == null || token.length() == 0 ? null : token;
- }
-
- public static void setRegistrationToken(RealmConfigData data, String clientId, String token) {
- data.getClients().put(clientId, token == null ? "" : token);
- }
-
- public static void saveTokens(AccessTokenResponse tokens, String endpoint, String realm, String clientId, String signKey, Long sigExpiresAt, String secret,
- String grantTypeForAuthentication) {
- handler.saveMergeConfig(config -> {
- config.setServerUrl(endpoint);
- config.setRealm(realm);
-
- RealmConfigData realmConfig = config.ensureRealmConfigData(endpoint, realm);
- realmConfig.setToken(tokens.getToken());
- realmConfig.setRefreshToken(tokens.getRefreshToken());
- realmConfig.setSigningToken(signKey);
- realmConfig.setSecret(secret);
- realmConfig.setExpiresAt(System.currentTimeMillis() + tokens.getExpiresIn() * 1000);
- if (realmConfig.getRefreshToken() != null) {
- realmConfig.setRefreshExpiresAt(tokens.getRefreshExpiresIn() == 0 ?
- Long.MAX_VALUE : System.currentTimeMillis() + tokens.getRefreshExpiresIn() * 1000);
- }
- realmConfig.setSigExpiresAt(sigExpiresAt);
- realmConfig.setClientId(clientId);
- realmConfig.setGrantTypeForAuthentication(grantTypeForAuthentication);
- });
- }
-
- public static void checkServerInfo(ConfigData config) {
- if (config.getServerUrl() == null || config.getRealm() == null) {
- throw new RuntimeException("No server or realm specified. Use --server, --realm, or '" + OsUtil.CMD + " config credentials'.");
- }
- }
-
- public static void checkAuthInfo(ConfigData config) {
- checkServerInfo(config);
- }
-
- public static boolean credentialsAvailable(ConfigData config) {
- // Just supporting "client_credentials" grant type for the case when refresh token is missing
- boolean credsAvailable = config.getServerUrl() != null && config.getRealm() != null
- && config.sessionRealmConfigData() != null &&
- (config.sessionRealmConfigData().getRefreshToken() != null || (config.sessionRealmConfigData().getToken() != null && OAuth2Constants.CLIENT_CREDENTIALS.equals(config.sessionRealmConfigData().getGrantTypeForAuthentication())));
- return credsAvailable;
- }
-
- public static ConfigData loadConfig() {
- if (handler == null) {
- throw new RuntimeException("No ConfigHandler set");
- }
-
- return handler.loadConfig();
- }
-
- public static void saveMergeConfig(ConfigUpdateOperation op) {
- if (handler == null) {
- throw new RuntimeException("No ConfigHandler set");
- }
-
- handler.saveMergeConfig(op);
- }
-
- public static void setupInMemoryHandler(ConfigData config) {
- InMemoryConfigHandler memhandler = null;
- if (handler instanceof InMemoryConfigHandler) {
- memhandler = (InMemoryConfigHandler) handler;
- } else {
- memhandler = new InMemoryConfigHandler();
- handler = memhandler;
- }
- memhandler.setConfigData(config);
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/DebugBufferedInputStream.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/DebugBufferedInputStream.java
deleted file mode 100644
index fa200d660e..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/DebugBufferedInputStream.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package org.keycloak.client.registration.cli.util;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * @author Marko Strukelj
- */
-public class DebugBufferedInputStream extends BufferedInputStream {
-
- public DebugBufferedInputStream(InputStream in) {
- super(in);
- }
-
- @Override
- public synchronized int read() throws IOException {
- log("read() >>>");
- int b = super.read();
- log("read() <<< " + (char) b + " (" + b + ")");
- return b;
- }
-
- @Override
- public synchronized int read(byte[] b, int off, int len) throws IOException {
- log("read(buf, off, len) >>>");
- int c = super.read(b, off, len);
- log("read(buf, off, len) <<< " + (c != -1 ? "[" + new String(b, off, c) + "]" : "-1"));
- return c;
- }
-
- @Override
- public synchronized long skip(long n) throws IOException {
- log("skip()");
- return super.skip(n);
- }
-
- @Override
- public synchronized int available() throws IOException {
- log("available() >>>");
- int c = super.available();
- log("available() >>> " + c);
- return c;
- }
-
- @Override
- public synchronized void mark(int readlimit) {
- log("mark()");
- super.mark(readlimit);
- }
-
- @Override
- public synchronized void reset() throws IOException {
- log("reset()");
- super.reset();
- }
-
- @Override
- public boolean markSupported() {
- log("markSupported()");
- return super.markSupported();
- }
-
- @Override
- public void close() throws IOException {
- log("close()");
- super.close();
- }
-
- @Override
- public int read(byte[] b) throws IOException {
- return read(b, 0, b.length);
- }
-
- private void log(String msg) {
- System.err.println(msg);
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/HttpUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/HttpUtil.java
deleted file mode 100644
index 6f2c58f764..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/HttpUtil.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.client.registration.cli.util;
-
-import org.apache.http.Header;
-import org.apache.http.HttpHeaders;
-import org.apache.http.HttpResponse;
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpDelete;
-import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
-import org.apache.http.client.methods.HttpPut;
-import org.apache.http.client.methods.HttpRequestBase;
-import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
-import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
-import org.apache.http.ssl.SSLContextBuilder;
-import org.apache.http.ssl.SSLContexts;
-import org.apache.http.entity.StringEntity;
-import org.apache.http.impl.client.HttpClientBuilder;
-import org.keycloak.client.registration.cli.common.EndpointType;
-import org.keycloak.util.JsonSerialization;
-
-import javax.net.ssl.SSLContext;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.security.KeyManagementException;
-
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * @author Marko Strukelj
- */
-public class HttpUtil {
-
- public static final String APPLICATION_XML = "application/xml";
- public static final String APPLICATION_JSON = "application/json";
- public static final String APPLICATION_FORM_URL_ENCODED = "application/x-www-form-urlencoded";
- public static final String UTF_8 = "utf-8";
-
- private static HttpClient httpClient;
- private static SSLConnectionSocketFactory sslsf;
- private static final AtomicBoolean tlsWarningEmitted = new AtomicBoolean();
-
- public static InputStream doGet(String url, String acceptType, String authorization) {
- try {
- HttpGet request = new HttpGet(url);
- request.setHeader(HttpHeaders.ACCEPT, acceptType);
- return doRequest(authorization, request);
- } catch (IOException e) {
- throw new RuntimeException("Failed to send request - " + e.getMessage(), e);
- }
- }
-
- public static InputStream doPost(String url, String contentType, String acceptType, String content, String authorization) {
- try {
- return doPostOrPut(contentType, acceptType, content, authorization, new HttpPost(url));
- } catch (IOException e) {
- throw new RuntimeException("Failed to send request - " + e.getMessage(), e);
- }
- }
-
- public static InputStream doPut(String url, String contentType, String acceptType, String content, String authorization) {
- try {
- return doPostOrPut(contentType, acceptType, content, authorization, new HttpPut(url));
- } catch (IOException e) {
- throw new RuntimeException("Failed to send request - " + e.getMessage(), e);
- }
- }
-
- public static void doDelete(String url, String authorization) {
- try {
- HttpDelete request = new HttpDelete(url);
- doRequest(authorization, request);
- } catch (IOException e) {
- throw new RuntimeException("Failed to send request - " + e.getMessage(), e);
- }
- }
-
- private static InputStream doPostOrPut(String contentType, String acceptType, String content, String authorization, HttpEntityEnclosingRequestBase request) throws IOException {
- request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
- request.setHeader(HttpHeaders.ACCEPT, acceptType);
- if (content != null) {
- request.setEntity(new StringEntity(content));
- }
-
- return doRequest(authorization, request);
- }
-
- private static InputStream doRequest(String authorization, HttpRequestBase request) throws IOException {
- addAuth(request, authorization);
-
- HttpResponse response = getHttpClient().execute(request);
- InputStream responseStream = null;
- if (response.getEntity() != null) {
- responseStream = response.getEntity().getContent();
- }
-
- int code = response.getStatusLine().getStatusCode();
- if (code >= 200 && code < 300) {
- return responseStream;
- } else {
- Map error = null;
- try {
- Header header = response.getEntity().getContentType();
- if (header != null && APPLICATION_JSON.equals(header.getValue())) {
- error = JsonSerialization.readValue(responseStream, Map.class);
- }
- } catch (Exception e) {
- throw new RuntimeException("Failed to read error response - " + e.getMessage(), e);
- } finally {
- responseStream.close();
- }
-
- String message = null;
- if (error != null) {
- message = error.get("error_description") + " [" + error.get("error") + "]";
- }
- throw new RuntimeException(message != null ? message : response.getStatusLine().getStatusCode() + " " + response.getStatusLine().getReasonPhrase());
- }
- }
-
- private static void addAuth(HttpRequestBase request, String authorization) {
- if (authorization != null) {
- request.setHeader(HttpHeaders.AUTHORIZATION, authorization);
- }
- }
-
- public static HttpClient getHttpClient() {
- if (httpClient == null) {
- if (sslsf != null) {
- httpClient = HttpClientBuilder.create().useSystemProperties().setSSLSocketFactory(sslsf).build();
- } else {
- httpClient = HttpClientBuilder.create().useSystemProperties().build();
- }
- }
- return httpClient;
- }
-
- public static String getExpectedContentType(EndpointType type) {
- switch (type) {
- case DEFAULT:
- case OIDC:
- return APPLICATION_JSON;
- case SAML2:
- return APPLICATION_XML;
- default:
- throw new RuntimeException("Unsupported endpoint type: " + type);
- }
- }
-
- public static String urlencode(String value) {
- try {
- return URLEncoder.encode(value, UTF_8);
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException("Failed to urlencode", e);
- }
- }
-
- public static void setTruststore(File file, String password) throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, KeyManagementException {
- if (!file.isFile()) {
- throw new RuntimeException("Truststore file not found: " + file.getAbsolutePath());
- }
- SSLContext theContext = SSLContexts.custom()
- .useProtocol("TLS")
- .loadTrustMaterial(file, password == null ? null : password.toCharArray(), TrustSelfSignedStrategy.INSTANCE)
- .build();
- sslsf = new SSLConnectionSocketFactory(theContext);
- }
-
- public static void setSkipCertificateValidation() {
- if (!tlsWarningEmitted.getAndSet(true)) {
- // Since this is a static util, it may happen that TLS is setup many times in one command
- // invocation (e.g. when a command requires logging in). However, we would like to
- // prevent this warning from appearing multiple times. That's why we need to guard it with a boolean.
- System.err.println("The server is configured to use TLS but there is no truststore specified.");
- System.err.println("The tool will skip certificate validation. This is highly discouraged for production use cases");
- }
-
- SSLContextBuilder builder = new SSLContextBuilder();
- try {
- builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
- sslsf = new SSLConnectionSocketFactory(builder.build());
- } catch (Exception e) {
- throw new RuntimeException("Failed setting up TLS", e);
- }
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/IoUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/IoUtil.java
deleted file mode 100644
index e1c38d38c8..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/IoUtil.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2016 Red Hat, Inc. and/or its affiliates
- * and other contributors as indicated by the @author tags.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.keycloak.client.registration.cli.util;
-
-import java.io.Console;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.attribute.AclEntry;
-import java.nio.file.attribute.AclEntryPermission;
-import java.nio.file.attribute.AclEntryType;
-import java.nio.file.attribute.AclFileAttributeView;
-import java.nio.file.attribute.PosixFilePermission;
-import java.nio.file.attribute.UserPrincipal;
-import java.util.Formatter;
-import java.util.HashSet;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Set;
-
-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;
-
-/**
- * @author Marko Strukelj
- */
-public class IoUtil {
-
- public static String readFileOrStdin(String file) {
- String content;
- if ("-".equals(file)) {
- content = readFully(System.in);
- } else {
- try (InputStream is = new FileInputStream(file)) {
- content = readFully(is);
- } catch (FileNotFoundException e) {
- throw new RuntimeException("File not found: " + file);
- } catch (IOException e) {
- throw new RuntimeException("Failed to read file: " + file, e);
- }
- }
- return content;
- }
-
- public static void waitFor(long millis) {
- try {
- Thread.sleep(millis);
- } catch (InterruptedException e) {
- throw new RuntimeException("Interrupted");
- }
- }
-
- 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);
- }
- throw new RuntimeException("Console is not active, or no password provided");
- }
-
- public static String readFully(InputStream is) {
- Charset charset = Charset.forName("utf-8");
- StringBuilder out = new StringBuilder();
- byte [] buf = new byte[8192];
-
- int rc;
- try {
- while ((rc = is.read(buf)) != -1) {
- out.append(new String(buf, 0, rc, charset));
- }
- } catch (Exception e) {
- throw new RuntimeException("Failed to read stream", e);
- }
- return out.toString();
- }
-
- public static void ensureFile(Path path) throws IOException {
-
- FileSystem fs = FileSystems.getDefault();
- Set supportedViews = fs.supportedFileAttributeViews();
- Path parent = path.getParent();
-
- if (!isDirectory(parent)) {
- createDirectories(parent);
- // make sure only owner can read/write it
- if (supportedViews.contains("posix")) {
- setUnixPermissions(parent);
- } else if (supportedViews.contains("acl")) {
- setWindowsPermissions(parent);
- } else {
- warnErr("Failed to restrict access permissions on .keycloak directory: " + parent);
- }
- }
- if (!isRegularFile(path)) {
- createFile(path);
- // make sure only owner can read/write it
- if (FileSystems.getDefault().supportedFileAttributeViews().contains("posix")) {
- setUnixPermissions(path);
- } else if (supportedViews.contains("acl")) {
- setWindowsPermissions(path);
- } else {
- warnErr("Failed to restrict access permissions on config file: " + path);
- }
- }
- }
-
- private static void setUnixPermissions(Path path) throws IOException {
- Set perms = new HashSet<>();
- perms.add(PosixFilePermission.OWNER_READ);
- perms.add(PosixFilePermission.OWNER_WRITE);
- if (isDirectory(path)) {
- perms.add(PosixFilePermission.OWNER_EXECUTE);
- }
- Files.setPosixFilePermissions(path, perms);
- }
-
- private static void setWindowsPermissions(Path path) throws IOException {
- AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class);
- UserPrincipal owner = view.getOwner();
- List acl = view.getAcl();
- ListIterator it = acl.listIterator();
- while (it.hasNext()) {
- AclEntry entry = it.next();
- if ("BUILTIN\\Administrators".equals(entry.principal().getName()) || "NT AUTHORITY\\SYSTEM".equals(entry.principal().getName())) {
- continue;
- }
- it.remove();
- }
- AclEntry entry = AclEntry.newBuilder()
- .setType(AclEntryType.ALLOW)
- .setPrincipal(owner)
- .setPermissions(AclEntryPermission.READ_DATA, AclEntryPermission.WRITE_DATA,
- AclEntryPermission.APPEND_DATA, AclEntryPermission.READ_NAMED_ATTRS,
- AclEntryPermission.WRITE_NAMED_ATTRS, AclEntryPermission.EXECUTE,
- AclEntryPermission.READ_ATTRIBUTES, AclEntryPermission.WRITE_ATTRIBUTES,
- AclEntryPermission.DELETE, AclEntryPermission.READ_ACL, AclEntryPermission.SYNCHRONIZE)
- .build();
- acl.add(entry);
- view.setAcl(acl);
- }
-
- public static void printOut(String msg) {
- System.out.println(msg);
- }
-
- public static void printErr(String msg) {
- System.err.println(msg);
- }
-
- public static void printfOut(String format, String ... params) {
- System.out.println(new Formatter().format("WARN: " + format, params));
- }
-
- public static void warnOut(String msg) {
- System.out.println("WARN: " + msg);
- }
-
- public static void warnErr(String msg) {
- System.err.println("WARN: " + msg);
- }
-
- public static void warnfOut(String format, String ... params) {
- System.out.println(new Formatter().format("WARN: " + format, params));
- }
-
- public static void warnfErr(String format, String ... params) {
- System.err.println(new Formatter().format("WARN: " + format, params));
- }
-
- public static void logOut(String msg) {
- System.out.println("LOG: " + msg);
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/OsArch.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/OsArch.java
deleted file mode 100644
index 823d1fbb07..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/OsArch.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2014 Red Hat, Inc. and/or its affiliates.
- *
- * Licensed under the Eclipse Public License version 1.0, available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.keycloak.client.registration.cli.util;
-
-/**
- * @author Marko Strukelj
- */
-public class OsArch {
-
- private String os;
- private String arch;
- private boolean legacy;
-
- public OsArch(String os, String arch) {
- this(os, arch, false);
- }
-
- public OsArch(String os, String arch, boolean legacy) {
- this.os = os;
- this.arch = arch;
- this.legacy = legacy;
- }
-
- public String os() {
- return os;
- }
-
- public String arch() {
- return arch;
- }
-
- public boolean isLegacy() {
- return legacy;
- }
-
- public boolean isWindows() {
- return "win32".equals(os);
- }
-
- public String envVar(String var) {
- if (isWindows()) {
- return "%" + var + "%";
- } else {
- return "$" + var;
- }
- }
-
- public String path(String path) {
- if (isWindows()) {
- path = path.replaceAll("/", "\\\\");
- if (path.startsWith("~")) {
- path = "%HOMEPATH%" + path.substring(1);
- }
- }
- return path;
- }
-}
\ No newline at end of file
diff --git a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/OsUtil.java b/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/OsUtil.java
deleted file mode 100644
index 1dd54b1348..0000000000
--- a/integration/client-cli/client-registration-cli/src/main/java/org/keycloak/client/registration/cli/util/OsUtil.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package org.keycloak.client.registration.cli.util;
-
-/**
- * @author Marko Strukelj
- */
-public class OsUtil {
-
- public static final OsArch OS_ARCH = determineOSAndArch();
-
- public static final String CMD = OS_ARCH.isWindows() ? "kcreg.bat" : "kcreg.sh";
-
- public static final String PROMPT = OS_ARCH.isWindows() ? "c:\\>" : "$";
-
- public static final String EOL = OS_ARCH.isWindows() ? "\r\n" : "\n";
-
-
- public static OsArch determineOSAndArch() {
- String os = System.getProperty("os.name").toLowerCase();
- String arch = System.getProperty("os.arch");
-
- if (arch.equals("amd64")) {
- arch = "x86_64";
- }
-
- if (os.startsWith("linux")) {
- if (arch.equals("x86") || arch.equals("i386") || arch.equals("i586")) {
- arch = "i686";
- }
- return new OsArch("linux", arch);
- } else if (os.startsWith("windows")) {
- if (arch.equals("x86")) {
- arch = "i386";
- }
- if (os.indexOf("2008") != -1 || os.indexOf("2003") != -1 || os.indexOf("vista") != -1) {
- return new OsArch("win32", arch, true);
- } else {
- return new OsArch("win32", arch);
- }
- } else if (os.startsWith("sunos")) {
- return new OsArch("sunos5", "x86_64");
- } else if (os.startsWith("mac os x")) {
- return new OsArch("osx", "x86_64");
- } else if (os.startsWith("freebsd")) {
- return new OsArch("freebsd", arch);
- } else if (os.startsWith("openbsd")) {
- return new OsArch("openbsd", arch);
- }
-
- // unsupported platform
- throw new RuntimeException("Could not determine OS and architecture for this operating system: " + os);
- }
-}
diff --git a/integration/client-cli/client-registration-cli/src/test/java/org/keycloak/client/registration/cli/util/ReflectionUtilTest.java b/integration/client-cli/client-registration-cli/src/test/java/org/keycloak/client/registration/cli/ReflectionUtilTest.java
similarity index 96%
rename from integration/client-cli/client-registration-cli/src/test/java/org/keycloak/client/registration/cli/util/ReflectionUtilTest.java
rename to integration/client-cli/client-registration-cli/src/test/java/org/keycloak/client/registration/cli/ReflectionUtilTest.java
index 2a20e54bcd..85423f0c31 100644
--- a/integration/client-cli/client-registration-cli/src/test/java/org/keycloak/client/registration/cli/util/ReflectionUtilTest.java
+++ b/integration/client-cli/client-registration-cli/src/test/java/org/keycloak/client/registration/cli/ReflectionUtilTest.java
@@ -1,11 +1,12 @@
-package org.keycloak.client.registration.cli.util;
+package org.keycloak.client.registration.cli;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
-import org.keycloak.client.registration.cli.common.AttributeKey;
-import org.keycloak.client.registration.cli.common.AttributeKey.Component;
-import org.keycloak.client.registration.cli.common.AttributeOperation;
+import org.keycloak.client.cli.common.AttributeKey;
+import org.keycloak.client.cli.common.AttributeOperation;
+import org.keycloak.client.cli.common.AttributeKey.Component;
+import org.keycloak.client.registration.cli.ReflectionUtil;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
@@ -18,8 +19,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import static org.keycloak.client.registration.cli.common.AttributeOperation.Type.DELETE;
-import static org.keycloak.client.registration.cli.common.AttributeOperation.Type.SET;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.DELETE;
+import static org.keycloak.client.cli.common.AttributeOperation.Type.SET;
/**
* @author Marko Strukelj
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/cli/exec/AbstractExec.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/cli/exec/AbstractExec.java
index e7cd34de86..42eda58f73 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/cli/exec/AbstractExec.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/cli/exec/AbstractExec.java
@@ -1,6 +1,6 @@
package org.keycloak.testsuite.cli.exec;
-import org.keycloak.client.admin.cli.util.OsUtil;
+import org.keycloak.client.cli.util.OsUtil;
import org.keycloak.testsuite.cli.OsArch;
import org.keycloak.testsuite.cli.OsUtils;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
index 5031d27247..300ba1476c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/FineGrainAdminUnitTest.java
@@ -25,7 +25,7 @@ import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
-import org.keycloak.client.admin.cli.util.ConfigUtil;
+import org.keycloak.client.cli.util.ConfigUtil;
import org.keycloak.common.Profile;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/AbstractAdmCliTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/AbstractAdmCliTest.java
index a9afe73139..a69a060217 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/AbstractAdmCliTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/AbstractAdmCliTest.java
@@ -3,9 +3,9 @@ package org.keycloak.testsuite.cli.admin;
import org.junit.Assert;
import org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthenticator;
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
-import org.keycloak.client.admin.cli.config.ConfigData;
-import org.keycloak.client.admin.cli.config.FileConfigHandler;
-import org.keycloak.client.admin.cli.config.RealmConfigData;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.RealmConfigData;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmCreateTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmCreateTest.java
index 9766aa9c60..106f4f53b5 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmCreateTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmCreateTest.java
@@ -3,7 +3,7 @@ package org.keycloak.testsuite.cli.admin;
import org.junit.Assert;
import org.junit.Test;
import org.keycloak.admin.client.resource.RealmResource;
-import org.keycloak.client.admin.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.FileConfigHandler;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.testsuite.cli.KcAdmExec;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmSessionTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmSessionTest.java
index d6c7611108..a8c686e580 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmSessionTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmSessionTest.java
@@ -4,7 +4,7 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.junit.Assert;
import org.junit.Test;
-import org.keycloak.client.admin.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.FileConfigHandler;
import org.keycloak.testsuite.cli.KcAdmExec;
import org.keycloak.testsuite.util.TempFileResource;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTest.java
index 9641aa7d84..17a8d3e58c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTest.java
@@ -2,9 +2,9 @@ package org.keycloak.testsuite.cli.admin;
import org.junit.Assert;
import org.junit.Test;
-import org.keycloak.client.admin.cli.config.ConfigData;
-import org.keycloak.client.admin.cli.config.FileConfigHandler;
-import org.keycloak.client.admin.cli.config.RealmConfigData;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.RealmConfigData;
import org.keycloak.common.util.KeystoreUtil;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.testsuite.cli.KcAdmExec;
@@ -18,8 +18,8 @@ import java.io.IOException;
import java.util.List;
import java.util.UUID;
-import static org.keycloak.client.admin.cli.util.OsUtil.CMD;
-import static org.keycloak.client.admin.cli.util.OsUtil.EOL;
+import static org.keycloak.client.admin.cli.KcAdmMain.CMD;
+import static org.keycloak.client.cli.util.OsUtil.EOL;
import static org.keycloak.testsuite.cli.KcAdmExec.execute;
/**
@@ -67,7 +67,7 @@ public class KcAdmTest extends AbstractAdmCliTest {
exe = KcAdmExec.execute("config credentials");
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 --user USER [--password PASSWORD] [ARGUMENTS]", exe.stdoutLines().get(0));
+ Assert.assertEquals("help message", " " + CMD + " config credentials --server SERVER_URL --realm REALM --user USER [--password PASSWORD] [ARGUMENTS]", exe.stdoutLines().get(1));
exe = KcAdmExec.execute("config truststore");
assertExitCodeAndStdErrSize(exe, 2, 0);
@@ -184,9 +184,9 @@ public class KcAdmTest extends AbstractAdmCliTest {
exe = KcAdmExec.execute("config credentials --help");
assertExitCodeAndStdErrSize(exe, 0, 0);
- Assert.assertEquals("stdout first line",
- "Usage: " + CMD + " config credentials --server SERVER_URL --realm REALM --user USER [--password PASSWORD] [ARGUMENTS]",
- exe.stdoutLines().get(0));
+ Assert.assertEquals("stdout line",
+ " " + CMD + " config credentials --server SERVER_URL --realm REALM --user USER [--password PASSWORD] [ARGUMENTS]",
+ exe.stdoutLines().get(1));
exe = KcAdmExec.execute("config truststore --help");
assertExitCodeAndStdErrSize(exe, 0, 0);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTruststoreTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTruststoreTest.java
index 2e64c72517..fced3bfbfc 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTruststoreTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmTruststoreTest.java
@@ -2,9 +2,9 @@ package org.keycloak.testsuite.cli.admin;
import org.junit.Assert;
import org.junit.Test;
-import org.keycloak.client.admin.cli.config.ConfigData;
-import org.keycloak.client.admin.cli.config.FileConfigHandler;
-import org.keycloak.client.admin.cli.util.OsUtil;
+import org.keycloak.client.admin.cli.KcAdmMain;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.FileConfigHandler;
import org.keycloak.testsuite.cli.KcAdmExec;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.TempFileResource;
@@ -12,8 +12,8 @@ import org.keycloak.testsuite.util.TempFileResource;
import java.io.File;
import java.io.IOException;
-import static org.keycloak.client.admin.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_PATH;
-import static org.keycloak.client.admin.cli.util.OsUtil.EOL;
+import static org.keycloak.client.admin.cli.KcAdmMain.DEFAULT_CONFIG_FILE_PATH;
+import static org.keycloak.client.cli.util.OsUtil.EOL;
import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_SSL_REQUIRED;
import static org.keycloak.testsuite.cli.KcAdmExec.execute;
@@ -31,7 +31,7 @@ public class KcAdmTruststoreTest extends AbstractAdmCliTest {
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 + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
+ Assert.assertEquals("try help", "Try '" + KcAdmMain.CMD + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
// only run this test if ssl protected keycloak server is available
if (!AUTH_SERVER_SSL_REQUIRED) {
@@ -101,12 +101,12 @@ public class KcAdmTruststoreTest extends AbstractAdmCliTest {
exe = execute("config truststore --delete '" + truststore.getAbsolutePath() + "'");
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 '" + OsUtil.CMD + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
+ Assert.assertEquals("try help", "Try '" + KcAdmMain.CMD + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
exe = execute("config truststore --delete --trustpass secret");
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 '" + OsUtil.CMD + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
+ Assert.assertEquals("try help", "Try '" + KcAdmMain.CMD + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
FileConfigHandler cfghandler = new FileConfigHandler();
FileConfigHandler.setConfigFile(DEFAULT_CONFIG_FILE_PATH);
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmUpdateTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmUpdateTest.java
index 3f537d8353..002e3ec7e4 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmUpdateTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/admin/KcAdmUpdateTest.java
@@ -2,7 +2,6 @@ package org.keycloak.testsuite.cli.admin;
import org.junit.Assert;
import org.junit.Test;
-import org.keycloak.client.admin.cli.config.FileConfigHandler;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.testsuite.cli.KcAdmExec;
import org.keycloak.testsuite.util.TempFileResource;
@@ -18,6 +17,7 @@ import static org.hamcrest.Matchers.is;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.broker.saml.SAMLIdentityProviderConfig;
import org.keycloak.broker.saml.SAMLIdentityProviderFactory;
+import org.keycloak.client.cli.config.FileConfigHandler;
import org.keycloak.representations.idm.IdentityProviderRepresentation;
import static org.hamcrest.MatcherAssert.assertThat;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/AbstractRegCliTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/AbstractRegCliTest.java
index 30e5816a59..6d4f1686df 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/AbstractRegCliTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/AbstractRegCliTest.java
@@ -6,9 +6,9 @@ import org.keycloak.admin.client.resource.ClientInitialAccessResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.authentication.authenticators.client.ClientIdAndSecretAuthenticator;
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.config.FileConfigHandler;
-import org.keycloak.client.registration.cli.config.RealmConfigData;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.RealmConfigData;
import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
import org.keycloak.representations.idm.ClientInitialAccessPresentation;
import org.keycloak.representations.idm.ClientRepresentation;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegConfigTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegConfigTest.java
index 6d0c766993..476dc50fd9 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegConfigTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegConfigTest.java
@@ -2,14 +2,14 @@ package org.keycloak.testsuite.cli.registration;
import org.junit.Assert;
import org.junit.Test;
-import org.keycloak.client.registration.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.FileConfigHandler;
import org.keycloak.testsuite.cli.KcRegExec;
import org.keycloak.testsuite.util.TempFileResource;
import java.io.IOException;
-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.cli.util.OsUtil.EOL;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
import static org.keycloak.testsuite.cli.KcRegExec.execute;
/**
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegCreateTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegCreateTest.java
index 53e9565139..52b88ff41c 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegCreateTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegCreateTest.java
@@ -9,8 +9,8 @@ import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.ClientsResource;
import org.keycloak.admin.client.resource.RealmResource;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.FileConfigHandler;
import org.keycloak.common.Profile;
import org.keycloak.common.constants.ServiceAccountConstants;
import org.keycloak.common.crypto.FipsMode;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java
index dc35e1e226..0f5752a76a 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTest.java
@@ -3,9 +3,9 @@ package org.keycloak.testsuite.cli.registration;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.config.FileConfigHandler;
-import org.keycloak.client.registration.cli.config.RealmConfigData;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.RealmConfigData;
import org.keycloak.common.util.KeystoreUtil;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.testsuite.cli.KcRegExec;
@@ -19,8 +19,8 @@ import java.io.IOException;
import java.util.List;
import java.util.UUID;
-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.cli.util.OsUtil.EOL;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_SSL_REQUIRED;
import static org.keycloak.testsuite.cli.KcRegExec.execute;
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTruststoreTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTruststoreTest.java
index d6cb6af448..b1a74289e7 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTruststoreTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegTruststoreTest.java
@@ -2,9 +2,8 @@ package org.keycloak.testsuite.cli.registration;
import org.junit.Assert;
import org.junit.Test;
-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.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.FileConfigHandler;
import org.keycloak.testsuite.cli.KcRegExec;
import org.keycloak.testsuite.util.OAuthClient;
import org.keycloak.testsuite.util.TempFileResource;
@@ -12,9 +11,9 @@ import org.keycloak.testsuite.util.TempFileResource;
import java.io.File;
import java.io.IOException;
-import static org.keycloak.client.registration.cli.util.ConfigUtil.DEFAULT_CONFIG_FILE_PATH;
-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.KcRegMain.DEFAULT_CONFIG_FILE_PATH;
+import static org.keycloak.client.cli.util.OsUtil.EOL;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
import static org.keycloak.testsuite.util.ServerURLs.AUTH_SERVER_SSL_REQUIRED;
import static org.keycloak.testsuite.cli.KcRegExec.execute;
@@ -32,7 +31,7 @@ public class KcRegTruststoreTest extends AbstractRegCliTest {
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 + " config truststore --help' for more information on the available options.", exe.stderrLines().get(1));
+ Assert.assertEquals("try help", "Try '" + 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) {
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTest.java
index 7c6d4c50e9..5b5810b265 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTest.java
@@ -2,7 +2,7 @@ package org.keycloak.testsuite.cli.registration;
import org.junit.Assert;
import org.junit.Test;
-import org.keycloak.client.registration.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.FileConfigHandler;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.testsuite.cli.KcRegExec;
import org.keycloak.testsuite.util.TempFileResource;
@@ -12,7 +12,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
-import static org.keycloak.client.registration.cli.util.OsUtil.CMD;
+import static org.keycloak.client.registration.cli.KcRegMain.CMD;
import static org.keycloak.testsuite.cli.KcRegExec.execute;
/**
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTokenTest.java
index 3a57aac7c6..9796c55658 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTokenTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/cli/registration/KcRegUpdateTokenTest.java
@@ -2,10 +2,10 @@ package org.keycloak.testsuite.cli.registration;
import org.junit.Assert;
import org.junit.Test;
-import org.keycloak.client.registration.cli.config.ConfigData;
-import org.keycloak.client.registration.cli.config.FileConfigHandler;
-import org.keycloak.client.registration.cli.config.RealmConfigData;
-import org.keycloak.client.registration.cli.util.ConfigUtil;
+import org.keycloak.client.cli.config.ConfigData;
+import org.keycloak.client.cli.config.FileConfigHandler;
+import org.keycloak.client.cli.config.RealmConfigData;
+import org.keycloak.client.cli.util.ConfigUtil;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.testsuite.cli.KcRegExec;
import org.keycloak.testsuite.util.TempFileResource;