mirror of https://github.com/hyperledger/besu
commit
24d8f999dd
@ -1,290 +0,0 @@ |
|||||||
/* |
|
||||||
* 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.enclave.testutil; |
|
||||||
|
|
||||||
import static com.google.common.io.Files.readLines; |
|
||||||
|
|
||||||
import java.io.File; |
|
||||||
import java.io.FileWriter; |
|
||||||
import java.io.IOException; |
|
||||||
import java.net.URI; |
|
||||||
import java.net.URISyntaxException; |
|
||||||
import java.nio.charset.StandardCharsets; |
|
||||||
import java.nio.file.Path; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.HashMap; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Optional; |
|
||||||
import java.util.stream.Collectors; |
|
||||||
|
|
||||||
import com.google.common.base.Charsets; |
|
||||||
import io.vertx.core.json.JsonArray; |
|
||||||
import org.assertj.core.util.Files; |
|
||||||
import org.slf4j.Logger; |
|
||||||
import org.slf4j.LoggerFactory; |
|
||||||
import org.testcontainers.containers.GenericContainer; |
|
||||||
import org.testcontainers.containers.Network; |
|
||||||
import org.testcontainers.containers.wait.strategy.Wait; |
|
||||||
import org.testcontainers.utility.MountableFile; |
|
||||||
|
|
||||||
/** The Tessera test harness. */ |
|
||||||
public class TesseraTestHarness implements EnclaveTestHarness { |
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(TesseraTestHarness.class); |
|
||||||
|
|
||||||
private final EnclaveConfiguration enclaveConfiguration; |
|
||||||
|
|
||||||
private boolean isRunning; |
|
||||||
private URI nodeURI; |
|
||||||
private URI q2TUri; |
|
||||||
private URI thirdPartyUri; |
|
||||||
|
|
||||||
/** The constant TESSERA_VERSION. */ |
|
||||||
public static final String TESSERA_VERSION = "22.10.0"; |
|
||||||
|
|
||||||
private final int thirdPartyPort = 9081; |
|
||||||
private final int q2TPort = 9082; |
|
||||||
|
|
||||||
/** The constant p2pPort. */ |
|
||||||
public static final int p2pPort = 9001; |
|
||||||
|
|
||||||
private final String containerKeyDir = "/tmp/keys/"; |
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes") |
|
||||||
private GenericContainer tesseraContainer; |
|
||||||
|
|
||||||
private final Optional<Network> containerNetwork; |
|
||||||
private final String containerName; |
|
||||||
|
|
||||||
/** |
|
||||||
* Instantiates a new Tessera test harness. |
|
||||||
* |
|
||||||
* @param enclaveConfiguration the enclave configuration |
|
||||||
* @param containerNetwork the container network |
|
||||||
*/ |
|
||||||
protected TesseraTestHarness( |
|
||||||
final EnclaveConfiguration enclaveConfiguration, final Optional<Network> containerNetwork) { |
|
||||||
this.enclaveConfiguration = enclaveConfiguration; |
|
||||||
this.containerNetwork = containerNetwork; |
|
||||||
this.containerName = enclaveConfiguration.getName(); |
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(this::stop)); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void start() { |
|
||||||
if (!isRunning) { |
|
||||||
final File tempFolder = Files.newTemporaryFolder(); |
|
||||||
LOG.info("Temporary directory: " + tempFolder.getAbsolutePath()); |
|
||||||
final String configFile = createConfigFile(enclaveConfiguration.getName()); |
|
||||||
|
|
||||||
tesseraContainer = buildTesseraContainer(configFile); |
|
||||||
containerNetwork.ifPresent(network -> addNetwork(tesseraContainer, containerName, network)); |
|
||||||
tesseraContainer.start(); |
|
||||||
isRunning = true; |
|
||||||
|
|
||||||
try { |
|
||||||
final String host = "http://" + tesseraContainer.getHost(); |
|
||||||
nodeURI = new URI(host + ":" + tesseraContainer.getMappedPort(p2pPort)); |
|
||||||
LOG.info("Tessera node URI: {}", nodeURI); |
|
||||||
q2TUri = new URI(host + ':' + tesseraContainer.getMappedPort(q2TPort)); |
|
||||||
LOG.info("Tessera client URI: {}", q2TUri); |
|
||||||
thirdPartyUri = new URI(host + ':' + tesseraContainer.getMappedPort(thirdPartyPort)); |
|
||||||
LOG.info("Tessera thirdParty URI: {}", thirdPartyUri); |
|
||||||
} catch (final URISyntaxException e) { |
|
||||||
throw new RuntimeException(e); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void stop() { |
|
||||||
if (isRunning) { |
|
||||||
tesseraContainer.stop(); |
|
||||||
isRunning = false; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void close() { |
|
||||||
stop(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public List<Path> getPublicKeyPaths() { |
|
||||||
return Arrays.asList(enclaveConfiguration.getPublicKeys()); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public String getDefaultPublicKey() { |
|
||||||
return readFile(enclaveConfiguration.getPublicKeys()[0]); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public List<String> getPublicKeys() { |
|
||||||
return Arrays.stream(enclaveConfiguration.getPublicKeys()) |
|
||||||
.map(TesseraTestHarness::readFile) |
|
||||||
.collect(Collectors.toList()); |
|
||||||
} |
|
||||||
|
|
||||||
private static String readFile(final Path path) { |
|
||||||
try { |
|
||||||
return readLines(path.toFile(), Charsets.UTF_8).get(0); |
|
||||||
} catch (final IOException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
return ""; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public URI clientUrl() { |
|
||||||
return q2TUri; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public URI nodeUrl() { |
|
||||||
return nodeURI; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void addOtherNode(final URI otherNode) { |
|
||||||
enclaveConfiguration.addOtherNode(otherNode.toString()); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public EnclaveType getEnclaveType() { |
|
||||||
return EnclaveType.TESSERA; |
|
||||||
} |
|
||||||
|
|
||||||
private String createConfigFile(final String nodeName) { |
|
||||||
// create a config file
|
|
||||||
|
|
||||||
// @formatter:off
|
|
||||||
String confString = |
|
||||||
"{\n" |
|
||||||
+ " \"mode\" : \"orion\",\n" |
|
||||||
+ enclaveConfiguration.getEnclaveEncryptorType().toTesseraEncryptorConfigJSON() |
|
||||||
+ " \"useWhiteList\": false,\n" |
|
||||||
+ " \"jdbc\": {\n" |
|
||||||
+ " \"username\": \"sa\",\n" |
|
||||||
+ " \"password\": \"\",\n" |
|
||||||
+ " \"url\": \"jdbc:h2:/tmp/db;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0\",\n" |
|
||||||
+ " \"autoCreateTables\": true\n" |
|
||||||
+ " },\n" |
|
||||||
+ " \"serverConfigs\":[\n" |
|
||||||
+ " {\n" |
|
||||||
+ " \"app\":\"ThirdParty\",\n" |
|
||||||
+ " \"enabled\": true,\n" |
|
||||||
+ " \"serverAddress\": \"http://" |
|
||||||
+ nodeName |
|
||||||
+ ":" |
|
||||||
+ thirdPartyPort |
|
||||||
+ "\",\n" |
|
||||||
+ " \"cors\" : {\n" |
|
||||||
+ " \"allowedMethods\" : [\"GET\", \"OPTIONS\"],\n" |
|
||||||
+ " \"allowedOrigins\" : [\"*\"]\n" |
|
||||||
+ " },\n" |
|
||||||
+ " \"communicationType\" : \"REST\"\n" |
|
||||||
+ " },\n" |
|
||||||
+ " {\n" |
|
||||||
+ " \"app\":\"Q2T\",\n" |
|
||||||
+ " \"enabled\": true,\n" |
|
||||||
+ " \"serverAddress\":\"http://" |
|
||||||
+ nodeName |
|
||||||
+ ":" |
|
||||||
+ q2TPort |
|
||||||
+ "\",\n" |
|
||||||
+ " \"communicationType\" : \"REST\"\n" |
|
||||||
+ " },\n" |
|
||||||
+ " {\n" |
|
||||||
+ " \"app\":\"P2P\",\n" |
|
||||||
+ " \"enabled\": true,\n" |
|
||||||
+ " \"serverAddress\":\"http://" |
|
||||||
+ nodeName |
|
||||||
+ ":" |
|
||||||
+ p2pPort |
|
||||||
+ "\",\n" |
|
||||||
+ " \"communicationType\" : \"REST\"\n" |
|
||||||
+ " }\n" |
|
||||||
+ " ],\n" |
|
||||||
+ " \"keys\": {\n" |
|
||||||
+ " \"passwords\": [],\n" |
|
||||||
+ " \"keyData\": " |
|
||||||
+ buildKeyConfig() |
|
||||||
+ "\n" |
|
||||||
+ " },\n" |
|
||||||
+ " \"alwaysSendTo\": []"; |
|
||||||
|
|
||||||
if (enclaveConfiguration.getOtherNodes().size() != 0) { |
|
||||||
confString += |
|
||||||
",\n" |
|
||||||
+ " \"peer\": [\n" |
|
||||||
+ " {\n" |
|
||||||
+ " \"url\": \"" |
|
||||||
+ enclaveConfiguration.getOtherNodes().get(0) |
|
||||||
+ "\"\n" |
|
||||||
+ " }\n" |
|
||||||
+ " ]"; |
|
||||||
} else { |
|
||||||
confString += ",\n" + " \"peer\": []"; |
|
||||||
} |
|
||||||
|
|
||||||
confString += "\n}"; |
|
||||||
|
|
||||||
final File configFile = Files.newTemporaryFile(); |
|
||||||
try { |
|
||||||
final FileWriter fw = new FileWriter(configFile, StandardCharsets.UTF_8); |
|
||||||
fw.write(confString); |
|
||||||
fw.close(); |
|
||||||
} catch (final IOException e) { |
|
||||||
throw new RuntimeException(e); |
|
||||||
} |
|
||||||
|
|
||||||
return configFile.getAbsolutePath(); |
|
||||||
} |
|
||||||
|
|
||||||
private String buildKeyConfig() { |
|
||||||
final JsonArray keyArray = new JsonArray(); |
|
||||||
final List<Path> pubKeysPaths = Arrays.asList(enclaveConfiguration.getPublicKeys()); |
|
||||||
final List<Path> privKeyPaths = Arrays.asList(enclaveConfiguration.getPrivateKeys()); |
|
||||||
|
|
||||||
for (int count = 0; count < pubKeysPaths.size(); count++) { |
|
||||||
final HashMap<String, String> stringStringHashMap = new HashMap<>(); |
|
||||||
stringStringHashMap.put( |
|
||||||
"publicKeyPath", containerKeyDir + pubKeysPaths.get(count).getFileName()); |
|
||||||
stringStringHashMap.put( |
|
||||||
"privateKeyPath", containerKeyDir + privKeyPaths.get(count).getFileName()); |
|
||||||
keyArray.add(stringStringHashMap); |
|
||||||
} |
|
||||||
|
|
||||||
return keyArray.toString(); |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes") |
|
||||||
private GenericContainer buildTesseraContainer(final String configFilePath) { |
|
||||||
final String containerConfigFilePath = "/tmp/config.json"; |
|
||||||
final String keyDir = enclaveConfiguration.getTempDir().toString(); |
|
||||||
return new GenericContainer<>("quorumengineering/tessera:" + TESSERA_VERSION) |
|
||||||
.withCopyFileToContainer(MountableFile.forHostPath(configFilePath), containerConfigFilePath) |
|
||||||
.withFileSystemBind(keyDir, containerKeyDir) |
|
||||||
.withCommand("--configfile " + containerConfigFilePath) |
|
||||||
.withExposedPorts(p2pPort, q2TPort, thirdPartyPort) |
|
||||||
.waitingFor(Wait.forHttp("/upcheck").withMethod("GET").forStatusCode(200)); |
|
||||||
} |
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes") |
|
||||||
private void addNetwork( |
|
||||||
final GenericContainer container, final String containerName, final Network network) { |
|
||||||
container.withNetwork(network).withNetworkAliases(containerName); |
|
||||||
} |
|
||||||
} |
|
@ -1,126 +0,0 @@ |
|||||||
/* |
|
||||||
* 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.enclave.testutil; |
|
||||||
|
|
||||||
import static org.apache.tuweni.io.file.Files.copyResource; |
|
||||||
|
|
||||||
import java.io.IOException; |
|
||||||
import java.nio.file.Path; |
|
||||||
import java.util.Arrays; |
|
||||||
import java.util.Collections; |
|
||||||
import java.util.List; |
|
||||||
import java.util.Optional; |
|
||||||
import javax.annotation.Nonnull; |
|
||||||
|
|
||||||
import org.testcontainers.containers.Network; |
|
||||||
|
|
||||||
/** The Tessera test harness factory. */ |
|
||||||
public class TesseraTestHarnessFactory { |
|
||||||
private static final String storage = "memory"; |
|
||||||
|
|
||||||
/** Default constructor */ |
|
||||||
private TesseraTestHarnessFactory() {} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create tessera test harness. |
|
||||||
* |
|
||||||
* @param name the name |
|
||||||
* @param tempDir the temp dir |
|
||||||
* @param enclaveConfig the enclave config |
|
||||||
* @param containerNetwork the container network |
|
||||||
* @return the tessera test harness |
|
||||||
*/ |
|
||||||
public static TesseraTestHarness create( |
|
||||||
final String name, |
|
||||||
final Path tempDir, |
|
||||||
final EnclaveKeyConfiguration enclaveConfig, |
|
||||||
final Optional<Network> containerNetwork) { |
|
||||||
return create( |
|
||||||
name, |
|
||||||
tempDir, |
|
||||||
enclaveConfig.getPubKeyPaths(), |
|
||||||
enclaveConfig.getPrivKeyPaths(), |
|
||||||
enclaveConfig.getEnclaveEncryptorType(), |
|
||||||
Collections.emptyList(), |
|
||||||
containerNetwork); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create tessera test harness. |
|
||||||
* |
|
||||||
* @param name the name |
|
||||||
* @param tempDir the temp dir |
|
||||||
* @param pubKeyPaths the pub key paths |
|
||||||
* @param privKeyPaths the priv key paths |
|
||||||
* @param enclaveEncryptorType the enclave encryptor type |
|
||||||
* @param othernodes the othernodes |
|
||||||
* @param containerNetwork the container network |
|
||||||
* @return the tessera test harness |
|
||||||
*/ |
|
||||||
public static TesseraTestHarness create( |
|
||||||
final String name, |
|
||||||
final Path tempDir, |
|
||||||
final String[] pubKeyPaths, |
|
||||||
final String[] privKeyPaths, |
|
||||||
final EnclaveEncryptorType enclaveEncryptorType, |
|
||||||
final List<String> othernodes, |
|
||||||
final Optional<Network> containerNetwork) { |
|
||||||
final Path[] pubKeys = stringArrayToPathArray(tempDir, pubKeyPaths); |
|
||||||
final Path[] privKeys = stringArrayToPathArray(tempDir, privKeyPaths); |
|
||||||
|
|
||||||
return create( |
|
||||||
name, tempDir, pubKeys, privKeys, enclaveEncryptorType, othernodes, containerNetwork); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Create tessera test harness. |
|
||||||
* |
|
||||||
* @param name the name |
|
||||||
* @param tempDir the temp dir |
|
||||||
* @param key1pubs the key 1 pubs |
|
||||||
* @param key1keys the key 1 keys |
|
||||||
* @param enclaveEncryptorType the enclave encryptor type |
|
||||||
* @param othernodes the othernodes |
|
||||||
* @param containerNetwork the container network |
|
||||||
* @return the tessera test harness |
|
||||||
*/ |
|
||||||
public static TesseraTestHarness create( |
|
||||||
final String name, |
|
||||||
final Path tempDir, |
|
||||||
final Path[] key1pubs, |
|
||||||
final Path[] key1keys, |
|
||||||
final EnclaveEncryptorType enclaveEncryptorType, |
|
||||||
final List<String> othernodes, |
|
||||||
final Optional<Network> containerNetwork) { |
|
||||||
return new TesseraTestHarness( |
|
||||||
new EnclaveConfiguration( |
|
||||||
name, key1pubs, key1keys, enclaveEncryptorType, tempDir, othernodes, false, storage), |
|
||||||
containerNetwork); |
|
||||||
} |
|
||||||
|
|
||||||
@Nonnull |
|
||||||
private static Path[] stringArrayToPathArray(final Path tempDir, final String[] privKeyPaths) { |
|
||||||
return Arrays.stream(privKeyPaths) |
|
||||||
.map( |
|
||||||
(pk) -> { |
|
||||||
try { |
|
||||||
return copyResource(pk, tempDir.resolve(pk)); |
|
||||||
} catch (final IOException e) { |
|
||||||
throw new RuntimeException(e); |
|
||||||
} |
|
||||||
}) |
|
||||||
.toArray(Path[]::new); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue