Polishing.

Reformat code. Rollback Jackson customizations on request objects in favor of explicit request body creaction.

Reduce method visibility to avoid unintended exposure.

See gh-620
Original pull request: gh-778
This commit is contained in:
Mark Paluch
2023-04-19 09:04:35 +02:00
parent 0fe33b78f5
commit 42cdfaa2c9
10 changed files with 652 additions and 439 deletions

View File

@@ -38,6 +38,7 @@ import java.util.function.Function;
* {@link #doWithVault(Function) without a session}.
*
* @author Mark Paluch
* @author James Luke
* @since 2.0
* @see #doWithSession(Function)
* @see #doWithVault(Function)
@@ -48,6 +49,21 @@ import java.util.function.Function;
*/
public interface ReactiveVaultOperations {
/**
* @return the operations interface to interact with the Vault transit backend.
* @since 3.1
*/
ReactiveVaultTransitOperations opsForTransit();
/**
* Return {@link ReactiveVaultTransitOperations} if the transit backend is mounted on
* a different path than {@code transit}.
* @param path the mount path
* @return the operations interface to interact with the Vault transit backend.
* @since 3.1
*/
ReactiveVaultTransitOperations opsForTransit(String path);
/**
* Read from a Vault path. Reading data using this method is suitable for API
* calls/secret backends that do not require a request body.
@@ -122,17 +138,4 @@ public interface ReactiveVaultOperations {
<V, T extends Publisher<V>> T doWithSession(Function<WebClient, ? extends T> sessionCallback)
throws VaultException, WebClientException;
/**
* @return the operations interface to interact with the Vault transit backend.
*/
ReactiveVaultTransitOperations opsForTransit();
/**
* Return {@link ReactiveVaultTransitOperations} if the transit backend is mounted on
* a different path than {@code transit}.
* @param path the mount path
* @return the operations interface to interact with the Vault transit backend.
*/
ReactiveVaultTransitOperations opsForTransit(String path);
}

View File

@@ -56,6 +56,7 @@ import static org.springframework.web.reactive.function.client.ExchangeFilterFun
*
* @author Mark Paluch
* @author Raoof Mohammed
* @author James Luke
* @see SessionManager
* @since 2.0
*/
@@ -226,6 +227,16 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
}));
}
@Override
public ReactiveVaultTransitOperations opsForTransit() {
return opsForTransit("transit");
}
@Override
public ReactiveVaultTransitOperations opsForTransit(String path) {
return new ReactiveVaultTransitTemplate(this, path);
}
@Override
public Mono<VaultResponse> read(String path) {
@@ -365,14 +376,4 @@ public class ReactiveVaultTemplate implements ReactiveVaultOperations {
}
@Override
public ReactiveVaultTransitOperations opsForTransit() {
return opsForTransit("transit");
}
@Override
public ReactiveVaultTransitOperations opsForTransit(String path) {
return new ReactiveVaultTransitTemplate(this, path);
}
}

View File

