Skip to content

Commit

Permalink
[ELY-2496] Move common methods and variables to Command class
Browse files Browse the repository at this point in the history
  • Loading branch information
jessicarod7 committed May 23, 2023
1 parent 2dca6cc commit 051f5ee
Show file tree
Hide file tree
Showing 10 changed files with 346 additions and 263 deletions.
2 changes: 1 addition & 1 deletion tool/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
</resources>

<plugins>
<plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
Expand Down
134 changes: 133 additions & 1 deletion tool/src/main/java/org/wildfly/security/tool/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,36 @@

import java.io.BufferedReader;
import java.io.Console;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.Set;
import java.util.function.Supplier;

import javax.crypto.SecretKey;

import org.wildfly.security.credential.Credential;
import org.wildfly.security.credential.SecretKeyCredential;
import org.wildfly.security.credential.store.CredentialStore;
import org.wildfly.security.credential.store.CredentialStoreException;
import org.wildfly.security.credential.store.impl.PropertiesCredentialStore;
import org.wildfly.security.encryption.SecretKeyUtil;
import org.wildfly.security.password.WildFlyElytronPasswordProvider;

/**
* Base command class
* @author <a href="mailto:[email protected]">Peter Skopek</a>
Expand All @@ -48,8 +63,14 @@ public abstract class Command {
*/
public static final int GENERAL_CONFIGURATION_ERROR = 7;

public static final int GENERAL_CONFIGURATION_WARNING = 1;

public static final int INPUT_DATA_NOT_CONFIRMED = 3;

public static Supplier<Provider[]> ELYTRON_PASSWORD_PROVIDERS = () -> new Provider[] {
WildFlyElytronPasswordProvider.getInstance()
};

private int status = 255;

private List<String> redirectionValues;
Expand Down Expand Up @@ -106,7 +127,7 @@ public static boolean isWindows() {
* @param confirm confirm data after the first input
* @param confirmPrompt confirmation text
* @return data as user inputs it
* @throws Exception
* @throws Exception if a {@link BufferedReader} cannot be created
*/
protected String prompt(boolean echo, String prompt, boolean confirm, String confirmPrompt) throws Exception {
Console console = System.console();
Expand Down Expand Up @@ -204,6 +225,27 @@ public void printDuplicatesWarning(CommandLine cmdLine, List<String> duplicatesA
}
}

/**
* Print a warning message.
*
* @param warning The warning to be shown
*/
protected void warningHandler(String warning) {
System.out.print("WARNING: ");
System.out.println(warning);
}

/**
* Set an {@value GENERAL_CONFIGURATION_ERROR} and raise the exception
*
* @param e The exception thrown during execution
* @throws Exception The exception to be handled by Elytron Tool
*/
protected void errorHandler(Exception e) throws Exception {
setStatus(GENERAL_CONFIGURATION_ERROR);
throw e;
}

/**
* Get the command debug option
*/
Expand Down Expand Up @@ -270,4 +312,94 @@ protected Supplier<Provider[]> getProvidersSupplier(final String providersList)
}
};
}

/**
* Acquire a given secret key from a {@link CredentialStore}.
*
* @param alias the name for a secret key within the CredentialStore
* @return the requested {@link SecretKey}, or {@code null} if it could not be retrieved
* @throws CredentialStoreException when credential store initialization or an operation fails
* @throws NoSuchAlgorithmException if the credential store algorithm cannot be found
* @throws GeneralSecurityException when a secret key cannot be generated
* @throws Exception when an existing credential store does not contain the secret key
*/
SecretKey getSecretKey(Boolean createCredentialStore, String credentialStoreLocation, String alias, Boolean populate,
String inputRealmLocation) throws Exception {
CredentialStore credentialStore;
String csType = PropertiesCredentialStore.NAME;
try {
credentialStore = CredentialStore.getInstance(csType);
} catch (NoSuchAlgorithmException e) {
// fallback to load all possible providers
credentialStore = CredentialStore.getInstance(csType, getProvidersSupplier(null));
}
Map<String, String> implProps = new HashMap<>();
implProps.put("create", String.valueOf(createCredentialStore));
implProps.put("location", credentialStoreLocation);
implProps.put("modifiable", Boolean.TRUE.toString());
credentialStore.initialize(implProps);
try {
credentialStore.retrieve(alias, SecretKeyCredential.class).getSecretKey();
System.out.println(ElytronToolMessages.msg.existingCredentialStore());
} catch (Exception e) {
if (!createCredentialStore) {
warningHandler(ElytronToolMessages.msg.skippingBlockMissingCredentialStore());
return null;
}
if (populate) {
SecretKey key = SecretKeyUtil.generateSecretKey(256);
Credential keyCredential = new SecretKeyCredential(key);
credentialStore.store(alias, keyCredential);
credentialStore.flush();
} else {
errorHandler(ElytronToolMessages.msg.cmdFileSystemPopulateUnspecified());
}
}
SecretKey key;
try {
key = credentialStore.retrieve(alias, SecretKeyCredential.class).getSecretKey();
} catch (NullPointerException e) {
System.out.println(ElytronToolMessages.msg.cmdFileSystemEncryptionNoSecretKey(credentialStoreLocation, inputRealmLocation));
return null;
}

return key;
}
}

class Params {
static final String ALIAS_PARAM = "alias";
static final String BULK_CONVERT_PARAM = "bulk-convert";
static final String CREDENTIAL_STORE_LOCATION_PARAM = "credential-store";
static final String CREATE_CREDENTIAL_STORE_PARAM = "create";
static final String CREDENTIAL_STORE_TYPE_PARAM = "type";
static final String CUSTOM_CREDENTIAL_STORE_PROVIDER_PARAM = "credential-store-provider";
static final String ENCODED_PARAM = "encoded";
static final String FILE_PARAM = "file";
static final String DEBUG_PARAM = "debug";
static final String DIRECTORY_PARAM = "directory";
static final String HASH_ENCODING_PARAM = "hash-encoding";
static final String HELP_PARAM = "help";
static final String IMPLEMENTATION_PROPERTIES_PARAM = "properties";
static final String INPUT_LOCATION_PARAM = "input-location";
static final String ITERATION_PARAM = "iteration";
static final String KEYSTORE_PARAM = "keystore";
static final String LEVELS_PARAM = "levels";
static final String NAME_PARAM = "name";
static final String OTHER_PROVIDERS_PARAM = "other-providers";
static final String OUTPUT_LOCATION_PARAM = "output-location";
static final String PASSWORD_PARAM = "password";
static final String REALM_NAME_PARAM = "realm-name";
static final String SALT_PARAM = "salt";
static final String SECRET_KEY_ALIAS_PARAM = "secret-key";
static final String SILENT_PARAM = "silent";
static final String STORE_LOCATION_PARAM = "location";
static final String SUMMARY_PARAM = "summary";

// Other constants
static final Integer DEFAULT_LEVELS = 2;
static final String DEFAULT_SECRET_KEY_ALIAS = "key";
static final String FILE_SEPARATOR = File.separator;
static final String LINE_SEPARATOR = System.lineSeparator();
static final String SUMMARY_DIVIDER = "-".repeat(100);
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,20 @@
import org.wildfly.security.pem.Pem;
import org.wildfly.security.ssh.util.SshUtil;

import static org.wildfly.security.tool.Params.ALIAS_PARAM;
import static org.wildfly.security.tool.Params.CREATE_CREDENTIAL_STORE_PARAM;
import static org.wildfly.security.tool.Params.CREDENTIAL_STORE_TYPE_PARAM;
import static org.wildfly.security.tool.Params.CUSTOM_CREDENTIAL_STORE_PROVIDER_PARAM;
import static org.wildfly.security.tool.Params.DEBUG_PARAM;
import static org.wildfly.security.tool.Params.HELP_PARAM;
import static org.wildfly.security.tool.Params.IMPLEMENTATION_PROPERTIES_PARAM;
import static org.wildfly.security.tool.Params.ITERATION_PARAM;
import static org.wildfly.security.tool.Params.OTHER_PROVIDERS_PARAM;
import static org.wildfly.security.tool.Params.PASSWORD_PARAM;
import static org.wildfly.security.tool.Params.SALT_PARAM;
import static org.wildfly.security.tool.Params.STORE_LOCATION_PARAM;
import static org.wildfly.security.tool.Params.SUMMARY_PARAM;

/**
* Credential Store Command
* Performs credential store related operations.
Expand All @@ -80,34 +94,20 @@ class CredentialStoreCommand extends Command {

public static int ACTION_NOT_DEFINED = 5;
public static int ALIAS_NOT_FOUND = 6;
public static int GENERAL_CONFIGURATION_ERROR = 7;

public static final String RSA_ALGORITHM = "RSA";
public static final String DSA_ALGORITHM = "DSA";
public static final String EC_ALGORITHM = "EC";

public static final String CREDENTIAL_STORE_COMMAND = "credential-store";

public static final String STORE_LOCATION_PARAM = "location";
public static final String IMPLEMENTATION_PROPERTIES_PARAM = "properties";
public static final String CREDENTIAL_STORE_PASSWORD_PARAM = "password";
public static final String CREDENTIAL_STORE_TYPE_PARAM = "type";
public static final String SALT_PARAM = "salt";
public static final String ITERATION_PARAM = "iteration";
public static final String PASSWORD_CREDENTIAL_VALUE_PARAM = "secret";
public static final String ADD_ALIAS_PARAM = "add";
public static final String ALIAS_ARGUMENT = "alias";
public static final String CHECK_ALIAS_PARAM = "exists";
public static final String ALIASES_PARAM = "aliases";
public static final String CREDENTIAL_TYPES = "credential-types";
public static final String REMOVE_ALIAS_PARAM = "remove";
public static final String CREATE_CREDENTIAL_STORE_PARAM = "create";
public static final String HELP_PARAM = "help";
public static final String PRINT_SUMMARY_PARAM = "summary";
public static final String ENTRY_TYPE_PARAM = "entry-type";
public static final String OTHER_PROVIDERS_PARAM = "other-providers";
public static final String DEBUG_PARAM = "debug";
public static final String CUSTOM_CREDENTIAL_STORE_PROVIDER_PARAM = "credential-store-provider";
public static final String SIZE_PARAM = "size";

public static final String GENERATE_KEY_PAIR_PARAM = "generate-key-pair";
Expand Down Expand Up @@ -142,7 +142,7 @@ class CredentialStoreCommand extends Command {
options.addOption(opt);
opt = new Option("u", IMPLEMENTATION_PROPERTIES_PARAM, true, ElytronToolMessages.msg.cmdLineImplementationPropertiesDesc());
options.addOption(opt);
opt = new Option("p", CREDENTIAL_STORE_PASSWORD_PARAM, true, ElytronToolMessages.msg.cmdLineCredentialStorePassword());
opt = new Option("p", PASSWORD_PARAM, true, ElytronToolMessages.msg.cmdLineCredentialStorePassword());
opt.setArgName("pwd");
options.addOption(opt);
options.addOption("s", SALT_PARAM, true, ElytronToolMessages.msg.cmdLineSaltDesc());
Expand All @@ -167,7 +167,7 @@ class CredentialStoreCommand extends Command {
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());
options.addOption("f", SUMMARY_PARAM, false, ElytronToolMessages.msg.cmdLinePrintSummary());

options.addOption("j", SIZE_PARAM, true, ElytronToolMessages.msg.cmdLineKeySizeDesc());
options.addOption("k", ALGORITHM_PARAM, true, ElytronToolMessages.msg.cmdLineKeyAlgorithmDesc());
Expand Down Expand Up @@ -210,7 +210,7 @@ class CredentialStoreCommand extends Command {
options.addOption(Option.builder()
.longOpt(ENTRY)
.hasArg()
.argName(ALIAS_ARGUMENT)
.argName(ALIAS_PARAM)
.desc(ElytronToolMessages.msg.cmdLineEntryDesc())
.build());

Expand Down Expand Up @@ -247,25 +247,25 @@ class CredentialStoreCommand extends Command {
og.addOption(Option.builder()
.longOpt(GENERATE_SECRET_KEY)
.hasArg()
.argName(ALIAS_ARGUMENT)
.argName(ALIAS_PARAM)
.desc(ElytronToolMessages.msg.generateSecretKey())
.build());
og.addOption(Option.builder()
.longOpt(EXPORT_SECRET_KEY)
.hasArg()
.argName(ALIAS_ARGUMENT)
.argName(ALIAS_PARAM)
.desc(ElytronToolMessages.msg.exportSecretKey())
.build());
og.addOption(Option.builder()
.longOpt(IMPORT_SECRET_KEY)
.hasArg()
.argName(ALIAS_ARGUMENT)
.argName(ALIAS_PARAM)
.desc(ElytronToolMessages.msg.importSecretKey())
.build());
og.addOption(Option.builder()
.longOpt(ENCRYPT)
.hasArg()
.argName(ALIAS_ARGUMENT)
.argName(ALIAS_PARAM)
.desc(ElytronToolMessages.msg.encrypt())
.build());

Expand Down Expand Up @@ -352,7 +352,7 @@ public void execute(String[] args) throws Exception {
setStatus(GENERAL_CONFIGURATION_ERROR);
throw ElytronToolMessages.msg.storageFileDoesNotExist(location);
}
String csPassword = cmdLine.getOptionValue(CREDENTIAL_STORE_PASSWORD_PARAM);
String csPassword = cmdLine.getOptionValue(PASSWORD_PARAM);
String password = csPassword == null ? "" : csPassword;
String salt = cmdLine.getOptionValue(SALT_PARAM);
String csType = cmdLine.getOptionValue(CREDENTIAL_STORE_TYPE_PARAM, KeyStoreCredentialStore.KEY_STORE_CREDENTIAL_STORE);
Expand All @@ -368,7 +368,7 @@ public void execute(String[] args) throws Exception {
if (!createStorage && location != null && !Files.exists(Paths.get(location))) {
throw ElytronToolMessages.msg.locationDoesNotExistCreationDisabled(location);
}
boolean printSummary = cmdLine.hasOption(PRINT_SUMMARY_PARAM);
boolean printSummary = cmdLine.hasOption(SUMMARY_PARAM);
String secret = cmdLine.getOptionValue(PASSWORD_CREDENTIAL_VALUE_PARAM);
String key = cmdLine.getOptionValue(KEY_PARAM);

Expand Down Expand Up @@ -404,7 +404,7 @@ public void execute(String[] args) throws Exception {
csPassword = prompt(false, ElytronToolMessages.msg.credentialStorePasswordPrompt(), createStorage, ElytronToolMessages.msg.credentialStorePasswordPromptConfirm());
if (csPassword == null) {
setStatus(GENERAL_CONFIGURATION_ERROR);
throw ElytronToolMessages.msg.optionNotSpecified(CREDENTIAL_STORE_PASSWORD_PARAM);
throw ElytronToolMessages.msg.optionNotSpecified(PASSWORD_PARAM);
}
}
if (csPassword != null) {
Expand Down Expand Up @@ -718,7 +718,7 @@ private void generateSecretKey(CredentialStore credentialStore, String entryType
String alias = cmdLine.getOptionValue(GENERATE_SECRET_KEY);
if (alias.length() == 0) {
setStatus(GENERAL_CONFIGURATION_ERROR);
throw ElytronToolMessages.msg.optionNotSpecified(ALIAS_ARGUMENT);
throw ElytronToolMessages.msg.optionNotSpecified(ALIAS_PARAM);
}

final SecretKey secretKey;
Expand All @@ -744,7 +744,7 @@ private void exportSecretKey(CredentialStore credentialStore) throws Exception {
String alias = cmdLine.getOptionValue(EXPORT_SECRET_KEY);
if (alias.length() == 0) {
setStatus(GENERAL_CONFIGURATION_ERROR);
throw ElytronToolMessages.msg.optionNotSpecified(ALIAS_ARGUMENT);
throw ElytronToolMessages.msg.optionNotSpecified(ALIAS_PARAM);
}

if (credentialStore.exists(alias, SecretKeyCredential.class)) {
Expand All @@ -762,7 +762,7 @@ private void importSecretKey(CredentialStore credentialStore, String entryType,
String alias = cmdLine.getOptionValue(IMPORT_SECRET_KEY);
if (alias.length() == 0) {
setStatus(GENERAL_CONFIGURATION_ERROR);
throw ElytronToolMessages.msg.optionNotSpecified(ALIAS_ARGUMENT);
throw ElytronToolMessages.msg.optionNotSpecified(ALIAS_PARAM);
}

if (key == null) {
Expand Down Expand Up @@ -797,7 +797,7 @@ private String encrypt(CredentialStore credentialStore) throws Exception {
String alias = cmdLine.getOptionValue(ENCRYPT);
if (alias.length() == 0) {
setStatus(GENERAL_CONFIGURATION_ERROR);
throw ElytronToolMessages.msg.optionNotSpecified(ALIAS_ARGUMENT);
throw ElytronToolMessages.msg.optionNotSpecified(ALIAS_PARAM);
}

String cipherTextToken = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,4 @@ Command findCommand(String commandName) {
return null;
}

}
}
Loading

0 comments on commit 051f5ee

Please sign in to comment.