fix: adds handling for all kcadm prompts as env variables (#29430)

closes: #21961

Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
Steven Hawkins
2024-06-06 09:08:23 -04:00
committed by GitHub
parent f34baf3c24
commit c7e9ee2bff
26 changed files with 95 additions and 306 deletions

View File

@@ -44,6 +44,11 @@ public class KcAdmMain {
return DEFAULT_CONFIG_FILE_PATH;
}
@Override
public boolean isTokenGlobal() {
return true;
};
};
public static void main(String [] args) {

View File

@@ -22,7 +22,6 @@ import org.keycloak.client.cli.config.ConfigData;
import picocli.CommandLine.Option;
/**
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
*/

View File

@@ -21,7 +21,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
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;
@@ -264,10 +263,6 @@ public class AddRolesCmd extends AbstractAuthOptionsCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " add-roles (--uusername USERNAME | --uid ID) [--cclientid CLIENT_ID | --cid ID] (--rolename NAME | --roleid ID)+ [ARGUMENTS]");
@@ -284,21 +279,7 @@ public class AddRolesCmd extends AbstractAuthOptionsCmd {
out.println("to a specific user. If group is specified using --gname, --gpath or --gid then roles are added to a specific group.");
out.println("If composite role is specified using --rname or --rid then roles are added to a specific composite role.");
out.println("One or more roles have to be specified using --rolename or --roleid so that they are added to a group, a user or a composite role.");
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 (" + 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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" --uusername User's 'username'. If more than one user exists with the same username");
out.println(" you'll have to use --uid to specify the target user");
out.println(" --uid User's 'id' attribute");
@@ -333,4 +314,5 @@ public class AddRolesCmd extends AbstractAuthOptionsCmd {
out.println("Use '" + CMD + " help' for general information and a list of commands");
return sb.toString();
}
}

View File

@@ -16,8 +16,6 @@
*/
package org.keycloak.client.admin.cli.commands;
import org.keycloak.client.admin.cli.KcAdmMain;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -75,10 +73,6 @@ public class CreateCmd extends AbstractRequestCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " create ENDPOINT_URI [ARGUMENTS]");
@@ -87,21 +81,7 @@ public class CreateCmd extends AbstractRequestCmd {
out.println();
out.println("Use '" + CMD + " config credentials' to establish an authenticated sessions, or use --no-config with ");
out.println("CREDENTIALS OPTIONS to perform one time authentication.");
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 (" + 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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" ENDPOINT_URI URI used to compose a target resource url. Commonly used values are:");
out.println(" realms, users, roles, groups, clients, keys, serverinfo, components ...");
out.println(" If it starts with 'http://' then it will be used as target resource url");

View File

@@ -16,8 +16,6 @@
*/
package org.keycloak.client.admin.cli.commands;
import org.keycloak.client.admin.cli.KcAdmMain;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -39,10 +37,6 @@ public class DeleteCmd extends CreateCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " delete ENDPOINT_URI [ARGUMENTS]");
@@ -51,21 +45,7 @@ public class DeleteCmd extends CreateCmd {
out.println();
out.println("Use '" + CMD + " config credentials' to establish an authenticated sessions, or use CREDENTIALS OPTIONS");
out.println("to perform one time authentication.");
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 (" + 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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" ENDPOINT_URI URI used to compose a target resource url. Commonly used values start with:");
out.println(" realms/, users/, roles/, groups/, clients/, keys/, components/ ...");
out.println(" If it starts with 'http://' then it will be used as target resource url");

View File

@@ -16,8 +16,6 @@
*/
package org.keycloak.client.admin.cli.commands;
import org.keycloak.client.admin.cli.KcAdmMain;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -75,10 +73,6 @@ public class GetCmd extends AbstractRequestCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " get ENDPOINT_URI [ARGUMENTS]");
@@ -87,21 +81,7 @@ public class GetCmd extends AbstractRequestCmd {
out.println();
out.println("Use '" + CMD + " config credentials' to establish an authenticated session, or use CREDENTIALS OPTIONS");
out.println("to perform one time authentication.");
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 (" + 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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" ENDPOINT_URI URI used to compose a target resource url. Commonly used values are:");
out.println(" realms, users, roles, groups, clients, keys, serverinfo, components ...");
out.println(" If it starts with 'http://' then it will be used as target resource url");

View File

@@ -16,7 +16,6 @@
*/
package org.keycloak.client.admin.cli.commands;
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;
@@ -293,10 +292,6 @@ public class GetRolesCmd extends GetCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " get-roles [--cclientid CLIENT_ID | --cid ID] [ARGUMENTS]");
@@ -319,21 +314,7 @@ public class GetRolesCmd extends GetCmd {
out.println("If --effective is specified, then roles added to the target user or group are transitively resolved and a full");
out.println("set of roles in effect for that user, group or composite role is returned.");
out.println("If --all is specified, then client roles for all clients are returned in addition to realm roles.");
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 (" + 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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" --uusername User's 'username'. If more than one user exists with the same username");
out.println(" you'll have to use --uid to specify the target user");
out.println(" --uid User's 'id' attribute");

View File

@@ -52,35 +52,35 @@ public class HelpCmd implements Runnable {
break;
}
case "create": {
printOut(CreateCmd.usage());
printOut(new CreateCmd().help());
break;
}
case "get": {
printOut(GetCmd.usage());
printOut(new GetCmd().help());
break;
}
case "update": {
printOut(UpdateCmd.usage());
printOut(new UpdateCmd().help());
break;
}
case "delete": {
printOut(DeleteCmd.usage());
printOut(new DeleteCmd().help());
break;
}
case "get-roles": {
printOut(GetRolesCmd.usage());
printOut(new GetRolesCmd().help());
break;
}
case "add-roles": {
printOut(AddRolesCmd.usage());
printOut(new AddRolesCmd().help());
break;
}
case "remove-roles": {
printOut(RemoveRolesCmd.usage());
printOut(new RemoveRolesCmd().help());
break;
}
case "set-password": {
printOut(SetPasswordCmd.usage());
printOut(new SetPasswordCmd().help());
break;
}
case "new-object": {

View File

@@ -16,7 +16,6 @@
*/
package org.keycloak.client.admin.cli.commands;
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;
@@ -271,10 +270,6 @@ public class RemoveRolesCmd extends AbstractAuthOptionsCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " remove-roles (--uusername USERNAME | --uid ID) [--cclientid CLIENT_ID | --cid ID] (--rolename NAME | --roleid ID)+ [ARGUMENTS]");
@@ -291,21 +286,7 @@ public class RemoveRolesCmd extends AbstractAuthOptionsCmd {
out.println("from a specific user. If group is specified using --gname, --gpath or --gid then roles are removed from a specific group.");
out.println("If composite role is specified using --rname or --rid then roles are removed from a specific composite role.");
out.println("One or more roles have to be specified using --rolename or --roleid to be removed from a group, a user or a composite role.");
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 (" + 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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" --uusername User's 'username'. If more than one user exists with the same username");
out.println(" you'll have to use --uid to specify the target user");
out.println(" --uid User's 'id' attribute");

View File

@@ -16,7 +16,6 @@
*/
package org.keycloak.client.admin.cli.commands;
import org.keycloak.client.admin.cli.KcAdmMain;
import org.keycloak.client.cli.config.ConfigData;
import java.io.PrintWriter;
@@ -45,7 +44,7 @@ public class SetPasswordCmd extends AbstractAuthOptionsCmd {
@Option(names = "--userid", description = "User ID")
String userid;
@Option(names = {"-p", "--new-password"}, description = "New password")
@Option(names = {"-p", "--new-password"}, description = "New password", defaultValue = "${env:KC_CLI_PASSWORD}")
String pass;
@Option(names = {"-t", "--temporary"}, description = "is password temporary")
@@ -99,10 +98,6 @@ public class SetPasswordCmd extends AbstractAuthOptionsCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " set-password (--username USERNAME | --userid ID) [--new-password PASSWORD] [ARGUMENTS]");
@@ -111,24 +106,10 @@ public class SetPasswordCmd extends AbstractAuthOptionsCmd {
out.println();
out.println("Use `" + CMD + " config credentials` to establish an authenticated session, or use CREDENTIALS OPTIONS");
out.println("to perform one time authentication.");
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 (" + 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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" --username USERNAME Identify target user by 'username'");
out.println(" --userid ID Identify target user by 'id'");
out.println(" -p, --new-password New password to set. If not specified you will be prompted for it.");
out.println(" -p, --new-password New password to set. If not specified and the env variable KC_CLI_PASSWORD is not defined, you will be prompted for it.");
out.println(" -t, --temporary Make the new password temporary - user has to change it on next logon");
out.println(" -a, --admin-root URL URL of Admin REST endpoint root if not default - e.g. http://localhost:8080/admin");
out.println(" -r, --target-realm REALM Target realm to issue requests against if not the one authenticated against");

View File

@@ -17,8 +17,6 @@
package org.keycloak.client.admin.cli.commands;
import org.keycloak.client.admin.cli.KcAdmMain;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -81,10 +79,6 @@ public class UpdateCmd extends AbstractRequestCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " update ENDPOINT_URI [ARGUMENTS]");
@@ -93,21 +87,7 @@ public class UpdateCmd extends AbstractRequestCmd {
out.println();
out.println("Use '" + CMD + " config credentials' to establish an authenticated sessions, or use CREDENTIALS OPTIONS");
out.println("to perform one time authentication.");
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 (" + 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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified and --truststore is used)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" ENDPOINT_URI URI used to compose a target resource url. Commonly used values start with:");
out.println(" realms/, users/, roles/, groups/, clients/, keys/, components/ ...");
out.println(" If it starts with 'http://' then it will be used as target resource url");

View File

@@ -28,6 +28,7 @@ import org.keycloak.client.cli.util.HttpUtil;
import org.keycloak.client.cli.util.IoUtil;
import java.io.File;
import java.io.PrintWriter;
import picocli.CommandLine.Option;
@@ -62,19 +63,19 @@ public abstract class BaseAuthOptionsCmd extends BaseGlobalOptionsCmd {
@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)")
@Option(names = "--password", description = "Password to login with (prompted for if not specified, --user is used, and the env variable KC_CLI_PASSWORD is not defined)", defaultValue = "${env:KC_CLI_PASSWORD}")
protected String password;
@Option(names = "--secret", description = "Secret to authenticate the client (prompted for if no --user or --keystore is specified)")
@Option(names = "--secret", description = "Secret to authenticate the client (prompted for if no --user nor --keystore is specified, and the env variable KC_CLI_CLIENT_SECRET is not defined)", defaultValue = "${env:KC_CLI_CLIENT_SECRET}")
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)")
@Option(names = "--storepass", description = "Keystore password (prompted for if not specified, --keystore is used, and the env variable KC_CLI_STORE_PASSWORD is undefined)", defaultValue = "${env:KC_CLI_STORE_PASSWORD}")
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)")
@Option(names = "--keypass", description = "Key password (prompted for if not specified and --keystore is used without --storepass, \n otherwise defaults to keystore password)", defaultValue = "${env:KC_CLI_KEY_PASSWORD}")
protected String keyPass;
@Option(names = "--alias", description = "Alias of the key inside a keystore (defaults to the value of ClientId)")
@@ -83,7 +84,7 @@ public abstract class BaseAuthOptionsCmd extends BaseGlobalOptionsCmd {
@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)")
@Option(names = "--trustpass", description = "Truststore password (prompted for if not specified, --user is used, and the env variable KC_CLI_TRUSTSTORE_PASSWORD is not defined)", defaultValue = "${env:KC_CLI_TRUSTSTORE_PASSWORD}")
protected String trustPass;
@Option(names = "--insecure", description = "Turns off TLS validation")
@@ -273,4 +274,23 @@ public abstract class BaseAuthOptionsCmd extends BaseGlobalOptionsCmd {
return AuthUtil.ensureToken(config, getCommand());
}
protected void globalOptions(PrintWriter out) {
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 (" + commandState.getDefaultConfigFilePath() + " by default)");
out.println(" --no-config Don't use config file - no authentication info is loaded or saved");
if (commandState.isTokenGlobal()) {
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");
out.println(" --trustpass PASSWORD Truststore password (prompted for if not specified, --truststore is used, and the KC_CLI_TRUSTSTORE_PASSWORD env property is not defined)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + commandState.getCommand() + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
}
}

View File

@@ -113,10 +113,8 @@ public class BaseConfigCredentialsCmd extends BaseAuthOptionsCmd {
} 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 && secret == null) {
secret = readSecret("Enter client secret: ");
}
}
@@ -196,18 +194,18 @@ public class BaseConfigCredentialsCmd extends BaseAuthOptionsCmd {
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(" --trustpass PASSWORD Truststore password (prompted for if not specified, --truststore is used, and the KC_CLI_TRUSTSTORE_PASSWORD env property is not defined)");
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(" --password PASSWORD Password to login with (prompted for if not specified, --user is used, and the env variable KC_CLI_PASSWORD is not defined)");
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(" --secret SECRET Secret to authenticate the client (prompted for if no --user nor --keystore is specified, and the env variable KC_CLI_CLIENT_SECRET is not defined)");
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(" --storepass PASSWORD Keystore password (prompted for if not specified, --keystore is used, and the env variable KC_CLI_STORE_PASSWORD)");
out.println(" --keypass PASSWORD Key password (prompted for if not specified, --keystore is used without --storepass, and KC_CLI_KEY_PASSWORD");
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();

View File

@@ -115,7 +115,7 @@ public class BaseConfigTruststoreCmd extends BaseAuthOptionsCmd {
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(" --trustpass PASSWORD Truststore password to unlock truststore (prompted for if set to '-'), defaults to the env variable KC_CLI_TRUSTSTORE_PASSWORD");
out.println(" -d, --delete Remove truststore configuration");
out.println();
out.println();

View File

@@ -23,4 +23,6 @@ public interface CommandState {
String getDefaultConfigFilePath();
boolean isTokenGlobal();
}

View File

@@ -65,14 +65,6 @@ public class IoUtil {
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 = System.console();
if (cons == null) {

View File

@@ -28,6 +28,11 @@ public class KcRegMain {
return DEFAULT_CONFIG_FILE_PATH;
}
@Override
public boolean isTokenGlobal() {
return false;
};
};
public static void main(String [] args) {

View File

@@ -20,7 +20,6 @@ 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.KcRegMain;
import org.keycloak.client.cli.common.AttributeOperation;
import org.keycloak.client.cli.config.ConfigData;
import org.keycloak.client.cli.util.HttpUtil;
@@ -200,10 +199,6 @@ public class CreateCmd extends AbstractAuthOptionsCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " create [ARGUMENTS]");
@@ -211,20 +206,7 @@ public class CreateCmd extends AbstractAuthOptionsCmd {
out.println("Command to create new client configurations on the server. If Initial Access Token is specified (-t TOKEN)");
out.println("or has previously been set for the server, and realm in the configuration ('" + CMD + " config initial-token'),");
out.println("then that will be used, otherwise session access / refresh tokens will be used.");
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 (" + 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)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" -t, --token TOKEN Use the specified Initial Access Token for authorization or read it from standard input ");
out.println(" if '-' is specified. This overrides any token set by '" + CMD + " config initial-token'.");
out.println(" If not specified, session credentials are used - see: CREDENTIALS OPTIONS.");

View File

@@ -17,7 +17,6 @@
package org.keycloak.client.registration.cli.commands;
import org.keycloak.client.registration.cli.KcRegMain;
import org.keycloak.client.cli.config.ConfigData;
import org.keycloak.client.registration.cli.CmdStdinContext;
@@ -98,30 +97,13 @@ public class DeleteCmd extends AbstractAuthOptionsCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " delete CLIENT [ARGUMENTS]");
out.println();
out.println("Command to delete a specific client configuration. If registration access token is specified or is available in ");
out.println("configuration file, then it is used. Otherwise, current active session is used.");
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 (" + 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)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" CLIENT ClientId of the client to delete");
out.println(" -t, --token TOKEN Use the specified Registration Access Token for authorization");
out.println();

View File

@@ -17,7 +17,6 @@
package org.keycloak.client.registration.cli.commands;
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;
@@ -160,30 +159,13 @@ public class GetCmd extends AbstractAuthOptionsCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " get CLIENT [ARGUMENTS]");
out.println();
out.println("Command to retrieve a client configuration description for a specified client. If registration access token");
out.println("is specified or is available in configuration file, then it is used. Otherwise, current active session is used.");
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 (" + 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)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" CLIENT ClientId of the client to display");
out.println(" -t, --token TOKEN Use the specified Registration Access Token for authorization");
out.println(" -c, --compressed Don't pretty print the output");

View File

@@ -48,19 +48,19 @@ public class HelpCmd implements Runnable {
break;
}
case "create": {
printOut(CreateCmd.usage());
printOut(new CreateCmd().help());
break;
}
case "get": {
printOut(GetCmd.usage());
printOut(new GetCmd().help());
break;
}
case "update": {
printOut(UpdateCmd.usage());
printOut(new UpdateCmd().help());
break;
}
case "delete": {
printOut(DeleteCmd.usage());
printOut(new DeleteCmd().help());
break;
}
case "attrs": {
@@ -68,7 +68,7 @@ public class HelpCmd implements Runnable {
break;
}
case "update-token": {
printOut(UpdateTokenCmd.usage());
printOut(new UpdateTokenCmd().help());
break;
}
default: {

View File

@@ -28,7 +28,6 @@ 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.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;
@@ -311,10 +310,6 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " update CLIENT [ARGUMENTS]");
@@ -323,19 +318,7 @@ public class UpdateCmd extends AbstractAuthOptionsCmd {
out.println("Otherwise, if 'registrationAccessToken' attribute is set, that is used. Otherwise, if registration access");
out.println("token is available in configuration file, we use that. Finally, if it's not available anywhere, the current ");
out.println("active session is used.");
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 (" + 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)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
globalOptions(out);
out.println(" Command specific options:");
out.println(" CLIENT ClientId of the client to update");
out.println(" -t, --token TOKEN Use the specified Registration Access Token for authorization");

View File

@@ -22,7 +22,6 @@ import com.fasterxml.jackson.core.type.TypeReference;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
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;
@@ -120,30 +119,13 @@ public class UpdateTokenCmd extends AbstractAuthOptionsCmd {
@Override
protected String help() {
return usage();
}
public static String usage() {
StringWriter sb = new StringWriter();
PrintWriter out = new PrintWriter(sb);
out.println("Usage: " + CMD + " update-token CLIENT [ARGUMENTS]");
out.println();
out.println("Command to reissue, and set a new registration access token if an old one is lost or becomes invalid.");
out.println("It requires an authenticated session using an account with administrator privileges.");
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 (" + 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)");
out.println(" CREDENTIALS OPTIONS Same set of options as accepted by '" + CMD + " config credentials' in order to establish");
out.println(" an authenticated sessions. In combination with --no-config option this allows transient");
out.println(" (on-the-fly) authentication to be performed which leaves no tokens in config file.");
out.println();
out.println(" Command specific options:");
globalOptions(out);
out.println(" CLIENT ClientId of the client to reissue a new Registration Access Token for");
out.println(" The new token is saved to a config file or printed to stdout if --no-config");
out.println(" (on-the-fly) authentication is used");