From 8a2292a495c9e33601463e688246f9817abfba99 Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Fri, 28 Dec 2018 16:09:28 +0000 Subject: [PATCH 1/2] Remove unused validation classes Add pattern for matching when a password is not provided for a locked key --- .../tessera/config/JaxbConfigFactory.java | 2 +- .../com/quorum/tessera/config/KeyData.java | 6 - .../config/adapters/KeyDataAdapter.java | 4 +- .../config/constraints/Base64Validator.java | 3 +- .../constraints/InlineKeypairValidator.java | 37 ------- .../constraints/KeyDataConfigValidator.java | 37 ------- .../constraints/ValidInlineKeypair.java | 27 ----- .../constraints/ValidKeyDataConfig.java | 27 ----- .../config/keypairs/FilesystemKeyPair.java | 63 +++++++---- .../config/keypairs/InlineKeypair.java | 36 +++--- .../quorum/tessera/config/ValidationTest.java | 61 +--------- .../adapters/KeyConfigurationAdapterTest.java | 6 +- .../InlineKeypairValidatorTest.java | 89 --------------- .../KeyDataConfigValidatorTest.java | 104 ------------------ .../keypairs/FilesystemKeyPairTest.java | 1 - .../config/keypairs/InlineKeypairTest.java | 28 +++++ 16 files changed, 104 insertions(+), 427 deletions(-) delete mode 100644 config/src/main/java/com/quorum/tessera/config/constraints/InlineKeypairValidator.java delete mode 100644 config/src/main/java/com/quorum/tessera/config/constraints/KeyDataConfigValidator.java delete mode 100644 config/src/main/java/com/quorum/tessera/config/constraints/ValidInlineKeypair.java delete mode 100644 config/src/main/java/com/quorum/tessera/config/constraints/ValidKeyDataConfig.java delete mode 100644 config/src/test/java/com/quorum/tessera/config/constraints/InlineKeypairValidatorTest.java delete mode 100644 config/src/test/java/com/quorum/tessera/config/constraints/KeyDataConfigValidatorTest.java create mode 100644 config/src/test/java/com/quorum/tessera/config/keypairs/InlineKeypairTest.java diff --git a/config/src/main/java/com/quorum/tessera/config/JaxbConfigFactory.java b/config/src/main/java/com/quorum/tessera/config/JaxbConfigFactory.java index 862a193cf2..b8f9f36ae9 100644 --- a/config/src/main/java/com/quorum/tessera/config/JaxbConfigFactory.java +++ b/config/src/main/java/com/quorum/tessera/config/JaxbConfigFactory.java @@ -42,7 +42,7 @@ public Config create(final InputStream configData, final List new } else if (config.getKeys().getPasswordFile() != null) { this.createFile(config.getKeys().getPasswordFile()); Files.write(config.getKeys().getPasswordFile(), newPasswords, APPEND); - } else if (!newPasswords.stream().allMatch(""::equals)) { + } else if (!newPasswords.stream().allMatch(Objects::isNull)) { final List existingPasswords = config .getKeys() .getKeyData() diff --git a/config/src/main/java/com/quorum/tessera/config/KeyData.java b/config/src/main/java/com/quorum/tessera/config/KeyData.java index cccbed665e..3773f2e04a 100644 --- a/config/src/main/java/com/quorum/tessera/config/KeyData.java +++ b/config/src/main/java/com/quorum/tessera/config/KeyData.java @@ -1,8 +1,6 @@ package com.quorum.tessera.config; import com.quorum.tessera.config.adapters.PathAdapter; -import com.quorum.tessera.config.constraints.ValidBase64; -import com.quorum.tessera.config.constraints.ValidKeyDataConfig; import javax.validation.constraints.Pattern; import javax.xml.bind.annotation.XmlAccessType; @@ -14,13 +12,9 @@ @XmlAccessorType(XmlAccessType.FIELD) public class KeyData extends ConfigItem { - @ValidKeyDataConfig @XmlElement private KeyDataConfig config; - @ValidBase64 - @Pattern(regexp = "^((?!NACL_FAILURE).)*$", - message = "Could not decrypt the private key with the provided password, please double check the passwords provided") @XmlElement private String privateKey; diff --git a/config/src/main/java/com/quorum/tessera/config/adapters/KeyDataAdapter.java b/config/src/main/java/com/quorum/tessera/config/adapters/KeyDataAdapter.java index e64f411bce..672bf99394 100644 --- a/config/src/main/java/com/quorum/tessera/config/adapters/KeyDataAdapter.java +++ b/config/src/main/java/com/quorum/tessera/config/adapters/KeyDataAdapter.java @@ -9,7 +9,9 @@ public class KeyDataAdapter extends XmlAdapter { public static final String NACL_FAILURE_TOKEN = "NACL_FAILURE"; - + + public static final String MISSING_PASSWORD_TOKEN = "MISSING_PASSWORD"; + @Override public ConfigKeyPair unmarshal(final KeyData keyData) { diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/Base64Validator.java b/config/src/main/java/com/quorum/tessera/config/constraints/Base64Validator.java index 83425412f4..2c6384618d 100644 --- a/config/src/main/java/com/quorum/tessera/config/constraints/Base64Validator.java +++ b/config/src/main/java/com/quorum/tessera/config/constraints/Base64Validator.java @@ -1,5 +1,6 @@ package com.quorum.tessera.config.constraints; +import static com.quorum.tessera.config.adapters.KeyDataAdapter.MISSING_PASSWORD_TOKEN; import static com.quorum.tessera.config.adapters.KeyDataAdapter.NACL_FAILURE_TOKEN; import java.util.Base64; import java.util.Objects; @@ -19,7 +20,7 @@ public boolean isValid(String value, ConstraintValidatorContext cvc) { return true; } - if(value.startsWith(NACL_FAILURE_TOKEN)) { + if(value.startsWith(NACL_FAILURE_TOKEN) || value.startsWith(MISSING_PASSWORD_TOKEN)) { return true; } diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/InlineKeypairValidator.java b/config/src/main/java/com/quorum/tessera/config/constraints/InlineKeypairValidator.java deleted file mode 100644 index 154a54ef23..0000000000 --- a/config/src/main/java/com/quorum/tessera/config/constraints/InlineKeypairValidator.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.quorum.tessera.config.constraints; - -import com.quorum.tessera.config.PrivateKeyType; -import com.quorum.tessera.config.keypairs.InlineKeypair; - -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -public class InlineKeypairValidator implements ConstraintValidator { - - private ValidInlineKeypair annotation; - - @Override - public void initialize(ValidInlineKeypair annotation) { - this.annotation = annotation; - } - - @Override - public boolean isValid(InlineKeypair inlineKeypair, ConstraintValidatorContext cvc) { - - if (inlineKeypair == null) { - return true; - } - - if (inlineKeypair.getPrivateKeyConfig().getType() == null) { - return true; - } - - if (inlineKeypair.getPrivateKeyConfig().getType() == PrivateKeyType.UNLOCKED) { - return true; - } - - return !inlineKeypair.getPassword().isEmpty(); - - } - -} diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/KeyDataConfigValidator.java b/config/src/main/java/com/quorum/tessera/config/constraints/KeyDataConfigValidator.java deleted file mode 100644 index 75700b5d20..0000000000 --- a/config/src/main/java/com/quorum/tessera/config/constraints/KeyDataConfigValidator.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.quorum.tessera.config.constraints; - -import com.quorum.tessera.config.KeyDataConfig; -import com.quorum.tessera.config.PrivateKeyType; -import java.util.Objects; -import javax.validation.ConstraintValidator; -import javax.validation.ConstraintValidatorContext; - -public class KeyDataConfigValidator implements ConstraintValidator { - - private ValidKeyDataConfig annotation; - - @Override - public void initialize(ValidKeyDataConfig annotation) { - this.annotation = annotation; - } - - @Override - public boolean isValid(KeyDataConfig keyDataConfig, ConstraintValidatorContext cvc) { - - if (keyDataConfig == null) { - return true; - } - - if (keyDataConfig.getType() == null) { - return true; - } - - if (keyDataConfig.getType() == PrivateKeyType.UNLOCKED) { - return true; - } - - return Objects.nonNull(keyDataConfig.getPassword()); - - } - -} diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/ValidInlineKeypair.java b/config/src/main/java/com/quorum/tessera/config/constraints/ValidInlineKeypair.java deleted file mode 100644 index 36948b70e9..0000000000 --- a/config/src/main/java/com/quorum/tessera/config/constraints/ValidInlineKeypair.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.quorum.tessera.config.constraints; - -import javax.validation.Constraint; -import javax.validation.Payload; -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.PARAMETER; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -@Target({FIELD, PARAMETER, ANNOTATION_TYPE, ElementType.TYPE}) -@Retention(RUNTIME) -@Constraint(validatedBy = InlineKeypairValidator.class) -@Documented -public @interface ValidInlineKeypair { - - String message() default "{InlineKeyData.message}"; - - Class[] groups() default {}; - - Class[] payload() default {}; - -} diff --git a/config/src/main/java/com/quorum/tessera/config/constraints/ValidKeyDataConfig.java b/config/src/main/java/com/quorum/tessera/config/constraints/ValidKeyDataConfig.java deleted file mode 100644 index 7f0ba0c967..0000000000 --- a/config/src/main/java/com/quorum/tessera/config/constraints/ValidKeyDataConfig.java +++ /dev/null @@ -1,27 +0,0 @@ - -package com.quorum.tessera.config.constraints; - -import java.lang.annotation.Documented; -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.PARAMETER; -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}) -@Retention(RUNTIME) -@Constraint(validatedBy = KeyDataConfigValidator.class) -@Documented -public @interface ValidKeyDataConfig { - - - String message() default "{ValidKeyDataConfig.message}"; - - Class[] groups() default {}; - - Class[] payload() default {}; -} 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 581b810152..c51067e445 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,12 +2,17 @@ import com.quorum.tessera.config.KeyDataConfig; import com.quorum.tessera.config.adapters.PathAdapter; +import com.quorum.tessera.config.constraints.ValidBase64; 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; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import java.nio.file.Files; @@ -17,14 +22,16 @@ public class FilesystemKeyPair implements ConfigKeyPair { - @ValidContent(minLines = 1,maxLines = 1,message = "file expected to contain a single non empty value") + private static final Logger LOGGER = LoggerFactory.getLogger(FilesystemKeyPair.class); + + @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") + @ValidContent(minLines = 1, message = "file expected to contain at least one line") @NotNull @ValidPath(checkExists = true, message = "File does not exist") @XmlElement @@ -33,28 +40,48 @@ public class FilesystemKeyPair implements ConfigKeyPair { private InlineKeypair inlineKeypair; - private String password = ""; + private String password; public FilesystemKeyPair(final Path publicKeyPath, final Path privateKeyPath) { this.publicKeyPath = publicKeyPath; this.privateKeyPath = privateKeyPath; + + try { + loadKeys(); + } catch (final Exception ex) { + //silently discard errors as these get picked up by the validator + LOGGER.debug("Unable to read key files", ex); + } } @Override + @Size(min = 1) + @ValidBase64(message = "Invalid Base64 key provided") public String getPublicKey() { - loadKeys(); + if (this.inlineKeypair == null) { + return null; + } return this.inlineKeypair.getPublicKey(); } @Override + @Size(min = 1) + @ValidBase64(message = "Invalid Base64 key provided") + @Pattern(regexp = "^((?!NACL_FAILURE).)*$", message = "Could not decrypt the private key with the provided password, please double check the passwords provided") + @Pattern(regexp = "^((?!MISSING_PASSWORD).)*$", message = "{ValidKeyDataConfig.message}") public String getPrivateKey() { - loadKeys(); + if (this.inlineKeypair == null) { + return null; + } return this.inlineKeypair.getPrivateKey(); } @Override public void withPassword(final String password) { this.password = password; + if (this.inlineKeypair != null) { + this.inlineKeypair.withPassword(this.password); + } } @Override @@ -70,24 +97,18 @@ public Path getPrivateKeyPath() { return privateKeyPath; } - private void loadKeys() { - if(inlineKeypair == null) { - this.inlineKeypair = new InlineKeypair( - IOCallback.execute(() -> new String(Files.readAllBytes(this.publicKeyPath), UTF_8)), - JaxbUtil.unmarshal( - IOCallback.execute(() -> Files.newInputStream(privateKeyPath)), - KeyDataConfig.class - ) - ); - } - this.inlineKeypair.withPassword(this.password); - } - - //For testing only - //TODO: remove public InlineKeypair getInlineKeypair() { - loadKeys(); return inlineKeypair; } + private void loadKeys() { + this.inlineKeypair = new InlineKeypair( + IOCallback.execute(() -> new String(Files.readAllBytes(this.publicKeyPath), UTF_8)), + JaxbUtil.unmarshal( + IOCallback.execute(() -> Files.newInputStream(privateKeyPath)), + KeyDataConfig.class + ) + ); + } + } 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 1a7b902f97..b6c7ad7327 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 @@ -3,7 +3,6 @@ import com.quorum.tessera.config.KeyDataConfig; import com.quorum.tessera.config.PrivateKeyData; import com.quorum.tessera.config.constraints.ValidBase64; -import com.quorum.tessera.config.constraints.ValidInlineKeypair; import com.quorum.tessera.config.keys.KeyEncryptorFactory; import com.quorum.tessera.nacl.NaclException; @@ -12,15 +11,10 @@ import javax.xml.bind.annotation.XmlElement; 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 private final String publicKey; @@ -28,7 +22,9 @@ public class InlineKeypair implements ConfigKeyPair { @XmlElement(name = "config") private final KeyDataConfig privateKeyConfig; - private String password = ""; + private String password; + + private String cachedValue; public InlineKeypair(final String publicKey, final KeyDataConfig privateKeyConfig) { this.publicKey = publicKey; @@ -40,25 +36,39 @@ public KeyDataConfig getPrivateKeyConfig() { } @Override + @Size(min = 1) + @NotNull + @ValidBase64(message = "Invalid Base64 key provided") public String getPublicKey() { return this.publicKey; } @Override + @NotNull + @Size(min = 1) + @ValidBase64(message = "Invalid Base64 key provided") @Pattern(regexp = "^((?!NACL_FAILURE).)*$", message = "Could not decrypt the private key with the provided password, please double check the passwords provided") + @Pattern(regexp = "^((?!MISSING_PASSWORD).)*$", message = "{ValidKeyDataConfig.message}") public String getPrivateKey() { final PrivateKeyData pkd = privateKeyConfig.getPrivateKeyData(); if (privateKeyConfig.getType() == UNLOCKED) { return privateKeyConfig.getValue(); - } else { - try { - PrivateKey privateKey = KeyEncryptorFactory.create().decryptPrivateKey(pkd, password); - return privateKey.encodeToBase64(); - } catch (final NaclException ex) { - return "NACL_FAILURE"; + } + + if (this.cachedValue == null) { + if (password == null) { + this.cachedValue = "MISSING_PASSWORD"; + } else { + try { + this.cachedValue = KeyEncryptorFactory.create().decryptPrivateKey(pkd, password).encodeToBase64(); + } catch (final NaclException ex) { + this.cachedValue = "NACL_FAILURE"; + } } } + + return this.cachedValue; } @Override diff --git a/config/src/test/java/com/quorum/tessera/config/ValidationTest.java b/config/src/test/java/com/quorum/tessera/config/ValidationTest.java index 6b404a9041..fa40efd1a8 100644 --- a/config/src/test/java/com/quorum/tessera/config/ValidationTest.java +++ b/config/src/test/java/com/quorum/tessera/config/ValidationTest.java @@ -50,71 +50,14 @@ public void validateArgonOptionsAllNullAlgoHasDefaultValue() { } - @Test - public void keyDataConfigMissingPassword() { - PrivateKeyData privateKeyData = new PrivateKeyData(null, "snonce", "asalt", "sbox", mock(ArgonOptions.class), null); - KeyDataConfig keyDataConfig = new KeyDataConfig(privateKeyData, PrivateKeyType.LOCKED); - - KeyData keyData = new KeyData(); - keyData.setConfig(keyDataConfig); - keyData.setPublicKey("publicKey"); - keyData.setPrivateKey("privateKey"); - - Set> violations = validator.validate(keyData); - assertThat(violations).hasSize(1); - - ConstraintViolation violation = violations.iterator().next(); - - assertThat(violation.getMessageTemplate()).isEqualTo("{ValidKeyDataConfig.message}"); - assertThat(violation.getPropertyPath().toString()).isEqualTo("config"); - } - - @Test - public void keyDataConfigNaclFailure() { - PrivateKeyData privateKeyData = new PrivateKeyData(null, "snonce", "asalt", "sbox", mock(ArgonOptions.class), "SECRET"); - KeyDataConfig keyDataConfig = new KeyDataConfig(privateKeyData, PrivateKeyType.LOCKED); - - KeyData keyData = new KeyData(); - keyData.setConfig(keyDataConfig); - keyData.setPrivateKey("NACL_FAILURE"); - keyData.setPublicKey("publicKey"); - - Set> violations = validator.validate(keyData); - assertThat(violations).hasSize(1); - - ConstraintViolation violation = violations.iterator().next(); - - assertThat(violation.getMessageTemplate()).isEqualTo("Could not decrypt the private key with the provided password, please double check the passwords provided"); - assertThat(violation.getPropertyPath().toString()).isEqualTo("privateKey"); - } - - @Test - public void keyDataConfigInvalidBase64() { - PrivateKeyData privateKeyData = new PrivateKeyData(null, "snonce", "asalt", "sbox", mock(ArgonOptions.class), "SECRET"); - KeyDataConfig keyDataConfig = new KeyDataConfig(privateKeyData, PrivateKeyType.LOCKED); - - KeyData keyData = new KeyData(); - keyData.setConfig(keyDataConfig); - keyData.setPrivateKey("INVALID_BASE"); - keyData.setPublicKey("publicKey"); - - Set> violations = validator.validate(keyData); - assertThat(violations).hasSize(1); - - ConstraintViolation violation = violations.iterator().next(); - - assertThat(violation.getMessageTemplate()).isEqualTo("{ValidBase64.message}"); - assertThat(violation.getPropertyPath().toString()).isEqualTo("privateKey"); - } - @Test public void inlineKeyPairNoPasswordProvided() { KeyDataConfig keyConfig = mock(KeyDataConfig.class); when(keyConfig.getType()).thenReturn(PrivateKeyType.LOCKED); - when(keyConfig.getValue()).thenReturn(""); + when(keyConfig.getValue()).thenReturn(null); InlineKeypair spy = Mockito.spy(new InlineKeypair("validkey", keyConfig)); - doReturn("validkey").when(spy).getPrivateKey(); + doReturn("MISSING_PASSWORD").when(spy).getPrivateKey(); KeyConfiguration keyConfiguration = new KeyConfiguration(null, null, singletonList(spy), null, null); diff --git a/config/src/test/java/com/quorum/tessera/config/adapters/KeyConfigurationAdapterTest.java b/config/src/test/java/com/quorum/tessera/config/adapters/KeyConfigurationAdapterTest.java index c978f65e70..3d7335a31b 100644 --- a/config/src/test/java/com/quorum/tessera/config/adapters/KeyConfigurationAdapterTest.java +++ b/config/src/test/java/com/quorum/tessera/config/adapters/KeyConfigurationAdapterTest.java @@ -41,7 +41,7 @@ public void emptyPasswordsReturnsSameKeys() { final ConfigKeyPair returned = configuration.getKeyData().get(0); //passwords are always non-null, set to empty string if not present or not needed - assertThat(returned.getPassword()).isEqualTo(""); + assertThat(returned.getPassword()).isNull(); assertThat(returned).isSameAs(keypair); } @@ -58,7 +58,7 @@ public void noPasswordsReturnsSameKeys() { final ConfigKeyPair returned = configuration.getKeyData().get(0); //passwords are always non-null, set to empty string if not present or not needed - assertThat(returned.getPassword()).isEqualTo(""); + assertThat(returned.getPassword()).isNull(); assertThat(returned).isSameAs(keypair); } @@ -89,7 +89,7 @@ public void unreadablePasswordFileGivesNoPasswords() throws IOException { assertThat(configuration.getKeyData()).hasSize(1); final ConfigKeyPair returned = configuration.getKeyData().get(0); - assertThat(returned.getPassword()).isEqualTo(""); + assertThat(returned.getPassword()).isNull(); } diff --git a/config/src/test/java/com/quorum/tessera/config/constraints/InlineKeypairValidatorTest.java b/config/src/test/java/com/quorum/tessera/config/constraints/InlineKeypairValidatorTest.java deleted file mode 100644 index 67e6558cab..0000000000 --- a/config/src/test/java/com/quorum/tessera/config/constraints/InlineKeypairValidatorTest.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.quorum.tessera.config.constraints; - -import com.quorum.tessera.config.KeyDataConfig; -import com.quorum.tessera.config.PrivateKeyType; -import com.quorum.tessera.config.keypairs.InlineKeypair; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import javax.validation.ConstraintValidatorContext; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; - -public class InlineKeypairValidatorTest { - - private InlineKeypairValidator validator = new InlineKeypairValidator(); - - private ValidInlineKeypair validInlineKeypair = mock(ValidInlineKeypair.class); - - private ConstraintValidatorContext constraintValidatorContext; - - @Before - public void onSetUp() { - this.constraintValidatorContext = mock(ConstraintValidatorContext.class); - this.validator.initialize(validInlineKeypair); - } - - @After - public void onTearDown() { - verifyZeroInteractions(constraintValidatorContext); - } - - - @Test - public void unlockedReturnsTrue() { - - InlineKeypair keyDataConfig = mock(InlineKeypair.class); - KeyDataConfig keyData = mock(KeyDataConfig.class); - when(keyDataConfig.getPrivateKeyConfig()).thenReturn(keyData); - when(keyDataConfig.getPrivateKeyConfig().getType()).thenReturn(PrivateKeyType.UNLOCKED); - - assertThat(validator.isValid(keyDataConfig, constraintValidatorContext)).isTrue(); - - } - - @Test - public void nullTypeReturnTrue() { - - InlineKeypair keyDataConfig = mock(InlineKeypair.class); - KeyDataConfig keyData = mock(KeyDataConfig.class); - when(keyDataConfig.getPrivateKeyConfig()).thenReturn(keyData); - - assertThat(validator.isValid(keyDataConfig, constraintValidatorContext)).isTrue(); - - } - - @Test - public void nullConfigReturnsTrue() { - - assertThat(validator.isValid(null, constraintValidatorContext)).isTrue(); - - } - - @Test - public void lockedWithNullPasswordIsInvalid() { - - InlineKeypair keyDataConfig = mock(InlineKeypair.class); - KeyDataConfig keyData = mock(KeyDataConfig.class); - when(keyDataConfig.getPrivateKeyConfig()).thenReturn(keyData); - when(keyDataConfig.getPassword()).thenReturn(""); - when(keyDataConfig.getPrivateKeyConfig().getType()).thenReturn(PrivateKeyType.LOCKED); - - assertThat(validator.isValid(keyDataConfig, constraintValidatorContext)).isFalse(); - - } - - @Test - public void lockedWithPasswordIsValid() { - - InlineKeypair keyDataConfig = mock(InlineKeypair.class); - KeyDataConfig keyData = mock(KeyDataConfig.class); - when(keyDataConfig.getPrivateKeyConfig()).thenReturn(keyData); - when(keyDataConfig.getPrivateKeyConfig().getType()).thenReturn(PrivateKeyType.LOCKED); - when(keyDataConfig.getPassword()).thenReturn("SECRET"); - assertThat(validator.isValid(keyDataConfig, constraintValidatorContext)).isTrue(); - - } -} diff --git a/config/src/test/java/com/quorum/tessera/config/constraints/KeyDataConfigValidatorTest.java b/config/src/test/java/com/quorum/tessera/config/constraints/KeyDataConfigValidatorTest.java deleted file mode 100644 index ff0d7a8b5a..0000000000 --- a/config/src/test/java/com/quorum/tessera/config/constraints/KeyDataConfigValidatorTest.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.quorum.tessera.config.constraints; - -import com.quorum.tessera.config.KeyDataConfig; -import com.quorum.tessera.config.PrivateKeyType; -import javax.validation.ConstraintValidatorContext; -import static org.assertj.core.api.Assertions.assertThat; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class KeyDataConfigValidatorTest { - - private ConstraintValidatorContext constraintValidatorContext; - - @Before - public void onSetUp() { - constraintValidatorContext = mock(ConstraintValidatorContext.class); - } - - @After - public void onTearDown() { - verifyZeroInteractions(constraintValidatorContext); - } - - - @Test - public void unlockedReturnsTrue() { - - - KeyDataConfigValidator validator = new KeyDataConfigValidator(); - - ValidKeyDataConfig validKeyDataConfig = mock(ValidKeyDataConfig.class); - - validator.initialize(validKeyDataConfig); - - KeyDataConfig keyDataConfig = mock(KeyDataConfig.class); - when(keyDataConfig.getType()).thenReturn(PrivateKeyType.UNLOCKED); - - assertThat(validator.isValid(keyDataConfig, constraintValidatorContext)).isTrue(); - - } - - @Test - public void nullTypeReturnTrue() { - - - KeyDataConfigValidator validator = new KeyDataConfigValidator(); - - ValidKeyDataConfig validKeyDataConfig = mock(ValidKeyDataConfig.class); - - validator.initialize(validKeyDataConfig); - - KeyDataConfig keyDataConfig = mock(KeyDataConfig.class); - - assertThat(validator.isValid(keyDataConfig, constraintValidatorContext)).isTrue(); - - } - - @Test - public void nullConfigReturnsTrue() { - - KeyDataConfigValidator validator = new KeyDataConfigValidator(); - - ValidKeyDataConfig validKeyDataConfig = mock(ValidKeyDataConfig.class); - - validator.initialize(validKeyDataConfig); - - assertThat(validator.isValid(null, constraintValidatorContext)).isTrue(); - - } - - @Test - public void lockedWithNullPasswordIsInvalid() { - - KeyDataConfigValidator validator = new KeyDataConfigValidator(); - - ValidKeyDataConfig validKeyDataConfig = mock(ValidKeyDataConfig.class); - validator.initialize(validKeyDataConfig); - - KeyDataConfig keyDataConfig = mock(KeyDataConfig.class); - when(keyDataConfig.getType()).thenReturn(PrivateKeyType.LOCKED); - - assertThat(validator.isValid(keyDataConfig, constraintValidatorContext)).isFalse(); - - } - - @Test - public void lockedWithPasswordIsValid() { - - KeyDataConfigValidator validator = new KeyDataConfigValidator(); - - ValidKeyDataConfig validKeyDataConfig = mock(ValidKeyDataConfig.class); - validator.initialize(validKeyDataConfig); - - KeyDataConfig keyDataConfig = mock(KeyDataConfig.class); - when(keyDataConfig.getType()).thenReturn(PrivateKeyType.LOCKED); - when(keyDataConfig.getPassword()).thenReturn("SECRET"); - assertThat(validator.isValid(keyDataConfig, constraintValidatorContext)).isTrue(); - - } -} diff --git a/config/src/test/java/com/quorum/tessera/config/keypairs/FilesystemKeyPairTest.java b/config/src/test/java/com/quorum/tessera/config/keypairs/FilesystemKeyPairTest.java index 3812b20757..970f37a902 100644 --- a/config/src/test/java/com/quorum/tessera/config/keypairs/FilesystemKeyPairTest.java +++ b/config/src/test/java/com/quorum/tessera/config/keypairs/FilesystemKeyPairTest.java @@ -31,7 +31,6 @@ public void getInlineKeypairReturnsKeysReadFromFile() throws Exception { Path pubFile = Files.createTempFile(UUID.randomUUID().toString(), ".pub"); Path privFile = Paths.get(getClass().getResource("/unlockedprivatekey.json").toURI()); - pubFile.toFile().deleteOnExit(); String pub = "public"; Files.write(pubFile, pub.getBytes()); diff --git a/config/src/test/java/com/quorum/tessera/config/keypairs/InlineKeypairTest.java b/config/src/test/java/com/quorum/tessera/config/keypairs/InlineKeypairTest.java new file mode 100644 index 0000000000..9bd1bea30e --- /dev/null +++ b/config/src/test/java/com/quorum/tessera/config/keypairs/InlineKeypairTest.java @@ -0,0 +1,28 @@ +package com.quorum.tessera.config.keypairs; + +import com.quorum.tessera.config.KeyDataConfig; +import com.quorum.tessera.config.PrivateKeyData; +import com.quorum.tessera.config.PrivateKeyType; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class InlineKeypairTest { + + @Test + public void missingPasswordGetsCorrectFailureToken() { + + //even though its an unlocked key, we have specified it as locked + //so a locked key + missing password is picked up + + final KeyDataConfig privKeyDataConfig = new KeyDataConfig( + new PrivateKeyData("Wl+xSyXVuuqzpvznOS7dOobhcn4C5auxkFRi7yLtgtA=", null, null, null, null, null), + PrivateKeyType.LOCKED + ); + + final InlineKeypair result = new InlineKeypair("public", privKeyDataConfig); + + assertThat(result.getPrivateKey()).isEqualTo("MISSING_PASSWORD"); + } + +} From d12b5972a31d40d70f86994c296856627217cfa3 Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Fri, 28 Dec 2018 16:13:52 +0000 Subject: [PATCH 2/2] Update message name --- .../com/quorum/tessera/config/keypairs/FilesystemKeyPair.java | 2 +- .../java/com/quorum/tessera/config/keypairs/InlineKeypair.java | 2 +- config/src/main/resources/ValidationMessages.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 c51067e445..25c82e2e10 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 @@ -68,7 +68,7 @@ public String getPublicKey() { @Size(min = 1) @ValidBase64(message = "Invalid Base64 key provided") @Pattern(regexp = "^((?!NACL_FAILURE).)*$", message = "Could not decrypt the private key with the provided password, please double check the passwords provided") - @Pattern(regexp = "^((?!MISSING_PASSWORD).)*$", message = "{ValidKeyDataConfig.message}") + @Pattern(regexp = "^((?!MISSING_PASSWORD).)*$", message = "{InlineKeyData.missingPassword.message}") public String getPrivateKey() { if (this.inlineKeypair == null) { return null; 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 b6c7ad7327..514303a9c9 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 @@ -48,7 +48,7 @@ public String getPublicKey() { @Size(min = 1) @ValidBase64(message = "Invalid Base64 key provided") @Pattern(regexp = "^((?!NACL_FAILURE).)*$", message = "Could not decrypt the private key with the provided password, please double check the passwords provided") - @Pattern(regexp = "^((?!MISSING_PASSWORD).)*$", message = "{ValidKeyDataConfig.message}") + @Pattern(regexp = "^((?!MISSING_PASSWORD).)*$", message = "{InlineKeyData.missingPassword.message}") public String getPrivateKey() { final PrivateKeyData pkd = privateKeyConfig.getPrivateKeyData(); diff --git a/config/src/main/resources/ValidationMessages.properties b/config/src/main/resources/ValidationMessages.properties index 1abe27bf2c..458bd9f23d 100644 --- a/config/src/main/resources/ValidationMessages.properties +++ b/config/src/main/resources/ValidationMessages.properties @@ -18,7 +18,7 @@ UnsupportedKeyPair.bothInlineKeysRequired.message=Invalid inline key-pair. Ensur UnsupportedKeyPair.bothAzureKeysRequired.message=Invalid Azure Key Vault key-pair. Ensure that both the public key ID and private key ID for the key-pair have been provided. UnsupportedKeyPair.allHashicorpKeyDataRequired.message=Invalid Hashicorp Key Vault key-pair. Ensure that the secret name, secret engine name, public key ID and private key ID for the key-pair have been provided. UnsupportedKeyPair.bothFilesystemKeysRequired.message=Invalid filesystem key-pair. Ensure that both the public key path and private key path for the key-pair have been provided. -ValidKeyDataConfig.message=A locked key was provided without a password.\n Please ensure the same number of passwords are provided as there are keys and remember to include empty passwords for unlocked keys +InlineKeyData.missingPassword.message=A locked key was provided without a password.\n Please ensure the same number of passwords are provided as there are keys and remember to include empty passwords for unlocked keys InlineKeyData.message=A locked key was provided without a password.\n Please ensure the same number of passwords are provided as there are keys and remember to include empty passwords for unlocked keys AzureVaultKeyData.message=Only one key version was provided for the Azure vault key pair. Either set the version for both the public and private key, or leave both unset ValidKeyConfiguration.message=A password file and inline passwords were provided. Please choose one or the other