mirror of https://github.com/hyperledger/besu
commit
5d2361ecc2
@ -0,0 +1,206 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* 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.stable; |
||||
|
||||
import org.hyperledger.besu.cli.DefaultCommandValues; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; |
||||
import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; |
||||
import org.hyperledger.besu.ethereum.permissioning.LocalPermissioningConfiguration; |
||||
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; |
||||
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfigurationBuilder; |
||||
import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration; |
||||
|
||||
import java.nio.file.Path; |
||||
import java.util.Optional; |
||||
|
||||
import org.slf4j.Logger; |
||||
import picocli.CommandLine; |
||||
|
||||
/** Handles configuration options for permissions in Besu. */ |
||||
public class PermissionsOptions { |
||||
@CommandLine.Option( |
||||
names = {"--permissions-nodes-config-file-enabled"}, |
||||
description = "Enable node level permissions (default: ${DEFAULT-VALUE})") |
||||
private final Boolean permissionsNodesEnabled = false; |
||||
|
||||
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
|
||||
@CommandLine.Option( |
||||
names = {"--permissions-nodes-config-file"}, |
||||
description = |
||||
"Node permissioning config TOML file (default: a file named \"permissions_config.toml\" in the Besu data folder)") |
||||
private String nodePermissionsConfigFile = null; |
||||
|
||||
@CommandLine.Option( |
||||
names = {"--permissions-accounts-config-file-enabled"}, |
||||
description = "Enable account level permissions (default: ${DEFAULT-VALUE})") |
||||
private final Boolean permissionsAccountsEnabled = false; |
||||
|
||||
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
|
||||
@CommandLine.Option( |
||||
names = {"--permissions-accounts-config-file"}, |
||||
description = |
||||
"Account permissioning config TOML file (default: a file named \"permissions_config.toml\" in the Besu data folder)") |
||||
private String accountPermissionsConfigFile = null; |
||||
|
||||
@CommandLine.Option( |
||||
names = {"--permissions-nodes-contract-address"}, |
||||
description = "Address of the node permissioning smart contract", |
||||
arity = "1") |
||||
private final Address permissionsNodesContractAddress = null; |
||||
|
||||
@CommandLine.Option( |
||||
names = {"--permissions-nodes-contract-version"}, |
||||
description = "Version of the EEA Node Permissioning interface (default: ${DEFAULT-VALUE})") |
||||
private final Integer permissionsNodesContractVersion = 1; |
||||
|
||||
@CommandLine.Option( |
||||
names = {"--permissions-nodes-contract-enabled"}, |
||||
description = "Enable node level permissions via smart contract (default: ${DEFAULT-VALUE})") |
||||
private final Boolean permissionsNodesContractEnabled = false; |
||||
|
||||
@CommandLine.Option( |
||||
names = {"--permissions-accounts-contract-address"}, |
||||
description = "Address of the account permissioning smart contract", |
||||
arity = "1") |
||||
private final Address permissionsAccountsContractAddress = null; |
||||
|
||||
@CommandLine.Option( |
||||
names = {"--permissions-accounts-contract-enabled"}, |
||||
description = |
||||
"Enable account level permissions via smart contract (default: ${DEFAULT-VALUE})") |
||||
private final Boolean permissionsAccountsContractEnabled = false; |
||||
|
||||
/** |
||||
* Creates a PermissioningConfiguration based on the provided options. |
||||
* |
||||
* @param jsonRpcHttpOptions The JSON-RPC HTTP options |
||||
* @param rpcWebsocketOptions The RPC websocket options |
||||
* @param enodeDnsConfiguration The enode DNS configuration |
||||
* @param dataPath The data path |
||||
* @param logger The logger |
||||
* @param commandLine The command line |
||||
* @return An Optional PermissioningConfiguration instance |
||||
* @throws Exception If an error occurs while creating the configuration |
||||
*/ |
||||
public Optional<PermissioningConfiguration> permissioningConfiguration( |
||||
final JsonRpcHttpOptions jsonRpcHttpOptions, |
||||
final RpcWebsocketOptions rpcWebsocketOptions, |
||||
final EnodeDnsConfiguration enodeDnsConfiguration, |
||||
final Path dataPath, |
||||
final Logger logger, |
||||
final CommandLine commandLine) |
||||
throws Exception { |
||||
if (!(localPermissionsEnabled() || contractPermissionsEnabled())) { |
||||
if (jsonRpcHttpOptions.getRpcHttpApis().contains(RpcApis.PERM.name()) |
||||
|| rpcWebsocketOptions.getRpcWsApis().contains(RpcApis.PERM.name())) { |
||||
logger.warn( |
||||
"Permissions are disabled. Cannot enable PERM APIs when not using Permissions."); |
||||
} |
||||
return Optional.empty(); |
||||
} |
||||
|
||||
final Optional<LocalPermissioningConfiguration> localPermissioningConfigurationOptional; |
||||
if (localPermissionsEnabled()) { |
||||
final Optional<String> nodePermissioningConfigFile = |
||||
Optional.ofNullable(nodePermissionsConfigFile); |
||||
final Optional<String> accountPermissioningConfigFile = |
||||
Optional.ofNullable(accountPermissionsConfigFile); |
||||
|
||||
final LocalPermissioningConfiguration localPermissioningConfiguration = |
||||
PermissioningConfigurationBuilder.permissioningConfiguration( |
||||
permissionsNodesEnabled, |
||||
enodeDnsConfiguration, |
||||
nodePermissioningConfigFile.orElse(getDefaultPermissioningFilePath(dataPath)), |
||||
permissionsAccountsEnabled, |
||||
accountPermissioningConfigFile.orElse(getDefaultPermissioningFilePath(dataPath))); |
||||
|
||||
localPermissioningConfigurationOptional = Optional.of(localPermissioningConfiguration); |
||||
} else { |
||||
if (nodePermissionsConfigFile != null && !permissionsNodesEnabled) { |
||||
logger.warn( |
||||
"Node permissioning config file set {} but no permissions enabled", |
||||
nodePermissionsConfigFile); |
||||
} |
||||
|
||||
if (accountPermissionsConfigFile != null && !permissionsAccountsEnabled) { |
||||
logger.warn( |
||||
"Account permissioning config file set {} but no permissions enabled", |
||||
accountPermissionsConfigFile); |
||||
} |
||||
localPermissioningConfigurationOptional = Optional.empty(); |
||||
} |
||||
|
||||
final SmartContractPermissioningConfiguration smartContractPermissioningConfiguration = |
||||
SmartContractPermissioningConfiguration.createDefault(); |
||||
|
||||
if (Boolean.TRUE.equals(permissionsNodesContractEnabled)) { |
||||
if (permissionsNodesContractAddress == null) { |
||||
throw new CommandLine.ParameterException( |
||||
commandLine, |
||||
"No node permissioning contract address specified. Cannot enable smart contract based node permissioning."); |
||||
} else { |
||||
smartContractPermissioningConfiguration.setSmartContractNodeAllowlistEnabled( |
||||
permissionsNodesContractEnabled); |
||||
smartContractPermissioningConfiguration.setNodeSmartContractAddress( |
||||
permissionsNodesContractAddress); |
||||
smartContractPermissioningConfiguration.setNodeSmartContractInterfaceVersion( |
||||
permissionsNodesContractVersion); |
||||
} |
||||
} else if (permissionsNodesContractAddress != null) { |
||||
logger.warn( |
||||
"Node permissioning smart contract address set {} but smart contract node permissioning is disabled.", |
||||
permissionsNodesContractAddress); |
||||
} |
||||
|
||||
if (Boolean.TRUE.equals(permissionsAccountsContractEnabled)) { |
||||
if (permissionsAccountsContractAddress == null) { |
||||
throw new CommandLine.ParameterException( |
||||
commandLine, |
||||
"No account permissioning contract address specified. Cannot enable smart contract based account permissioning."); |
||||
} else { |
||||
smartContractPermissioningConfiguration.setSmartContractAccountAllowlistEnabled( |
||||
permissionsAccountsContractEnabled); |
||||
smartContractPermissioningConfiguration.setAccountSmartContractAddress( |
||||
permissionsAccountsContractAddress); |
||||
} |
||||
} else if (permissionsAccountsContractAddress != null) { |
||||
logger.warn( |
||||
"Account permissioning smart contract address set {} but smart contract account permissioning is disabled.", |
||||
permissionsAccountsContractAddress); |
||||
} |
||||
|
||||
final PermissioningConfiguration permissioningConfiguration = |
||||
new PermissioningConfiguration( |
||||
localPermissioningConfigurationOptional, |
||||
Optional.of(smartContractPermissioningConfiguration)); |
||||
|
||||
return Optional.of(permissioningConfiguration); |
||||
} |
||||
|
||||
private boolean localPermissionsEnabled() { |
||||
return permissionsAccountsEnabled || permissionsNodesEnabled; |
||||
} |
||||
|
||||
private boolean contractPermissionsEnabled() { |
||||
return permissionsNodesContractEnabled || permissionsAccountsContractEnabled; |
||||
} |
||||
|
||||
private String getDefaultPermissioningFilePath(final Path dataPath) { |
||||
return dataPath |
||||
+ System.getProperty("file.separator") |
||||
+ DefaultCommandValues.PERMISSIONING_CONFIG_LOCATION; |
||||
} |
||||
} |
@ -0,0 +1,453 @@ |
||||
/* |
||||
* Copyright Hyperledger Besu Contributors. |
||||
* |
||||
* 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; |
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8; |
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
import static org.mockito.Mockito.verify; |
||||
|
||||
import org.hyperledger.besu.cli.CommandTestAbstract; |
||||
import org.hyperledger.besu.datatypes.Address; |
||||
import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; |
||||
import org.hyperledger.besu.ethereum.permissioning.LocalPermissioningConfiguration; |
||||
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; |
||||
import org.hyperledger.besu.ethereum.permissioning.SmartContractPermissioningConfiguration; |
||||
import org.hyperledger.besu.plugin.data.EnodeURL; |
||||
|
||||
import java.io.IOException; |
||||
import java.net.URL; |
||||
import java.nio.file.Files; |
||||
import java.nio.file.Path; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.stream.Collectors; |
||||
|
||||
import com.google.common.collect.Lists; |
||||
import com.google.common.io.Resources; |
||||
import org.junit.jupiter.api.Test; |
||||
import org.junit.jupiter.api.extension.ExtendWith; |
||||
import org.junit.jupiter.api.io.TempDir; |
||||
import org.mockito.Mockito; |
||||
import org.mockito.junit.jupiter.MockitoExtension; |
||||
|
||||
@ExtendWith(MockitoExtension.class) |
||||
public class PermissionsOptionsTest extends CommandTestAbstract { |
||||
private static final String PERMISSIONING_CONFIG_TOML = "/permissioning_config.toml"; |
||||
|
||||
@Test |
||||
public void errorIsRaisedIfStaticNodesAreNotAllowed(final @TempDir Path testFolder) |
||||
throws IOException { |
||||
final Path staticNodesFile = testFolder.resolve("static-nodes.json"); |
||||
final Path permissioningConfig = testFolder.resolve("permissioning.json"); |
||||
|
||||
final EnodeURL staticNodeURI = |
||||
EnodeURLImpl.builder() |
||||
.nodeId( |
||||
"50203c6bfca6874370e71aecc8958529fd723feb05013dc1abca8fc1fff845c5259faba05852e9dfe5ce172a7d6e7c2a3a5eaa8b541c8af15ea5518bbff5f2fa") |
||||
.ipAddress("127.0.0.1") |
||||
.useDefaultPorts() |
||||
.build(); |
||||
|
||||
final EnodeURL allowedNode = |
||||
EnodeURLImpl.builder() |
||||
.nodeId( |
||||
"50203c6bfca6874370e71aecc8958529fd723feb05013dc1abca8fc1fff845c5259faba05852e9dfe5ce172a7d6e7c2a3a5eaa8b541c8af15ea5518bbff5f2fa") |
||||
.useDefaultPorts() |
||||
.ipAddress("127.0.0.1") |
||||
.listeningPort(30304) |
||||
.build(); |
||||
|
||||
Files.write(staticNodesFile, ("[\"" + staticNodeURI.toString() + "\"]").getBytes(UTF_8)); |
||||
Files.write( |
||||
permissioningConfig, |
||||
("nodes-allowlist=[\"" + allowedNode.toString() + "\"]").getBytes(UTF_8)); |
||||
|
||||
parseCommand( |
||||
"--data-path=" + testFolder, |
||||
"--bootnodes", |
||||
"--permissions-nodes-config-file-enabled=true", |
||||
"--permissions-nodes-config-file=" + permissioningConfig); |
||||
assertThat(commandErrorOutput.toString(UTF_8)) |
||||
.contains(staticNodeURI.toString(), "not in nodes-allowlist"); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissionsSmartContractWithoutOptionMustError() { |
||||
parseCommand("--permissions-nodes-contract-address"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)) |
||||
.startsWith("Missing required parameter for option '--permissions-nodes-contract-address'"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissionsEnabledWithoutContractAddressMustError() { |
||||
parseCommand("--permissions-nodes-contract-enabled"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)) |
||||
.contains("No node permissioning contract address specified"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissionsEnabledWithInvalidContractAddressMustError() { |
||||
parseCommand( |
||||
"--permissions-nodes-contract-enabled", |
||||
"--permissions-nodes-contract-address", |
||||
"invalid-smart-contract-address"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).contains("Invalid value"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissionsEnabledWithTooShortContractAddressMustError() { |
||||
parseCommand( |
||||
"--permissions-nodes-contract-enabled", "--permissions-nodes-contract-address", "0x1234"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).contains("Invalid value"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissionsSmartContractMustUseOption() { |
||||
|
||||
final String smartContractAddress = "0x0000000000000000000000000000000000001234"; |
||||
|
||||
parseCommand( |
||||
"--permissions-nodes-contract-enabled", |
||||
"--permissions-nodes-contract-address", |
||||
smartContractAddress); |
||||
final SmartContractPermissioningConfiguration smartContractPermissioningConfiguration = |
||||
new SmartContractPermissioningConfiguration(); |
||||
smartContractPermissioningConfiguration.setNodeSmartContractAddress( |
||||
Address.fromHexString(smartContractAddress)); |
||||
smartContractPermissioningConfiguration.setSmartContractNodeAllowlistEnabled(true); |
||||
|
||||
verify(mockRunnerBuilder) |
||||
.permissioningConfiguration(permissioningConfigurationArgumentCaptor.capture()); |
||||
verify(mockRunnerBuilder).build(); |
||||
|
||||
final PermissioningConfiguration config = |
||||
permissioningConfigurationArgumentCaptor.getValue().get(); |
||||
assertThat(config.getSmartContractConfig().get()) |
||||
.usingRecursiveComparison() |
||||
.isEqualTo(smartContractPermissioningConfiguration); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissionsContractVersionDefaultValue() { |
||||
final SmartContractPermissioningConfiguration expectedConfig = |
||||
new SmartContractPermissioningConfiguration(); |
||||
expectedConfig.setNodeSmartContractAddress( |
||||
Address.fromHexString("0x0000000000000000000000000000000000001234")); |
||||
expectedConfig.setSmartContractNodeAllowlistEnabled(true); |
||||
expectedConfig.setNodeSmartContractInterfaceVersion(1); |
||||
|
||||
parseCommand( |
||||
"--permissions-nodes-contract-enabled", |
||||
"--permissions-nodes-contract-address", |
||||
"0x0000000000000000000000000000000000001234"); |
||||
|
||||
verify(mockRunnerBuilder) |
||||
.permissioningConfiguration(permissioningConfigurationArgumentCaptor.capture()); |
||||
verify(mockRunnerBuilder).build(); |
||||
|
||||
final PermissioningConfiguration config = |
||||
permissioningConfigurationArgumentCaptor.getValue().get(); |
||||
assertThat(config.getSmartContractConfig().get()) |
||||
.usingRecursiveComparison() |
||||
.isEqualTo(expectedConfig); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissionsContractVersionSetsValue() { |
||||
final SmartContractPermissioningConfiguration expectedConfig = |
||||
new SmartContractPermissioningConfiguration(); |
||||
expectedConfig.setNodeSmartContractAddress( |
||||
Address.fromHexString("0x0000000000000000000000000000000000001234")); |
||||
expectedConfig.setSmartContractNodeAllowlistEnabled(true); |
||||
expectedConfig.setNodeSmartContractInterfaceVersion(2); |
||||
|
||||
parseCommand( |
||||
"--permissions-nodes-contract-enabled", |
||||
"--permissions-nodes-contract-address", |
||||
"0x0000000000000000000000000000000000001234", |
||||
"--permissions-nodes-contract-version", |
||||
"2"); |
||||
|
||||
verify(mockRunnerBuilder) |
||||
.permissioningConfiguration(permissioningConfigurationArgumentCaptor.capture()); |
||||
verify(mockRunnerBuilder).build(); |
||||
|
||||
final PermissioningConfiguration config = |
||||
permissioningConfigurationArgumentCaptor.getValue().get(); |
||||
assertThat(config.getSmartContractConfig().get()) |
||||
.usingRecursiveComparison() |
||||
.isEqualTo(expectedConfig); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissionsSmartContractWithoutOptionMustError() { |
||||
parseCommand("--permissions-accounts-contract-address"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)) |
||||
.startsWith( |
||||
"Missing required parameter for option '--permissions-accounts-contract-address'"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissionsEnabledWithoutContractAddressMustError() { |
||||
parseCommand("--permissions-accounts-contract-enabled"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)) |
||||
.contains("No account permissioning contract address specified"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissionsEnabledWithInvalidContractAddressMustError() { |
||||
parseCommand( |
||||
"--permissions-accounts-contract-enabled", |
||||
"--permissions-accounts-contract-address", |
||||
"invalid-smart-contract-address"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).contains("Invalid value"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissionsEnabledWithTooShortContractAddressMustError() { |
||||
parseCommand( |
||||
"--permissions-accounts-contract-enabled", |
||||
"--permissions-accounts-contract-address", |
||||
"0x1234"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).contains("Invalid value"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissionsSmartContractMustUseOption() { |
||||
final String smartContractAddress = "0x0000000000000000000000000000000000001234"; |
||||
|
||||
parseCommand( |
||||
"--permissions-accounts-contract-enabled", |
||||
"--permissions-accounts-contract-address", |
||||
smartContractAddress); |
||||
final SmartContractPermissioningConfiguration smartContractPermissioningConfiguration = |
||||
new SmartContractPermissioningConfiguration(); |
||||
smartContractPermissioningConfiguration.setAccountSmartContractAddress( |
||||
Address.fromHexString(smartContractAddress)); |
||||
smartContractPermissioningConfiguration.setSmartContractAccountAllowlistEnabled(true); |
||||
|
||||
verify(mockRunnerBuilder) |
||||
.permissioningConfiguration(permissioningConfigurationArgumentCaptor.capture()); |
||||
final PermissioningConfiguration permissioningConfiguration = |
||||
permissioningConfigurationArgumentCaptor.getValue().get(); |
||||
assertThat(permissioningConfiguration.getSmartContractConfig()).isPresent(); |
||||
|
||||
final SmartContractPermissioningConfiguration effectiveSmartContractConfig = |
||||
permissioningConfiguration.getSmartContractConfig().get(); |
||||
assertThat(effectiveSmartContractConfig.isSmartContractAccountAllowlistEnabled()).isTrue(); |
||||
assertThat(effectiveSmartContractConfig.getAccountSmartContractAddress()) |
||||
.isEqualTo(Address.fromHexString(smartContractAddress)); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissioningTomlPathWithoutOptionMustDisplayUsage() { |
||||
parseCommand("--permissions-nodes-config-file"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)) |
||||
.startsWith("Missing required parameter for option '--permissions-nodes-config-file'"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissioningTomlPathWithoutOptionMustDisplayUsage() { |
||||
parseCommand("--permissions-accounts-config-file"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)) |
||||
.startsWith("Missing required parameter for option '--permissions-accounts-config-file'"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissioningEnabledWithNonexistentConfigFileMustError() { |
||||
parseCommand( |
||||
"--permissions-nodes-config-file-enabled", |
||||
"--permissions-nodes-config-file", |
||||
"file-does-not-exist"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).contains("Configuration file does not exist"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissioningEnabledWithNonexistentConfigFileMustError() { |
||||
parseCommand( |
||||
"--permissions-accounts-config-file-enabled", |
||||
"--permissions-accounts-config-file", |
||||
"file-does-not-exist"); |
||||
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).contains("Configuration file does not exist"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissioningTomlFileWithNoPermissionsEnabledMustNotError() throws IOException { |
||||
|
||||
final URL configFile = this.getClass().getResource(PERMISSIONING_CONFIG_TOML); |
||||
final Path permToml = createTempFile("toml", Resources.toByteArray(configFile)); |
||||
parseCommand("--permissions-nodes-config-file", permToml.toString()); |
||||
|
||||
verify(mockRunnerBuilder).build(); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissioningTomlFileWithNoPermissionsEnabledMustNotError() |
||||
throws IOException { |
||||
|
||||
final URL configFile = this.getClass().getResource(PERMISSIONING_CONFIG_TOML); |
||||
final Path permToml = createTempFile("toml", Resources.toByteArray(configFile)); |
||||
parseCommand("--permissions-accounts-config-file", permToml.toString()); |
||||
|
||||
verify(mockRunnerBuilder).build(); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void defaultPermissionsTomlFileWithNoPermissionsEnabledMustNotError() { |
||||
parseCommand("--p2p-enabled", "false"); |
||||
|
||||
verify(mockRunnerBuilder).build(); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).doesNotContain("no permissions enabled"); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void nodePermissioningTomlPathMustUseOption() throws IOException { |
||||
final List<EnodeURL> allowedNodes = |
||||
Lists.newArrayList( |
||||
EnodeURLImpl.fromString( |
||||
"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.9:4567"), |
||||
EnodeURLImpl.fromString( |
||||
"enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.169.0.9:4568")); |
||||
|
||||
final URL configFile = this.getClass().getResource(PERMISSIONING_CONFIG_TOML); |
||||
final Path permToml = createTempFile("toml", Resources.toByteArray(configFile)); |
||||
|
||||
final String allowedNodesString = |
||||
allowedNodes.stream().map(Object::toString).collect(Collectors.joining(",")); |
||||
parseCommand( |
||||
"--permissions-nodes-config-file-enabled", |
||||
"--permissions-nodes-config-file", |
||||
permToml.toString(), |
||||
"--bootnodes", |
||||
allowedNodesString); |
||||
final LocalPermissioningConfiguration localPermissioningConfiguration = |
||||
LocalPermissioningConfiguration.createDefault(); |
||||
localPermissioningConfiguration.setNodePermissioningConfigFilePath(permToml.toString()); |
||||
localPermissioningConfiguration.setNodeAllowlist(allowedNodes); |
||||
|
||||
verify(mockRunnerBuilder) |
||||
.permissioningConfiguration(permissioningConfigurationArgumentCaptor.capture()); |
||||
verify(mockRunnerBuilder).build(); |
||||
|
||||
final PermissioningConfiguration config = |
||||
permissioningConfigurationArgumentCaptor.getValue().get(); |
||||
assertThat(config.getLocalConfig().get()) |
||||
.usingRecursiveComparison() |
||||
.isEqualTo(localPermissioningConfiguration); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
|
||||
@Test |
||||
public void accountPermissioningTomlPathMustUseOption() throws IOException { |
||||
|
||||
final URL configFile = this.getClass().getResource(PERMISSIONING_CONFIG_TOML); |
||||
final Path permToml = createTempFile("toml", Resources.toByteArray(configFile)); |
||||
|
||||
parseCommand( |
||||
"--permissions-accounts-config-file-enabled", |
||||
"--permissions-accounts-config-file", |
||||
permToml.toString()); |
||||
final LocalPermissioningConfiguration localPermissioningConfiguration = |
||||
LocalPermissioningConfiguration.createDefault(); |
||||
localPermissioningConfiguration.setAccountPermissioningConfigFilePath(permToml.toString()); |
||||
localPermissioningConfiguration.setAccountAllowlist( |
||||
Collections.singletonList("0x0000000000000000000000000000000000000009")); |
||||
|
||||
verify(mockRunnerBuilder) |
||||
.permissioningConfiguration(permissioningConfigurationArgumentCaptor.capture()); |
||||
final PermissioningConfiguration permissioningConfiguration = |
||||
permissioningConfigurationArgumentCaptor.getValue().get(); |
||||
assertThat(permissioningConfiguration.getLocalConfig()).isPresent(); |
||||
|
||||
final LocalPermissioningConfiguration effectiveLocalPermissioningConfig = |
||||
permissioningConfiguration.getLocalConfig().get(); |
||||
assertThat(effectiveLocalPermissioningConfig.isAccountAllowlistEnabled()).isTrue(); |
||||
assertThat(effectiveLocalPermissioningConfig.getAccountPermissioningConfigFilePath()) |
||||
.isEqualTo(permToml.toString()); |
||||
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); |
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty(); |
||||
} |
||||
} |
Loading…
Reference in new issue