Updated ATs DSL to create PKI QBFT node configuration (#2670)

Signed-off-by: Lucas Saldanha <lucascrsaldanha@gmail.com>
This commit is contained in:
Lucas Saldanha
2021-08-25 16:54:36 +12:00
committed by GitHub
parent 9d91136ffd
commit 68f222be5c
14 changed files with 319 additions and 38 deletions

View File

@@ -14,6 +14,7 @@ dependencies {
implementation project(':ethereum:eth')
implementation project(':ethereum:p2p')
implementation project(':pki')
implementation project(path: ':pki', configuration: 'testArtifacts')
implementation project(':ethereum:permissioning')
implementation project(':ethereum:rlp')
implementation project(':metrics:core')

View File

@@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.NodeConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
@@ -118,6 +119,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
private final List<String> staticNodes;
private boolean isDnsEnabled = false;
private Optional<Integer> exitCode = Optional.empty();
private Optional<PkiKeyStoreConfiguration> pkiKeyStoreConfiguration = Optional.empty();
public BesuNode(
final String name,
@@ -145,7 +147,8 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
final boolean isDnsEnabled,
final Optional<PrivacyParameters> privacyParameters,
final List<String> runCommand,
final Optional<KeyPair> keyPair)
final Optional<KeyPair> keyPair,
final Optional<PkiKeyStoreConfiguration> pkiKeyStoreConfiguration)
throws IOException {
this.homeDirectory = dataPath.orElseGet(BesuNode::createTmpDataDirectory);
keyfilePath.ifPresent(
@@ -195,6 +198,7 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
this.staticNodes = staticNodes;
this.isDnsEnabled = isDnsEnabled;
privacyParameters.ifPresent(this::setPrivacyParameters);
this.pkiKeyStoreConfiguration = pkiKeyStoreConfiguration;
LOG.info("Created BesuNode {}", this.toString());
}
@@ -656,6 +660,10 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable
return runCommand;
}
public Optional<PkiKeyStoreConfiguration> getPkiKeyStoreConfiguration() {
return pkiKeyStoreConfiguration;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)

View File

@@ -319,6 +319,34 @@ public class ProcessBesuNodeRunner implements BesuNodeRunner {
String.valueOf(
permissioningConfiguration.getNodeSmartContractInterfaceVersion()));
});
node.getPkiKeyStoreConfiguration()
.ifPresent(
pkiConfig -> {
params.add("--Xpki-block-creation-enabled");
params.add("--Xpki-block-creation-keystore-certificate-alias");
params.add(pkiConfig.getCertificateAlias());
params.add("--Xpki-block-creation-keystore-type");
params.add(pkiConfig.getKeyStoreType());
params.add("--Xpki-block-creation-keystore-file");
params.add(pkiConfig.getKeyStorePath().toAbsolutePath().toString());
params.add("--Xpki-block-creation-keystore-password-file");
params.add(pkiConfig.getKeyStorePasswordPath().toAbsolutePath().toString());
params.add("--Xpki-block-creation-truststore-type");
params.add(pkiConfig.getTrustStoreType());
params.add("--Xpki-block-creation-truststore-file");
params.add(pkiConfig.getTrustStorePath().toAbsolutePath().toString());
params.add("--Xpki-block-creation-truststore-password-file");
params.add(pkiConfig.getTrustStorePasswordPath().toAbsolutePath().toString());
});
params.addAll(node.getExtraCLIOptions());
params.add("--key-value-storage");

View File

@@ -20,6 +20,7 @@ import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH;
import org.hyperledger.besu.Runner;
import org.hyperledger.besu.RunnerBuilder;
import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfigurationProvider;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.controller.BesuControllerBuilder;
import org.hyperledger.besu.crypto.KeyPairSecurityModule;
@@ -163,6 +164,10 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.isRevertReasonEnabled(node.isRevertReasonEnabled())
.storageProvider(storageProvider)
.gasLimitCalculator(GasLimitCalculator.constant())
.pkiBlockCreationConfiguration(
node.getPkiKeyStoreConfiguration()
.map(
(pkiConfig) -> new PkiBlockCreationConfigurationProvider().load(pkiConfig)))
.build();
final RunnerBuilder runnerBuilder = new RunnerBuilder();

View File