@@ -37,17 +37,18 @@ import reactor.core.publisher.Mono;
import java.util.List;
/**
* Interface that specifies a set of {@code transit} operations executed on a reactive
* infrastructure, implemented by
* {@link org.springframework.vault.core.ReactiveVaultTransitTemplate}.
* * Interface that specifies operations using the {@code transit} backend.
*
* @author James Luke
* @since 3.1
* @see <a href="https://www.vaultproject.io/docs/secrets/transit/index.html">Transit
* Secret Backend</a>
*/
public interface ReactiveVaultTransitOperations {
/**
* Create a new named encryption key given a {@code name}
* @param keyName must not be empty or {@literal null}
* Create a new named encryption key given a {@code name}.
* @param keyName must not be empty or {@literal null}.
*/
Mono<Void> createKey(String keyName);
@@ -61,7 +62,8 @@ public interface ReactiveVaultTransitOperations {
Mono<Void> createKey(String keyName, VaultTransitKeyCreationRequest createKeyRequest);
/**
* @return stream of transit key names.
* Get a {@link Flux} of transit key names.
* @return {@link Flux} of transit key names.
*/
Flux<String> getKeys();
@@ -78,14 +80,14 @@ public interface ReactiveVaultTransitOperations {
* operation.
* @param keyName must not be empty or {@literal null}.
* @param type must not be {@literal null}.
* @return the {@link RawTransitKey}. May be empty if key does not exist
* @return the {@link RawTransitKey}. Empty if key does not exist
*/
Mono<RawTransitKey> exportKey(String keyName, TransitKeyType type);
/**
* Return information about a named encryption key.
* @param keyName must not be empty or {@literal null}.
* @return the {@link VaultTransitKey}. May be empty if key does not exist
* @return the {@link VaultTransitKey}. Empty if key does not exist.
*/
Mono<VaultTransitKey> getKey(String keyName);
@@ -230,10 +232,10 @@ public interface ReactiveVaultTransitOperations {
* a type that supports rotation, configured {@link VaultHmacRequest#getKeyVersion()}
* will be used.
* @param keyName must not be empty or {@literal null}.
* @param hmacRequest the {@link VaultHmacRequest}, must not be {@literal null}.
* @param request the {@link VaultHmacRequest}, must not be {@literal null}.
* @return the digest of given data the default hash algorithm and the named key.
*/
Mono<Hmac> getHmac(String keyName, VaultHmacRequest hmacRequest);
Mono<Hmac> getHmac(String keyName, VaultHmacRequest request);
/**
* Create a cryptographic signature using {@code keyName} of the given
@@ -250,10 +252,10 @@ public interface ReactiveVaultTransitOperations {
* {@link VaultSignRequest} and the specified hash algorithm. The key must be of a
* type that supports signing.
* @param keyName must not be empty or {@literal null}.
* @param signRequest {@link VaultSignRequest} must not be empty or {@literal null}.
* @param request {@link VaultSignRequest} must not be empty or {@literal null}.
* @return Signature for {@link VaultSignRequest}.
*/
Mono<Signature> sign(String keyName, VaultSignRequest signRequest);
Mono<Signature> sign(String keyName, VaultSignRequest request);
/**
* Verify the cryptographic signature using {@code keyName} of the given
@@ -269,10 +271,10 @@ public interface ReactiveVaultTransitOperations {
* Verify the cryptographic signature using {@code keyName} of the given
* {@link VaultSignRequest}.
* @param keyName must not be empty or {@literal null}.
* @param verificationRequest {@link VaultSignatureVerificationRequest} must not be
* @param request {@link VaultSignatureVerificationRequest} must not be
* {@literal null}.
* @return the resulting {@link SignatureValidation}.
*/
Mono<SignatureValidation> verify(String keyName, VaultSignatureVerificationRequest verificationRequest);
Mono<SignatureValidation> verify(String keyName, VaultSignatureVerificationRequest request);
}

View File

@@ -47,9 +47,10 @@ import java.util.Map;
import static org.springframework.vault.core.VaultTransitTemplate.*;
/**
* Default implementation of {@link ReactiveVaultTransitOperations}
* Default implementation of {@link ReactiveVaultTransitOperations}.
*
* @author James Luke
* @since 3.1
*/
public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperations {
@@ -58,6 +59,7 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
private final String path;
public ReactiveVaultTransitTemplate(ReactiveVaultOperations reactiveVaultOperations, String path) {
Assert.notNull(reactiveVaultOperations, "ReactiveVaultOperations must not be null");
Assert.hasText(path, "Path must not be empty");
@@ -67,6 +69,7 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
@Override
public Mono<Void> createKey(String keyName) {
Assert.hasText(keyName, "Key name must not be empty");
return this.reactiveVaultOperations.write(String.format("%s/keys/%s", this.path, keyName), null).then();
@@ -74,15 +77,17 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
@Override
public Mono<Void> createKey(String keyName, VaultTransitKeyCreationRequest createKeyRequest) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(createKeyRequest, "VaultTransitKeyCreationRequest must not be empty");
return this.reactiveVaultOperations.write(String.format("%s/keys/%s", this.path, keyName), createKeyRequest)
.then();
.then();
}
@Override
public Mono<Void> rotate(String keyName) {
Assert.hasText(keyName, "Key name must not be empty");
return this.reactiveVaultOperations.write(String.format("%s/keys/%s/rotate", this.path, keyName), null).then();
@@ -90,6 +95,7 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
@Override
public Mono<String> encrypt(String keyName, String plaintext) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(plaintext, "Plaintext must not be null");
@@ -98,20 +104,23 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
request.put("plaintext", Base64.getEncoder().encodeToString(plaintext.getBytes()));
return this.reactiveVaultOperations.write(String.format("%s/encrypt/%s", this.path, keyName), request)
.map(it -> (String) it.getRequiredData().get("ciphertext"));
.map(it -> (String) it.getRequiredData().get("ciphertext"));
}
@Override
public Mono<Void> configureKey(String keyName, VaultTransitKeyConfiguration keyConfiguration) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(keyConfiguration, "VaultKeyConfiguration must not be empty");
return this.reactiveVaultOperations
.write(String.format("%s/keys/%s/config", this.path, keyName), keyConfiguration).then();
.write(String.format("%s/keys/%s/config", this.path, keyName), keyConfiguration)
.then();
}
@Override
public Mono<Void> deleteKey(String keyName) {
Assert.hasText(keyName, "Key name must not be empty");
return this.reactiveVaultOperations.delete(String.format("%s/keys/%s", this.path, keyName));
@@ -121,11 +130,12 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
@SuppressWarnings("unchecked")
public Flux<String> getKeys() {
return this.reactiveVaultOperations.read(String.format("%s/keys?list=true", this.path))
.flatMapIterable(it -> (List<String>) it.getRequiredData().get("keys"));
.flatMapIterable(it -> (List<String>) it.getRequiredData().get("keys"));
}
@Override
public Mono<String> encrypt(String keyName, byte[] plaintext, VaultTransitContext transitContext) {
Assert.notNull(plaintext, "Plaintext must not be null");
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(transitContext, "VaultTransitContext must not be null");
@@ -137,20 +147,22 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
applyTransitOptions(transitContext, request);
return this.reactiveVaultOperations.write(String.format("%s/encrypt/%s", this.path, keyName), request)
.map(it -> (String) it.getRequiredData().get("ciphertext"));
.map(it -> (String) it.getRequiredData().get("ciphertext"));
}
@Override
public Mono<Ciphertext> encrypt(String keyName, Plaintext plaintext) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(plaintext, "Plaintext must not be null");
return encrypt(keyName, plaintext.getPlaintext(), plaintext.getContext())
.map(ciphertext -> toCiphertext(ciphertext, plaintext.getContext()));
.map(ciphertext -> toCiphertext(ciphertext, plaintext.getContext()));
}
@Override
public Mono<String> decrypt(String keyName, String ciphertext) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.hasText(ciphertext, "Ciphertext must not be empty");
@@ -159,21 +171,23 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
request.put("ciphertext", ciphertext);
return this.reactiveVaultOperations.write(String.format("%s/decrypt/%s", this.path, keyName), request)
.map(it -> (String) it.getRequiredData().get("plaintext"))
.map(plaintext -> new String(Base64.getDecoder().decode(plaintext)));
.map(it -> (String) it.getRequiredData().get("plaintext"))
.map(plaintext -> new String(Base64.getDecoder().decode(plaintext)));
}
@Override
public Mono<Plaintext> decrypt(String keyName, Ciphertext ciphertext) {
Assert.hasText(keyName, "Key name must not be null");
Assert.notNull(ciphertext, "Ciphertext must not be null");
return decrypt(keyName, ciphertext.getCiphertext(), ciphertext.getContext())
.map(plaintext -> Plaintext.of(plaintext).with(ciphertext.getContext()));
.map(plaintext -> Plaintext.of(plaintext).with(ciphertext.getContext()));
}
@Override
public Mono<byte[]> decrypt(String keyName, String ciphertext, VaultTransitContext transitContext) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.hasText(ciphertext, "Ciphertext must not be empty");
Assert.notNull(transitContext, "VaultTransitContext must not be null");
@@ -185,11 +199,13 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
applyTransitOptions(transitContext, request);
return this.reactiveVaultOperations.write(String.format("%s/decrypt/%s", this.path, keyName), request)
.map(it -> (String) it.getRequiredData().get("plaintext")).map(Base64.getDecoder()::decode);
.map(it -> (String) it.getRequiredData().get("plaintext"))
.map(Base64.getDecoder()::decode);
}
@Override
public Mono<String> rewrap(String keyName, String ciphertext) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.hasText(ciphertext, "Ciphertext must not be empty");
@@ -197,11 +213,12 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
request.put("ciphertext", ciphertext);
return this.reactiveVaultOperations.write(String.format("%s/rewrap/%s", this.path, keyName), request)
.map(response -> (String) response.getRequiredData().get("ciphertext"));
.map(response -> (String) response.getRequiredData().get("ciphertext"));
}
@Override
public Mono<String> rewrap(String keyName, String ciphertext, VaultTransitContext transitContext) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.hasText(ciphertext, "Ciphertext must not be empty");
Assert.notNull(transitContext, "VaultTransitContext must not be null");
@@ -213,7 +230,7 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
applyTransitOptions(transitContext, request);
return this.reactiveVaultOperations.write(String.format("%s/rewrap/%s", this.path, keyName), request)
.map(response -> (String) response.getRequiredData().get("ciphertext"));
.map(response -> (String) response.getRequiredData().get("ciphertext"));
}
@Override
@@ -226,14 +243,16 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
vaultRequest.put("plaintext", Base64.getEncoder().encodeToString(request.getPlaintext()));
applyTransitOptions(request.getContext(), vaultRequest);
return vaultRequest;
}).collectList()
.flatMap(batch -> this.reactiveVaultOperations.write(String.format("%s/encrypt/%s", this.path, keyName),
Collections.singletonMap("batch_input", batch)))
.flatMapIterable(vaultResponse -> toEncryptionResults(vaultResponse, batchRequest));
})
.collectList()
.flatMap(batch -> this.reactiveVaultOperations.write(String.format("%s/encrypt/%s", this.path, keyName),
Collections.singletonMap("batch_input", batch)))
.flatMapIterable(vaultResponse -> toEncryptionResults(vaultResponse, batchRequest));
}
@Override
public Flux<VaultDecryptionResult> decrypt(String keyName, List<Ciphertext> batchRequest) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notEmpty(batchRequest, "BatchRequest must not be null and must have at least one entry");
@@ -242,14 +261,16 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
vaultRequest.put("ciphertext", request.getCiphertext());
applyTransitOptions(request.getContext(), vaultRequest);
return vaultRequest;
}).collectList()
.flatMap(batch -> this.reactiveVaultOperations.write(String.format("%s/decrypt/%s", this.path, keyName),
Collections.singletonMap("batch_input", batch)))
.flatMapIterable(vaultResponse -> toDecryptionResults(vaultResponse, batchRequest));
})
.collectList()
.flatMap(batch -> this.reactiveVaultOperations.write(String.format("%s/decrypt/%s", this.path, keyName),
Collections.singletonMap("batch_input", batch)))
.flatMapIterable(vaultResponse -> toDecryptionResults(vaultResponse, batchRequest));
}
@Override
public Mono<Hmac> getHmac(String keyName, Plaintext plaintext) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(plaintext, "Plaintext must not be null");
@@ -260,15 +281,19 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
@Override
public Mono<Hmac> getHmac(String keyName, VaultHmacRequest hmacRequest) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(hmacRequest, "HMAC request must not be null");
return this.reactiveVaultOperations.write(String.format("%s/hmac/%s", this.path, keyName), hmacRequest)
.map(vaultResponse -> (String) vaultResponse.getRequiredData().get("hmac")).map(Hmac::of);
return this.reactiveVaultOperations
.write(String.format("%s/hmac/%s", this.path, keyName), toRequestBody(hmacRequest))
.map(vaultResponse -> (String) vaultResponse.getRequiredData().get("hmac"))
.map(Hmac::of);
}
@Override
public Mono<Signature> sign(String keyName, Plaintext plaintext) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(plaintext, "Plaintext must not be null");
@@ -279,15 +304,19 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
@Override
public Mono<Signature> sign(String keyName, VaultSignRequest signRequest) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(signRequest, "Sign request must not be null");
return this.reactiveVaultOperations.write(String.format("%s/sign/%s", this.path, keyName), signRequest)
.map(vaultResponse -> (String) vaultResponse.getRequiredData().get("signature")).map(Signature::of);
return this.reactiveVaultOperations
.write(String.format("%s/sign/%s", this.path, keyName), toRequestBody(signRequest))
.map(vaultResponse -> (String) vaultResponse.getRequiredData().get("signature"))
.map(Signature::of);
}
@Override
public Mono<Boolean> verify(String keyName, Plaintext plaintext, Signature signature) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(plaintext, "Plaintext must not be null");
Assert.notNull(signature, "Signature must not be null");
@@ -299,36 +328,41 @@ public class ReactiveVaultTransitTemplate implements ReactiveVaultTransitOperati
@Override
public Mono<SignatureValidation> verify(String keyName, VaultSignatureVerificationRequest verificationRequest) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(verificationRequest, "Signature verification request must not be null");
return this.reactiveVaultOperations
.write(String.format("%s/verify/%s", this.path, keyName), verificationRequest)
.map(VaultResponse::getRequiredData).map(vaultResponse -> {
if (vaultResponse.containsKey("valid") && (Boolean) vaultResponse.get("valid")) {
return SignatureValidation.valid();
}
return SignatureValidation.invalid();
});
.write(String.format("%s/verify/%s", this.path, keyName), toRequestBody(verificationRequest))
.map(VaultResponse::getRequiredData)
.map(vaultResponse -> {
if (vaultResponse.containsKey("valid") && (Boolean) vaultResponse.get("valid")) {
return SignatureValidation.valid();
}
return SignatureValidation.invalid();
});
}
@Override
public Mono<RawTransitKey> exportKey(String keyName, TransitKeyType type) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(type, "Key type must not be null");
return this.reactiveVaultOperations
.read(String.format("%s/export/%s/%s", this.path, type.getValue(), keyName),
VaultTransitTemplate.RawTransitKeyImpl.class)
.flatMap(vaultResponse -> Mono.justOrEmpty(vaultResponse.getRequiredData()));
.read(String.format("%s/export/%s/%s", this.path, type.getValue(), keyName),
VaultTransitTemplate.RawTransitKeyImpl.class)
.flatMap(vaultResponse -> Mono.justOrEmpty(vaultResponse.getRequiredData()));
}
@Override
public Mono<VaultTransitKey> getKey(String keyName) {
Assert.hasText(keyName, "Key name must not be empty");
return this.reactiveVaultOperations
.read(String.format("%s/keys/%s", this.path, keyName), VaultTransitKeyImpl.class)
.map(VaultResponseSupport::getRequiredData);
.read(String.format("%s/keys/%s", this.path, keyName), VaultTransitKeyImpl.class)
.map(VaultResponseSupport::getRequiredData);
}
}

