Polishing.

Rename VaultExportKeyTypes to TransitKeyType, rename VaultTransitKeyExport to RawTransitKey. Reorder methods. Extend year range in license header. Remove Exception declaration from integration tests.

Add guards to tests for versions not supporting key export.

Original pull request: gh-101.
This commit is contained in:
Mark Paluch
2017-06-11 17:18:32 +02:00
parent 95848940e2
commit 6c192d4942
7 changed files with 93 additions and 102 deletions

View File

@@ -17,12 +17,12 @@ package org.springframework.vault.core;
import java.util.List; import java.util.List;
import org.springframework.vault.support.VaultExportKeyTypes; import org.springframework.vault.support.TransitKeyType;
import org.springframework.vault.support.VaultTransitContext; import org.springframework.vault.support.VaultTransitContext;
import org.springframework.vault.support.VaultTransitKey; import org.springframework.vault.support.VaultTransitKey;
import org.springframework.vault.support.VaultTransitKeyConfiguration; import org.springframework.vault.support.VaultTransitKeyConfiguration;
import org.springframework.vault.support.VaultTransitKeyCreationRequest; import org.springframework.vault.support.VaultTransitKeyCreationRequest;
import org.springframework.vault.support.VaultTransitKeyExport; import org.springframework.vault.support.RawTransitKey;
/** /**
* Interface that specifies operations using the {@code transit} backend. * Interface that specifies operations using the {@code transit} backend.
@@ -66,6 +66,17 @@ public interface VaultTransitOperations {
*/ */
void configureKey(String keyName, VaultTransitKeyConfiguration keyConfiguration); void configureKey(String keyName, VaultTransitKeyConfiguration keyConfiguration);
/**
* Returns the value of the named encryption key. Depending on the type of key,
* different information may be returned. The key must be exportable to support this
* operation.
*
* @param keyName must not be empty or {@literal null}.
* @param type must not be {@literal null}.
* @return the {@link RawTransitKey}.
*/
RawTransitKey exportKey(String keyName, TransitKeyType type);
/** /**
* Return information about a named encryption key. * Return information about a named encryption key.
* *
@@ -82,18 +93,6 @@ public interface VaultTransitOperations {
*/ */
void deleteKey(String keyName); void deleteKey(String keyName);
/**
* Returns the value of the named encryption key. Depending on the type of key,
* different information may be returned. The key must be exportable to support this
* operation.
*
* @param keyName must not be empty or {@literal null}.
* @param vaultExportKeyTypes must not be {@literal null}.
* @return the {@link VaultTransitKeyExport}.
*/
VaultTransitKeyExport exportKey(String keyName,
VaultExportKeyTypes vaultExportKeyTypes);
/** /**
* Rotates the version of the named key. After rotation, new plaintext requests will * Rotates the version of the named key. After rotation, new plaintext requests will
* be encrypted with the new version of the key. To upgrade ciphertext to be encrypted * be encrypted with the new version of the key. To upgrade ciphertext to be encrypted

View File

@@ -25,14 +25,14 @@ import lombok.Data;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.Base64Utils; import org.springframework.util.Base64Utils;
import org.springframework.vault.support.VaultExportKeyTypes; import org.springframework.vault.support.TransitKeyType;
import org.springframework.vault.support.VaultResponse; import org.springframework.vault.support.VaultResponse;
import org.springframework.vault.support.VaultResponseSupport; import org.springframework.vault.support.VaultResponseSupport;
import org.springframework.vault.support.VaultTransitContext; import org.springframework.vault.support.VaultTransitContext;
import org.springframework.vault.support.VaultTransitKey; import org.springframework.vault.support.VaultTransitKey;
import org.springframework.vault.support.VaultTransitKeyConfiguration; import org.springframework.vault.support.VaultTransitKeyConfiguration;
import org.springframework.vault.support.VaultTransitKeyCreationRequest; import org.springframework.vault.support.VaultTransitKeyCreationRequest;
import org.springframework.vault.support.VaultTransitKeyExport; import org.springframework.vault.support.RawTransitKey;
/** /**
* Default implementation of {@link VaultTransitOperations}. * Default implementation of {@link VaultTransitOperations}.
@@ -64,8 +64,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
} }
@Override @Override
public void createKey(String keyName, public void createKey(String keyName, VaultTransitKeyCreationRequest createKeyRequest) {
VaultTransitKeyCreationRequest createKeyRequest) {
Assert.hasText(keyName, "KeyName must not be empty"); Assert.hasText(keyName, "KeyName must not be empty");
Assert.notNull(createKeyRequest, Assert.notNull(createKeyRequest,
@@ -78,16 +77,15 @@ public class VaultTransitTemplate implements VaultTransitOperations {
@Override @Override
public List<String> getKeys() { public List<String> getKeys() {
VaultResponse response = vaultOperations VaultResponse response = vaultOperations.read(String.format("%s/keys?list=true",
.read(String.format("%s/keys?list=true", path)); path));
return response == null ? Collections.emptyList() : (List) response.getData() return response == null ? Collections.emptyList() : (List) response.getData()
.get("keys"); .get("keys");
} }
@Override @Override
public void configureKey(String keyName, public void configureKey(String keyName, VaultTransitKeyConfiguration keyConfiguration) {
VaultTransitKeyConfiguration keyConfiguration) {
Assert.hasText(keyName, "KeyName must not be empty"); Assert.hasText(keyName, "KeyName must not be empty");
Assert.notNull(keyConfiguration, "VaultKeyConfiguration must not be empty"); Assert.notNull(keyConfiguration, "VaultKeyConfiguration must not be empty");
@@ -96,6 +94,19 @@ public class VaultTransitTemplate implements VaultTransitOperations {
keyConfiguration); keyConfiguration);
} }
@Override
public RawTransitKey exportKey(String keyName, TransitKeyType type) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.notNull(type, "Key type must not be null");
VaultResponseSupport<RawTransitKeyImpl> result = vaultOperations.read(
String.format("%s/export/%s/%s", path, type.getValue(), keyName),
RawTransitKeyImpl.class);
return result != null ? result.getData() : null;
}
@Override @Override
public VaultTransitKey getKey(String keyName) { public VaultTransitKey getKey(String keyName) {
@@ -119,25 +130,6 @@ public class VaultTransitTemplate implements VaultTransitOperations {
vaultOperations.delete(String.format("%s/keys/%s", path, keyName)); vaultOperations.delete(String.format("%s/keys/%s", path, keyName));
} }
@Override
public VaultTransitKeyExport exportKey(String keyName,
VaultExportKeyTypes vaultExportKeyType) {
Assert.hasText(keyName, "KeyName must not be empty");
Assert.notNull(vaultExportKeyType, "vaultExportKeyTypes must not be null");
VaultResponseSupport<VaultTransitKeyExportImpl> result = vaultOperations.read(
String.format("%s/export/%s/%s", path,
vaultExportKeyType.getValue(), keyName),
VaultTransitKeyExportImpl.class);
if (result != null) {
return result.getData();
}
return null;
}
@Override @Override
public void rotate(String keyName) { public void rotate(String keyName) {
@@ -302,15 +294,13 @@ public class VaultTransitTemplate implements VaultTransitOperations {
return this.cipherMode; return this.cipherMode;
} }
} }
@Data @Data
static class VaultTransitKeyExportImpl implements VaultTransitKeyExport { static class RawTransitKeyImpl implements RawTransitKey {
private Map<String, String> keys; private Map<String, String> keys;
private String name; private String name;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2016 the original author or authors. * Copyright 2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -22,7 +22,7 @@ import java.util.Map;
* *
* @author Sven Schürmann * @author Sven Schürmann
*/ */
public interface VaultTransitKeyExport { public interface RawTransitKey {
/** /**
* @return a {@link Map} of key version to its key value. * @return a {@link Map} of key version to its key value.
@@ -33,5 +33,4 @@ public interface VaultTransitKeyExport {
* @return name of the key * @return name of the key
*/ */
String getName(); String getName();
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2016 the original author or authors. * Copyright 2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -15,21 +15,21 @@
*/ */
package org.springframework.vault.support; package org.springframework.vault.support;
import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
/** /**
* Enumeration to specify the type of the key to export. Intended for use * Enumeration to specify the type of the transit key. Intended for use with
* with {@link org.springframework.vault.core.VaultTransitTemplate} * {@link org.springframework.vault.core.VaultTransitOperations}
* *
* @author Sven Schürmann * @author Sven Schürmann
* @author Mark Paluch
*/ */
@AllArgsConstructor @Getter
public enum VaultExportKeyTypes { @RequiredArgsConstructor
public enum TransitKeyType {
ENCRYPTION_KEY("encryption-key"), SIGNING_KEY("signing-key"), HMAC_KEY("hmac-key"); ENCRYPTION_KEY("encryption-key"), SIGNING_KEY("signing-key"), HMAC_KEY("hmac-key");
@Getter
String value;
final String value;
} }

View File

@@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.

View File

@@ -21,7 +21,7 @@ import org.springframework.util.Assert;
/** /**
* Transit backend key creation request options. * Transit backend key creation request options.
* *
* @author Mark Paluch * @author Mark Paluch
* @author Sven Schürmann * @author Sven Schürmann
*/ */
@@ -114,7 +114,7 @@ public class VaultTransitKeyCreationRequest {
/** /**
* Configure key derivation. * Configure key derivation.
* *
* @param derived {@literal true} if key derivation MUST be used. If enabled, all * @param derived {@literal true} if key derivation MUST be used. If enabled, all
* encrypt/decrypt requests to this named key must provide a context which is used * encrypt/decrypt requests to this named key must provide a context which is used
* for key derivation. Defaults to {@literal false}. * for key derivation. Defaults to {@literal false}.
@@ -136,6 +136,7 @@ public class VaultTransitKeyCreationRequest {
*/ */
public VaultTransitKeyCreationRequestBuilder convergentEncryption( public VaultTransitKeyCreationRequestBuilder convergentEncryption(
boolean convergentEncryption) { boolean convergentEncryption) {
this.convergentEncryption = convergentEncryption; this.convergentEncryption = convergentEncryption;
return this; return this;
} }
@@ -163,8 +164,8 @@ public class VaultTransitKeyCreationRequest {
Assert.hasText(type, "Type must not be empty"); Assert.hasText(type, "Type must not be empty");
return new VaultTransitKeyCreationRequest(derived, type, convergentEncryption, return new VaultTransitKeyCreationRequest(derived, type,
exportable); convergentEncryption, exportable);
} }
} }
} }