@@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
import java.nio.file.Path;
@@ -58,6 +59,7 @@ public class BesuNodeConfiguration {
private final List<String> runCommand;
private final NetworkName network;
private final Optional<KeyPair> keyPair;
private final Optional<PkiKeyStoreConfiguration> pkiKeyStoreConfiguration;
BesuNodeConfiguration(
final String name,
@@ -85,7 +87,8 @@ public class BesuNodeConfiguration {
final boolean isDnsEnabled,
final Optional<PrivacyParameters> privacyParameters,
final List<String> runCommand,
final Optional<KeyPair> keyPair) {
final Optional<KeyPair> keyPair,
final Optional<PkiKeyStoreConfiguration> pkiKeyStoreConfiguration) {
this.name = name;
this.miningParameters = miningParameters;
this.jsonRpcConfiguration = jsonRpcConfiguration;
@@ -112,6 +115,7 @@ public class BesuNodeConfiguration {
this.privacyParameters = privacyParameters;
this.runCommand = runCommand;
this.keyPair = keyPair;
this.pkiKeyStoreConfiguration = pkiKeyStoreConfiguration;
}
public String getName() {
@@ -217,4 +221,8 @@ public class BesuNodeConfiguration {
public Optional<KeyPair> getKeyPair() {
return keyPair;
}
public Optional<PkiKeyStoreConfiguration> getPkiKeyStoreConfiguration() {
return pkiKeyStoreConfiguration;
}
}

View File

@@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration;
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
@@ -80,6 +81,7 @@ public class BesuNodeConfigurationBuilder {
private Optional<PrivacyParameters> privacyParameters = Optional.empty();
private List<String> runCommand = new ArrayList<>();
private Optional<KeyPair> keyPair = Optional.empty();
private Optional<PkiKeyStoreConfiguration> pkiKeyStoreConfiguration = Optional.empty();
public BesuNodeConfigurationBuilder() {
// Check connections more frequently during acceptance tests to cut down on
@@ -349,6 +351,13 @@ public class BesuNodeConfigurationBuilder {
return tempFile.toPath();
}
public BesuNodeConfigurationBuilder pkiBlockCreationEnabled(
final PkiKeyStoreConfiguration pkiKeyStoreConfiguration) {
this.pkiKeyStoreConfiguration = Optional.of(pkiKeyStoreConfiguration);
return this;
}
public BesuNodeConfigurationBuilder discoveryEnabled(final boolean discoveryEnabled) {
this.discoveryEnabled = discoveryEnabled;
return this;
@@ -433,6 +442,7 @@ public class BesuNodeConfigurationBuilder {
isDnsEnabled,
privacyParameters,
runCommand,
keyPair);
keyPair,
pkiKeyStoreConfiguration);
}
}

View File

@@ -37,6 +37,7 @@ import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki.PkiKeystoreConfigurationFactory;
import java.io.File;
import java.io.IOException;
@@ -54,6 +55,8 @@ public class BesuNodeFactory {
private final GenesisConfigurationFactory genesis = new GenesisConfigurationFactory();
private final NodeConfigurationFactory node = new NodeConfigurationFactory();
private final PkiKeystoreConfigurationFactory pkiKeystoreConfigurationFactory =
new PkiKeystoreConfigurationFactory();
public BesuNode create(final BesuNodeConfiguration config) throws IOException {
return new BesuNode(
@@ -82,7 +85,8 @@ public class BesuNodeFactory {
config.isDnsEnabled(),
config.getPrivacyParameters(),
config.getRunCommand(),
config.getKeyPair());
config.getKeyPair(),
config.getPkiKeyStoreConfiguration());
}
public BesuNode createMinerNode(final String name) throws IOException {
@@ -392,6 +396,19 @@ public class BesuNodeFactory {
.build());
}
public BesuNode createPkiQbftNode(final String name) throws IOException {
return create(
new BesuNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false))
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.devMode(false)
.genesisConfigProvider(genesis::createQbftGenesisConfig)
.pkiBlockCreationEnabled(pkiKeystoreConfigurationFactory.createPkiConfig())
.build());
}
public BesuNode createCustomGenesisNode(
final String name, final String genesisPath, final boolean canBeBootnode) throws IOException {
return createCustomGenesisNode(name, genesisPath, canBeBootnode, false);
@@ -504,6 +521,24 @@ public class BesuNodeFactory {
.build());
}
public BesuNode createPkiQbftNodeWithValidators(final String name, final String... validators)
throws IOException {
return create(
new BesuNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithQbftEnabledConfig(false))
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.devMode(false)
.pkiBlockCreationEnabled(pkiKeystoreConfigurationFactory.createPkiConfig())
.genesisConfigProvider(
nodes ->
node.createGenesisConfigForValidators(
asList(validators), nodes, genesis::createQbftGenesisConfig))
.build());
}
public BesuNode createNodeWithStaticNodes(final String name, final List<Node> staticNodes)
throws IOException {

View File

@@ -0,0 +1,147 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See
* the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki;
import static org.hyperledger.besu.pki.util.TestCertificateUtils.createKeyPair;
import static org.hyperledger.besu.pki.util.TestCertificateUtils.createSelfSignedCertificate;
import static org.hyperledger.besu.pki.util.TestCertificateUtils.issueCertificate;
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.UUID;
public class PkiKeystoreConfigurationFactory {
public static final String KEYSTORE_DEFAULT_TYPE = "PKCS12";
public static final String KEYSTORE_DEFAULT_PASSWORD = "password";
public static final String KEYSTORE_DEFAULT_CERT_ALIAS = "validator";
private KeyPair caKeyPair;
private X509Certificate caCertificate;
private Path trustStoreFile;
private Path passwordFile;
public PkiKeyStoreConfiguration createPkiConfig() {
PkiKeyStoreConfiguration.Builder pkiKeyStoreConfigBuilder =
new PkiKeyStoreConfiguration.Builder();
pkiKeyStoreConfigBuilder.withTrustStoreType(KEYSTORE_DEFAULT_TYPE);
pkiKeyStoreConfigBuilder.withTrustStorePath(createTrustStore());
pkiKeyStoreConfigBuilder.withTrustStorePasswordPath(passwordFile);
pkiKeyStoreConfigBuilder.withKeyStoreType(KEYSTORE_DEFAULT_TYPE);
pkiKeyStoreConfigBuilder.withKeyStorePath(createKeyStore());
pkiKeyStoreConfigBuilder.withKeyStorePasswordPath(passwordFile);
pkiKeyStoreConfigBuilder.withCertificateAlias(KEYSTORE_DEFAULT_CERT_ALIAS);
return pkiKeyStoreConfigBuilder.build();
}
private Path createTrustStore() {
// Only create the truststore if this is the first time this method is being called
if (caKeyPair == null) {
try {
caKeyPair = createKeyPair();
caCertificate = createSelfSignedCertificate("ca", notBefore(), notAfter(), caKeyPair);
final KeyStore truststore = KeyStore.getInstance(KEYSTORE_DEFAULT_TYPE);
truststore.load(null, null);
truststore.setCertificateEntry("ca", caCertificate);
final String uniqueId = UUID.randomUUID().toString();
trustStoreFile = writeKeyStoreFile(truststore, "truststore", uniqueId);
passwordFile = writePasswordFile(KEYSTORE_DEFAULT_PASSWORD, "password", uniqueId);
} catch (final Exception e) {
throw new RuntimeException("Error creating truststore for Acceptance Test", e);
}
}
return trustStoreFile;
}
private Path createKeyStore() {
if (caKeyPair == null) {
createTrustStore();
}
final KeyPair kp = createKeyPair();
final X509Certificate certificate =
issueCertificate(caCertificate, caKeyPair, "validator", notBefore(), notAfter(), kp, false);
try {
final KeyStore keyStore = KeyStore.getInstance(KEYSTORE_DEFAULT_TYPE);
keyStore.load(null, null);
keyStore.setKeyEntry(
"validator",
kp.getPrivate(),
KEYSTORE_DEFAULT_PASSWORD.toCharArray(),
new Certificate[] {certificate, caCertificate});
final String id = UUID.randomUUID().toString();
return writeKeyStoreFile(keyStore, "keystore", id);
} catch (final Exception e) {
throw new RuntimeException("Error creating keystore for Acceptance Test", e);
}
}
private Path writeKeyStoreFile(
final KeyStore keyStore, final String prefix, final String suffix) {
try {
final Path file = Files.createTempFile(prefix, suffix != null ? suffix : "");
file.toFile().deleteOnExit();
final FileOutputStream keyStoreFOS = new FileOutputStream(file.toFile());
keyStore.store(keyStoreFOS, KEYSTORE_DEFAULT_PASSWORD.toCharArray());
return file;
} catch (final Exception e) {
throw new RuntimeException("Error creating keystore file", e);
}
}
private Path writePasswordFile(final String password, final String prefix, final String suffix) {
try {
final Path file = Files.createTempFile(prefix, suffix);
file.toFile().deleteOnExit();
Files.write(file, password.getBytes(StandardCharsets.UTF_8));
return file;
} catch (final IOException e) {
throw new RuntimeException("Error creating password file", e);
}
}
private Instant notBefore() {
return Instant.now().minus(1, ChronoUnit.DAYS);
}
private Instant notAfter() {
return Instant.now().plus(10, ChronoUnit.DAYS);
}
}

View File

@@ -123,6 +123,7 @@ public class PrivacyNode implements AutoCloseable {
besuConfig.isDnsEnabled(),
besuConfig.getPrivacyParameters(),
List.of(),
Optional.empty(),
Optional.empty());
}

View File

@@ -19,7 +19,6 @@ import static java.util.Arrays.asList;
import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP;
import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider;
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration;
import java.nio.file.Path;
@@ -119,14 +118,11 @@ public class PkiBlockCreationOptions {
new PkiKeyStoreConfiguration.Builder()
.withKeyStoreType(keyStoreType)
.withKeyStorePath(keyStoreFile)
.withKeyStorePasswordSupplier(new FileBasedPasswordProvider(keyStorePasswordFile))
.withKeyStorePasswordPath(keyStorePasswordFile)
.withCertificateAlias(certificateAlias)
.withTrustStoreType(trustStoreType)
.withTrustStorePath(trustStoreFile)
.withTrustStorePasswordSupplier(
null == trustStorePasswordFile
? null
: new FileBasedPasswordProvider(trustStorePasswordFile))
.withTrustStorePasswordPath(trustStorePasswordFile)
.withCrlFilePath(crlFile)
.build());
}

View File

@@ -19,6 +19,8 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfigurationProvider.KeyStoreWrapperProvider;
@@ -48,14 +50,17 @@ public class PkiBlockCreationConfigurationProviderTest {
.thenReturn(trustStoreWrapper);
final PkiKeyStoreConfiguration pkiKeyStoreConfiguration =
new PkiKeyStoreConfiguration.Builder()
.withKeyStorePath(Path.of("/tmp/keystore"))
.withKeyStorePasswordSupplier(() -> "pwd")
.withTrustStorePath(Path.of("/tmp/truststore"))
.withTrustStorePasswordSupplier(() -> "pwd")
.withCertificateAlias("anAlias")
.withCrlFilePath(Path.of("/tmp/crl"))
.build();
spy(
new PkiKeyStoreConfiguration.Builder()
.withKeyStorePath(Path.of("/tmp/keystore"))
.withKeyStorePasswordPath(Path.of("/tmp/password"))
.withTrustStorePath(Path.of("/tmp/truststore"))
.withTrustStorePasswordPath(Path.of("/tmp/password"))
.withCertificateAlias("anAlias")
.withCrlFilePath(Path.of("/tmp/crl"))
.build());
doReturn("pwd").when(pkiKeyStoreConfiguration).getKeyStorePassword();
doReturn("pwd").when(pkiKeyStoreConfiguration).getTrustStorePassword();
final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider =
new PkiBlockCreationConfigurationProvider(keyStoreWrapperProvider);

View File

@@ -38,3 +38,13 @@ dependencies {
testImplementation 'org.mockito:mockito-core'
testImplementation 'org.apache.logging.log4j:log4j-core'
}
configurations { testArtifacts }
task testJar(type: Jar) {
archiveBaseName = "${project.name}-test"
from sourceSets.test.output
}
artifacts {
testArtifacts testJar
}

View File

@@ -16,9 +16,13 @@ package org.hyperledger.besu.pki.config;
import static java.util.Objects.requireNonNull;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;
import com.google.common.annotations.VisibleForTesting;
public class PkiKeyStoreConfiguration {
@@ -27,29 +31,29 @@ public class PkiKeyStoreConfiguration {
private final String keyStoreType;
private final Path keyStorePath;
private final Supplier<String> keyStorePasswordSupplier;
private final Path keyStorePasswordPath;
private final String certificateAlias;
private final String trustStoreType;
private final Path trustStorePath;
private final Supplier<String> trustStorePasswordSupplier;
private final Path trustStorePasswordPath;
private final Optional<Path> crlFilePath;
public PkiKeyStoreConfiguration(
final String keyStoreType,
final Path keyStorePath,
final Supplier<String> keyStorePasswordSupplier,
final Path keyStorePasswordPath,
final String certificateAlias,
final String trustStoreType,
final Path trustStorePath,
final Supplier<String> trustStorePasswordSupplier,
final Path trustStorePasswordPath,
final Optional<Path> crlFilePath) {
this.keyStoreType = keyStoreType;
this.keyStorePath = keyStorePath;
this.keyStorePasswordSupplier = keyStorePasswordSupplier;
this.keyStorePasswordPath = keyStorePasswordPath;
this.certificateAlias = certificateAlias;
this.trustStoreType = trustStoreType;
this.trustStorePath = trustStorePath;
this.trustStorePasswordSupplier = trustStorePasswordSupplier;
this.trustStorePasswordPath = trustStorePasswordPath;
this.crlFilePath = crlFilePath;
}
@@ -61,8 +65,13 @@ public class PkiKeyStoreConfiguration {
return keyStorePath;
}
@VisibleForTesting
public Path getKeyStorePasswordPath() {
return keyStorePasswordPath;
}
public String getKeyStorePassword() {
return null == keyStorePasswordSupplier ? null : keyStorePasswordSupplier.get();
return readPasswordFromFile(keyStorePasswordPath);
}
public String getCertificateAlias() {
@@ -77,8 +86,13 @@ public class PkiKeyStoreConfiguration {
return trustStorePath;
}
@VisibleForTesting
public Path getTrustStorePasswordPath() {
return trustStorePasswordPath;
}
public String getTrustStorePassword() {
return trustStorePasswordSupplier.get();
return readPasswordFromFile(trustStorePasswordPath);
}
public Optional<Path> getCrlFilePath() {
@@ -89,11 +103,11 @@ public class PkiKeyStoreConfiguration {
private String keyStoreType = DEFAULT_KEYSTORE_TYPE;
private Path keyStorePath;
private Supplier<String> keyStorePasswordSupplier;
private Path keyStorePasswordPath;
private String certificateAlias = DEFAULT_CERTIFICATE_ALIAS;
private String trustStoreType = DEFAULT_KEYSTORE_TYPE;
private Path trustStorePath;
private Supplier<String> trustStorePasswordSupplier;
private Path trustStorePasswordPath;
private Path crlFilePath;
public Builder() {}
@@ -108,8 +122,8 @@ public class PkiKeyStoreConfiguration {
return this;
}
public Builder withKeyStorePasswordSupplier(final Supplier<String> keyStorePasswordSupplier) {
this.keyStorePasswordSupplier = keyStorePasswordSupplier;
public Builder withKeyStorePasswordPath(final Path keyStorePasswordPath) {
this.keyStorePasswordPath = keyStorePasswordPath;
return this;
}
@@ -128,9 +142,8 @@ public class PkiKeyStoreConfiguration {
return this;
}
public Builder withTrustStorePasswordSupplier(
final Supplier<String> trustStorePasswordSupplier) {
this.trustStorePasswordSupplier = trustStorePasswordSupplier;
public Builder withTrustStorePasswordPath(final Path trustStorePasswordPath) {
this.trustStorePasswordPath = trustStorePasswordPath;
return this;
}
@@ -141,16 +154,29 @@ public class PkiKeyStoreConfiguration {
public PkiKeyStoreConfiguration build() {
requireNonNull(keyStoreType, "Key Store Type must not be null");
requireNonNull(keyStorePasswordSupplier, "Key Store password supplier must not be null");
requireNonNull(keyStorePasswordPath, "Key Store password file must not be null");
return new PkiKeyStoreConfiguration(
keyStoreType,
keyStorePath,
keyStorePasswordSupplier,
keyStorePasswordPath,
certificateAlias,
trustStoreType,
trustStorePath,
trustStorePasswordSupplier,
trustStorePasswordPath,
Optional.ofNullable(crlFilePath));
}
}
private String readPasswordFromFile(final Path passwordFile) {
try (final Stream<String> fileStream = Files.lines(passwordFile)) {
return fileStream.findFirst().orElseThrow(() -> errorReadingFileException(passwordFile));
} catch (final IOException e) {
throw errorReadingFileException(passwordFile);
}
}
private RuntimeException errorReadingFileException(final Path path) {
return new RuntimeException(String.format("Unable to read keystore password from %s", path));
}
}

View File

@@ -162,7 +162,8 @@ public class SoftwareKeyStoreWrapper extends AbstractKeyStoreWrapper {
}
return certificateChain;
} catch (final Exception e) {
throw new PkiException("Failed to certificate chain for alias: " + certificateAlias, e);
throw new PkiException(
"Failed to retrieve certificate chain for alias: " + certificateAlias, e);
}
}