diff --git a/argon2/pom.xml b/argon2/pom.xml index 4ad108a99e..719c8c18b2 100644 --- a/argon2/pom.xml +++ b/argon2/pom.xml @@ -11,7 +11,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT diff --git a/config-cli/pom.xml b/config-cli/pom.xml index 9ba0bde10b..1d1a2fd963 100644 --- a/config-cli/pom.xml +++ b/config-cli/pom.xml @@ -6,7 +6,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT config-cli diff --git a/config-cli/src/test/java/com/quorum/tessera/config/cli/DefaultCliAdapterTest.java b/config-cli/src/test/java/com/quorum/tessera/config/cli/DefaultCliAdapterTest.java index d3563318e5..d34dbf3a60 100644 --- a/config-cli/src/test/java/com/quorum/tessera/config/cli/DefaultCliAdapterTest.java +++ b/config-cli/src/test/java/com/quorum/tessera/config/cli/DefaultCliAdapterTest.java @@ -25,6 +25,7 @@ import java.util.UUID; import static com.quorum.tessera.test.util.ElUtil.createAndPopulatePaths; +import java.util.Arrays; import static org.assertj.core.api.Assertions.*; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.*; @@ -102,7 +103,7 @@ public void withConstraintViolations() throws Exception { cliDelegate.execute("-configfile", configFile.toString()); failBecauseExceptionWasNotThrown(ConstraintViolationException.class); } catch (ConstraintViolationException ex) { - assertThat(ex.getConstraintViolations()).hasSize(2); + assertThat(ex.getConstraintViolations()).hasSize(4); } @@ -113,7 +114,13 @@ public void keygenWithConfig() throws Exception { KeyGenerator keyGenerator = MockKeyGeneratorFactory.getMockKeyGenerator(); - FilesystemKeyPair keypair = new FilesystemKeyPair(Paths.get(""), Paths.get("")); + Path publicKeyPath = Files.createTempFile(UUID.randomUUID().toString(), ""); + Path privateKeyPath = Files.createTempFile(UUID.randomUUID().toString(), ""); + + Files.write(privateKeyPath, Arrays.asList("SOMEDATA")); + Files.write(publicKeyPath, Arrays.asList("SOMEDATA")); + + FilesystemKeyPair keypair = new FilesystemKeyPair(publicKeyPath, privateKeyPath); when(keyGenerator.generate(anyString(), eq(null))).thenReturn(keypair); Path unixSocketPath = Files.createTempFile(UUID.randomUUID().toString(), ".ipc"); @@ -175,8 +182,14 @@ public void outputWithoutKeygenOrConfig() { public void output() throws Exception { KeyGenerator keyGenerator = MockKeyGeneratorFactory.getMockKeyGenerator(); - - FilesystemKeyPair keypair = new FilesystemKeyPair(Paths.get(""), Paths.get("")); + + Path publicKeyPath = Files.createTempFile(UUID.randomUUID().toString(), ""); + Path privateKeyPath = Files.createTempFile(UUID.randomUUID().toString(), ""); + + Files.write(privateKeyPath, Arrays.asList("SOMEDATA")); + Files.write(publicKeyPath, Arrays.asList("SOMEDATA")); + + FilesystemKeyPair keypair = new FilesystemKeyPair(publicKeyPath, privateKeyPath); when(keyGenerator.generate(anyString(), eq(null))).thenReturn(keypair); Path generatedKey = Paths.get("/tmp/" + UUID.randomUUID().toString()); @@ -355,7 +368,13 @@ public void suppressStartupForKeygenOption() throws Exception { @Test public void allowStartupForKeygenAndConfigfileOptions() throws Exception { final KeyGenerator keyGenerator = MockKeyGeneratorFactory.getMockKeyGenerator(); - final FilesystemKeyPair keypair = new FilesystemKeyPair(Paths.get(""), Paths.get("")); + Path publicKeyPath = Files.createTempFile(UUID.randomUUID().toString(), ""); + Path privateKeyPath = Files.createTempFile(UUID.randomUUID().toString(), ""); + + Files.write(privateKeyPath, Arrays.asList("SOMEDATA")); + Files.write(publicKeyPath, Arrays.asList("SOMEDATA")); + + FilesystemKeyPair keypair = new FilesystemKeyPair(publicKeyPath, privateKeyPath); when(keyGenerator.generate(anyString(), eq(null))).thenReturn(keypair); final Path configFile = createAndPopulatePaths(getClass().getResource("/sample-config.json")); diff --git a/config-migration/pom.xml b/config-migration/pom.xml index 106c95cff3..78cd7c0d3d 100644 --- a/config-migration/pom.xml +++ b/config-migration/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT config-migration jar diff --git a/config-migration/src/test/java/com/quorum/tessera/config/migration/LegacyCliAdapterTest.java b/config-migration/src/test/java/com/quorum/tessera/config/migration/LegacyCliAdapterTest.java index dbe9e44230..b307a4656a 100644 --- a/config-migration/src/test/java/com/quorum/tessera/config/migration/LegacyCliAdapterTest.java +++ b/config-migration/src/test/java/com/quorum/tessera/config/migration/LegacyCliAdapterTest.java @@ -245,7 +245,8 @@ public void ifConfigParameterIsNotSetInTomlOrCliThenDefaultIsUsed() throws Excep Path configFile = Files.createTempFile("emptyConfig", ".txt"); Path keysFile = Paths.get("abcxyz"); Files.deleteIfExists(keysFile); - Files.createFile(Paths.get("abcxyz")); + Files.createFile(keysFile); + Files.write(keysFile, Arrays.asList("SOMEDATA")); String[] requiredParams = { "--tomlfile=" + configFile.toString(), diff --git a/config/pom.xml b/config/pom.xml index f645c87fed..fb72ecba4f 100644 --- a/config/pom.xml +++ b/config/pom.xml @@ -11,7 +11,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/ValidContent.java b/config/src/main/java/com/quorum/tessera/config/constraints/ValidContent.java new file mode 100644 index 0000000000..875255dcb6 --- /dev/null +++ b/config/src/main/java/com/quorum/tessera/config/constraints/ValidContent.java @@ -0,0 +1,27 @@ +package com.quorum.tessera.config.constraints; + +import java.lang.annotation.Documented; +import static java.lang.annotation.ElementType.*; +import java.lang.annotation.Retention; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import java.lang.annotation.Target; +import javax.validation.Constraint; +import javax.validation.Payload; + +@Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE, TYPE_PARAMETER, TYPE_USE}) +@Retention(RUNTIME) +@Constraint(validatedBy = ValidContentValidator.class) +@Documented +public @interface ValidContent { + + String message() default "{ValidContent.message}"; + + Class[] groups() default {}; + + Class[] payload() default {}; + + int minLines() default 0; + + int maxLines() default Integer.MAX_VALUE; + +} diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/ValidContentValidator.java b/config/src/main/java/com/quorum/tessera/config/constraints/ValidContentValidator.java new file mode 100644 index 0000000000..2677caceb5 --- /dev/null +++ b/config/src/main/java/com/quorum/tessera/config/constraints/ValidContentValidator.java @@ -0,0 +1,40 @@ +package com.quorum.tessera.config.constraints; + +import com.quorum.tessera.io.FilesDelegate; +import java.nio.file.Files; +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +public class ValidContentValidator implements ConstraintValidator { + + private ValidContent config; + + @Override + public void initialize(ValidContent constraintAnnotation) { + this.config = constraintAnnotation; + } + + @Override + public boolean isValid(Path path, ConstraintValidatorContext context) { + + if (Objects.isNull(path)) { + return true; + } + + if (!Files.exists(path)) { + return true; + } + + List lines = FilesDelegate.create().lines(path) + .filter(line -> !Objects.equals("", line)) + .collect(Collectors.toList()); + + return lines.size() >= config.minLines() && lines.size() <= config.maxLines(); + + } + +} diff --git a/config/src/main/java/com/quorum/tessera/config/keypairs/DirectKeyPair.java b/config/src/main/java/com/quorum/tessera/config/keypairs/DirectKeyPair.java index 653c3f95c3..3324b5a597 100644 --- a/config/src/main/java/com/quorum/tessera/config/keypairs/DirectKeyPair.java +++ b/config/src/main/java/com/quorum/tessera/config/keypairs/DirectKeyPair.java @@ -3,15 +3,19 @@ import com.quorum.tessera.config.constraints.ValidBase64; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; import javax.xml.bind.annotation.XmlElement; public class DirectKeyPair implements ConfigKeyPair { + @Size(min = 1) @NotNull @ValidBase64(message = "Invalid Base64 key provided") @XmlElement private final String publicKey; + + @Size(min = 1) @NotNull @ValidBase64(message = "Invalid Base64 key provided") @XmlElement diff --git a/config/src/main/java/com/quorum/tessera/config/keypairs/FilesystemKeyPair.java b/config/src/main/java/com/quorum/tessera/config/keypairs/FilesystemKeyPair.java index a55f4ddcfc..581b810152 100644 --- a/config/src/main/java/com/quorum/tessera/config/keypairs/FilesystemKeyPair.java +++ b/config/src/main/java/com/quorum/tessera/config/keypairs/FilesystemKeyPair.java @@ -2,6 +2,7 @@ import com.quorum.tessera.config.KeyDataConfig; import com.quorum.tessera.config.adapters.PathAdapter; +import com.quorum.tessera.config.constraints.ValidContent; import com.quorum.tessera.config.constraints.ValidPath; import com.quorum.tessera.config.util.JaxbUtil; import com.quorum.tessera.io.IOCallback; @@ -16,12 +17,14 @@ public class FilesystemKeyPair implements ConfigKeyPair { + @ValidContent(minLines = 1,maxLines = 1,message = "file expected to contain a single non empty value") @NotNull @ValidPath(checkExists = true, message = "File does not exist") @XmlElement @XmlJavaTypeAdapter(PathAdapter.class) private final Path publicKeyPath; + @ValidContent(minLines = 1,message = "file expected to contain at least one line") @NotNull @ValidPath(checkExists = true, message = "File does not exist") @XmlElement diff --git a/config/src/main/java/com/quorum/tessera/config/keypairs/InlineKeypair.java b/config/src/main/java/com/quorum/tessera/config/keypairs/InlineKeypair.java index d94744cd4c..1a7b902f97 100644 --- a/config/src/main/java/com/quorum/tessera/config/keypairs/InlineKeypair.java +++ b/config/src/main/java/com/quorum/tessera/config/keypairs/InlineKeypair.java @@ -13,10 +13,12 @@ import static com.quorum.tessera.config.PrivateKeyType.UNLOCKED; import com.quorum.tessera.encryption.PrivateKey; +import javax.validation.constraints.Size; @ValidInlineKeypair public class InlineKeypair implements ConfigKeyPair { + @Size(min = 1) @NotNull @ValidBase64(message = "Invalid Base64 key provided") @XmlElement diff --git a/config/src/main/java/com/quorum/tessera/config/keypairs/KeyPairConverter.java b/config/src/main/java/com/quorum/tessera/config/keypairs/KeyPairConverter.java index 569ca1bfe1..0e0d560208 100644 --- a/config/src/main/java/com/quorum/tessera/config/keypairs/KeyPairConverter.java +++ b/config/src/main/java/com/quorum/tessera/config/keypairs/KeyPairConverter.java @@ -41,8 +41,8 @@ private KeyPair convert(ConfigKeyPair configKeyPair) { } return new KeyPair( - PublicKey.from(Base64.getDecoder().decode(encodedPub)), - PrivateKey.from(Base64.getDecoder().decode(encodedPriv)) + PublicKey.from(Base64.getDecoder().decode(encodedPub.trim())), + PrivateKey.from(Base64.getDecoder().decode(encodedPriv.trim())) ); } diff --git a/config/src/test/java/com/quorum/tessera/config/constraints/ValidContentValidatorTest.java b/config/src/test/java/com/quorum/tessera/config/constraints/ValidContentValidatorTest.java new file mode 100644 index 0000000000..2e65916906 --- /dev/null +++ b/config/src/test/java/com/quorum/tessera/config/constraints/ValidContentValidatorTest.java @@ -0,0 +1,141 @@ +package com.quorum.tessera.config.constraints; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.UUID; +import javax.validation.ConstraintValidatorContext; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ValidContentValidatorTest { + + @Test + public void ignoreNullPath() { + ValidContentValidator validator = new ValidContentValidator(); + ValidContent validContent = mock(ValidContent.class); + validator.initialize(validContent); + + ConstraintValidatorContext context = mock(ConstraintValidatorContext.class); + + assertThat(validator.isValid(null, context)).isTrue(); + + } + + @Test + public void ignoreNonExistPath() { + ValidContentValidator validator = new ValidContentValidator(); + ValidContent validContent = mock(ValidContent.class); + validator.initialize(validContent); + + ConstraintValidatorContext context = mock(ConstraintValidatorContext.class); + + Path path = Paths.get(UUID.randomUUID().toString()); + + assertThat(path).doesNotExist(); + + assertThat(validator.isValid(path, context)).isTrue(); + + } + + @Test + public void defaultValuesIgnoreEmptyFile() throws Exception { + ValidContentValidator validator = new ValidContentValidator(); + ValidContent validContent = mock(ValidContent.class); + + validator.initialize(validContent); + + ConstraintValidatorContext context = mock(ConstraintValidatorContext.class); + + Path path = Files.createTempFile(UUID.randomUUID().toString(), ""); + + assertThat(path).exists(); + + assertThat(validator.isValid(path, context)).isTrue(); + + } + + @Test + public void expectSingleLineButFileIsEmpty() throws Exception { + ValidContentValidator validator = new ValidContentValidator(); + ValidContent validContent = mock(ValidContent.class); + when(validContent.minLines()).thenReturn(1); + when(validContent.maxLines()).thenReturn(1); + + validator.initialize(validContent); + + ConstraintValidatorContext context = mock(ConstraintValidatorContext.class); + + Path path = Files.createTempFile(UUID.randomUUID().toString(), ""); + + assertThat(path).exists(); + + assertThat(validator.isValid(path, context)).isFalse(); + + } + + @Test + public void expectSingleLineFileIsValid() throws Exception { + ValidContentValidator validator = new ValidContentValidator(); + ValidContent validContent = mock(ValidContent.class); + when(validContent.minLines()).thenReturn(1); + when(validContent.maxLines()).thenReturn(1); + + validator.initialize(validContent); + + ConstraintValidatorContext context = mock(ConstraintValidatorContext.class); + + Path path = Files.createTempFile(UUID.randomUUID().toString(), ""); + Files.write(path, "SOMEDATA".getBytes()); + + assertThat(path).exists(); + + assertThat(validator.isValid(path, context)).isTrue(); + + } + + @Test + public void tooManyLines() throws Exception { + ValidContentValidator validator = new ValidContentValidator(); + ValidContent validContent = mock(ValidContent.class); + when(validContent.minLines()).thenReturn(1); + when(validContent.maxLines()).thenReturn(1); + + validator.initialize(validContent); + + final ConstraintValidatorContext context = mock(ConstraintValidatorContext.class); + + Path path = Files.createTempFile(UUID.randomUUID().toString(), ""); + Files.write(path, Arrays.asList("SOMEDATA","SOMEMOREDATA")); + + assertThat(path).exists(); + + assertThat(validator.isValid(path, context)).isFalse(); + + } + + @Test + public void emptyLine() throws Exception { + ValidContentValidator validator = new ValidContentValidator(); + ValidContent validContent = mock(ValidContent.class); + when(validContent.minLines()).thenReturn(1); + when(validContent.maxLines()).thenReturn(1); + + validator.initialize(validContent); + + final ConstraintValidatorContext context = mock(ConstraintValidatorContext.class); + + Path path = Files.createTempFile(UUID.randomUUID().toString(), ""); + Files.write(path, Arrays.asList("")); + + assertThat(path).exists(); + + assertThat(validator.isValid(path, context)).isFalse(); + + } + + +} diff --git a/config/src/test/java/com/quorum/tessera/config/keypairs/KeyPairConverterTest.java b/config/src/test/java/com/quorum/tessera/config/keypairs/KeyPairConverterTest.java index fc61e4d387..595fbd837a 100644 --- a/config/src/test/java/com/quorum/tessera/config/keypairs/KeyPairConverterTest.java +++ b/config/src/test/java/com/quorum/tessera/config/keypairs/KeyPairConverterTest.java @@ -117,4 +117,20 @@ public void convertMultipleKeyPairs() { final KeyPair resultB = it.next(); assertThat(resultB).isEqualToComparingFieldByField(expectedB); } + + @Test + public void convertKeyPairWithNewlineOrSpace() { + final DirectKeyPair keyPair = + new DirectKeyPair("gybY1t9GOYiuN6QgwcrvM2+pQzIu4UrHwiMG7yKQnTg=\n", + " yTjqANGAvPCy8AfhcIZ+e4O8CHZPbHkIeOmae5W3srY=\n\n\n"); + + Collection result = converter.convert(Collections.singletonList(keyPair)); + + KeyPair expected = new KeyPair( + PublicKey.from(decodeBase64("gybY1t9GOYiuN6QgwcrvM2+pQzIu4UrHwiMG7yKQnTg=")), + PrivateKey.from(decodeBase64("yTjqANGAvPCy8AfhcIZ+e4O8CHZPbHkIeOmae5W3srY="))); + + KeyPair resultKeyPair = result.iterator().next(); + assertThat(resultKeyPair).isEqualToComparingFieldByField(expected); + } } diff --git a/data-migration/pom.xml b/data-migration/pom.xml index a51696a3c3..2d4ee5cd84 100644 --- a/data-migration/pom.xml +++ b/data-migration/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT data-migration jar diff --git a/encryption/encryption-api/pom.xml b/encryption/encryption-api/pom.xml index dc81e38141..c15e9ebbab 100644 --- a/encryption/encryption-api/pom.xml +++ b/encryption/encryption-api/pom.xml @@ -9,7 +9,7 @@ com.quorum.tessera encryption - 0.7 + 0.7.1-SNAPSHOT \ No newline at end of file diff --git a/encryption/encryption-jnacl/pom.xml b/encryption/encryption-jnacl/pom.xml index 25a536dc76..81a4a259f1 100644 --- a/encryption/encryption-jnacl/pom.xml +++ b/encryption/encryption-jnacl/pom.xml @@ -11,7 +11,7 @@ com.quorum.tessera encryption - 0.7 + 0.7.1-SNAPSHOT diff --git a/encryption/encryption-kalium/pom.xml b/encryption/encryption-kalium/pom.xml index 5395635bac..7df9cbb405 100644 --- a/encryption/encryption-kalium/pom.xml +++ b/encryption/encryption-kalium/pom.xml @@ -11,7 +11,7 @@ com.quorum.tessera encryption - 0.7 + 0.7.1-SNAPSHOT diff --git a/encryption/pom.xml b/encryption/pom.xml index bac6c040a8..2603e7ca39 100644 --- a/encryption/pom.xml +++ b/encryption/pom.xml @@ -9,7 +9,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT diff --git a/grpc-api/pom.xml b/grpc-api/pom.xml index 0d8d0e621e..45302f56ec 100644 --- a/grpc-api/pom.xml +++ b/grpc-api/pom.xml @@ -3,7 +3,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/grpc-service/pom.xml b/grpc-service/pom.xml index 2bfefa3aed..7c1de59129 100644 --- a/grpc-service/pom.xml +++ b/grpc-service/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT grpc-service jar diff --git a/grpc/pom.xml b/grpc/pom.xml index 1478bfcc03..56a268f06b 100644 --- a/grpc/pom.xml +++ b/grpc/pom.xml @@ -3,7 +3,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/jaxrs-client/pom.xml b/jaxrs-client/pom.xml index cec7835a9a..3c758eb000 100644 --- a/jaxrs-client/pom.xml +++ b/jaxrs-client/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT jaxrs-client jar diff --git a/jaxrs-service/pom.xml b/jaxrs-service/pom.xml index 21380ab061..63dd21fbb0 100644 --- a/jaxrs-service/pom.xml +++ b/jaxrs-service/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT jaxrs-service jar diff --git a/jaxrs-service/src/main/java/com/quorum/tessera/api/ConfigResource.java b/jaxrs-service/src/main/java/com/quorum/tessera/api/ConfigResource.java index 2e33d1176a..b8e80f1c07 100644 --- a/jaxrs-service/src/main/java/com/quorum/tessera/api/ConfigResource.java +++ b/jaxrs-service/src/main/java/com/quorum/tessera/api/ConfigResource.java @@ -2,6 +2,9 @@ import com.quorum.tessera.config.Peer; import com.quorum.tessera.core.config.ConfigService; +import com.quorum.tessera.node.PartyInfoService; +import com.quorum.tessera.node.model.Party; +import com.quorum.tessera.node.model.PartyInfo; import javax.validation.Valid; import javax.ws.rs.*; @@ -9,6 +12,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import java.net.URI; +import java.util.Collections; import java.util.List; import java.util.Objects; import javax.ws.rs.core.GenericEntity; @@ -20,9 +24,15 @@ public class ConfigResource { private final ConfigService configService; - public ConfigResource(final ConfigService configService) { + private final PartyInfoService partyInfoService; + + public ConfigResource(ConfigService configService, + PartyInfoService partyInfoService) { this.configService = Objects.requireNonNull(configService); + this.partyInfoService = Objects.requireNonNull(partyInfoService); } + + @PUT @Path("/peers") @@ -30,6 +40,10 @@ public Response addPeer(@Valid final Peer peer) { this.configService.addPeer(peer.getUrl()); + partyInfoService.updatePartyInfo( + new PartyInfo(peer.getUrl(),Collections.EMPTY_SET, + Collections.singleton(new Party(peer.getUrl())))); + //TODO: this seems a bit presumptuous, search for the peer instead? final int index = this.configService.getPeers().size() - 1; diff --git a/jaxrs-service/src/main/java/com/quorum/tessera/api/exception/KeyNotFoundExceptionMapper.java b/jaxrs-service/src/main/java/com/quorum/tessera/api/exception/KeyNotFoundExceptionMapper.java index 9f49c8b7c4..a3cbe74533 100644 --- a/jaxrs-service/src/main/java/com/quorum/tessera/api/exception/KeyNotFoundExceptionMapper.java +++ b/jaxrs-service/src/main/java/com/quorum/tessera/api/exception/KeyNotFoundExceptionMapper.java @@ -16,7 +16,8 @@ public class KeyNotFoundExceptionMapper implements ExceptionMapper + diff --git a/jaxrs-service/src/test/java/com/quorum/tessera/api/ConfigResourceTest.java b/jaxrs-service/src/test/java/com/quorum/tessera/api/ConfigResourceTest.java index 1946d46790..d48c6cd0a1 100644 --- a/jaxrs-service/src/test/java/com/quorum/tessera/api/ConfigResourceTest.java +++ b/jaxrs-service/src/test/java/com/quorum/tessera/api/ConfigResourceTest.java @@ -2,6 +2,8 @@ import com.quorum.tessera.config.Peer; import com.quorum.tessera.core.config.ConfigService; +import com.quorum.tessera.node.PartyInfoService; +import com.quorum.tessera.node.model.PartyInfo; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -11,6 +13,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import org.mockito.Mockito; import static org.mockito.Mockito.mock; @@ -24,15 +27,19 @@ public class ConfigResourceTest { private ConfigService configService; + private PartyInfoService partyInfoService; + @Before public void onSetUp() { configService = mock(ConfigService.class); - configResource = new ConfigResource(configService); + partyInfoService = mock(PartyInfoService.class); + configResource = new ConfigResource(configService,partyInfoService); + } @After public void onTearDown() { - verifyNoMoreInteractions(configService); + verifyNoMoreInteractions(configService,partyInfoService); } @Test @@ -53,6 +60,7 @@ public void addPeerIsSucessful() { assertThat(peers).containsExactly(peer); verify(configService).addPeer(peer.getUrl()); verify(configService).getPeers(); + verify(partyInfoService).updatePartyInfo(any(PartyInfo.class)); } @Test @@ -66,7 +74,6 @@ public void getPeerIsSucessful() { assertThat(response.getEntity()).isEqualTo(peer); verify(configService).getPeers(); - } @Test diff --git a/key-generation/pom.xml b/key-generation/pom.xml index dfba05253d..02f0496ac0 100644 --- a/key-generation/pom.xml +++ b/key-generation/pom.xml @@ -3,7 +3,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/key-generation/src/test/java/com/quorum/tessera/key/generation/AzureVaultKeyGeneratorTest.java b/key-generation/src/test/java/com/quorum/tessera/key/generation/AzureVaultKeyGeneratorTest.java index a9bc09cf54..2d8bda2460 100644 --- a/key-generation/src/test/java/com/quorum/tessera/key/generation/AzureVaultKeyGeneratorTest.java +++ b/key-generation/src/test/java/com/quorum/tessera/key/generation/AzureVaultKeyGeneratorTest.java @@ -107,7 +107,7 @@ public void allowedCharactersUsedInVaultIdDoesNotThrowException() { @Test public void exceptionThrownIfDisallowedCharactersUsedInVaultId() { - final String invalidId = "!@£$%^&*()"; + final String invalidId = "/tmp/abc@+"; final Throwable throwable = catchThrowable( () -> azureVaultKeyGenerator.generate(invalidId, null) diff --git a/key-vault/azure-key-vault/pom.xml b/key-vault/azure-key-vault/pom.xml index 94d9150eed..98c8ec6837 100644 --- a/key-vault/azure-key-vault/pom.xml +++ b/key-vault/azure-key-vault/pom.xml @@ -3,7 +3,7 @@ key-vault com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/key-vault/key-vault-api/pom.xml b/key-vault/key-vault-api/pom.xml index cf31372b71..c91c6b1f06 100644 --- a/key-vault/key-vault-api/pom.xml +++ b/key-vault/key-vault-api/pom.xml @@ -3,7 +3,7 @@ key-vault com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/key-vault/pom.xml b/key-vault/pom.xml index 3fedf92671..1192dcab4f 100644 --- a/key-vault/pom.xml +++ b/key-vault/pom.xml @@ -3,7 +3,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/pom.xml b/pom.xml index 9596e6d89f..66fe160be7 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT tessera pom @@ -20,7 +20,7 @@ https://github.com/jpmorganchase/tessera scm:git:git://github.com/jpmorganchase/tessera.git scm:git:git@github.com:jpmorganchase/tessera.git - tessera-0.7 + patch-release-0.7.1 @@ -68,7 +68,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.22.0 + 3.0.0-M1 true @@ -269,148 +269,148 @@ com.quorum.tessera encryption-api - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera argon2 - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera config - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera config-cli - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera security - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera encryption-jnacl - 0.7 + 0.7.1-SNAPSHOT runtime com.quorum.tessera encryption-kalium - 0.7 + 0.7.1-SNAPSHOT runtime com.quorum.tessera service-locator-api - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera service-locator-spring - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera server-api - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera jersey-server - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera resteasy-server - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera grpc-server - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera grpc - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera grpc-api - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera test-util - 0.7 + 0.7.1-SNAPSHOT test com.quorum.tessera shared - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera tessera-core - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera grpc-service - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera jaxrs-service - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera key-vault-api - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera azure-key-vault - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera key-generation - 0.7 + 0.7.1-SNAPSHOT com.quorum.tessera jaxrs-client - 0.7 + 0.7.1-SNAPSHOT diff --git a/security/pom.xml b/security/pom.xml index d04f53e69c..16a3cd2223 100644 --- a/security/pom.xml +++ b/security/pom.xml @@ -4,7 +4,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/server/grpc-server/pom.xml b/server/grpc-server/pom.xml index 30347e8f26..67fd0fe701 100644 --- a/server/grpc-server/pom.xml +++ b/server/grpc-server/pom.xml @@ -4,7 +4,7 @@ server com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/server/jersey-server/pom.xml b/server/jersey-server/pom.xml index 8ba53679d5..e30bb52a85 100644 --- a/server/jersey-server/pom.xml +++ b/server/jersey-server/pom.xml @@ -11,7 +11,7 @@ com.quorum.tessera server - 0.7 + 0.7.1-SNAPSHOT diff --git a/server/pom.xml b/server/pom.xml index c544ed13ab..bddb4fb58f 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -9,7 +9,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT diff --git a/server/resteasy-server/pom.xml b/server/resteasy-server/pom.xml index ac8282c6e4..879d12f678 100644 --- a/server/resteasy-server/pom.xml +++ b/server/resteasy-server/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera server - 0.7 + 0.7.1-SNAPSHOT resteasy-server jar diff --git a/server/server-api/pom.xml b/server/server-api/pom.xml index a81baf9d9a..4be52a4c0e 100644 --- a/server/server-api/pom.xml +++ b/server/server-api/pom.xml @@ -9,7 +9,7 @@ com.quorum.tessera server - 0.7 + 0.7.1-SNAPSHOT diff --git a/server/unix-socket-server/pom.xml b/server/unix-socket-server/pom.xml index 24dcc5e811..c30fd53ba4 100644 --- a/server/unix-socket-server/pom.xml +++ b/server/unix-socket-server/pom.xml @@ -9,7 +9,7 @@ server com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT diff --git a/service-locator/pom.xml b/service-locator/pom.xml index ce06405b7b..f347ba7acc 100644 --- a/service-locator/pom.xml +++ b/service-locator/pom.xml @@ -9,7 +9,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT diff --git a/service-locator/service-locator-api/pom.xml b/service-locator/service-locator-api/pom.xml index cf309e0526..ce3ed87ec7 100644 --- a/service-locator/service-locator-api/pom.xml +++ b/service-locator/service-locator-api/pom.xml @@ -11,7 +11,7 @@ com.quorum.tessera service-locator - 0.7 + 0.7.1-SNAPSHOT \ No newline at end of file diff --git a/service-locator/service-locator-spring/pom.xml b/service-locator/service-locator-spring/pom.xml index dbee07f961..3be7ecacab 100644 --- a/service-locator/service-locator-spring/pom.xml +++ b/service-locator/service-locator-spring/pom.xml @@ -11,7 +11,7 @@ com.quorum.tessera service-locator - 0.7 + 0.7.1-SNAPSHOT diff --git a/shared/pom.xml b/shared/pom.xml index 09ae8e8bec..e351ea7089 100644 --- a/shared/pom.xml +++ b/shared/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT shared jar diff --git a/tessera-app/pom.xml b/tessera-app/pom.xml index 881fc513f8..d44430fb88 100644 --- a/tessera-app/pom.xml +++ b/tessera-app/pom.xml @@ -8,7 +8,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT @@ -54,7 +54,7 @@ com.quorum.tessera unix-socket-server - 0.7 + 0.7.1-SNAPSHOT runtime diff --git a/tessera-core/pom.xml b/tessera-core/pom.xml index f9f49a038c..2144a69eaf 100644 --- a/tessera-core/pom.xml +++ b/tessera-core/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera tessera - 0.7 + 0.7.1-SNAPSHOT tessera-core jar diff --git a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParser.java b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParser.java index 405635e093..3f1cf9e447 100644 --- a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParser.java +++ b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParser.java @@ -5,6 +5,7 @@ import com.quorum.tessera.node.model.PartyInfo; import com.quorum.tessera.node.model.Recipient; import com.quorum.tessera.util.BinaryEncoder; +import static java.lang.Math.toIntExact; import org.apache.commons.lang3.ArrayUtils; import java.nio.ByteBuffer; @@ -15,6 +16,7 @@ import java.util.stream.Collectors; import static java.nio.charset.StandardCharsets.UTF_8; +import java.util.Optional; /** * A parser for PartyInfo node discovery information @@ -32,24 +34,33 @@ default PartyInfo from(final byte[] encoded) { final ByteBuffer byteBuffer = ByteBuffer.wrap(encoded); - final int urlLength = (int) byteBuffer.getLong(); + final int urlLength = (int) toIntExact(byteBuffer.getLong()); + checkLength(urlLength); + final byte[] urlBytes = new byte[urlLength]; byteBuffer.get(urlBytes); final String url = new String(urlBytes, UTF_8); - final int numberOfRecipients = (int) byteBuffer.getLong(); + final int numberOfRecipients = (int) toIntExact(byteBuffer.getLong()); + checkLength(urlLength); final Set recipients = new HashSet<>(); for (int i = 0; i < numberOfRecipients; i++) { - final int recipientKeyLength = (int) byteBuffer.getLong(); + final int recipientKeyLength = (int) toIntExact(byteBuffer.getLong()); + checkLength(recipientKeyLength); + final byte[] recipientKeyBytes = new byte[recipientKeyLength]; byteBuffer.get(recipientKeyBytes); - final int recipientUrlValueLength = (int) byteBuffer.getLong(); + final int recipientUrlValueLength = (int) toIntExact(byteBuffer.getLong()); + checkLength(recipientUrlValueLength); + final byte[] urlValueData = new byte[recipientUrlValueLength]; + + byteBuffer.get(urlValueData); final String recipientUrl = new String(urlValueData, UTF_8); @@ -57,12 +68,15 @@ default PartyInfo from(final byte[] encoded) { } - final int partyCount = (int) byteBuffer.getLong(); - + final int partyCount = (int) toIntExact(byteBuffer.getLong()); + checkLength(partyCount); + final Party[] parties = new Party[partyCount]; for (int i = 0; i < partyCount; i++) { long partyElementLength = byteBuffer.getLong(); - byte[] ptyData = new byte[(int) partyElementLength]; + checkLength(partyElementLength); + + byte[] ptyData = new byte[(int) toIntExact(partyElementLength)]; byteBuffer.get(ptyData); String ptyURL = new String(ptyData, UTF_8); parties[i] = new Party(ptyURL); @@ -89,28 +103,28 @@ default byte[] to(final PartyInfo partyInfo) { //each element in the list is one encoded element from the map //so the prefix is always 2 (2 elements) and final List recipients = partyInfo.getRecipients() - .stream() - .map(r -> { - final byte[] encodedKey = encodeField(r.getKey().getKeyBytes()); - final byte[] encodedUrl = encodeField(r.getUrl().getBytes(UTF_8)); - - //using Apache Commons array utils since it is already available - //other concat the two arrays manually - return ArrayUtils.addAll(encodedKey, encodedUrl); - }).collect(Collectors.toList()); + .stream() + .map(r -> { + final byte[] encodedKey = encodeField(r.getKey().getKeyBytes()); + final byte[] encodedUrl = encodeField(r.getUrl().getBytes(UTF_8)); + + //using Apache Commons array utils since it is already available + //other concat the two arrays manually + return ArrayUtils.addAll(encodedKey, encodedUrl); + }).collect(Collectors.toList()); final int recipientLength = recipients.stream().mapToInt(r -> r.length).sum(); final List parties = partyInfo.getParties() - .stream() - .map(p -> p.getUrl().getBytes(UTF_8)) - .collect(Collectors.toList()); + .stream() + .map(p -> p.getUrl().getBytes(UTF_8)) + .collect(Collectors.toList()); final byte[] partiesBytes = encodeArray(parties); final ByteBuffer byteBuffer = ByteBuffer - .allocate(url.length + Long.BYTES + recipientLength + partiesBytes.length) - .put(url) - .putLong(partyInfo.getRecipients().size()); + .allocate(url.length + Long.BYTES + recipientLength + partiesBytes.length) + .put(url) + .putLong(partyInfo.getRecipients().size()); recipients.forEach(byteBuffer::put); byteBuffer.put(partiesBytes); @@ -129,4 +143,19 @@ static PartyInfoParser create() { }; } + + static void checkLength(long value) { + Optional.of(value) + .filter(v -> v >= 0) + .filter(v -> v < Long.MAX_VALUE - 1) + .orElseThrow(() -> new PartyInfoParserException("Invalid length "+ value)); + } + + static void checkLength(int value) { + Optional.of(value) + .filter(v -> v >= 0) + .filter(v -> v < Integer.MAX_VALUE - 1) + .orElseThrow(() -> new PartyInfoParserException("Invalid length "+ value)); + } + } diff --git a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParserException.java b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParserException.java new file mode 100644 index 0000000000..1c2b28b28c --- /dev/null +++ b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoParserException.java @@ -0,0 +1,13 @@ + +package com.quorum.tessera.node; + +import com.quorum.tessera.exception.TesseraException; + + +public class PartyInfoParserException extends TesseraException { + + public PartyInfoParserException(String message) { + super(message); + } + +} diff --git a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoServiceImpl.java b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoServiceImpl.java index b39560cba7..6584eb6139 100644 --- a/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoServiceImpl.java +++ b/tessera-core/src/main/java/com/quorum/tessera/node/PartyInfoServiceImpl.java @@ -35,14 +35,22 @@ public PartyInfoServiceImpl(final PartyInfoStore partyInfoStore, final String advertisedUrl = configService.getServerUri() + "/"; + final Set initialParties = configService + .getPeers() + .stream() + .map(Peer::getUrl) + .map(Party::new) + .collect(toSet()); + final Set ourKeys = keyManager - .getPublicKeys() - .stream() - .map(key -> PublicKey.from(key.getKeyBytes())) - .map(key -> new Recipient(key, advertisedUrl)) - .collect(toSet()); + .getPublicKeys() + .stream() + .map(key -> PublicKey.from(key.getKeyBytes())) + .map(key -> new Recipient(key, advertisedUrl)) + .collect(toSet()); + + partyInfoStore.store(new PartyInfo(advertisedUrl, ourKeys, initialParties)); - partyInfoStore.store(new PartyInfo(advertisedUrl, ourKeys, Collections.emptySet())); } @Override @@ -105,7 +113,7 @@ public String getURLFromRecipientKey(final PublicKey key) { .stream() .filter(recipient -> key.equals(recipient.getKey())) .findAny() - .orElseThrow(() -> new KeyNotFoundException("Recipient not found")); + .orElseThrow(() -> new KeyNotFoundException("Recipient not found for key: "+ key.encodeToBase64())); return retrievedRecipientFromStore.getUrl(); } diff --git a/tessera-core/src/main/java/com/quorum/tessera/node/model/Party.java b/tessera-core/src/main/java/com/quorum/tessera/node/model/Party.java index 1361f96233..4de2499b81 100644 --- a/tessera-core/src/main/java/com/quorum/tessera/node/model/Party.java +++ b/tessera-core/src/main/java/com/quorum/tessera/node/model/Party.java @@ -27,4 +27,11 @@ public int hashCode() { return Objects.hash(url); } + @Override + public String toString() { + return "Party{" + "url=" + url + '}'; + } + + + } diff --git a/tessera-core/src/main/resources/tessera-core-spring.xml b/tessera-core/src/main/resources/tessera-core-spring.xml index fda9ca78dd..a9b7559ed7 100644 --- a/tessera-core/src/main/resources/tessera-core-spring.xml +++ b/tessera-core/src/main/resources/tessera-core-spring.xml @@ -40,25 +40,10 @@ - - - - - - - - - - - - - - - - - - + + + @@ -225,4 +210,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserExceptionTest.java b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserExceptionTest.java new file mode 100644 index 0000000000..5884fb73d0 --- /dev/null +++ b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserExceptionTest.java @@ -0,0 +1,19 @@ + +package com.quorum.tessera.node; + +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + + +public class PartyInfoParserExceptionTest { + + @Test + public void createWithMessage() { + + PartyInfoParserException result = new PartyInfoParserException("OUCH"); + + assertThat(result).hasMessage("OUCH"); + + } + +} diff --git a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserTest.java b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserTest.java index 6deefb6a52..4eedfe22e1 100644 --- a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserTest.java +++ b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoParserTest.java @@ -14,7 +14,7 @@ public class PartyInfoParserTest { - private final int[] sampleDataTwo = new int[]{0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 7,0, 0, 0, 0, 0, 0, 0, 32, 214, 36, 217, 117, 239, 231, 116, 17, 239, 206, 23, 37, 237, 94, 188, 199, 142, 21, 199, 186, 101, 242, 124, 49, 244, 186, 167, 51, 240, 31, 37, 72, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 51, 58, 57, 48, 48, 51, 47, 0, 0, 0, 0, 0, 0, 0, 32, 81, 243, 82, 121, 33, 178, 73, 226, 160, 215, 80, 213, 52, 73, 234, 173, 75, 113, 97, 21, 104, 175, 143, 130, 190, 91, 136, 242, 213, 111, 235, 102, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 54, 58, 57, 48, 48, 54, 47, 0, 0, 0, 0, 0, 0, 0, 32, 160, 219, 41, 60, 248, 44, 205, 85, 5, 195, 74, 166, 24, 87, 214, 194, 29, 110, 197, 85, 23, 130, 240, 113, 149, 229, 206, 68, 120, 244, 238, 15, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 32, 71, 158, 160, 203, 135, 103, 219, 134, 14, 143, 12, 158, 177, 55, 51, 97, 175, 38, 231, 24, 79, 234, 17, 118, 185, 51, 2, 142, 239, 245, 198, 70, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 53, 58, 57, 48, 48, 53, 47, 0, 0, 0, 0, 0, 0, 0, 32, 68, 224, 25, 5, 107, 82, 105, 204, 87, 66, 179, 158, 220, 81, 128, 168, 144, 242, 38, 49, 94, 61, 30, 92, 123, 132, 210, 35, 57, 137, 208, 23, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 55, 58, 57, 48, 48, 55, 47, 0, 0, 0, 0, 0, 0, 0, 32, 5, 66, 222, 71, 194, 114, 81, 104, 98, 186, 224, 140, 83, 241, 203, 3, 68, 57, 167, 57, 24, 79, 231, 7, 32, 141, 217, 40, 23, 178, 220, 26, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 48, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 32, 65, 247, 131, 3, 43, 61, 48, 240, 236, 217, 113, 196, 198, 215, 60, 226, 50, 134, 31, 22, 96, 253, 168, 249, 216, 52, 225, 210, 251, 64, 221, 119, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 50, 58, 57, 48, 48, 50, 47, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 48, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 55, 58, 57, 48, 48, 55, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 54, 58, 57, 48, 48, 54, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 50, 58, 57, 48, 48, 50, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 53, 58, 57, 48, 48, 53, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 51, 58, 57, 48, 48, 51, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + private final int[] sampleDataTwo = new int[]{0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 32, 214, 36, 217, 117, 239, 231, 116, 17, 239, 206, 23, 37, 237, 94, 188, 199, 142, 21, 199, 186, 101, 242, 124, 49, 244, 186, 167, 51, 240, 31, 37, 72, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 51, 58, 57, 48, 48, 51, 47, 0, 0, 0, 0, 0, 0, 0, 32, 81, 243, 82, 121, 33, 178, 73, 226, 160, 215, 80, 213, 52, 73, 234, 173, 75, 113, 97, 21, 104, 175, 143, 130, 190, 91, 136, 242, 213, 111, 235, 102, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 54, 58, 57, 48, 48, 54, 47, 0, 0, 0, 0, 0, 0, 0, 32, 160, 219, 41, 60, 248, 44, 205, 85, 5, 195, 74, 166, 24, 87, 214, 194, 29, 110, 197, 85, 23, 130, 240, 113, 149, 229, 206, 68, 120, 244, 238, 15, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 32, 71, 158, 160, 203, 135, 103, 219, 134, 14, 143, 12, 158, 177, 55, 51, 97, 175, 38, 231, 24, 79, 234, 17, 118, 185, 51, 2, 142, 239, 245, 198, 70, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 53, 58, 57, 48, 48, 53, 47, 0, 0, 0, 0, 0, 0, 0, 32, 68, 224, 25, 5, 107, 82, 105, 204, 87, 66, 179, 158, 220, 81, 128, 168, 144, 242, 38, 49, 94, 61, 30, 92, 123, 132, 210, 35, 57, 137, 208, 23, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 55, 58, 57, 48, 48, 55, 47, 0, 0, 0, 0, 0, 0, 0, 32, 5, 66, 222, 71, 194, 114, 81, 104, 98, 186, 224, 140, 83, 241, 203, 3, 68, 57, 167, 57, 24, 79, 231, 7, 32, 141, 217, 40, 23, 178, 220, 26, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 48, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 32, 65, 247, 131, 3, 43, 61, 48, 240, 236, 217, 113, 196, 198, 215, 60, 226, 50, 134, 31, 22, 96, 253, 168, 249, 216, 52, 225, 210, 251, 64, 221, 119, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 50, 58, 57, 48, 48, 50, 47, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 49, 58, 57, 48, 48, 49, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 55, 58, 57, 48, 48, 55, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 54, 58, 57, 48, 48, 54, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 52, 58, 57, 48, 48, 52, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 50, 58, 57, 48, 48, 50, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 53, 58, 57, 48, 48, 53, 47, 0, 0, 0, 0, 0, 0, 0, 23, 104, 116, 116, 112, 115, 58, 47, 47, 49, 50, 55, 46, 48, 46, 48, 46, 51, 58, 57, 48, 48, 51, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; private byte[] dataTwo; @@ -139,7 +139,7 @@ public void toUsingSameInfoFromFixture() { final byte[] keyData = new byte[32]; byteBuffer.get(keyData); assertThat(keyData).hasSize(32) - .isEqualTo(partyInfo.getRecipients().iterator().next().getKey().getKeyBytes()); + .isEqualTo(partyInfo.getRecipients().iterator().next().getKey().getKeyBytes()); long recipientUrlLength = byteBuffer.getLong(); assertThat(recipientUrlLength).isEqualTo(21L); @@ -164,4 +164,35 @@ public void toUsingSameInfoFromFixture() { } + @Test + public void checkLengthZero() { + PartyInfoParser.checkLength(0); + //NO ERROR + } + + @Test(expected = PartyInfoParserException.class) + public void checkLengthMinusValue() { + PartyInfoParser.checkLength(-1); + } + + @Test + public void checkLengthZeroLong() { + PartyInfoParser.checkLength((long) 0); + } + + @Test(expected = PartyInfoParserException.class) + public void checkLengthMaxValue() { + PartyInfoParser.checkLength(Integer.MAX_VALUE); + } + + @Test(expected = PartyInfoParserException.class) + public void checkLengthMinusValueLong() { + PartyInfoParser.checkLength((long) -1); + } + + @Test(expected = PartyInfoParserException.class) + public void checkLengthMaxValueLong() { + PartyInfoParser.checkLength(Long.MAX_VALUE); + } + } diff --git a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoServiceTest.java b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoServiceTest.java index 1b8eea1128..fd9cdcf47c 100644 --- a/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoServiceTest.java +++ b/tessera-core/src/test/java/com/quorum/tessera/node/PartyInfoServiceTest.java @@ -70,6 +70,7 @@ public void after() { //Called in constructor verify(keyManager).getPublicKeys(); verify(configService).getServerUri(); + verify(configService,atLeast(1)).getPeers(); verify(partyInfoStore, atLeast(1)).store(any(PartyInfo.class)); verifyNoMoreInteractions(partyInfoStore); @@ -120,7 +121,7 @@ public void getRecipientURLFromPartyInfoStoreFailsIfKeyDoesntExist() { final PublicKey failingKey = PublicKey.from("otherKey".getBytes()); final Throwable throwable = catchThrowable(() -> partyInfoService.getURLFromRecipientKey(failingKey)); - assertThat(throwable).isInstanceOf(KeyNotFoundException.class).hasMessage("Recipient not found"); + assertThat(throwable).isInstanceOf(KeyNotFoundException.class).hasMessage("Recipient not found for key: "+ failingKey.encodeToBase64()); verify(partyInfoStore).getPartyInfo(); } @@ -205,7 +206,6 @@ public void autoDiscoveryDisabledUnknownPeer() { .hasMessage("Peer SomeUnknownUri not found in known peer list"); verify(configService).isDisablePeerDiscovery(); - verify(configService).getPeers(); } @@ -227,7 +227,7 @@ public void autoDiscoveryDisabledOnlyKnownKeysAdded() { verify(configService).isDisablePeerDiscovery(); - verify(configService).getPeers(); + verify(configService,times(2)).getPeers(); //check that the only added keys were from that node (and our own) final ArgumentCaptor captor = ArgumentCaptor.forClass(PartyInfo.class); @@ -263,27 +263,18 @@ public void autoDiscoveryDisabledNoIncomingPeersAdded() { Stream.of(new Party("known"), new Party("unknown")).collect(toSet()) ); + partyInfoService.updatePartyInfo(forUpdate); verify(configService).isDisablePeerDiscovery(); - verify(configService).getPeers(); + verify(configService,times(2)).getPeers(); //check that the only added keys were from that node (and our own) final ArgumentCaptor captor = ArgumentCaptor.forClass(PartyInfo.class); verify(partyInfoStore).getPartyInfo(); - verify(partyInfoStore, times(2)).store(captor.capture()); - - final List allRegisteredParties = captor - .getAllValues() - .stream() - .map(PartyInfo::getParties) - .flatMap(Set::stream) - .collect(toList()); + verify(partyInfoStore,times(2)).store(captor.capture()); - assertThat(allRegisteredParties) - .hasSize(1) - .containsExactlyInAnyOrder(new Party("http://other-node.com:8080")); } diff --git a/tessera-core/src/test/java/com/quorum/tessera/node/PartyTest.java b/tessera-core/src/test/java/com/quorum/tessera/node/PartyTest.java new file mode 100644 index 0000000000..af545fdd4f --- /dev/null +++ b/tessera-core/src/test/java/com/quorum/tessera/node/PartyTest.java @@ -0,0 +1,20 @@ + +package com.quorum.tessera.node; + +import com.quorum.tessera.node.model.Party; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Test; + + +public class PartyTest { + + @Test + public void toStringContainsUrl() { + Party party = new Party("someurl"); + + assertThat(party.toString()).contains("someurl"); + + } + + +} diff --git a/tests/acceptance-test/pom.xml b/tests/acceptance-test/pom.xml index af54337df9..822d092c24 100644 --- a/tests/acceptance-test/pom.xml +++ b/tests/acceptance-test/pom.xml @@ -9,7 +9,7 @@ com.quorum.tessera tests - 0.7 + 0.7.1-SNAPSHOT @@ -18,7 +18,7 @@ com.quorum.tessera tessera-app app - 0.7 + 0.7.1-SNAPSHOT @@ -58,7 +58,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 2.21.0 + 3.0.0-M1 false 0 diff --git a/tests/acceptance-test/src/test/java/admin/cmd/ExecutionResult.java b/tests/acceptance-test/src/test/java/admin/cmd/ExecutionResult.java new file mode 100644 index 0000000000..8386140d3c --- /dev/null +++ b/tests/acceptance-test/src/test/java/admin/cmd/ExecutionResult.java @@ -0,0 +1,40 @@ + +package admin.cmd; + +import java.util.ArrayList; +import java.util.List; + + +public class ExecutionResult { + + private int exitCode; + + private final List output = new ArrayList<>(); + + private final List errors = new ArrayList<>(); + + public int getExitCode() { + return exitCode; + } + + public void setExitCode(int exitCode) { + this.exitCode = exitCode; + } + + public void addOutputLine(String line) { + this.output.add(line); + } + + public void addErrorLine(String line) { + this.errors.add(line); + } + + public List getOutput() { + return output; + } + + public List getErrors() { + return errors; + } + +} diff --git a/tests/acceptance-test/src/test/java/admin/cmd/StartupSteps.java b/tests/acceptance-test/src/test/java/admin/cmd/StartupSteps.java new file mode 100644 index 0000000000..791aebff3d --- /dev/null +++ b/tests/acceptance-test/src/test/java/admin/cmd/StartupSteps.java @@ -0,0 +1,72 @@ +package admin.cmd; + +import com.quorum.tessera.config.Config; +import com.quorum.tessera.test.Party; +import com.quorum.tessera.test.util.ElUtil; +import cucumber.api.java8.En; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import static org.assertj.core.api.Assertions.*; + +public class StartupSteps implements En { + + public StartupSteps() { + + List partyHolder = new ArrayList<>(); + + Given("configuration file with empty public and private key values", () -> { + URL url = getClass().getResource("/empty-keys-config.json"); + + Party party = new Party("", url, "X"); + Config config = party.getConfig(); + assertThat(config.getKeys().getKeyData().get(0).getPrivateKey()).isEmpty(); + assertThat(config.getKeys().getKeyData().get(0).getPublicKey()).isEmpty(); + partyHolder.add(party); + }); + + Given("configuration file with with key paths containing empty values", () -> { + URL url = getClass().getResource("/empty-keyspath-config.json"); + Path emptyKeyFile = Files.createTempFile(UUID.randomUUID().toString(), ""); + Path ipcFile = Files.createTempFile(UUID.randomUUID().toString(), ""); + Map params = new HashMap<>(); + params.put("emptyKeyFilePath", emptyKeyFile.toAbsolutePath().toString()); + params.put("unixSocketPath", ipcFile.toAbsolutePath().toString()); + Path configFile = ElUtil.createTempFileFromTemplate(url, params); + Party party = new Party("", configFile.toUri().toURL(), "X"); + Config config = party.getConfig(); + assertThat(emptyKeyFile).exists(); + + partyHolder.add(party); + }); + + List results = new ArrayList<>(); + When("admin user executes start", () -> { + assertThat(partyHolder).hasSize(1); + Party party = partyHolder.iterator().next(); + ExecutionResult result = Utils.start(party); + results.add(result); + }); + + Then("node returns error message and exits", () -> { + assertThat(results).hasSize(1); + ExecutionResult result = results.get(0); + assertThat(result.getExitCode()).isNotEqualTo(0); + assertThat(result.getOutput()).hasSize(2); + + assertThat(result.getOutput()) + .anyMatch(m -> m.startsWith("Config validation issue: keys.keyData[0].privateKey")); + + assertThat(result.getOutput()) + .anyMatch(m -> m.startsWith("Config validation issue: keys.keyData[0].publicKey")); + + }); + + } + +} diff --git a/tests/acceptance-test/src/test/java/admin/cmd/Utils.java b/tests/acceptance-test/src/test/java/admin/cmd/Utils.java index b17ced62a4..651d0133f0 100644 --- a/tests/acceptance-test/src/test/java/admin/cmd/Utils.java +++ b/tests/acceptance-test/src/test/java/admin/cmd/Utils.java @@ -1,12 +1,15 @@ package admin.cmd; +import com.quorum.tessera.config.CommunicationType; import com.quorum.tessera.test.Party; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.UncheckedIOException; import java.util.*; import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Stream; import org.slf4j.Logger; @@ -14,21 +17,86 @@ public class Utils { - private static String jarPath = System.getProperty("application.jar", "../../tessera-app/target/tessera-app-0.7-SNAPSHOT-app.jar"); + private static String jarPath = System.getProperty("application.jar", "../../tessera-app/target/tessera-app-0.7.1-SNAPSHOT-app.jar"); private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class); + public static ExecutionResult start(Party party) throws IOException, InterruptedException { + + List args = Arrays.asList( + "java", + "-Dspring.profiles.active=disable-unixsocket,disable-sync-poller", + "-Dnode.number=" + party.getAlias(), + "-jar", + jarPath, + "-configfile", + party.getConfigFilePath().toString(), + "-server.communicationType", + CommunicationType.REST.name() + ); + + ExecutorService executorService = Executors.newCachedThreadPool(); + + ProcessBuilder processBuilder = new ProcessBuilder(args); + + processBuilder.redirectErrorStream(false); + Process process = processBuilder.start(); + + ExecutionResult executionResult = new ExecutionResult(); + + executorService.submit(() -> { + + try (BufferedReader reader = Stream.of(process.getInputStream()) + .map(InputStreamReader::new) + .map(BufferedReader::new) + .findAny().get()) { + + String line = null; + while ((line = reader.readLine()) != null) { + System.out.println(line); + executionResult.addOutputLine(line); + } + + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + + executorService.submit(() -> { + + try (BufferedReader reader = Stream.of(process.getErrorStream()) + .map(InputStreamReader::new) + .map(BufferedReader::new) + .findAny().get()) { + + String line = null; + while ((line = reader.readLine()) != null) { + System.err.println(line); + executionResult.addErrorLine(line); + } + + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + + executionResult.setExitCode(process.waitFor()); + + return executionResult; + + } + public static int addPeer(Party party, String url) throws IOException, InterruptedException { - + List args = Arrays.asList( - "java", - "-jar", - jarPath, - "-configfile", - party.getConfigFilePath().toAbsolutePath().toString(), - "admin", - "-addpeer", - url + "java", + "-jar", + jarPath, + "-configfile", + party.getConfigFilePath().toAbsolutePath().toString(), + "admin", + "-addpeer", + url ); LOGGER.info("exec : {}", String.join(" ", args)); @@ -38,13 +106,12 @@ public static int addPeer(Party party, String url) throws IOException, Interrupt Process process = processBuilder.start(); Collection streamConsumers = Arrays.asList( - new StreamConsumer(process.getErrorStream(), true), - new StreamConsumer(process.getInputStream(), false) + new StreamConsumer(process.getErrorStream(), true), + new StreamConsumer(process.getInputStream(), false) ); Executors.newCachedThreadPool().invokeAll(streamConsumers); - return process.waitFor(); } @@ -60,15 +127,14 @@ static class StreamConsumer implements Callable { this.isError = isError; } - @Override public Void call() throws Exception { try (BufferedReader reader = Stream.of(inputStream) - .map(InputStreamReader::new) - .map(BufferedReader::new) - .findAny() - .get()) { + .map(InputStreamReader::new) + .map(BufferedReader::new) + .findAny() + .get()) { String line = null; while ((line = reader.readLine()) != null) { @@ -80,7 +146,7 @@ public Void call() throws Exception { } return null; - } + } } diff --git a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/Party.java b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/Party.java index c67fcf4edb..dc19d16fa3 100644 --- a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/Party.java +++ b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/Party.java @@ -104,6 +104,10 @@ public Path getConfigFilePath() { return configFilePath; } + public Config getConfig() { + return config; + } + public List getConfiguredPeers() { return Collections.unmodifiableList(config.getPeers()); } diff --git a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/ProcessManager.java b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/ProcessManager.java index ec60d8dfef..acc00ea65b 100644 --- a/tests/acceptance-test/src/test/java/com/quorum/tessera/test/ProcessManager.java +++ b/tests/acceptance-test/src/test/java/com/quorum/tessera/test/ProcessManager.java @@ -56,7 +56,10 @@ public String findJarFilePath() { } public void startNodes() throws Exception { - for (String nodeAlias : configFiles.keySet()) { + List nodeAliases = Arrays.asList(configFiles.keySet().toArray(new String[0])); + Collections.shuffle(nodeAliases); + + for (String nodeAlias : nodeAliases) { start(nodeAlias); } } @@ -94,7 +97,7 @@ public void start(String nodeAlias) throws Exception { List args = Arrays.asList( "java", - "-Dspring.profiles.active=disable-unixsocket", + "-Dspring.profiles.active=disable-unixsocket,disable-sync-poller", "-Dnode.number=" + nodeAlias, "-Dlogback.configurationFile=" + logbackConfigFile.getFile(), "-Ddebug=true", diff --git a/tests/acceptance-test/src/test/resources/empty-keys-config.json b/tests/acceptance-test/src/test/resources/empty-keys-config.json new file mode 100644 index 0000000000..36d01e50eb --- /dev/null +++ b/tests/acceptance-test/src/test/resources/empty-keys-config.json @@ -0,0 +1,28 @@ +{ + "useWhiteList": false, + "jdbc": { + "username": "sa", + "password": "", + "url": "jdbc:h2:./target/h2/rest1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9090" + }, + "server": { + "port": 8989, + "hostName": "http://localhost" + }, + "peer": [ + { + "url": "http://localhost:8990" + } + ], + "keys": { + "passwords": [], + "keyData": [ + { + "privateKey": "", + "publicKey": "" + } + ] + }, + "alwaysSendTo": [], + "unixSocketFile": "${unixSocketPath}" +} diff --git a/tests/acceptance-test/src/test/resources/empty-keyspath-config.json b/tests/acceptance-test/src/test/resources/empty-keyspath-config.json new file mode 100644 index 0000000000..104eea5b69 --- /dev/null +++ b/tests/acceptance-test/src/test/resources/empty-keyspath-config.json @@ -0,0 +1,28 @@ +{ + "useWhiteList": false, + "jdbc": { + "username": "sa", + "password": "", + "url": "jdbc:h2:./target/h2/rest1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0;AUTO_SERVER=TRUE;AUTO_SERVER_PORT=9090" + }, + "server": { + "port": 8989, + "hostName": "http://localhost" + }, + "peer": [ + { + "url": "http://localhost:8990" + } + ], + "keys": { + "passwords": [], + "keyData": [ + { + "privateKeyPath": "${emptyKeyFilePath}", + "publicKeyPath": "${emptyKeyFilePath}" + } + ] + }, + "alwaysSendTo": [], + "unixSocketFile": "${unixSocketPath}" +} diff --git a/tests/acceptance-test/src/test/resources/features/admin.feature b/tests/acceptance-test/src/test/resources/features/admin.feature index 4a04e971b2..b7d32de717 100644 --- a/tests/acceptance-test/src/test/resources/features/admin.feature +++ b/tests/acceptance-test/src/test/resources/features/admin.feature @@ -4,3 +4,14 @@ Feature: Runtime Admin functions Given any node is running When admin user executes add peer Then a peer is added to party + + Scenario: Admin user starts node with empty key values + Given configuration file with empty public and private key values + When admin user executes start + Then node returns error message and exits + + Scenario: Admin user starts node with key paths containing empty values + Given configuration file with with key paths containing empty values + When admin user executes start + Then node returns error message and exits + diff --git a/tests/acceptance-test/src/test/resources/grpc/config2.json b/tests/acceptance-test/src/test/resources/grpc/config2.json index 850ce8c12a..e0afd49147 100644 --- a/tests/acceptance-test/src/test/resources/grpc/config2.json +++ b/tests/acceptance-test/src/test/resources/grpc/config2.json @@ -13,7 +13,7 @@ }, "peer": [ { - "url": "http://localhost:50520" + "url": "http://localhost:50522" } ], "keys": { diff --git a/tests/acceptance-test/src/test/resources/grpc/config3.json b/tests/acceptance-test/src/test/resources/grpc/config3.json index c6189b4f20..8cac2e3c58 100644 --- a/tests/acceptance-test/src/test/resources/grpc/config3.json +++ b/tests/acceptance-test/src/test/resources/grpc/config3.json @@ -13,7 +13,7 @@ }, "peer": [ { - "url": "http://localhost:50520" + "url": "http://localhost:50523" } ], "keys": { diff --git a/tests/acceptance-test/src/test/resources/grpc/config4.json b/tests/acceptance-test/src/test/resources/grpc/config4.json index 2f00c679b3..99ca58c05a 100644 --- a/tests/acceptance-test/src/test/resources/grpc/config4.json +++ b/tests/acceptance-test/src/test/resources/grpc/config4.json @@ -13,7 +13,7 @@ }, "peer": [ { - "url": "http://localhost:50520" + "url": "http://localhost:50521" } ], "keys": { diff --git a/tests/acceptance-test/src/test/resources/rest/config2.json b/tests/acceptance-test/src/test/resources/rest/config2.json index 05579d1613..7151f9ee58 100644 --- a/tests/acceptance-test/src/test/resources/rest/config2.json +++ b/tests/acceptance-test/src/test/resources/rest/config2.json @@ -11,7 +11,7 @@ }, "peer": [ { - "url": "http://localhost:8080" + "url": "http://localhost:8082" } ], "keys": { diff --git a/tests/acceptance-test/src/test/resources/rest/config3.json b/tests/acceptance-test/src/test/resources/rest/config3.json index da60aaf9cc..42ef9c13a6 100644 --- a/tests/acceptance-test/src/test/resources/rest/config3.json +++ b/tests/acceptance-test/src/test/resources/rest/config3.json @@ -11,7 +11,7 @@ }, "peer": [ { - "url": "http://localhost:8080" + "url": "http://localhost:8083" } ], "keys": { diff --git a/tests/acceptance-test/src/test/resources/rest/config4.json b/tests/acceptance-test/src/test/resources/rest/config4.json index 6cc629db31..bbfb8b3f32 100644 --- a/tests/acceptance-test/src/test/resources/rest/config4.json +++ b/tests/acceptance-test/src/test/resources/rest/config4.json @@ -11,7 +11,7 @@ }, "peer": [ { - "url": "http://localhost:8080" + "url": "http://localhost:8081" } ], "keys": { diff --git a/tests/jmeter-test/pom.xml b/tests/jmeter-test/pom.xml index f3dd51cfee..43c3fefdbc 100644 --- a/tests/jmeter-test/pom.xml +++ b/tests/jmeter-test/pom.xml @@ -5,7 +5,7 @@ com.quorum.tessera tests - 0.7-SNAPSHOT + 0.7.1-SNAPSHOT 4.0.0 @@ -71,7 +71,7 @@ org.apache.maven.plugins maven-failsafe-plugin - 2.21.0 + 3.0.0-M1 false 0 diff --git a/tests/pom.xml b/tests/pom.xml index ca0060f87a..16b4092b61 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -3,7 +3,7 @@ tessera com.quorum.tessera - 0.7 + 0.7.1-SNAPSHOT 4.0.0 diff --git a/tests/test-util/pom.xml b/tests/test-util/pom.xml index f0b4fa6fde..994c71a715 100644 --- a/tests/test-util/pom.xml +++ b/tests/test-util/pom.xml @@ -4,7 +4,7 @@ com.quorum.tessera tests - 0.7 + 0.7.1-SNAPSHOT test-util jar