View File

@@ -28,17 +28,18 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.vault.VaultException; import org.springframework.vault.VaultException;
import org.springframework.vault.support.VaultExportKeyTypes; import org.springframework.vault.support.RawTransitKey;
import org.springframework.vault.support.TransitKeyType;
import org.springframework.vault.support.VaultMount; import org.springframework.vault.support.VaultMount;
import org.springframework.vault.support.VaultResponse; import org.springframework.vault.support.VaultResponse;
import org.springframework.vault.support.VaultTransitKey; import org.springframework.vault.support.VaultTransitKey;
import org.springframework.vault.support.VaultTransitKeyConfiguration; import org.springframework.vault.support.VaultTransitKeyConfiguration;
import org.springframework.vault.support.VaultTransitKeyCreationRequest; import org.springframework.vault.support.VaultTransitKeyCreationRequest;
import org.springframework.vault.support.VaultTransitKeyExport;
import org.springframework.vault.util.IntegrationTestSupport; import org.springframework.vault.util.IntegrationTestSupport;
import org.springframework.vault.util.Version; import org.springframework.vault.util.Version;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assume.assumeTrue;
/** /**
* Integration tests for {@link VaultTemplate} using the {@code transit} backend. * Integration tests for {@link VaultTemplate} using the {@code transit} backend.
@@ -50,14 +51,19 @@ import static org.assertj.core.api.Assertions.assertThat;
@ContextConfiguration(classes = VaultIntegrationTestConfiguration.class) @ContextConfiguration(classes = VaultIntegrationTestConfiguration.class)
public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport { public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport {
@Autowired @Autowired
private VaultOperations vaultOperations; private VaultOperations vaultOperations;
private Version vaultVersion;
@Before @Before
public void before() throws Exception { public void before() {
VaultSysOperations adminOperations = vaultOperations.opsForSys(); VaultSysOperations adminOperations = vaultOperations.opsForSys();
vaultVersion = prepare().getVersion();
if (!adminOperations.getMounts().containsKey("transit/")) { if (!adminOperations.getMounts().containsKey("transit/")) {
adminOperations.mount("transit", VaultMount.create("transit")); adminOperations.mount("transit", VaultMount.create("transit"));
} }
@@ -94,7 +100,7 @@ public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport
private void removeKeys() { private void removeKeys() {
if (prepare().getVersion().isGreaterThanOrEqualTo(Version.parse("0.6.4"))) { if (vaultVersion.isGreaterThanOrEqualTo(Version.parse("0.6.4"))) {
List<String> keys = vaultOperations.opsForTransit().getKeys(); List<String> keys = vaultOperations.opsForTransit().getKeys();
for (String keyName : keys) { for (String keyName : keys) {
deleteKey(keyName); deleteKey(keyName);
@@ -108,7 +114,7 @@ public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport
} }
@Test @Test
public void shouldEncrypt() throws Exception { public void shouldEncrypt() {
VaultResponse response = vaultOperations.write( VaultResponse response = vaultOperations.write(
"transit/encrypt/mykey", "transit/encrypt/mykey",
@@ -119,7 +125,7 @@ public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport
} }
@Test @Test
public void shouldEncryptAndDecrypt() throws Exception { public void shouldEncryptAndDecrypt() {
VaultResponse response = vaultOperations.write( VaultResponse response = vaultOperations.write(
"transit/encrypt/mykey", "transit/encrypt/mykey",
@@ -136,78 +142,74 @@ public class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport
} }
@Test @Test
public void shouldCreateNewExportableKey() throws Exception { public void shouldCreateNewExportableKey() {
VaultTransitOperations vaultTransitOperations = vaultOperations assumeTrue(vaultVersion.isGreaterThanOrEqualTo(Version.parse("0.6.5")));
.opsForTransit();
VaultTransitOperations vaultTransitOperations = vaultOperations.opsForTransit();
VaultTransitKeyCreationRequest vaultTransitKeyCreationRequest = VaultTransitKeyCreationRequest VaultTransitKeyCreationRequest vaultTransitKeyCreationRequest = VaultTransitKeyCreationRequest
.builder().exportable(true).derived(true).build(); .builder().exportable(true).derived(true).build();
vaultTransitOperations.createKey("export-test", vaultTransitKeyCreationRequest); vaultTransitOperations.createKey("export-test", vaultTransitKeyCreationRequest);
VaultTransitKey vaultTransitKey = vaultTransitOperations VaultTransitKey vaultTransitKey = vaultTransitOperations.getKey("export-test");
.getKey("export-test");
assertThat(vaultTransitKey.getName()).isEqualTo("export-test"); assertThat(vaultTransitKey.getName()).isEqualTo("export-test");
assertThat(vaultTransitKey.isExportable()).isTrue(); assertThat(vaultTransitKey.isExportable()).isTrue();
} }
@Test @Test
public void shouldNotCreateExportableKeyPerDefault() throws Exception { public void shouldCreateNotExportableKeyByDefault() {
VaultTransitOperations vaultTransitOperations = vaultOperations assumeTrue(vaultVersion.isGreaterThanOrEqualTo(Version.parse("0.6.5")));
.opsForTransit();
VaultTransitOperations vaultTransitOperations = vaultOperations.opsForTransit();
vaultTransitOperations.createKey("no-export"); vaultTransitOperations.createKey("no-export");
VaultTransitKey vaultTransitKey = vaultTransitOperations VaultTransitKey vaultTransitKey = vaultTransitOperations.getKey("no-export");
.getKey("no-export");
assertThat(vaultTransitKey.getName()).isEqualTo("no-export"); assertThat(vaultTransitKey.getName()).isEqualTo("no-export");
assertThat(vaultTransitKey.isExportable()).isFalse(); assertThat(vaultTransitKey.isExportable()).isFalse();
} }
@Test @Test
public void shouldExportEncryptionKey() throws Exception { public void shouldExportEncryptionKey() {
VaultTransitOperations vaultTransitOperations = vaultOperations assumeTrue(vaultVersion.isGreaterThanOrEqualTo(Version.parse("0.6.5")));
.opsForTransit();
VaultTransitKeyExport vaultTransitKeyExport = vaultTransitOperations VaultTransitOperations vaultTransitOperations = vaultOperations.opsForTransit();
.exportKey("export", VaultExportKeyTypes.ENCRYPTION_KEY);
assertThat(vaultTransitKeyExport.getName()).isEqualTo("export"); RawTransitKey rawTransitKey = vaultTransitOperations.exportKey("export",
assertThat(vaultTransitKeyExport.getKeys()).isNotEmpty(); TransitKeyType.ENCRYPTION_KEY);
assertThat(vaultTransitKeyExport.getKeys().get("1")).isNotBlank();
assertThat(rawTransitKey.getName()).isEqualTo("export");
assertThat(rawTransitKey.getKeys()).isNotEmpty();
assertThat(rawTransitKey.getKeys().get("1")).isNotBlank();
} }
@Test(expected = VaultException.class) @Test(expected = VaultException.class)
public void shouldNotExportSigningKey() throws Exception { public void shouldNotAllowExportSigningKey() {
VaultTransitOperations vaultTransitOperations = vaultOperations assumeTrue(vaultVersion.isGreaterThanOrEqualTo(Version.parse("0.6.5")));
.opsForTransit();
VaultTransitKeyExport vaultTransitKeyExport = vaultTransitOperations VaultTransitOperations vaultTransitOperations = vaultOperations.opsForTransit();
.exportKey("export", VaultExportKeyTypes.SIGNING_KEY);
vaultTransitOperations.exportKey("export", TransitKeyType.SIGNING_KEY);
} }
@Test @Test
public void shouldExportHmacKey() throws Exception { public void shouldExportHmacKey() {
VaultTransitOperations vaultTransitOperations = vaultOperations assumeTrue(vaultVersion.isGreaterThanOrEqualTo(Version.parse("0.6.5")));
.opsForTransit();
VaultTransitKeyExport vaultTransitKeyExport = vaultTransitOperations VaultTransitOperations vaultTransitOperations = vaultOperations.opsForTransit();
.exportKey("export", VaultExportKeyTypes.HMAC_KEY);
assertThat(vaultTransitKeyExport.getName()).isEqualTo("export"); RawTransitKey rawTransitKey = vaultTransitOperations.exportKey("export",
assertThat(vaultTransitKeyExport.getKeys()).isNotEmpty(); TransitKeyType.HMAC_KEY);
assertThat(vaultTransitKeyExport.getKeys().get("1")).isNotBlank();
assertThat(rawTransitKey.getName()).isEqualTo("export");
assertThat(rawTransitKey.getKeys()).isNotEmpty();
assertThat(rawTransitKey.getKeys().get("1")).isNotBlank();
} }
} }