mirror of https://github.com/hyperledger/besu
[PAN-2345] node permissioning controller (#1075)
* refactor NodeWhitelistController -> NodeLocalConfigPermissioningController * added smart contract permissioning config * only use SyncStatusProvider if Smart Contract Permissioning enabled * check we are not adding self enode * local permissioning controller isPermitted() should return true if either source OR destination is permitted Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>pull/2/head
parent
99cefd29a1
commit
0771d98a71
@ -0,0 +1,71 @@ |
||||
/* |
||||
* Copyright 2018 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. |
||||
*/ |
||||
package tech.pegasys.pantheon.ethereum.permissioning; |
||||
|
||||
import java.net.URI; |
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
|
||||
public class LocalPermissioningConfiguration { |
||||
private List<URI> nodeWhitelist; |
||||
private List<String> accountWhitelist; |
||||
private boolean nodeWhitelistEnabled; |
||||
private boolean accountWhitelistEnabled; |
||||
private String configurationFilePath; |
||||
|
||||
public List<URI> getNodeWhitelist() { |
||||
return nodeWhitelist; |
||||
} |
||||
|
||||
public static LocalPermissioningConfiguration createDefault() { |
||||
final LocalPermissioningConfiguration config = new LocalPermissioningConfiguration(); |
||||
config.nodeWhitelist = new ArrayList<>(); |
||||
config.accountWhitelist = new ArrayList<>(); |
||||
return config; |
||||
} |
||||
|
||||
public void setNodeWhitelist(final Collection<URI> nodeWhitelist) { |
||||
if (nodeWhitelist != null) { |
||||
this.nodeWhitelist.addAll(nodeWhitelist); |
||||
this.nodeWhitelistEnabled = true; |
||||
} |
||||
} |
||||
|
||||
public boolean isNodeWhitelistEnabled() { |
||||
return nodeWhitelistEnabled; |
||||
} |
||||
|
||||
public List<String> getAccountWhitelist() { |
||||
return accountWhitelist; |
||||
} |
||||
|
||||
public void setAccountWhitelist(final Collection<String> accountWhitelist) { |
||||
if (accountWhitelist != null) { |
||||
this.accountWhitelist.addAll(accountWhitelist); |
||||
this.accountWhitelistEnabled = true; |
||||
} |
||||
} |
||||
|
||||
public boolean isAccountWhitelistEnabled() { |
||||
return accountWhitelistEnabled; |
||||
} |
||||
|
||||
public String getConfigurationFilePath() { |
||||
return configurationFilePath; |
||||
} |
||||
|
||||
public void setConfigurationFilePath(final String configurationFilePath) { |
||||
this.configurationFilePath = configurationFilePath; |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
/* |
||||
* Copyright 2019 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. |
||||
*/ |
||||
package tech.pegasys.pantheon.ethereum.permissioning; |
||||
|
||||
import tech.pegasys.pantheon.ethereum.core.Synchronizer; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.node.NodePermissioningController; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.node.NodePermissioningProvider; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.node.provider.SyncStatusNodePermissioningProvider; |
||||
import tech.pegasys.pantheon.ethereum.transaction.TransactionSimulator; |
||||
import tech.pegasys.pantheon.util.enode.EnodeURL; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Collection; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
public class NodePermissioningControllerFactory { |
||||
|
||||
public NodePermissioningController create( |
||||
final PermissioningConfiguration permissioningConfiguration, |
||||
final Synchronizer synchronizer, |
||||
final Collection<EnodeURL> bootnodes, |
||||
final EnodeURL selfEnode, |
||||
final TransactionSimulator transactionSimulator) { |
||||
|
||||
Optional<SyncStatusNodePermissioningProvider> syncStatusProviderOptional; |
||||
|
||||
List<NodePermissioningProvider> providers = new ArrayList<>(); |
||||
if (permissioningConfiguration.getLocalConfig().isPresent()) { |
||||
LocalPermissioningConfiguration localPermissioningConfiguration = |
||||
permissioningConfiguration.getLocalConfig().get(); |
||||
if (localPermissioningConfiguration.isNodeWhitelistEnabled()) { |
||||
NodeLocalConfigPermissioningController localProvider = |
||||
new NodeLocalConfigPermissioningController( |
||||
localPermissioningConfiguration, new ArrayList<>(bootnodes), selfEnode); |
||||
providers.add(localProvider); |
||||
} |
||||
} |
||||
|
||||
if (permissioningConfiguration.getSmartContractConfig().isPresent()) { |
||||
SmartContractPermissioningConfiguration smartContractPermissioningConfiguration = |
||||
permissioningConfiguration.getSmartContractConfig().get(); |
||||
if (smartContractPermissioningConfiguration.isSmartContractNodeWhitelistEnabled()) { |
||||
SmartContractPermissioningController smartContractProvider = |
||||
new SmartContractPermissioningController( |
||||
smartContractPermissioningConfiguration.getSmartContractAddress(), |
||||
transactionSimulator); |
||||
providers.add(smartContractProvider); |
||||
} |
||||
|
||||
final SyncStatusNodePermissioningProvider syncStatusProvider = |
||||
new SyncStatusNodePermissioningProvider(synchronizer, bootnodes); |
||||
syncStatusProviderOptional = Optional.of(syncStatusProvider); |
||||
} else { |
||||
syncStatusProviderOptional = Optional.empty(); |
||||
} |
||||
return new NodePermissioningController(syncStatusProviderOptional, providers); |
||||
} |
||||
} |
@ -0,0 +1,37 @@ |
||||
/* |
||||
* Copyright 2018 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. |
||||
*/ |
||||
package tech.pegasys.pantheon.ethereum.permissioning; |
||||
|
||||
import tech.pegasys.pantheon.ethereum.core.Address; |
||||
|
||||
public class SmartContractPermissioningConfiguration { |
||||
private boolean smartContractNodeWhitelistEnabled; |
||||
private Address smartContractAddress; |
||||
|
||||
public boolean isSmartContractNodeWhitelistEnabled() { |
||||
return smartContractNodeWhitelistEnabled; |
||||
} |
||||
|
||||
public void setSmartContractNodeWhitelistEnabled( |
||||
final boolean smartContractNodeWhitelistEnabled) { |
||||
this.smartContractNodeWhitelistEnabled = smartContractNodeWhitelistEnabled; |
||||
} |
||||
|
||||
public Address getSmartContractAddress() { |
||||
return smartContractAddress; |
||||
} |
||||
|
||||
public void setSmartContractAddress(final Address smartContractAddress) { |
||||
this.smartContractAddress = smartContractAddress; |
||||
} |
||||
} |
@ -0,0 +1,138 @@ |
||||
/* |
||||
* Copyright 2019 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. |
||||
*/ |
||||
package tech.pegasys.pantheon.ethereum.permissioning.node; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
import tech.pegasys.pantheon.ethereum.core.Address; |
||||
import tech.pegasys.pantheon.ethereum.core.Synchronizer; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.LocalPermissioningConfiguration; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.NodeLocalConfigPermissioningController; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.NodePermissioningControllerFactory; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.SmartContractPermissioningConfiguration; |
||||
import tech.pegasys.pantheon.ethereum.permissioning.SmartContractPermissioningController; |
||||
import tech.pegasys.pantheon.ethereum.transaction.TransactionSimulator; |
||||
import tech.pegasys.pantheon.util.enode.EnodeURL; |
||||
|
||||
import java.util.Collection; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Optional; |
||||
|
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.mockito.Mock; |
||||
import org.mockito.junit.MockitoJUnitRunner; |
||||
|
||||
@RunWith(MockitoJUnitRunner.class) |
||||
public class NodePermissioningControllerFactoryTest { |
||||
|
||||
@Mock private Synchronizer synchronizer; |
||||
@Mock private TransactionSimulator transactionSimulator; |
||||
|
||||
private final String enode = |
||||
"enode://5f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.10:1111"; |
||||
Collection<EnodeURL> bootnodes = Collections.emptyList(); |
||||
EnodeURL selfEnode = new EnodeURL(enode); |
||||
LocalPermissioningConfiguration localPermissioningConfig; |
||||
SmartContractPermissioningConfiguration smartContractPermissioningConfiguration; |
||||
PermissioningConfiguration config; |
||||
|
||||
@Test |
||||
public void testCreateWithNeitherPermissioningEnabled() { |
||||
config = new PermissioningConfiguration(Optional.empty(), Optional.empty()); |
||||
NodePermissioningControllerFactory factory = new NodePermissioningControllerFactory(); |
||||
NodePermissioningController controller = |
||||
factory.create(config, synchronizer, bootnodes, selfEnode, transactionSimulator); |
||||
|
||||
List<NodePermissioningProvider> providers = controller.getProviders(); |
||||
assertThat(providers.size()).isEqualTo(0); |
||||
assertThat(controller.getSyncStatusNodePermissioningProvider()).isNotPresent(); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateWithSmartContractNodePermissioningEnabledOnly() { |
||||
smartContractPermissioningConfiguration = new SmartContractPermissioningConfiguration(); |
||||
smartContractPermissioningConfiguration.setSmartContractAddress( |
||||
Address.fromHexString("0x0000000000000000000000000000000000001234")); |
||||
smartContractPermissioningConfiguration.setSmartContractNodeWhitelistEnabled(true); |
||||
config = |
||||
new PermissioningConfiguration( |
||||
Optional.empty(), Optional.of(smartContractPermissioningConfiguration)); |
||||
|
||||
NodePermissioningControllerFactory factory = new NodePermissioningControllerFactory(); |
||||
NodePermissioningController controller = |
||||
factory.create(config, synchronizer, bootnodes, selfEnode, transactionSimulator); |
||||
|
||||
List<NodePermissioningProvider> providers = controller.getProviders(); |
||||
assertThat(providers.size()).isEqualTo(1); |
||||
|
||||
NodePermissioningProvider p1 = providers.get(0); |
||||
assertThat(p1).isInstanceOf(SmartContractPermissioningController.class); |
||||
assertThat(controller.getSyncStatusNodePermissioningProvider()).isPresent(); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateWithLocalNodePermissioningEnabledOnly() { |
||||
localPermissioningConfig = LocalPermissioningConfiguration.createDefault(); |
||||
localPermissioningConfig.setNodeWhitelist(Collections.emptyList()); |
||||
localPermissioningConfig.setConfigurationFilePath("fake-file-path"); |
||||
config = |
||||
new PermissioningConfiguration(Optional.of(localPermissioningConfig), Optional.empty()); |
||||
|
||||
NodePermissioningControllerFactory factory = new NodePermissioningControllerFactory(); |
||||
NodePermissioningController controller = |
||||
factory.create(config, synchronizer, bootnodes, selfEnode, transactionSimulator); |
||||
|
||||
List<NodePermissioningProvider> providers = controller.getProviders(); |
||||
assertThat(providers.size()).isEqualTo(1); |
||||
|
||||
NodePermissioningProvider p1 = providers.get(0); |
||||
assertThat(p1).isInstanceOf(NodeLocalConfigPermissioningController.class); |
||||
assertThat(controller.getSyncStatusNodePermissioningProvider()).isNotPresent(); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreateWithLocalNodeAndSmartContractPermissioningEnabled() { |
||||
localPermissioningConfig = LocalPermissioningConfiguration.createDefault(); |
||||
localPermissioningConfig.setNodeWhitelist(Collections.emptyList()); |
||||
localPermissioningConfig.setConfigurationFilePath("fake-file-path"); |
||||
|
||||
smartContractPermissioningConfiguration = new SmartContractPermissioningConfiguration(); |
||||
smartContractPermissioningConfiguration.setSmartContractAddress( |
||||
Address.fromHexString("0x0000000000000000000000000000000000001234")); |
||||
smartContractPermissioningConfiguration.setSmartContractNodeWhitelistEnabled(true); |
||||
config = |
||||
new PermissioningConfiguration( |
||||
Optional.of(localPermissioningConfig), |
||||
Optional.of(smartContractPermissioningConfiguration)); |
||||
|
||||
NodePermissioningControllerFactory factory = new NodePermissioningControllerFactory(); |
||||
NodePermissioningController controller = |
||||
factory.create(config, synchronizer, bootnodes, selfEnode, transactionSimulator); |
||||
|
||||
List<NodePermissioningProvider> providers = controller.getProviders(); |
||||
assertThat(providers.size()).isEqualTo(2); |
||||
|
||||
NodePermissioningProvider p1 = providers.get(0); |
||||
NodePermissioningProvider p2 = providers.get(1); |
||||
if (p1.getClass() == NodeLocalConfigPermissioningController.class) { |
||||
assertThat(p2).isInstanceOf(SmartContractPermissioningController.class); |
||||
} else { |
||||
assertThat(p2).isInstanceOf(NodeLocalConfigPermissioningController.class); |
||||
assertThat(p1).isInstanceOf(SmartContractPermissioningController.class); |
||||
} |
||||
assertThat(controller.getSyncStatusNodePermissioningProvider()).isPresent(); |
||||
} |
||||
} |
Loading…
Reference in new issue