Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compound PR - see commits and comments #16

Merged
merged 3 commits into from
Mar 2, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
57 changes: 57 additions & 0 deletions src/main/java/org/wildfly/security/tool/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
*/
package org.wildfly.security.tool;

import java.io.Console;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;

Expand All @@ -31,10 +33,16 @@ public abstract class Command {
*/
public static int GENERAL_CONFIGURATION_ERROR = 7;

public static int INPUT_DATA_NOT_CONFIRMED = 3;

private int status = 255;

public abstract void execute(String[] args) throws Exception;

/**
* Default help line width.
*/
public static int WIDTH = 160;

/**
* Display help to the command.
Expand Down Expand Up @@ -65,4 +73,53 @@ public static boolean isWindows() {
return (opsys.indexOf("win") >= 0);
}

/**
* Prompt for interactive user input with possible confirmation of input data.
* When data are not confirmed tool exits with {@link #INPUT_DATA_NOT_CONFIRMED} exit code
*
* @param echo echo the characters typed
* @param prompt text to display before the input
* @param confirm confirm data after the first input
* @param confirmPrompt confirmation text
* @return data as user inputs it
*/
protected String prompt(boolean echo, String prompt, boolean confirm, String confirmPrompt) {
Console console = System.console();
if (console == null) {
System.err.println(ElytronToolMessages.msg.cannotPromptConsoleMissing());
System.exit(GENERAL_CONFIGURATION_ERROR);
}
if (echo) {
String first = console.readLine(prompt);
if (first != null && confirm) {
String second = console.readLine(confirmPrompt);
if (first.equals(second)) {
return first;
} else {
System.err.println(ElytronToolMessages.msg.inputDataNotConfirmed());
System.exit(INPUT_DATA_NOT_CONFIRMED);
return null;
}
} else {
return first;
}
} else {
char[] inVisible = console.readPassword(prompt != null ? prompt : "Password:");
if (inVisible != null && confirm) {
char[] inVisible2 = console.readPassword(confirmPrompt != null ? confirmPrompt : "Confirm password:");
if (Arrays.equals(inVisible, inVisible2)) {
return new String(inVisible);
} else {
System.err.println(ElytronToolMessages.msg.inputDataNotConfirmed());
System.exit(INPUT_DATA_NOT_CONFIRMED);
return null;
}
}
if (inVisible != null) {
return new String(inVisible);
}
return null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,34 @@ class CredentialStoreCommand extends Command {

CredentialStoreCommand() {
options = new Options();
options.addOption("l", STORE_LOCATION_PARAM, true, ElytronToolMessages.msg.cmdLineStoreLocationDesc());
options.addOption("u", CONFIGURATION_URI_PARAM, true, ElytronToolMessages.msg.cmdLineURIDesc());
options.addOption("p", CREDENTIAL_STORE_PASSWORD_PARAM, true, ElytronToolMessages.msg.cmdLineCredentialStorePassword());
Option opt = new Option("l", STORE_LOCATION_PARAM, true, ElytronToolMessages.msg.cmdLineStoreLocationDesc());
opt.setArgName("loc");
options.addOption(opt);
opt = new Option("u", CONFIGURATION_URI_PARAM, true, ElytronToolMessages.msg.cmdLineURIDesc());
opt.setArgName("uri");
options.addOption(opt);
opt = new Option("p", CREDENTIAL_STORE_PASSWORD_PARAM, true, ElytronToolMessages.msg.cmdLineCredentialStorePassword());
opt.setArgName("pwd");
options.addOption(opt);
options.addOption("s", SALT_PARAM, true, ElytronToolMessages.msg.cmdLineSaltDesc());
options.addOption("i", ITERATION_PARAM, true, ElytronToolMessages.msg.cmdLineIterationCountDesc());
options.addOption("x", PASSWORD_CREDENTIAL_VALUE_PARAM, true, ElytronToolMessages.msg.cmdLinePasswordCredentialValueDesc());
opt = new Option("x", PASSWORD_CREDENTIAL_VALUE_PARAM, true, ElytronToolMessages.msg.cmdLinePasswordCredentialValueDesc());
opt.setArgName("secret to store");
opt.setOptionalArg(true);
options.addOption(opt);
options.addOption("c", CREATE_CREDENTIAL_STORE_PARAM, false, ElytronToolMessages.msg.cmdLineCreateCredentialStoreDesc());
options.addOption("t", CREDENTIAL_STORE_TYPE_PARAM, true, ElytronToolMessages.msg.cmdLineCredentialStoreTypeDesc());
opt = new Option("t", CREDENTIAL_STORE_TYPE_PARAM, true, ElytronToolMessages.msg.cmdLineCredentialStoreTypeDesc());
opt.setArgName("type");
options.addOption(opt);
options.addOption("f", PRINT_SUMMARY_PARAM, false, ElytronToolMessages.msg.cmdLinePrintSummary());

OptionGroup og = new OptionGroup();
Option a = new Option("a", ADD_ALIAS_PARAM, true, ElytronToolMessages.msg.cmdLineAddAliasDesc());
a.setArgName("alias");
Option e = new Option("e", CHECK_ALIAS_PARAM, true, ElytronToolMessages.msg.cmdLineCheckAliasDesc());
e.setArgName("alias");
Option r = new Option("r", REMOVE_ALIAS_PARAM, true, ElytronToolMessages.msg.cmdLineRemoveAliasDesc());
r.setArgName("alias");
Option v = new Option("v", ALIASES_PARAM, false, ElytronToolMessages.msg.cmdLineAliasesDesc());
Option h = new Option("h", HELP_PARAM, false, ElytronToolMessages.msg.cmdLineHelp());
og.addOption(a);
Expand All @@ -103,7 +117,7 @@ class CredentialStoreCommand extends Command {
@Override
public void execute(String[] args) throws Exception {
setStatus(GENERAL_CONFIGURATION_ERROR);
cmdLine = parser.parse(options, args, true);
cmdLine = parser.parse(options, args, false);
if (cmdLine.hasOption(HELP_PARAM)) {
help();
setStatus(ElytronTool.ElytronToolExitStatus_OK);
Expand Down Expand Up @@ -140,6 +154,11 @@ public void execute(String[] args) throws Exception {
credentialStoreConfigurationOptions.putIfAbsent("modifiable", Boolean.TRUE.toString());
credentialStoreConfigurationOptions.putIfAbsent("create", Boolean.valueOf(createKeyStore).toString());
credentialStoreConfigurationOptions.putIfAbsent("keyStoreType", "JCEKS");

if (csPassword == null) {
// prompt for password
csPassword = prompt(false, ElytronToolMessages.msg.credentialStorePasswordPrompt(), true, ElytronToolMessages.msg.credentialStorePasswordPromptConfirm());
}
if (csPassword != null) {
credentialStore.initialize(credentialStoreConfigurationOptions,
new CredentialStore.CredentialSourceProtectionParameter(
Expand All @@ -152,6 +171,10 @@ public void execute(String[] args) throws Exception {
if (cmdLine.hasOption(ADD_ALIAS_PARAM)) {
String alias = cmdLine.getOptionValue(ADD_ALIAS_PARAM);
String secret = cmdLine.getOptionValue(PASSWORD_CREDENTIAL_VALUE_PARAM);
if (secret == null) {
// prompt for secret
secret = prompt(false, ElytronToolMessages.msg.secretToStorePrompt(), true, ElytronToolMessages.msg.secretToStorePromptConfirm());
}
credentialStore.store(alias, createCredential(secret));
credentialStore.flush();
System.out.println(ElytronToolMessages.msg.aliasStored(alias));
Expand Down Expand Up @@ -295,6 +318,7 @@ private void parseQueryParameter(final String query, final String uri) {
@Override
public void help() {
HelpFormatter help = new HelpFormatter();
help.printHelp("java -jar " + ElytronTool.TOOL_JAR + " " + CREDENTIAL_STORE_COMMAND + " <sub-command> <options>", options, true);
help.setWidth(WIDTH);
help.printHelp(ElytronToolMessages.msg.cmdHelp(ElytronTool.TOOL_JAR, CREDENTIAL_STORE_COMMAND), options, true);
}
}
4 changes: 2 additions & 2 deletions src/main/java/org/wildfly/security/tool/ElytronTool.java
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ public static void main(String[] args) {
command.execute(newArgs);
System.exit(command.getStatus());
} catch (Exception e) {
System.err.printf(e.getLocalizedMessage());
System.err.println(e.getLocalizedMessage());
System.exit(command.getStatus());
}
} else {
System.err.print(ElytronToolMessages.msg.commandOrAliasNotFound(args[0]));
System.err.println(ElytronToolMessages.msg.commandOrAliasNotFound(args[0]));
System.exit(ElytronToolExitStatus_unrecognizedCommand);
}
} else {
Expand Down
29 changes: 28 additions & 1 deletion src/main/java/org/wildfly/security/tool/ElytronToolMessages.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,18 @@ public interface ElytronToolMessages extends BasicLogger {

ElytronToolMessages msg = Logger.getMessageLogger(ElytronToolMessages.class, "org.wildfly.security.tool");

// General messages
@Message(id = Message.NONE, value = "Command or alias \"%s\" not found.")
String commandOrAliasNotFound(String command);

@Message(id = Message.NONE, value = "Input data not confirmed. Exiting.")
String inputDataNotConfirmed();

@Message(id = Message.NONE, value = "Cannot start user prompt, console is missing.")
String cannotPromptConsoleMissing();

@Message(id = Message.NONE, value = "java -jar %s %s")
String cmdHelp(String jarFile, String commandName);

// CredentialStore command parameters descriptions
@Message(id = Message.NONE, value = "Missing arguments. Printing general help message:")
Expand All @@ -44,7 +53,13 @@ public interface ElytronToolMessages extends BasicLogger {
@Message(id = Message.NONE, value = "Location of credential store storage file")
String cmdLineStoreLocationDesc();

@Message(id = Message.NONE, value = "Configuration URI for credential store")
@Message(id = Message.NONE, value = "Configuration URI for credential store. URI basic form: \"cr-store://store_name?parameter1=value1; ... ;parameterN=valueN\"%n" +
"Supported parameters are dependent on credential store type%n" +
"Generally supported parameters for default credential store implementation:%n" +
"create - automatically creates credential store file%n" +
"modifiable - is the credential modifiable%n" +
"location - file location of credential store%n" +
"keyStoreType - specify the key store type to use")
String cmdLineURIDesc();

@Message(id = Message.NONE, value = "Password for credential store")
Expand Down Expand Up @@ -104,6 +119,18 @@ public interface ElytronToolMessages extends BasicLogger {
@Message(id = Message.NONE, value = "Action to perform on the credential store is not defined")
Exception actionToPerformNotDefined();

@Message(id = Message.NONE, value = "Credential store password: ")
String credentialStorePasswordPrompt();

@Message(id = Message.NONE, value = "Confirm credential store password: ")
String credentialStorePasswordPromptConfirm();

@Message(id = Message.NONE, value = "Secret to store: ")
String secretToStorePrompt();

@Message(id = Message.NONE, value = "Confirm secret to store: ")
String secretToStorePromptConfirm();

@Message(id = 1, value = "Opening quote has to be the first character in parameter value '%s'")
IllegalArgumentException credentialStoreURIParameterOpeningQuote(String uri);

Expand Down
10 changes: 7 additions & 3 deletions src/main/java/org/wildfly/security/tool/MaskCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class MaskCommand extends Command {
Option iteration = new Option("i", ITERATION_PARAM, true, ElytronToolMessages.msg.cmdMaskIterationCountDesc());
OptionGroup og = new OptionGroup();
Option x = new Option("x", SECRET_PARAM, true, ElytronToolMessages.msg.cmdMaskSecretDesc());
x.setArgName("to encrypt");
Option h = new Option("h", HELP_PARAM, false, ElytronToolMessages.msg.cmdLineHelp());
og.addOption(x);
og.addOption(h);
Expand All @@ -72,7 +73,7 @@ class MaskCommand extends Command {
@Override
public void execute(String[] args) throws Exception {
setStatus(GENERAL_CONFIGURATION_ERROR);
cmdLine = parser.parse(options, args, true);
cmdLine = parser.parse(options, args, false);
if (cmdLine.hasOption(HELP_PARAM)) {
help();
setStatus(ElytronTool.ElytronToolExitStatus_OK);
Expand Down Expand Up @@ -120,8 +121,11 @@ static String computeMasked(String secret, String salt, int iteration) throws Ge
@Override
public void help() {
HelpFormatter help = new HelpFormatter();
help.printHelp("java -jar " + ElytronTool.TOOL_JAR + " " + MASK_COMMAND + " <options>",
help.setWidth(WIDTH);
help.printHelp(ElytronToolMessages.msg.cmdHelp(ElytronTool.TOOL_JAR, MASK_COMMAND),
ElytronToolMessages.msg.cmdMaskHelpHeader(DEFAULT_ALGORITHM),
options, "",true);
options,
"",
true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
Expand Down Expand Up @@ -82,9 +83,10 @@ public void maskCSPassword() throws Exception {
}

/**
* basic test withot --password option.
* basic test without --password option.
* @throws Exception if something goes wrong
*/
@Ignore("Issue #15 - bypass prompting using callback handler")
@Test(expected = CredentialStoreException.class)
public void noPasswordSpecified() throws Exception {
ElytronTool tool = new ElytronTool();
Expand Down