Skip to content

Commit

Permalink
Use the node's configuration to decide if adding a peer with DNS in t…
Browse files Browse the repository at this point in the history
…he enode is allowed

Signed-off-by: Matthew Whitehead <[email protected]>
  • Loading branch information
matthew1001 committed Jun 12, 2023
1 parent cb12a2c commit 6acd277
Show file tree
Hide file tree
Showing 16 changed files with 87 additions and 10 deletions.
13 changes: 12 additions & 1 deletion besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.p2p.network.ProtocolManager;
import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration;
import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions;
import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissionsDenylist;
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration;
Expand Down Expand Up @@ -191,6 +192,7 @@ public class RunnerBuilder {
private JsonRpcIpcConfiguration jsonRpcIpcConfiguration;
private boolean legacyForkIdEnabled;
private Optional<Long> rpcMaxLogsRange;
private Optional<EnodeDnsConfiguration> enodeDnsConfiguration;

/**
* Add Vertx.
Expand Down Expand Up @@ -249,6 +251,14 @@ public RunnerBuilder p2pTLSConfiguration(final Optional<TLSConfiguration> p2pTLS
return this;
}

public RunnerBuilder enodeDnsConfiguration(
final Optional<EnodeDnsConfiguration> enodeDnsConfiguration) {
if (null != enodeDnsConfiguration) {
this.enodeDnsConfiguration = enodeDnsConfiguration;
}
return this;
}

/**
* Enable Discovery.
*
Expand Down Expand Up @@ -1224,7 +1234,8 @@ private Map<String, JsonRpcMethod> jsonRpcMethods(
dataDir,
besuController.getProtocolManager().ethContext().getEthPeers(),
consensusEngineServer,
rpcMaxLogsRange);
rpcMaxLogsRange,
enodeDnsConfiguration);
methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis));

final var pluginMethods =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3095,6 +3095,7 @@ private Runner synchronize(
.storageProvider(keyValueStorageProvider(keyValueStorageName))
.rpcEndpointService(rpcEndpointServiceImpl)
.rpcMaxLogsRange(rpcMaxLogsRange)
.enodeDnsConfiguration(Optional.of(getEnodeDnsConfiguration()))
.build();

addShutdownHook(runner);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,25 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.p2p.peers.DefaultPeer;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl;
import org.hyperledger.besu.ethereum.p2p.peers.Peer;
import org.hyperledger.besu.plugin.data.EnodeURL;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AdminAddPeer extends AdminModifyPeer {

private static final Logger LOG = LoggerFactory.getLogger(AdminAddPeer.class);
private final Optional<EnodeDnsConfiguration> enodeDnsConfiguration;

public AdminAddPeer(final P2PNetwork peerNetwork) {
public AdminAddPeer(
final P2PNetwork peerNetwork, final Optional<EnodeDnsConfiguration> enodeDnsConfiguration) {
super(peerNetwork);
this.enodeDnsConfiguration = enodeDnsConfiguration;
}

@Override
Expand All @@ -42,7 +48,10 @@ public String getName() {
@Override
protected JsonRpcResponse performOperation(final Object id, final String enode) {
LOG.debug("Adding ({}) to peers", enode);
final EnodeURL enodeURL = EnodeURLImpl.fromString(enode);
final EnodeURL enodeURL =
this.enodeDnsConfiguration.isEmpty()
? EnodeURLImpl.fromString(enode)
: EnodeURLImpl.fromString(enode, enodeDnsConfiguration.get());
final Peer peer = DefaultPeer.fromEnodeURL(enodeURL);
final boolean addedToNetwork = peerNetwork.addMaintainedConnectionPeer(peer);
return new JsonRpcSuccessResponse(id, addedToNetwork);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration;
import org.hyperledger.besu.nat.NatService;
import org.hyperledger.besu.plugin.BesuPlugin;

import java.math.BigInteger;
import java.util.Map;
import java.util.Optional;

public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods {

Expand All @@ -45,6 +47,7 @@ public class AdminJsonRpcMethods extends ApiGroupJsonRpcMethods {
private final NatService natService;
private final Map<String, BesuPlugin> namedPlugins;
private final EthPeers ethPeers;
private final Optional<EnodeDnsConfiguration> enodeDnsConfiguration;

public AdminJsonRpcMethods(
final String clientVersion,
Expand All @@ -54,7 +57,8 @@ public AdminJsonRpcMethods(
final BlockchainQueries blockchainQueries,
final Map<String, BesuPlugin> namedPlugins,
final NatService natService,
final EthPeers ethPeers) {
final EthPeers ethPeers,
final Optional<EnodeDnsConfiguration> enodeDnsConfiguration) {
this.clientVersion = clientVersion;
this.networkId = networkId;
this.genesisConfigOptions = genesisConfigOptions;
Expand All @@ -63,6 +67,7 @@ public AdminJsonRpcMethods(
this.namedPlugins = namedPlugins;
this.natService = natService;
this.ethPeers = ethPeers;
this.enodeDnsConfiguration = enodeDnsConfiguration;
}

@Override
Expand All @@ -73,7 +78,7 @@ protected String getApiGroup() {
@Override
protected Map<String, JsonRpcMethod> create() {
return mapOf(
new AdminAddPeer(p2pNetwork),
new AdminAddPeer(p2pNetwork, enodeDnsConfiguration),
new AdminRemovePeer(p2pNetwork),
new AdminNodeInfo(
clientVersion,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability;
import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController;
import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController;
Expand Down Expand Up @@ -76,13 +77,12 @@ public Map<String, JsonRpcMethod> methods(
final Path dataDir,
final EthPeers ethPeers,
final Vertx consensusEngineServer,
final Optional<Long> maxLogRange) {
final Optional<Long> maxLogRange,
final Optional<EnodeDnsConfiguration> enodeDnsConfiguration) {
final Map<String, JsonRpcMethod> enabled = new HashMap<>();

if (!rpcApis.isEmpty()) {
final JsonRpcMethod modules = new RpcModules(rpcApis);
enabled.put(modules.getName(), modules);

final List<JsonRpcMethods> availableApiGroups =
List.of(
new AdminJsonRpcMethods(
Expand All @@ -93,7 +93,8 @@ public Map<String, JsonRpcMethod> methods(
blockchainQueries,
namedPlugins,
natService,
ethPeers),
ethPeers,
enodeDnsConfiguration),
new DebugJsonRpcMethods(
blockchainQueries,
protocolContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ protected Map<String, JsonRpcMethod> getRpcMethods(
folder.getRoot().toPath(),
mock(EthPeers.class),
syncVertx,
Optional.empty(),
Optional.empty());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ public void initServerAndClient() throws Exception {
folder.getRoot().toPath(),
mock(EthPeers.class),
vertx,
Optional.empty(),
Optional.empty()));
service = createJsonRpcHttpService();
service.start().join();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ public static void initServerAndClient() throws Exception {
folder.getRoot().toPath(),
mock(EthPeers.class),
vertx,
Optional.empty(),
Optional.empty()));
service = createJsonRpcHttpService();
jwtAuth = service.authenticationService.get().getJwtAuthProvider();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ private JsonRpcHttpService createJsonRpcHttpServiceWithRpcApis(final JsonRpcConf
folder,
mock(EthPeers.class),
vertx,
Optional.empty(),
Optional.empty()));
final JsonRpcHttpService jsonRpcHttpService =
new JsonRpcHttpService(
Expand Down Expand Up @@ -335,6 +336,7 @@ private JsonRpcHttpService createJsonRpcHttpService(
folder,
mock(EthPeers.class),
vertx,
Optional.empty(),
Optional.empty()));
final JsonRpcHttpService jsonRpcHttpService =
new JsonRpcHttpService(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ public static void initServerAndClient() throws Exception {
folder.getRoot().toPath(),
ethPeersMock,
vertx,
Optional.empty(),
Optional.empty()));
service = createJsonRpcHttpService(createLimitedJsonRpcConfig());
service.start().join();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public void initServer() throws Exception {
folder.getRoot().toPath(),
mock(EthPeers.class),
vertx,
Optional.empty(),
Optional.empty()));

System.setProperty("javax.net.ssl.trustStore", CLIENT_AS_CA_CERT.getKeyStoreFile().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public void beforeEach() {
tempDir.getRoot(),
mock(EthPeers.class),
vertx,
Optional.empty(),
Optional.empty()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public void initServer() throws Exception {
folder.getRoot().toPath(),
mock(EthPeers.class),
vertx,
Optional.empty(),
Optional.empty()));
service = createJsonRpcHttpService(createJsonRpcConfig());
service.start().join();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork;
import org.hyperledger.besu.ethereum.p2p.network.exceptions.P2PDisabledException;
import org.hyperledger.besu.ethereum.p2p.peers.ImmutableEnodeDnsConfiguration;

import java.util.Optional;

import org.junit.Before;
import org.junit.Test;
Expand All @@ -48,13 +51,32 @@ public class AdminAddPeerTest {
+ "00000000000000000000000000000000"
+ "@127.0.0.1:30303";

final String validDNSEnode =
"enode://"
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"
+ "00000000000000000000000000000000"
+ "@node.acme.com:30303";

final JsonRpcRequestContext validRequest =
new JsonRpcRequestContext(
new JsonRpcRequest("2.0", "admin_addPeer", new String[] {validEnode}));

final JsonRpcRequestContext validDNSRequest =
new JsonRpcRequestContext(
new JsonRpcRequest("2.0", "admin_addPeer", new String[] {validDNSEnode}));

@Before
public void setup() {
method = new AdminAddPeer(p2pNetwork);
method =
new AdminAddPeer(
p2pNetwork,
Optional.of(
ImmutableEnodeDnsConfiguration.builder()
.dnsEnabled(true)
.updateEnabled(true)
.build()));
}

@Test
Expand Down Expand Up @@ -138,6 +160,20 @@ public void requestAddsValidEnode() {
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
}

@Test
public void requestAddsValidDNSEnode() {
when(p2pNetwork.addMaintainedConnectionPeer(any())).thenReturn(true);

final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(
validRequest.getRequest().getId(),
true); // DNS is mapped to an IP address, so we expect the non-DNS response

final JsonRpcResponse actualResponse = method.response(validDNSRequest);

assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
}

@Test
public void requestRefusesListOfNodes() {
final JsonRpcRequestContext request =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ public void before() throws URISyntaxException {
folder.getRoot().toPath(),
mock(EthPeers.class),
vertx,
Optional.empty(),
Optional.empty()));

websocketMethods.putAll(rpcMethods);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ public NodeLocalConfigPermissioningController(
"Number of times the node local permissioning provider has been checked and returned unpermitted");
}

public LocalPermissioningConfiguration getLocalPermissioningConfiguration() {
return this.configuration;
}

private void readNodesFromConfig(final LocalPermissioningConfiguration configuration) {
if (configuration.isNodeAllowlistEnabled() && configuration.getNodeAllowlist() != null) {
for (EnodeURL enodeURL : configuration.getNodeAllowlist()) {
Expand Down

0 comments on commit 6acd277

Please sign in to comment.