From 0e2332196dac7eb25e50957673932db05e69930e Mon Sep 17 00:00:00 2001 From: Marko Strukelj Date: Mon, 27 Nov 2017 16:12:00 +0100 Subject: [PATCH] KEYCLOAK-5741 [Admin CLI] Fix instructions in build-in help --- .../cli/commands/AbstractAuthOptionsCmd.java | 7 +++++-- .../client/admin/cli/commands/AddRolesCmd.java | 5 +++-- .../admin/cli/commands/ConfigCredentialsCmd.java | 2 ++ .../admin/cli/commands/ConfigTruststoreCmd.java | 3 ++- .../client/admin/cli/commands/CreateCmd.java | 9 +++++---- .../client/admin/cli/commands/DeleteCmd.java | 5 +++-- .../client/admin/cli/commands/GetCmd.java | 6 +++--- .../client/admin/cli/commands/GetRolesCmd.java | 5 +++-- .../client/admin/cli/commands/NewObjectCmd.java | 2 +- .../client/admin/cli/commands/RemoveRolesCmd.java | 5 +++-- .../client/admin/cli/commands/SetPasswordCmd.java | 5 +++-- .../client/admin/cli/commands/UpdateCmd.java | 5 +++-- .../keycloak/testsuite/cli/admin/KcAdmTest.java | 12 ++++++++++++ .../testsuite/cli/admin/KcAdmTruststoreTest.java | 15 +++++++++++---- 14 files changed, 59 insertions(+), 27 deletions(-) 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 1473d7ff53..d8d6b56917 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 @@ -47,7 +47,7 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd { @Option(name = "config", description = "Path to the config file (~/.keycloak/kcadm.config by default)") String config; - @Option(name = "no-config", description = "No configuration file should be used, no authentication info should be saved", hasValue = false) + @Option(name = "no-config", description = "Don't use config file - no authentication info is loaded or saved", hasValue = false) boolean noconfig; @Option(name = "server", description = "Server endpoint url (e.g. 'http://localhost:8080/auth')") @@ -259,9 +259,12 @@ public abstract class AbstractAuthOptionsCmd extends AbstractGlobalOptionsCmd { String value = options[++i]; if (value != null) { - throw new RuntimeException("Unsupported option: " + name); + 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/AddRolesCmd.java b/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AddRolesCmd.java index 2ca6cd39c7..549a6c73d0 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 @@ -338,11 +338,12 @@ public class AddRolesCmd extends AbstractAuthOptionsCmd { 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(" --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. This allows on-the-fly transient authentication that does"); - out.println(" not touch a config file."); + 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:"); out.println(" --uusername User's 'username'. If more than one user exists with the same username"); 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 c84c52e417..95fe628def 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 @@ -83,6 +83,8 @@ public class ConfigCredentialsCmd extends AbstractAuthOptionsCmd { return help ? CommandResult.SUCCESS : CommandResult.FAILURE; } + checkUnsupportedOptions("--no-config", booleanOptionForCheck(noconfig)); + processGlobalOptions(); return process(commandInvocation); 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 38f7b9fbec..24c0de13a3 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 @@ -111,7 +111,8 @@ public class ConfigTruststoreCmd extends AbstractAuthOptionsCmd { "--truststore", trustStore, "--keystore", keystore, "--keypass", keyPass, - "--alias", alias); + "--alias", alias, + "--no-config", booleanOptionForCheck(noconfig)); // now update the config processGlobalOptions(); 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 86ca3f19b3..49b2739531 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 @@ -91,19 +91,20 @@ public class CreateCmd extends AbstractRequestCmd { out.println(); out.println("Command to create new resources on the server."); 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("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 (" + 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. This allows on-the-fly transient authentication that does"); - out.println(" not touch a config file."); + 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:"); out.println(" ENDPOINT_URI URI used to compose a target resource url. Commonly used values are:"); 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 d84833db49..47a26f6495 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 @@ -66,11 +66,12 @@ public class DeleteCmd extends CreateCmd { 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(" --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. This allows on-the-fly transient authentication that does"); - out.println(" not touch a config file."); + 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:"); out.println(" ENDPOINT_URI URI used to compose a target resource url. Commonly used values start with:"); 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 27005e4d16..3910b994e3 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 @@ -98,11 +98,12 @@ public class GetCmd extends AbstractRequestCmd { 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(" --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. This allows on-the-fly transient authentication that does"); - out.println(" not touch a config file."); + 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:"); out.println(" ENDPOINT_URI URI used to compose a target resource url. Commonly used values are:"); @@ -116,7 +117,6 @@ public class GetCmd extends AbstractRequestCmd { out.println(" which some endpoints recognize"); out.println(); out.println(" -H, --print-headers Print response headers"); - out.println(" -o, --output After delete output any response to standard output"); out.println(" -F, --fields FILTER A filter pattern to specify which fields of a JSON response to output"); out.println(" -c, --compressed Don't pretty print the output"); out.println(" --format FORMAT Set output format to comma-separated-values by using 'csv'. Default format is 'json'"); 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 9a4fb659be..23cc591471 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 @@ -342,11 +342,12 @@ public class GetRolesCmd extends GetCmd { 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(" --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. This allows on-the-fly transient authentication that does"); - out.println(" not touch a config file."); + 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:"); out.println(" --uusername User's 'username'. If more than one user exists with the same username"); 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 33fcdc6ae7..6c1c03d166 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 @@ -167,7 +167,7 @@ public class NewObjectCmd extends AbstractGlobalOptionsCmd { out.println(); out.println("Command to compose JSON objects from attributes, and merge changes into existing JSON documents."); out.println(); - out.println("This is a local command that does not perform any server requests. It's functionality is fully "); + out.println("This is a local command that does not perform any server requests. Its functionality is fully "); out.println("integrated into 'create', 'update' and 'delete' commands. It's supposed to be a helper tool only."); out.println(); out.println("Arguments:"); 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 5338d232eb..4f9c49681d 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 @@ -338,11 +338,12 @@ public class RemoveRolesCmd extends AbstractAuthOptionsCmd { 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(" --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. This allows on-the-fly transient authentication that does"); - out.println(" not touch a config file."); + 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:"); out.println(" --uusername User's 'username'. If more than one user exists with the same username"); 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 805a8301bb..c0317ad365 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 @@ -150,11 +150,12 @@ public class SetPasswordCmd extends AbstractAuthOptionsCmd { 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(" --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. This allows on-the-fly transient authentication that does"); - out.println(" not touch a config file."); + 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:"); out.println(" --username USERNAME Identify target user by 'username'"); 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 6c194e9cd7..086985b765 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 @@ -107,11 +107,12 @@ public class UpdateCmd extends AbstractRequestCmd { 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(" --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. This allows on-the-fly transient authentication that does"); - out.println(" not touch a config file."); + 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:"); out.println(" ENDPOINT_URI URI used to compose a target resource url. Commonly used values start with:"); 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 3b427f0bde..077e427791 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 @@ -258,6 +258,18 @@ public class KcAdmTest extends AbstractAdmCliTest { Assert.assertEquals("try help", "Try '" + CMD + " help config credentials' for more information", exe.stderrLines().get(1)); } + @Test + public void testCredentialsWithNoConfig() { + /* + * Test with --no-config specified which is not supported + */ + KcAdmExec exe = KcAdmExec.execute("config credentials --no-config --server " + serverUrl + " --realm master --user admin --password admin"); + + assertExitCodeAndStreamSizes(exe, 1, 0, 2); + Assert.assertEquals("stderr first line", "Unsupported option: --no-config", exe.stderrLines().get(0)); + Assert.assertEquals("try help", "Try '" + CMD + " help config credentials' for more information", exe.stderrLines().get(1)); + } + @Test public void testUserLoginWithDefaultConfig() { /* 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 1346442b79..9ab712836a 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 @@ -4,6 +4,7 @@ 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.testsuite.cli.KcAdmExec; import org.keycloak.testsuite.util.TempFileResource; @@ -23,21 +24,27 @@ public class KcAdmTruststoreTest extends AbstractAdmCliTest { @Test public void testTruststore() throws IOException { + File truststore = new File("src/test/resources/keystore/keycloak.truststore"); + + KcAdmExec exe = execute("config truststore --no-config '" + truststore.getAbsolutePath() + "'"); + + assertExitCodeAndStreamSizes(exe, 1, 0, 2); + Assert.assertEquals("stderr first line", "Unsupported option: --no-config", exe.stderrLines().get(0)); + Assert.assertEquals("try help", "Try '" + OsUtil.CMD + " help config truststore' for more information", exe.stderrLines().get(1)); + // only run this test if ssl protected keycloak server is available if (!isAuthServerSSL()) { System.out.println("TEST SKIPPED - This test requires HTTPS. Run with '-Pauth-server-wildfly -Dauth.server.ssl.required=true'"); return; } - File truststore = new File("src/test/resources/keystore/keycloak.truststore"); - FileConfigHandler handler = initCustomConfigFile(); try (TempFileResource configFile = new TempFileResource(handler.getConfigFile())) { if (runIntermittentlyFailingTests()) { // configure truststore - KcAdmExec exe = execute("config truststore --config '" + configFile.getName() + "' '" + truststore.getAbsolutePath() + "'"); + exe = execute("config truststore --config '" + configFile.getName() + "' '" + truststore.getAbsolutePath() + "'"); assertExitCodeAndStreamSizes(exe, 0, 0, 0); @@ -80,7 +87,7 @@ public class KcAdmTruststoreTest extends AbstractAdmCliTest { } // configure truststore with password - KcAdmExec exe = execute("config truststore --trustpass secret '" + truststore.getAbsolutePath() + "'"); + exe = execute("config truststore --trustpass secret '" + truststore.getAbsolutePath() + "'"); assertExitCodeAndStreamSizes(exe, 0, 0, 0); // perform authentication against server - asks for password, then for truststore password