View File

@@ -187,7 +187,7 @@ public interface VaultTransitOperations {
byte[] decrypt(String keyName, String ciphertext, VaultTransitContext transitContext);
/**
* Decrypts the provided barch of cipher text using the named key and context. The*
* Decrypts the provided batch of cipher text using the named key and context. The*
* decryption is done using transit backend's batch operation.
* @param keyName must not be empty or {@literal null}.
* @param batchRequest a list of {@link Ciphertext} which includes plain text and an

View File

@@ -16,9 +16,10 @@
package org.springframework.vault.core;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.jetbrains.annotations.NotNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.vault.VaultException;
@@ -42,6 +43,7 @@ import org.springframework.vault.support.VaultTransitKeyConfiguration;
import org.springframework.vault.support.VaultTransitKeyCreationRequest;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
@@ -166,7 +168,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
Map<String, String> request = new LinkedHashMap<>();
request.put("plaintext", Base64Utils.encodeToString(plaintext.getBytes()));
request.put("plaintext", Base64.getEncoder().encodeToString(plaintext.getBytes()));
return (String) this.vaultOperations.write(String.format("%s/encrypt/%s", this.path, keyName), request)
.getRequiredData()
@@ -193,7 +195,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
Map<String, String> request = new LinkedHashMap<>();
request.put("plaintext", Base64Utils.encodeToString(plaintext));
request.put("plaintext", Base64.getEncoder().encodeToString(plaintext));
applyTransitOptions(transitContext, request);
@@ -214,7 +216,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
Map<String, String> vaultRequest = new LinkedHashMap<>(2);
vaultRequest.put("plaintext", Base64Utils.encodeToString(request.getPlaintext()));
vaultRequest.put("plaintext", Base64.getEncoder().encodeToString(request.getPlaintext()));
if (request.getContext() != null) {
applyTransitOptions(request.getContext(), vaultRequest);
@@ -244,7 +246,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
.getRequiredData()
.get("plaintext");
return new String(Base64Utils.decodeFromString(plaintext));
return new String(Base64.getDecoder().decode(plaintext));
}
@Override
@@ -276,7 +278,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
.getRequiredData()
.get("plaintext");
return Base64Utils.decodeFromString(plaintext);
return Base64.getDecoder().decode(plaintext);
}
@Override
@@ -355,12 +357,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(hmacRequest, "HMAC request must not be null");
Map<String, Object> request = new LinkedHashMap<>(3);
PropertyMapper mapper = PropertyMapper.get();
mapper.from(hmacRequest.getPlaintext()::getPlaintext).as(Base64Utils::encodeToString).to("input", request);
mapper.from(hmacRequest::getAlgorithm).whenHasText().to("algorithm", request);
mapper.from(hmacRequest::getKeyVersion).whenNonNull().to("key_version", request);
Map<String, Object> request = toRequestBody(hmacRequest);
String hmac = (String) this.vaultOperations.write(String.format("%s/hmac/%s", this.path, keyName), request)
.getRequiredData()
@@ -369,6 +366,20 @@ public class VaultTransitTemplate implements VaultTransitOperations {
return Hmac.of(hmac);
}
static Map<String, Object> toRequestBody(VaultHmacRequest hmacRequest) {
Map<String, Object> request = new LinkedHashMap<>(3);
PropertyMapper mapper = PropertyMapper.get();
mapper.from(hmacRequest.getPlaintext()::getPlaintext)
.as(Base64.getEncoder()::encodeToString)
.to("input", request);
mapper.from(hmacRequest::getAlgorithm).whenHasText().to("algorithm", request);
mapper.from(hmacRequest::getKeyVersion).whenNonNull().to("key_version", request);
return request;
}
@Override
public Signature sign(String keyName, Plaintext plaintext) {
@@ -382,15 +393,11 @@ public class VaultTransitTemplate implements VaultTransitOperations {
@Override
public Signature sign(String keyName, VaultSignRequest signRequest) {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(signRequest, "Sign request must not be null");
Map<String, Object> request = new LinkedHashMap<>(3);
PropertyMapper mapper = PropertyMapper.get();
mapper.from(signRequest.getPlaintext()::getPlaintext).as(Base64Utils::encodeToString).to("input", request);
mapper.from(signRequest::getHashAlgorithm).whenHasText().to("hash_algorithm", request);
mapper.from(signRequest::getSignatureAlgorithm).whenHasText().to("signature_algorithm", request);
Map<String, Object> request = toRequestBody(signRequest);
String signature = (String) this.vaultOperations.write(String.format("%s/sign/%s", this.path, keyName), request)
.getRequiredData()
@@ -399,6 +406,20 @@ public class VaultTransitTemplate implements VaultTransitOperations {
return Signature.of(signature);
}
static Map<String, Object> toRequestBody(VaultSignRequest signRequest) {
Map<String, Object> request = new LinkedHashMap<>(3);
PropertyMapper mapper = PropertyMapper.get();
mapper.from(signRequest.getPlaintext()::getPlaintext)
.as(Base64.getEncoder()::encodeToString)
.to("input", request);
mapper.from(signRequest::getHashAlgorithm).whenHasText().to("hash_algorithm", request);
mapper.from(signRequest::getSignatureAlgorithm).whenHasText().to("signature_algorithm", request);
return request;
}
@Override
public boolean verify(String keyName, Plaintext plainText, Signature signature) {
@@ -416,19 +437,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
Assert.hasText(keyName, "Key name must not be empty");
Assert.notNull(verificationRequest, "Signature verification request must not be null");
Map<String, Object> request = new LinkedHashMap<>(5);
PropertyMapper mapper = PropertyMapper.get();
mapper.from(verificationRequest.getPlaintext()::getPlaintext)
.as(Base64Utils::encodeToString)
.to("input", request);
mapper.from(verificationRequest::getHmac).whenNonNull().as(Hmac::getHmac).to("hmac", request);
mapper.from(verificationRequest::getSignature)
.whenNonNull()
.as(Signature::getSignature)
.to("signature", request);
mapper.from(verificationRequest::getHashAlgorithm).whenHasText().to("hash_algorithm", request);
mapper.from(verificationRequest::getSignatureAlgorithm).whenHasText().to("signature_algorithm", request);
Map<String, Object> request = toRequestBody(verificationRequest);
Map<String, Object> response = this.vaultOperations
.write(String.format("%s/verify/%s", this.path, keyName), request)
@@ -441,19 +450,37 @@ public class VaultTransitTemplate implements VaultTransitOperations {
return SignatureValidation.invalid();
}
public static void applyTransitOptions(VaultTransitContext context, Map<String, String> request) {
static Map<String, Object> toRequestBody(VaultSignatureVerificationRequest verificationRequest) {
Map<String, Object> request = new LinkedHashMap<>(5);
PropertyMapper mapper = PropertyMapper.get();
mapper.from(verificationRequest.getPlaintext()::getPlaintext)
.as(Base64.getEncoder()::encodeToString)
.to("input", request);
mapper.from(verificationRequest::getHmac).whenNonNull().as(Hmac::getHmac).to("hmac", request);
mapper.from(verificationRequest::getSignature)
.whenNonNull()
.as(Signature::getSignature)
.to("signature", request);
mapper.from(verificationRequest::getHashAlgorithm).whenHasText().to("hash_algorithm", request);
mapper.from(verificationRequest::getSignatureAlgorithm).whenHasText().to("signature_algorithm", request);
return request;
}
static void applyTransitOptions(VaultTransitContext context, Map<String, String> request) {
if (!ObjectUtils.isEmpty(context.getContext())) {
request.put("context", Base64Utils.encodeToString(context.getContext()));
request.put("context", Base64.getEncoder().encodeToString(context.getContext()));
}
if (!ObjectUtils.isEmpty(context.getNonce())) {
request.put("nonce", Base64Utils.encodeToString(context.getNonce()));
request.put("nonce", Base64.getEncoder().encodeToString(context.getNonce()));
}
}
public static List<VaultEncryptionResult> toEncryptionResults(VaultResponse vaultResponse,
List<Plaintext> batchRequest) {
static List<VaultEncryptionResult> toEncryptionResults(VaultResponse vaultResponse, List<Plaintext> batchRequest) {
List<VaultEncryptionResult> result = new ArrayList<>(batchRequest.size());
List<Map<String, String>> batchData = getBatchData(vaultResponse);
@@ -482,8 +509,7 @@ public class VaultTransitTemplate implements VaultTransitOperations {
return result;
}
public static List<VaultDecryptionResult> toDecryptionResults(VaultResponse vaultResponse,
List<Ciphertext> batchRequest) {
static List<VaultDecryptionResult> toDecryptionResults(VaultResponse vaultResponse, List<Ciphertext> batchRequest) {
List<VaultDecryptionResult> result = new ArrayList<>(batchRequest.size());
List<Map<String, String>> batchData = getBatchData(vaultResponse);
@@ -514,19 +540,19 @@ public class VaultTransitTemplate implements VaultTransitOperations {
if (StringUtils.hasText(data.get("plaintext"))) {
byte[] plaintext = Base64Utils.decodeFromString(data.get("plaintext"));
byte[] plaintext = Base64.getDecoder().decode(data.get("plaintext"));
return new VaultDecryptionResult(Plaintext.of(plaintext).with(ciphertext.getContext()));
}
return new VaultDecryptionResult(Plaintext.empty().with(ciphertext.getContext()));
}
public static Ciphertext toCiphertext(String ciphertext, @Nullable VaultTransitContext context) {
static Ciphertext toCiphertext(String ciphertext, @Nullable VaultTransitContext context) {
return context != null ? Ciphertext.of(ciphertext).with(context) : Ciphertext.of(ciphertext);
}
@SuppressWarnings("unchecked")
public static List<Map<String, String>> getBatchData(VaultResponse vaultResponse) {
static List<Map<String, String>> getBatchData(VaultResponse vaultResponse) {
return (List<Map<String, String>>) vaultResponse.getRequiredData().get("batch_results");
}

View File

@@ -31,14 +31,10 @@ import org.springframework.util.Assert;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class VaultHmacRequest {
@JsonProperty("input")
@JsonSerialize(converter = PlaintextToBase64StringConverter.class)
private final Plaintext plaintext;
@JsonProperty("algorithm")
private final @Nullable String algorithm;
@JsonProperty("key_version")
private final @Nullable Integer keyVersion;
private VaultHmacRequest(Plaintext plaintext, @Nullable String algorithm, @Nullable Integer keyVersion) {

View File

@@ -30,8 +30,6 @@ import org.springframework.util.Assert;
*/
public class VaultSignRequest {
@JsonProperty("input")
@JsonSerialize(converter = PlaintextToBase64StringConverter.class)
private final Plaintext plaintext;
private final @Nullable String hashAlgorithm;

View File

@@ -15,16 +15,8 @@
*/
package org.springframework.vault.support;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.vault.support.VaultSignatureVerificationRequest.VaultSignatureVerificationRequestSerializer;
import java.io.IOException;
/**
* Request for a signature verification.
@@ -35,7 +27,6 @@ import java.io.IOException;
* @author James Luke
* @since 2.0
*/
@JsonSerialize(using = VaultSignatureVerificationRequestSerializer.class)
public class VaultSignatureVerificationRequest {
private final Plaintext plaintext;
@@ -145,31 +136,6 @@ public class VaultSignatureVerificationRequest {
return getSignatureAlgorithm();
}
static class VaultSignatureVerificationRequestSerializer extends JsonSerializer<VaultSignatureVerificationRequest> {
static PlaintextToBase64StringConverter plaintextConverter = new PlaintextToBase64StringConverter();
@Override
public void serialize(VaultSignatureVerificationRequest request, JsonGenerator gen,
SerializerProvider serializers) throws IOException {
gen.writeStartObject();
gen.writeStringField("input", plaintextConverter.convert(request.plaintext));
if (request.getHmac() != null) {
gen.writeStringField("hmac", request.getHmac().getHmac());
}
if (request.getSignature() != null) {
gen.writeStringField("signature", request.getSignature().getSignature());
}
if (StringUtils.hasText(request.getAlgorithm())) {
gen.writeStringField("algorithm", request.getAlgorithm());
}
gen.writeEndObject();
}
}
/**
* Builder to build a {@link VaultSignatureVerificationRequest}.
*/