From c0970da4e6646729bd0d69ce51c26f4a5c8c6b90 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 5 Oct 2017 14:22:25 +0200 Subject: [PATCH] Adapt Vault API changes in transit key value/configuration objects. We now support min encryption/decryption versions via key configuration and expose these along with key capabilities through VaultTransitKey and VaultTransitKeyConfiguration. Closes gh-124. --- .../vault/core/VaultTransitTemplate.java | 41 ++++++++++- .../vault/support/VaultTransitKey.java | 42 +++++++++-- .../support/VaultTransitKeyConfiguration.java | 70 +++++++++++++++---- .../VaultTransitTemplateIntegrationTests.java | 37 +++++++++- 4 files changed, 165 insertions(+), 25 deletions(-) diff --git a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java index 73ef8d57..12c15fd9 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/core/VaultTransitTemplate.java @@ -440,6 +440,9 @@ public class VaultTransitTemplate implements VaultTransitOperations { @Data static class VaultTransitKeyImpl implements VaultTransitKey { + @Nullable + private String name; + @JsonProperty("cipher_mode") private String cipherMode = ""; @@ -457,13 +460,25 @@ public class VaultTransitTemplate implements VaultTransitOperations { private Map keys = Collections.emptyMap(); @JsonProperty("latest_version") - private boolean latestVersion; + private int latestVersion; @JsonProperty("min_decryption_version") private int minDecryptionVersion; - @Nullable - private String name; + @JsonProperty("min_encryption_version") + private int minEncryptionVersion; + + @JsonProperty("supports_decryption") + private boolean supportsDecryption; + + @JsonProperty("supports_encryption") + private boolean supportsEncryption; + + @JsonProperty("supports_derivation") + private boolean supportsDerivation; + + @JsonProperty("supports_signing") + private boolean supportsSigning; @Override public String getType() { @@ -474,6 +489,26 @@ public class VaultTransitTemplate implements VaultTransitOperations { return this.cipherMode; } + + @Override + public boolean supportsDecryption() { + return isSupportsDecryption(); + } + + @Override + public boolean supportsEncryption() { + return isSupportsEncryption(); + } + + @Override + public boolean supportsDerivation() { + return isSupportsDerivation(); + } + + @Override + public boolean supportsSigning() { + return isSupportsSigning(); + } } @Data diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKey.java b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKey.java index 31b1ade4..76045da8 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKey.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKey.java @@ -25,6 +25,16 @@ import java.util.Map; */ public interface VaultTransitKey { + /** + * @return name of the key + */ + String getName(); + + /** + * @return the key type ({@code aes-gcm}, {@code ecdsa-p256}, ...). + */ + String getType(); + /** * @return {@literal true} if deletion of the key is allowed. Key deletion must be * turned on to make keys deletable. @@ -47,9 +57,9 @@ public interface VaultTransitKey { Map getKeys(); /** - * @return {@literal true} if the key represents the latest version. + * @return the latest key version. */ - boolean isLatestVersion(); + int getLatestVersion(); /** * @return required key version to still be able to decrypt data. @@ -57,12 +67,32 @@ public interface VaultTransitKey { int getMinDecryptionVersion(); /** - * @return name of the key + * @return required key version to encrypt data. + * @since 1.1 */ - String getName(); + int getMinEncryptionVersion(); /** - * @return the key type ({@code aes-gcm}, {@code ecdsa-p256}, ...). + * @return whether the key supports decryption. + * @since 1.1 */ - String getType(); + boolean supportsDecryption(); + + /** + * @return whether the key supports encryption. + * @since 1.1 + */ + boolean supportsEncryption(); + + /** + * @return whether the key supports derivation. + * @since 1.1 + */ + boolean supportsDerivation(); + + /** + * @return whether the key supports signing. + * @since 1.1 + */ + boolean supportsSigning(); } diff --git a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyConfiguration.java b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyConfiguration.java index 598adad2..cc43d46c 100644 --- a/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyConfiguration.java +++ b/spring-vault-core/src/main/java/org/springframework/vault/support/VaultTransitKeyConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,15 +30,20 @@ public class VaultTransitKeyConfiguration { @Nullable private final Boolean deletionAllowed; - @JsonProperty("latest_version") + @JsonProperty("min_decryption_version") @Nullable - private final Integer latestVersion; + private final Integer minDecryptionVersion; + + @JsonProperty("min_encryption_version") + @Nullable + private final Integer minEncryptionVersion; private VaultTransitKeyConfiguration(@Nullable Boolean deletionAllowed, - @Nullable Integer latestVersion) { + @Nullable Integer minDecryptionVersion, @Nullable Integer minEncryptionVersion) { this.deletionAllowed = deletionAllowed; - this.latestVersion = latestVersion; + this.minDecryptionVersion = minDecryptionVersion; + this.minEncryptionVersion = minEncryptionVersion; } /** @@ -57,11 +62,22 @@ public class VaultTransitKeyConfiguration { } /** - * @return latest key version + * @return the minimum version of ciphertext allowed to be decrypted. + * @since 1.1 */ @Nullable - public Integer getLatestVersion() { - return latestVersion; + public Integer getMinDecryptionVersion() { + return minDecryptionVersion; + } + + /** + * @return the minimum version of the key that can be used to encrypt plaintext, sign + * payloads, or generate HMACs. + * @since 1.1 + */ + @Nullable + public Integer getMinEncryptionVersion() { + return minEncryptionVersion; } /** @@ -73,7 +89,10 @@ public class VaultTransitKeyConfiguration { private Boolean deletionAllowed; @Nullable - private Integer latestVersion; + private Integer minDecryptionVersion; + + @Nullable + private Integer minEncryptionVersion; VaultTransitKeyConfigurationBuilder() { } @@ -90,13 +109,35 @@ public class VaultTransitKeyConfiguration { } /** - * Set the latest key version. + * Specifies the minimum version of ciphertext allowed to be decrypted. Adjusting + * this as part of a key rotation policy can prevent old copies of ciphertext from + * being decrypted, should they fall into the wrong hands. For signatures, this + * value controls the minimum version of signature that can be verified against. + * For HMACs, this controls the minimum version of a key allowed to be used as the + * key for verification. * - * @param latestVersion key version. + * @param minDecryptionVersion key version. * @return {@code this} {@link VaultTransitKeyConfigurationBuilder}. + * @since 1.1 */ - public VaultTransitKeyConfigurationBuilder latestVersion(int latestVersion) { - this.latestVersion = latestVersion; + public VaultTransitKeyConfigurationBuilder minDecryptionVersion( + int minDecryptionVersion) { + this.minDecryptionVersion = minDecryptionVersion; + return this; + } + + /** + * Specifies the minimum version of the key that can be used to encrypt plaintext, + * sign payloads, or generate HMACs. Must be 0 (which will use the latest version) + * or a value greater or equal to {@link #minDecryptionVersion(int)}. + * + * @param minEncryptionVersion key version. + * @return {@code this} {@link VaultTransitKeyConfigurationBuilder}. + * @since 1.1 + */ + public VaultTransitKeyConfigurationBuilder minEncryptionVersion( + int minEncryptionVersion) { + this.minEncryptionVersion = minEncryptionVersion; return this; } @@ -106,7 +147,8 @@ public class VaultTransitKeyConfiguration { * @return a new {@link VaultTransitKeyConfiguration}. */ public VaultTransitKeyConfiguration build() { - return new VaultTransitKeyConfiguration(deletionAllowed, latestVersion); + return new VaultTransitKeyConfiguration(deletionAllowed, + minDecryptionVersion, minEncryptionVersion); } } } diff --git a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java index 8b6ee37e..2a4ce877 100644 --- a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java +++ b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTransitTemplateIntegrationTests.java @@ -130,7 +130,15 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport assertThat(mykey.isDeletionAllowed()).isFalse(); assertThat(mykey.isDerived()).isFalse(); assertThat(mykey.getMinDecryptionVersion()).isEqualTo(1); - assertThat(mykey.isLatestVersion()).isTrue(); + assertThat(mykey.getLatestVersion()).isEqualTo(1); + + if (vaultVersion.isGreaterThanOrEqualTo(Version.parse("0.7.0"))) { + + assertThat(mykey.supportsDecryption()).isTrue(); + assertThat(mykey.supportsEncryption()).isTrue(); + assertThat(mykey.supportsDerivation()).isTrue(); + assertThat(mykey.supportsSigning()).isFalse(); + } } @Test @@ -181,7 +189,32 @@ public class VaultTransitTemplateIntegrationTests extends IntegrationTestSupport assertThat(mykey.isDeletionAllowed()).isFalse(); assertThat(mykey.isDerived()).isTrue(); assertThat(mykey.getMinDecryptionVersion()).isEqualTo(1); - assertThat(mykey.isLatestVersion()).isTrue(); + assertThat(mykey.getLatestVersion()).isEqualTo(1); + } + + @Test + public void shouldConfigureKey() { + + transitOperations.createKey("mykey"); + transitOperations.rotate("mykey"); + transitOperations.rotate("mykey"); + + VaultTransitKeyConfiguration configuration = VaultTransitKeyConfiguration + .builder().deletionAllowed(true).minDecryptionVersion(1) + .minEncryptionVersion(2).build(); + + transitOperations.configureKey("mykey", configuration); + + VaultTransitKey mykey = transitOperations.getKey("mykey"); + + assertThat(mykey.getMinDecryptionVersion()).isEqualTo(1); + + if (vaultVersion.isGreaterThanOrEqualTo(Version.parse("0.8.0"))) { + assertThat(mykey.getMinEncryptionVersion()).isEqualTo(2); + } + else { + assertThat(mykey.getMinEncryptionVersion()).isEqualTo(0); + } } @Test