mirror of https://github.com/hyperledger/besu
PKI Block Creation cli configuration (#2619)
* Added CLI options for PKI Block Creation * BesuCommand changes for PKI Block Creation Signed-off-by: Lucas Saldanha <lucascrsaldanha@gmail.com>pull/2623/head
parent
b9e1ce05c0
commit
047b680ddc
@ -0,0 +1,144 @@ |
|||||||
|
/* |
||||||
|
* 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.cli.options.unstable; |
||||||
|
|
||||||
|
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; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
import org.apache.logging.log4j.Logger; |
||||||
|
import picocli.CommandLine; |
||||||
|
import picocli.CommandLine.Option; |
||||||
|
import picocli.CommandLine.ParameterException; |
||||||
|
|
||||||
|
public class PkiBlockCreationOptions { |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-enabled"}, |
||||||
|
hidden = true, |
||||||
|
description = "Enable PKI integration (default: ${DEFAULT-VALUE})") |
||||||
|
Boolean enabled = false; |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-keystore-type"}, |
||||||
|
hidden = true, |
||||||
|
paramLabel = "<NAME>", |
||||||
|
description = "PKI service keystore type. Required if PKI Block Creation is enabled.") |
||||||
|
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) |
||||||
|
String keyStoreType = PkiKeyStoreConfiguration.DEFAULT_KEYSTORE_TYPE; |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-keystore-file"}, |
||||||
|
hidden = true, |
||||||
|
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||||
|
description = "Keystore containing key/certificate for PKI Block Creation.") |
||||||
|
Path keyStoreFile = null; |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-keystore-password-file"}, |
||||||
|
hidden = true, |
||||||
|
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||||
|
description = |
||||||
|
"File containing password to unlock keystore for PKI Integration. Required if PKI Block Creation is enabled.") |
||||||
|
Path keyStorePasswordFile = null; |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-keystore-certificate-alias"}, |
||||||
|
hidden = true, |
||||||
|
paramLabel = "<NAME>", |
||||||
|
description = |
||||||
|
"Alias of the certificate that will be included in the blocks proposed by this validator.") |
||||||
|
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) |
||||||
|
String certificateAlias = PkiKeyStoreConfiguration.DEFAULT_CERTIFICATE_ALIAS; |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-truststore-type"}, |
||||||
|
hidden = true, |
||||||
|
paramLabel = "<NAME>", |
||||||
|
description = "PKI Integration truststore type.") |
||||||
|
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) |
||||||
|
String trustStoreType = PkiKeyStoreConfiguration.DEFAULT_KEYSTORE_TYPE; |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-truststore-file"}, |
||||||
|
hidden = true, |
||||||
|
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||||
|
description = "Truststore containing trusted certificates for PKI Block Creation.") |
||||||
|
Path trustStoreFile = null; |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-truststore-password-file"}, |
||||||
|
hidden = true, |
||||||
|
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||||
|
description = "File containing password to unlock truststore for PKI Block Creation.") |
||||||
|
Path trustStorePasswordFile = null; |
||||||
|
|
||||||
|
@Option( |
||||||
|
names = {"--Xpki-block-creation-crl-file"}, |
||||||
|
hidden = true, |
||||||
|
paramLabel = MANDATORY_FILE_FORMAT_HELP, |
||||||
|
description = "File with all CRLs for PKI Block Creation.") |
||||||
|
Path crlFile = null; |
||||||
|
|
||||||
|
public Optional<PkiKeyStoreConfiguration> asDomainConfig(final CommandLine commandLine) { |
||||||
|
if (!enabled) { |
||||||
|
return Optional.empty(); |
||||||
|
} |
||||||
|
|
||||||
|
if (keyStoreFile == null) { |
||||||
|
throw new ParameterException( |
||||||
|
commandLine, "KeyStore file is required when PKI Block Creation is enabled"); |
||||||
|
} |
||||||
|
|
||||||
|
if (keyStorePasswordFile == null) { |
||||||
|
throw new ParameterException( |
||||||
|
commandLine, |
||||||
|
"File containing password to unlock keystore is required when PKI Block Creation is enabled"); |
||||||
|
} |
||||||
|
|
||||||
|
return Optional.of( |
||||||
|
new PkiKeyStoreConfiguration.Builder() |
||||||
|
.withKeyStoreType(keyStoreType) |
||||||
|
.withKeyStorePath(keyStoreFile) |
||||||
|
.withKeyStorePasswordSupplier(new FileBasedPasswordProvider(keyStorePasswordFile)) |
||||||
|
.withCertificateAlias(certificateAlias) |
||||||
|
.withTrustStoreType(trustStoreType) |
||||||
|
.withTrustStorePath(trustStoreFile) |
||||||
|
.withTrustStorePasswordSupplier( |
||||||
|
null == trustStorePasswordFile |
||||||
|
? null |
||||||
|
: new FileBasedPasswordProvider(trustStorePasswordFile)) |
||||||
|
.withCrlFilePath(crlFile) |
||||||
|
.build()); |
||||||
|
} |
||||||
|
|
||||||
|
public void checkPkiBlockCreationOptionsDependencies( |
||||||
|
final Logger logger, final CommandLine commandLine) { |
||||||
|
CommandLineUtils.checkOptionDependencies( |
||||||
|
logger, |
||||||
|
commandLine, |
||||||
|
"--Xpki-block-creation-enabled", |
||||||
|
!enabled, |
||||||
|
asList( |
||||||
|
"--Xpki-block-creation-keystore-file", "--Xpki-block-creation-keystore-password-file")); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* 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.consensus.qbft.pki; |
||||||
|
|
||||||
|
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; |
||||||
|
|
||||||
|
public class PkiBlockCreationConfiguration { |
||||||
|
|
||||||
|
private final KeyStoreWrapper keyStore; |
||||||
|
private final KeyStoreWrapper trustStore; |
||||||
|
private final String certificateAlias; |
||||||
|
|
||||||
|
public PkiBlockCreationConfiguration( |
||||||
|
final KeyStoreWrapper keyStore, |
||||||
|
final KeyStoreWrapper trustStore, |
||||||
|
final String certificateAlias) { |
||||||
|
this.keyStore = keyStore; |
||||||
|
this.trustStore = trustStore; |
||||||
|
this.certificateAlias = certificateAlias; |
||||||
|
} |
||||||
|
|
||||||
|
public KeyStoreWrapper getKeyStore() { |
||||||
|
return keyStore; |
||||||
|
} |
||||||
|
|
||||||
|
public KeyStoreWrapper getTrustStore() { |
||||||
|
return trustStore; |
||||||
|
} |
||||||
|
|
||||||
|
public String getCertificateAlias() { |
||||||
|
return certificateAlias; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,91 @@ |
|||||||
|
/* |
||||||
|
* 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.consensus.qbft.pki; |
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull; |
||||||
|
|
||||||
|
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; |
||||||
|
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; |
||||||
|
import org.hyperledger.besu.pki.keystore.SoftwareKeyStoreWrapper; |
||||||
|
|
||||||
|
import java.nio.file.Path; |
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting; |
||||||
|
import org.apache.logging.log4j.LogManager; |
||||||
|
import org.apache.logging.log4j.Logger; |
||||||
|
|
||||||
|
public class PkiBlockCreationConfigurationProvider { |
||||||
|
|
||||||
|
private static final Logger LOG = LogManager.getLogger(); |
||||||
|
|
||||||
|
private final KeyStoreWrapperProvider keyStoreWrapperProvider; |
||||||
|
|
||||||
|
public PkiBlockCreationConfigurationProvider() { |
||||||
|
this(SoftwareKeyStoreWrapper::new); |
||||||
|
} |
||||||
|
|
||||||
|
@VisibleForTesting |
||||||
|
PkiBlockCreationConfigurationProvider(final KeyStoreWrapperProvider keyStoreWrapperProvider) { |
||||||
|
this.keyStoreWrapperProvider = checkNotNull(keyStoreWrapperProvider); |
||||||
|
} |
||||||
|
|
||||||
|
public PkiBlockCreationConfiguration load( |
||||||
|
final PkiKeyStoreConfiguration pkiKeyStoreConfiguration) { |
||||||
|
KeyStoreWrapper keyStore; |
||||||
|
try { |
||||||
|
keyStore = |
||||||
|
keyStoreWrapperProvider.apply( |
||||||
|
pkiKeyStoreConfiguration.getKeyStoreType(), |
||||||
|
pkiKeyStoreConfiguration.getKeyStorePath(), |
||||||
|
pkiKeyStoreConfiguration.getKeyStorePassword(), |
||||||
|
null); |
||||||
|
LOG.info("Loaded PKI Block Creation KeyStore {}", pkiKeyStoreConfiguration.getKeyStorePath()); |
||||||
|
} catch (Exception e) { |
||||||
|
final String message = "Error loading PKI Block Creation KeyStore"; |
||||||
|
LOG.error(message, e); |
||||||
|
throw new RuntimeException(message, e); |
||||||
|
} |
||||||
|
|
||||||
|
KeyStoreWrapper trustStore; |
||||||
|
try { |
||||||
|
trustStore = |
||||||
|
keyStoreWrapperProvider.apply( |
||||||
|
pkiKeyStoreConfiguration.getTrustStoreType(), |
||||||
|
pkiKeyStoreConfiguration.getTrustStorePath(), |
||||||
|
pkiKeyStoreConfiguration.getTrustStorePassword(), |
||||||
|
pkiKeyStoreConfiguration.getCrlFilePath().orElse(null)); |
||||||
|
LOG.info( |
||||||
|
"Loaded PKI Block Creation TrustStore {}", pkiKeyStoreConfiguration.getTrustStorePath()); |
||||||
|
} catch (Exception e) { |
||||||
|
final String message = "Error loading PKI Block Creation TrustStore"; |
||||||
|
LOG.error(message, e); |
||||||
|
throw new RuntimeException(message, e); |
||||||
|
} |
||||||
|
|
||||||
|
return new PkiBlockCreationConfiguration( |
||||||
|
keyStore, trustStore, pkiKeyStoreConfiguration.getCertificateAlias()); |
||||||
|
} |
||||||
|
|
||||||
|
@FunctionalInterface |
||||||
|
interface KeyStoreWrapperProvider { |
||||||
|
|
||||||
|
KeyStoreWrapper apply( |
||||||
|
final String keyStoreType, |
||||||
|
final Path keyStorePath, |
||||||
|
final String keyStorePassword, |
||||||
|
final Path crl); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,71 @@ |
|||||||
|
/* |
||||||
|
* 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.consensus.qbft.pki; |
||||||
|
|
||||||
|
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.when; |
||||||
|
|
||||||
|
import org.hyperledger.besu.consensus.qbft.pki.PkiBlockCreationConfigurationProvider.KeyStoreWrapperProvider; |
||||||
|
import org.hyperledger.besu.pki.config.PkiKeyStoreConfiguration; |
||||||
|
import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; |
||||||
|
|
||||||
|
import java.nio.file.Path; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.runner.RunWith; |
||||||
|
import org.mockito.Mock; |
||||||
|
import org.mockito.junit.MockitoJUnitRunner; |
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class) |
||||||
|
public class PkiBlockCreationConfigurationProviderTest { |
||||||
|
|
||||||
|
@Mock KeyStoreWrapperProvider keyStoreWrapperProvider; |
||||||
|
@Mock KeyStoreWrapper keyStoreWrapper; |
||||||
|
@Mock KeyStoreWrapper trustStoreWrapper; |
||||||
|
|
||||||
|
@Test |
||||||
|
public void pkiBlockCreationConfigurationIsLoadedCorrectly() { |
||||||
|
when(keyStoreWrapperProvider.apply(any(), eq(Path.of("/tmp/keystore")), eq("pwd"), isNull())) |
||||||
|
.thenReturn(keyStoreWrapper); |
||||||
|
when(keyStoreWrapperProvider.apply( |
||||||
|
any(), eq(Path.of("/tmp/truststore")), eq("pwd"), eq(Path.of("/tmp/crl")))) |
||||||
|
.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(); |
||||||
|
|
||||||
|
final PkiBlockCreationConfigurationProvider pkiBlockCreationConfigProvider = |
||||||
|
new PkiBlockCreationConfigurationProvider(keyStoreWrapperProvider); |
||||||
|
|
||||||
|
final PkiBlockCreationConfiguration pkiBlockCreationConfiguration = |
||||||
|
pkiBlockCreationConfigProvider.load(pkiKeyStoreConfiguration); |
||||||
|
|
||||||
|
assertThat(pkiBlockCreationConfiguration).isNotNull(); |
||||||
|
assertThat(pkiBlockCreationConfiguration.getKeyStore()).isNotNull(); |
||||||
|
assertThat(pkiBlockCreationConfiguration.getTrustStore()).isNotNull(); |
||||||
|
assertThat(pkiBlockCreationConfiguration.getCertificateAlias()).isEqualTo("anAlias"); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue