Skip to content

Commit

Permalink
Merge branch 'main' into replace-waitforpeertask-with-ethpeers-method
Browse files Browse the repository at this point in the history
  • Loading branch information
Matilda-Clerke authored Dec 18, 2024
2 parents 65a1b56 + d3773d9 commit cf0dbda
Show file tree
Hide file tree
Showing 13 changed files with 486 additions and 46 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
- Fast Sync

### Additions and Improvements
- Add RPC HTTP options to specify custom truststore and its password [#7978](https://github.com/hyperledger/besu/pull/7978)
- Retrieve all transaction receipts for a block in one request [#6646](https://github.com/hyperledger/besu/pull/6646)


### Bug fixes
- Fix serialization of state overrides when `movePrecompileToAddress` is present [#8204](https://github.com/hyperledger/besu/pull/8024)
- Revise the approach for setting level_compaction_dynamic_level_bytes RocksDB configuration option [#8037](https://github.com/hyperledger/besu/pull/8037)

## 24.12.2 Hotfix

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ public class JsonRpcHttpOptions {
"Enable to accept clients certificate signed by a valid CA for client authentication (default: ${DEFAULT-VALUE})")
private final Boolean isRpcHttpTlsCAClientsEnabled = false;

@CommandLine.Option(
names = {"--rpc-http-tls-truststore-file"},
paramLabel = DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP,
description = "Path to the truststore file for the JSON-RPC HTTP service.",
arity = "1")
private final Path rpcHttpTlsTruststoreFile = null;

@CommandLine.Option(
names = {"--rpc-http-tls-truststore-password-file"},
paramLabel = DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP,
description = "Path to the file containing the password for the truststore.",
arity = "1")
private final Path rpcHttpTlsTruststorePasswordFile = null;

@CommandLine.Option(
names = {"--rpc-http-tls-protocol", "--rpc-http-tls-protocols"},
description = "Comma separated list of TLS protocols to support (default: ${DEFAULT-VALUE})",
Expand Down Expand Up @@ -306,7 +320,6 @@ public JsonRpcConfiguration jsonRpcConfiguration(
jsonRpcConfiguration.setHost(
Strings.isNullOrEmpty(rpcHttpHost) ? defaultHostAddress : rpcHttpHost);
jsonRpcConfiguration.setHostsAllowlist(hostsAllowlist);
;
jsonRpcConfiguration.setHttpTimeoutSec(timoutSec);
return jsonRpcConfiguration;
}
Expand All @@ -330,7 +343,18 @@ private void checkRpcTlsClientAuthOptionsDependencies(
commandLine,
"--rpc-http-tls-client-auth-enabled",
!isRpcHttpTlsClientAuthEnabled,
asList("--rpc-http-tls-known-clients-file", "--rpc-http-tls-ca-clients-enabled"));
asList(
"--rpc-http-tls-known-clients-file",
"--rpc-http-tls-ca-clients-enabled",
"--rpc-http-tls-truststore-file",
"--rpc-http-tls-truststore-password-file"));

CommandLineUtils.checkOptionDependencies(
logger,
commandLine,
"--rpc-http-tls-truststore-file",
rpcHttpTlsTruststoreFile == null,
asList("--rpc-http-tls-truststore-password-file"));
}

private void checkRpcTlsOptionsDependencies(final Logger logger, final CommandLine commandLine) {
Expand Down Expand Up @@ -392,12 +416,31 @@ private void validateTls(final CommandLine commandLine) {
"File containing password to unlock keystore is required when TLS is enabled for JSON-RPC HTTP endpoint");
}

if (isRpcHttpTlsClientAuthEnabled
&& !isRpcHttpTlsCAClientsEnabled
&& rpcHttpTlsKnownClientsFile == null) {
throw new CommandLine.ParameterException(
commandLine,
"Known-clients file must be specified or CA clients must be enabled when TLS client authentication is enabled for JSON-RPC HTTP endpoint");
if (isRpcHttpTlsClientAuthEnabled) {
if (!isRpcHttpTlsCAClientsEnabled
&& rpcHttpTlsKnownClientsFile == null
&& rpcHttpTlsTruststoreFile == null) {
throw new CommandLine.ParameterException(
commandLine,
"Configuration error: TLS client authentication is enabled, but none of the following options are provided: "
+ "1. Specify a known-clients file (--rpc-http-tls-known-clients-file) and/or Enable CA clients (--rpc-http-tls-ca-clients-enabled). "
+ "2. Specify a truststore file and its password file (--rpc-http-tls-truststore-file and --rpc-http-tls-truststore-password-file). "
+ "Only one of these options must be configured");
}

if (rpcHttpTlsTruststoreFile != null && rpcHttpTlsTruststorePasswordFile == null) {
throw new CommandLine.ParameterException(
commandLine,
"Configuration error: A truststore file is specified for JSON RPC HTTP endpoint, but the corresponding truststore password file (--rpc-http-tls-truststore-password-file) is missing");
}

if ((isRpcHttpTlsCAClientsEnabled || rpcHttpTlsKnownClientsFile != null)
&& rpcHttpTlsTruststoreFile != null) {
throw new CommandLine.ParameterException(
commandLine,
"Configuration error: Truststore file (--rpc-http-tls-truststore-file) cannot be used together with CA clients (--rpc-http-tls-ca-clients-enabled) or a known-clients (--rpc-http-tls-known-clients-file) option. "
+ "These options are mutually exclusive. Choose either truststore-based authentication or known-clients/CA clients configuration.");
}
}

rpcHttpTlsProtocols.retainAll(getJDKEnabledProtocols());
Expand Down Expand Up @@ -441,10 +484,17 @@ private boolean isRpcTlsConfigurationRequired() {

private TlsClientAuthConfiguration rpcHttpTlsClientAuthConfiguration() {
if (isRpcHttpTlsClientAuthEnabled) {
return TlsClientAuthConfiguration.Builder.aTlsClientAuthConfiguration()
.withKnownClientsFile(rpcHttpTlsKnownClientsFile)
.withCaClientsEnabled(isRpcHttpTlsCAClientsEnabled)
.build();
TlsClientAuthConfiguration.Builder tlsClientAuthConfigurationBuilder =
TlsClientAuthConfiguration.Builder.aTlsClientAuthConfiguration()
.withKnownClientsFile(rpcHttpTlsKnownClientsFile)
.withCaClientsEnabled(isRpcHttpTlsCAClientsEnabled)
.withTruststorePath(rpcHttpTlsTruststoreFile);

if (rpcHttpTlsTruststorePasswordFile != null) {
tlsClientAuthConfigurationBuilder.withTruststorePasswordSupplier(
new FileBasedPasswordProvider(rpcHttpTlsTruststorePasswordFile));
}
return tlsClientAuthConfigurationBuilder.build();
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,10 @@ public void rpcHttpTlsClientAuthWithoutKnownFileReportsError() {
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8))
.contains(
"Known-clients file must be specified or CA clients must be enabled when TLS client authentication is enabled for JSON-RPC HTTP endpoint");
"Configuration error: TLS client authentication is enabled, but none of the following options are provided: "
+ "1. Specify a known-clients file (--rpc-http-tls-known-clients-file) and/or Enable CA clients (--rpc-http-tls-ca-clients-enabled). "
+ "2. Specify a truststore file and its password file (--rpc-http-tls-truststore-file and --rpc-http-tls-truststore-password-file). "
+ "Only one of these options must be configured");
}

@Test
Expand All @@ -342,6 +345,7 @@ public void rpcHttpTlsClientAuthWithKnownClientFile() {
final String keystoreFile = "/tmp/test.p12";
final String keystorePasswordFile = "/tmp/test.txt";
final String knownClientFile = "/tmp/knownClientFile";

parseCommand(
"--rpc-http-enabled",
"--rpc-http-host",
Expand Down Expand Up @@ -422,6 +426,90 @@ public void rpcHttpTlsClientAuthWithCAClient() {
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}

@Test
public void rpcHttpTlsClientAuthWithTrustStore() throws IOException {
final String host = "1.2.3.4";
final int port = 1234;
final String keystoreFile = "/tmp/test.p12";
final String keystorePasswordFile = "/tmp/test.txt";
final String truststoreFile = "/tmp/truststore.p12";
final String truststorePasswordFile = "/tmp/truststore.txt";

Files.writeString(Path.of(truststorePasswordFile), "password");
parseCommand(
"--rpc-http-enabled",
"--rpc-http-host",
host,
"--rpc-http-port",
String.valueOf(port),
"--rpc-http-tls-enabled",
"--rpc-http-tls-keystore-file",
keystoreFile,
"--rpc-http-tls-keystore-password-file",
keystorePasswordFile,
"--rpc-http-tls-client-auth-enabled",
"--rpc-http-tls-truststore-file",
truststoreFile,
"--rpc-http-tls-truststore-password-file",
truststorePasswordFile);

verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();

assertThat(jsonRpcConfigArgumentCaptor.getValue().getHost()).isEqualTo(host);
assertThat(jsonRpcConfigArgumentCaptor.getValue().getPort()).isEqualTo(port);
final Optional<TlsConfiguration> tlsConfiguration =
jsonRpcConfigArgumentCaptor.getValue().getTlsConfiguration();
assertThat(tlsConfiguration.isPresent()).isTrue();
assertThat(tlsConfiguration.get().getKeyStorePath()).isEqualTo(Path.of(keystoreFile));
assertThat(tlsConfiguration.get().getClientAuthConfiguration().isPresent()).isTrue();
assertThat(tlsConfiguration.get().getClientAuthConfiguration().get().getTruststorePath())
.isEqualTo(Optional.of(Path.of(truststoreFile)));
assertThat(tlsConfiguration.get().getClientAuthConfiguration().get().getTrustStorePassword())
.isEqualTo(Files.readString(Path.of(truststorePasswordFile)));

assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}

@Test
public void rpcHttpTlsClientAuthWithTrustStoreAndKnownClientsFileReportsError()
throws IOException {
final String host = "1.2.3.4";
final int port = 1234;
final String keystoreFile = "/tmp/test.p12";
final String keystorePasswordFile = "/tmp/test.txt";
final String truststoreFile = "/tmp/truststore.p12";
final String truststorePasswordFile = "/tmp/truststore.txt";
final String knownClientFile = "/tmp/knownClientFile";

Files.writeString(Path.of(truststorePasswordFile), "password");
parseCommand(
"--rpc-http-enabled",
"--rpc-http-host",
host,
"--rpc-http-port",
String.valueOf(port),
"--rpc-http-tls-enabled",
"--rpc-http-tls-keystore-file",
keystoreFile,
"--rpc-http-tls-keystore-password-file",
keystorePasswordFile,
"--rpc-http-tls-client-auth-enabled",
"--rpc-http-tls-truststore-file",
truststoreFile,
"--rpc-http-tls-truststore-password-file",
truststorePasswordFile,
"--rpc-http-tls-known-clients-file",
knownClientFile);

assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8))
.contains(
"Configuration error: Truststore file (--rpc-http-tls-truststore-file) cannot be used together with CA clients (--rpc-http-tls-ca-clients-enabled) or a known-clients (--rpc-http-tls-known-clients-file) option. "
+ "These options are mutually exclusive. Choose either truststore-based authentication or known-clients/CA clients configuration.");
}

@Test
public void rpcHttpTlsClientAuthWithCAClientAndKnownClientFile() {
final String host = "1.2.3.4";
Expand Down
2 changes: 2 additions & 0 deletions besu/src/test/resources/everything_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ rpc-http-tls-keystore-password-file="none.passwd"
rpc-http-tls-client-auth-enabled=false
rpc-http-tls-known-clients-file="rpc_tls_clients.txt"
rpc-http-tls-ca-clients-enabled=false
rpc-http-tls-truststore-file="none.pfx"
rpc-http-tls-truststore-password-file="none.passwd"
rpc-http-authentication-jwt-algorithm="RS256"
rpc-ws-authentication-jwt-algorithm="RS256"
rpc-http-tls-protocols=["TLSv1.2,TlSv1.1"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ private void applyTlsConfig(final HttpServerOptions httpServerOptions) {
try {
httpServerOptions
.setSsl(true)
.setPfxKeyCertOptions(
.setKeyCertOptions(
new PfxOptions()
.setPath(tlsConfiguration.getKeyStorePath().toString())
.setPassword(tlsConfiguration.getKeyStorePassword()))
Expand Down Expand Up @@ -472,6 +472,14 @@ private void applyTlsClientAuth(
httpServerOptions.setTrustOptions(
allowlistClients(
knownClientsFile, clientAuthConfiguration.isCaClientsEnabled())));
clientAuthConfiguration
.getTruststorePath()
.ifPresent(
truststorePath ->
httpServerOptions.setTrustOptions(
new PfxOptions()
.setPath(truststorePath.toString())
.setPassword(clientAuthConfiguration.getTrustStorePassword())));
}

private String tlsLogMessage() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,23 @@
import java.nio.file.Path;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Supplier;

public class TlsClientAuthConfiguration {
private final Optional<Path> knownClientsFile;
private final boolean caClientsEnabled;
private final Optional<Path> truststorePath;
private final Supplier<String> trustStorePasswordSupplier;

private TlsClientAuthConfiguration(
final Optional<Path> knownClientsFile, final boolean caClientsEnabled) {
final Optional<Path> knownClientsFile,
final boolean caClientsEnabled,
final Optional<Path> truststorePath,
final Supplier<String> trustStorePasswordSupplier) {
this.knownClientsFile = knownClientsFile;
this.caClientsEnabled = caClientsEnabled;
this.truststorePath = truststorePath;
this.trustStorePasswordSupplier = trustStorePasswordSupplier;
}

public Optional<Path> getKnownClientsFile() {
Expand All @@ -36,9 +44,19 @@ public boolean isCaClientsEnabled() {
return caClientsEnabled;
}

public Optional<Path> getTruststorePath() {
return truststorePath;
}

public String getTrustStorePassword() {
return trustStorePasswordSupplier.get();
}

public static final class Builder {
private Path knownClientsFile;
private boolean caClientsEnabled;
private Path truststorePath;
private Supplier<String> trustStorePasswordSupplier;

private Builder() {}

Expand All @@ -56,12 +74,29 @@ public Builder withCaClientsEnabled(final boolean caClientsEnabled) {
return this;
}

public Builder withTruststorePath(final Path truststorePath) {
this.truststorePath = truststorePath;
return this;
}

public Builder withTruststorePasswordSupplier(final Supplier<String> keyStorePasswordSupplier) {
this.trustStorePasswordSupplier = keyStorePasswordSupplier;
return this;
}

public TlsClientAuthConfiguration build() {
if (!caClientsEnabled) {
if (!caClientsEnabled && truststorePath == null) {
Objects.requireNonNull(knownClientsFile, "Known Clients File is required");
}
if (!caClientsEnabled && knownClientsFile == null) {
Objects.requireNonNull(truststorePath, "Truststore File is required");
}

return new TlsClientAuthConfiguration(
Optional.ofNullable(knownClientsFile), caClientsEnabled);
Optional.ofNullable(knownClientsFile),
caClientsEnabled,
Optional.ofNullable(truststorePath),
trustStorePasswordSupplier);
}
}
}
Loading

0 comments on commit cf0dbda

Please sign in to comment.