Skip to content

Commit

Permalink
Merge pull request #1464 from chris-j-h/security-advisories-and-keyge…
Browse files Browse the repository at this point in the history
…n-output

Improve keygen CLI output, fix security advisories in key vault modules
  • Loading branch information
Krish1979 authored Jun 22, 2022
2 parents 18cb1fc + fa4787e commit e05a99f
Show file tree
Hide file tree
Showing 28 changed files with 468 additions and 187 deletions.
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import java.time.Duration

plugins {
id "org.owasp.dependencycheck" version "7.0.4.1"
id "org.owasp.dependencycheck" version "7.1.0.1"
id 'jacoco'
id 'com.diffplug.gradle.spotless' version '3.25.0'
id "io.github.gradle-nexus.publish-plugin" version "1.1.0"
Expand Down Expand Up @@ -248,6 +248,9 @@ subprojects {
dependencyCheck {
failBuildOnCVSS = 0
suppressionFile = project.getRootProject().file("cvss-suppressions.xml")
analyzers {
assemblyEnabled = false
}
}

jacoco {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,12 @@ public void testConfigPathStaysNullWithoutSpecifiedPath() {
serverURIOutputMixin.updateConfig(null, config);
assertThat(config.getOutputServerURIPath()).isNull();
}

@Test
public void defaultDoNothing() {
final Config config = new Config();
assertThat(config.getOutputServerURIPath()).isNull();
serverURIOutputMixin.updateConfig(config);
assertThat(config.getOutputServerURIPath()).isNull();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import com.quorum.tessera.cli.CliException;
import com.quorum.tessera.cli.CliResult;
import com.quorum.tessera.config.*;
import com.quorum.tessera.config.keypairs.ConfigKeyPair;
import com.quorum.tessera.config.keypairs.*;
import com.quorum.tessera.config.util.ConfigFileUpdaterWriter;
import com.quorum.tessera.config.util.PasswordFileUpdaterWriter;
import com.quorum.tessera.key.generation.GeneratedKeyPair;
import com.quorum.tessera.key.generation.KeyGenerator;
import com.quorum.tessera.key.generation.KeyGeneratorFactory;
import com.quorum.tessera.key.generation.KeyVaultOptions;
Expand All @@ -18,6 +19,8 @@
import java.util.concurrent.Callable;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;

@CommandLine.Command(
Expand All @@ -34,6 +37,8 @@
subcommands = {CommandLine.HelpCommand.class})
public class KeyGenCommand implements Callable<CliResult> {

private static final Logger LOGGER = LoggerFactory.getLogger(KeyGenCommand.class);

private final KeyGeneratorFactory keyGeneratorFactory;

private final ConfigFileUpdaterWriter configFileUpdaterWriter;
Expand Down Expand Up @@ -83,6 +88,79 @@ public class KeyGenCommand implements Callable<CliResult> {
this.keyDataMarshaller = Objects.requireNonNull(keyDataMarshaller);
}

static void output(List<GeneratedKeyPair> generatedKeyPairs) {
StringJoiner sj = new StringJoiner("\n");
sj.add(String.format("%d keypair(s) generated:", generatedKeyPairs.size()));

int i = 0;
for (GeneratedKeyPair kp : generatedKeyPairs) {
i++;
if (kp.getConfigKeyPair() instanceof AzureVaultKeyPair) {
AzureVaultKeyPair akp = (AzureVaultKeyPair) kp.getConfigKeyPair();
String type = "azure";
String pubKey = kp.getPublicKey();
String pubId = akp.getPublicKeyId();
String privId = akp.getPrivateKeyId();
String pubVersion = akp.getPublicKeyVersion();
String privVersion = akp.getPrivateKeyVersion();

sj.add(String.format("\t%d: type=%s, pub=%s", i, type, pubKey));
sj.add(String.format("\t\tpub: id=%s, version=%s", pubId, pubVersion));
sj.add(String.format("\t\tprv: id=%s, version=%s", privId, privVersion));
} else if (kp.getConfigKeyPair() instanceof AWSKeyPair) {
AWSKeyPair akp = (AWSKeyPair) kp.getConfigKeyPair();
String type = "aws";
String pubKey = kp.getPublicKey();
String pubId = akp.getPublicKeyId();
String privId = akp.getPrivateKeyId();

sj.add(String.format("\t%d: type=%s, pub=%s", i, type, pubKey));
sj.add(String.format("\t\tpub: id=%s", pubId));
sj.add(String.format("\t\tprv: id=%s", privId));
} else if (kp.getConfigKeyPair() instanceof HashicorpVaultKeyPair) {
HashicorpVaultKeyPair hkp = (HashicorpVaultKeyPair) kp.getConfigKeyPair();
String type = "hashicorp";
String pubKey = kp.getPublicKey();
String name = hkp.getSecretName();
String secretEngine = hkp.getSecretEngineName();
String version = hkp.getSecretVersion().toString();
String pubId = hkp.getPublicKeyId();
String privId = hkp.getPrivateKeyId();

sj.add(String.format("\t%d: type=%s, pub=%s", i, type, pubKey));
sj.add(
String.format(
"\t\tpub: name=%s/%s, id=%s, version=%s", secretEngine, name, pubId, version));
sj.add(
String.format(
"\t\tprv: name=%s/%s, id=%s, version=%s", secretEngine, name, privId, version));
} else if (kp.getConfigKeyPair() instanceof FilesystemKeyPair) {
FilesystemKeyPair fkp = (FilesystemKeyPair) kp.getConfigKeyPair();
String type = "file";
String pubPath = fkp.getPublicKeyPath().toAbsolutePath().toString();
String privPath = fkp.getPrivateKeyPath().toAbsolutePath().toString();
String pubKey = kp.getPublicKey();

sj.add(String.format("\t%d: type=%s, pub=%s", i, type, pubKey));
sj.add(String.format("\t\tpub: path=%s", pubPath));
sj.add(String.format("\t\tprv: path=%s", privPath));
} else {
sj.add(
String.format("\t%d: type=unknown, pub=%s", i, kp.getConfigKeyPair().getPublicKey()));
}
}
System.out.println(sj);
}

static void prepareConfigForNewKeys(Config config) {
if (Objects.isNull(config.getKeys())) {
config.setKeys(new KeyConfiguration());
}
if (Objects.isNull(config.getKeys().getKeyData())) {
config.getKeys().setKeyData(new ArrayList<>());
}
}

@Override
public CliResult call() throws IOException {
if (Objects.nonNull(fileUpdateOptions) && Objects.isNull(fileUpdateOptions.getConfig())) {
Expand Down Expand Up @@ -118,12 +196,10 @@ public CliResult call() throws IOException {
.flatMap(c -> c.getKeyVaultConfig(keyVaultConfigOptions.getVaultType()))
.orElse(null);
} else {

final KeyVaultHandler keyVaultHandler = new DispatchingKeyVaultHandler();
keyVaultConfig = keyVaultHandler.handle(keyVaultConfigOptions);

if (keyVaultConfig.getKeyVaultType() == KeyVaultType.HASHICORP) {

if (Objects.isNull(keyOut)) {
throw new CliException(
"At least one -filename must be provided when saving generated keys in a Hashicorp Vault");
Expand All @@ -145,24 +221,30 @@ public CliResult call() throws IOException {
.map(List::copyOf)
.orElseGet(() -> List.of(""));

final List<ConfigKeyPair> newConfigKeyPairs =
final List<GeneratedKeyPair> generatedKeyPairs =
newKeyNames.stream()
.map(name -> keyGenerator.generate(name, argonOptions, keyVaultOptions))
.collect(Collectors.toList());

output(generatedKeyPairs);

final List<char[]> newPasswords =
newConfigKeyPairs.stream()
generatedKeyPairs.stream()
.filter(Objects::nonNull)
.map(GeneratedKeyPair::getConfigKeyPair)
.map(ConfigKeyPair::getPassword)
.collect(Collectors.toList());

final List<KeyData> newKeyData =
newConfigKeyPairs.stream().map(keyDataMarshaller::marshal).collect(Collectors.toList());

if (Objects.isNull(fileUpdateOptions)) {
return new CliResult(0, true, null);
}

final List<KeyData> newKeyData =
generatedKeyPairs.stream()
.map(GeneratedKeyPair::getConfigKeyPair)
.map(keyDataMarshaller::marshal)
.collect(Collectors.toList());

// prepare config for addition of new keys if required
prepareConfigForNewKeys(fileUpdateOptions.getConfig());

Expand All @@ -184,13 +266,4 @@ public CliResult call() throws IOException {

return new CliResult(0, true, fileUpdateOptions.getConfig());
}

static void prepareConfigForNewKeys(Config config) {
if (Objects.isNull(config.getKeys())) {
config.setKeys(new KeyConfiguration());
}
if (Objects.isNull(config.getKeys().getKeyData())) {
config.getKeys().setKeyData(new ArrayList<>());
}
}
}
Loading

0 comments on commit e05a99f

Please sign in to comment.