+ * Reusing a cached token can lead to authentication failures if the credential
+ * expires.
+ *
+ * @return a caching {@link CredentialSupplier}.
+ */
+ default CredentialSupplier cached() {
+
+ String credential = get();
+
+ return () -> credential;
+ }
+}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthentication.java
index a292cb46..f663a78d 100644
--- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthentication.java
+++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesAuthentication.java
@@ -61,7 +61,7 @@ public class KubernetesAuthentication
public KubernetesAuthentication(KubernetesAuthenticationOptions options,
RestOperations restOperations) {
- Assert.notNull(options, "KubeAuthenticationOptions must not be null");
+ Assert.notNull(options, "KubernetesAuthenticationOptions must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
this.options = options;
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesJwtSupplier.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesJwtSupplier.java
index 63a8f091..f8b11967 100644
--- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesJwtSupplier.java
+++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesJwtSupplier.java
@@ -15,8 +15,6 @@
*/
package org.springframework.vault.authentication;
-import java.util.function.Supplier;
-
/**
* Interface to obtain a Kubernetes Service Account Token for Kubernetes authentication.
* Implementations are used by {@link KubernetesAuthentication}.
@@ -27,30 +25,6 @@ import java.util.function.Supplier;
* @see KubernetesAuthentication
*/
@FunctionalInterface
-public interface KubernetesJwtSupplier extends Supplier
- * Reusing a cached token can lead to authentication failures if the token expires.
- *
- * @return a caching {@link KubernetesJwtSupplier}.
- * @since 2.2
- */
- default KubernetesJwtSupplier cached() {
-
- String jwt = get();
-
- return () -> jwt;
- }
}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesServiceAccountTokenFile.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesServiceAccountTokenFile.java
index 6a2a4cd5..4a886fe6 100644
--- a/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesServiceAccountTokenFile.java
+++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/KubernetesServiceAccountTokenFile.java
@@ -16,15 +16,9 @@
package org.springframework.vault.authentication;
import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
-import org.springframework.util.Assert;
-import org.springframework.util.StreamUtils;
-import org.springframework.vault.VaultException;
/**
* Mechanism to retrieve a Kubernetes service account token.
@@ -37,15 +31,14 @@ import org.springframework.vault.VaultException;
* @since 2.0
* @see KubernetesJwtSupplier
*/
-public class KubernetesServiceAccountTokenFile implements KubernetesJwtSupplier {
+public class KubernetesServiceAccountTokenFile extends ResourceCredentialSupplier
+ implements KubernetesJwtSupplier {
/**
* Default path to the service account token file.
*/
public static final String DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE = "/var/run/secrets/kubernetes.io/serviceaccount/token";
- private final Resource resource;
-
/**
* Create a new {@link KubernetesServiceAccountTokenFile} pointing to the
* {@link #DEFAULT_KUBERNETES_SERVICE_ACCOUNT_TOKEN_FILE}. Construction fails with an
@@ -88,38 +81,6 @@ public class KubernetesServiceAccountTokenFile implements KubernetesJwtSupplier
* @throws IllegalArgumentException if the{@code path} does not exist.
*/
public KubernetesServiceAccountTokenFile(Resource resource) {
-
- Assert.isTrue(resource.exists(),
- () -> String.format("Resource %s does not exist", resource));
-
- this.resource = resource;
- }
-
- @Override
- public String get() {
-
- try {
- return new String(readToken(this.resource), StandardCharsets.US_ASCII);
- }
- catch (IOException e) {
- throw new VaultException(String
- .format("Kube JWT token retrieval from %s failed", this.resource), e);
- }
- }
-
- /**
- * Read the token from {@link Resource}.
- *
- * @param resource the resource to read from, must not be {@literal null}.
- * @return the new byte array that has been copied to (possibly empty).
- * @throws IOException in case of I/O errors.
- */
- private static byte[] readToken(Resource resource) throws IOException {
-
- Assert.notNull(resource, "Resource must not be null");
-
- try (InputStream is = resource.getInputStream()) {
- return StreamUtils.copyToByteArray(is);
- }
+ super(resource);
}
}
diff --git a/spring-vault-core/src/main/java/org/springframework/vault/authentication/PcfAuthentication.java b/spring-vault-core/src/main/java/org/springframework/vault/authentication/PcfAuthentication.java
new file mode 100644
index 00000000..02dfad65
--- /dev/null
+++ b/spring-vault-core/src/main/java/org/springframework/vault/authentication/PcfAuthentication.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2019 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.vault.authentication;
+
+import java.nio.charset.StandardCharsets;
+import java.security.spec.RSAPrivateKeySpec;
+import java.time.Clock;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.bouncycastle.crypto.CryptoException;
+import org.bouncycastle.crypto.digests.SHA256Digest;
+import org.bouncycastle.crypto.engines.RSAEngine;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.crypto.signers.PSSSigner;
+
+import org.springframework.util.Assert;
+import org.springframework.util.Base64Utils;
+import org.springframework.vault.VaultException;
+import org.springframework.vault.support.PemObject;
+import org.springframework.vault.support.VaultResponse;
+import org.springframework.vault.support.VaultToken;
+import org.springframework.web.client.RestClientException;
+import org.springframework.web.client.RestOperations;
+
+/**
+ * PCF implementation of {@link ClientAuthentication}. {@link PcfAuthentication} uses a
+ * PCF instance certificate and key to login into Vault.
+ *
+ * Requires BouncyCastle to generate a RSA PSS signature.
+ *
+ * @author Mark Paluch
+ * @since 2.2
+ * @see PcfAuthenticationOptions
+ * @see RestOperations
+ * @see Auth Backend: PCF
+ */
+public class PcfAuthentication
+ implements ClientAuthentication, AuthenticationStepsFactory {
+
+ private static final Log logger = LogFactory.getLog(PcfAuthentication.class);
+
+ private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter
+ .ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
+
+ // SHA256 hash and a salt length of 222
+ private static final int SALT_LENGTH = 222;
+
+ private final PcfAuthenticationOptions options;
+
+ private final RestOperations restOperations;
+
+ /**
+ * Create a {@link PcfAuthentication} using {@link PcfAuthenticationOptions} and
+ * {@link RestOperations}.
+ *
+ * @param options must not be {@literal null}.
+ * @param restOperations must not be {@literal null}.
+ */
+ public PcfAuthentication(PcfAuthenticationOptions options,
+ RestOperations restOperations) {
+
+ Assert.notNull(options, "PcfAuthenticationOptions must not be null");
+ Assert.notNull(restOperations, "RestOperations must not be null");
+
+ this.options = options;
+ this.restOperations = restOperations;
+ }
+
+ /**
+ * Creates a {@link AuthenticationSteps} for pcf authentication given
+ * {@link PcfAuthenticationOptions}.
+ *
+ * @param options must not be {@literal null}.
+ * @return {@link AuthenticationSteps} for pcf authentication.
+ */
+ public static AuthenticationSteps createAuthenticationSteps(
+ PcfAuthenticationOptions options) {
+
+ Assert.notNull(options, "PcfAuthenticationOptions must not be null");
+
+ String instanceCert = options.getInstanceCertSupplier().get();
+ String instanceKey = options.getInstanceKeySupplier().get();
+ return AuthenticationSteps
+ .fromSupplier(() -> getPcfLogin(options.getRole(), options.getClock(),
+ instanceCert, instanceKey)) //
+ .login("auth/{mount}/login", options.getPath());
+ }
+
+ @Override
+ public VaultToken login() throws VaultException {
+
+ Map
+ * Authentication options provide the path, {@link Clock} and instance key/instance
+ * certificate {@link Supplier}s. {@link PcfAuthenticationOptions} can be constructed
+ * using {@link #builder()}. Instances of this class are immutable once constructed.
+ *
+ * Defaults to a cached instance certificate/key by resolving {@code CF_INSTANCE_CERT} and
+ * {@code CF_INSTANCE_KEY} env variables.
+ *
+ * @author Mark Paluch
+ * @see CredentialSupplier
+ * @see ResourceCredentialSupplier
+ * @see #builder()
+ */
+public class PcfAuthenticationOptions {
+
+ public static final String DEFAULT_PCF_AUTHENTICATION_PATH = "pcf";
+
+ /**
+ * Path of the pcf authentication backend mount.
+ */
+ private final String path;
+
+ /**
+ * Name of the role against which the login is being attempted.
+ */
+ private final String role;
+
+ private final Clock clock;
+
+ /**
+ * Supplier instance to obtain the instance certificate.
+ */
+ private final Supplier
+ * Falls back to the instance certificate at {@code CF_INSTANCE_CERT} if
+ * {@link #instanceCertificate(Supplier)} is not configured respective
+ * {@code CF_INSTANCE_KEY} if {@link #instanceKey(Supplier)} is not configured.
+ *
+ * @return a new {@link PcfAuthenticationOptions}.
+ * @throws IllegalStateException if {@link #instanceCertificate(Supplier)} or
+ * {@link #instanceKey(Supplier)} are not set and the corresponding
+ * environment variable {@code CF_INSTANCE_CERT} respective
+ * {@code CF_INSTANCE_KEY} is not set.
+ */
+ public PcfAuthenticationOptions build() {
+
+ Assert.notNull(role, "Role must not be null");
+
+ Supplier
+ * Mainly for use within the framework.
+ *
+ * @author Mark Paluch
+ * @since 2.2
+ */
+public class PemObject {
+
+ private static final Pattern KEY_PATTERN = Pattern
+ .compile("-+BEGIN\\s+.*PRIVATE\\s+KEY[^-]*-+(?:\\s|\\r|\\n)+" + // Header
+ "([a-z0-9+/=\\r\\n]+)" + // Base64 text
+ "-+END\\s+.*PRIVATE\\s+KEY[^-]*-+", // Footer
+ Pattern.CASE_INSENSITIVE);
+
+ private final byte[] content;
+
+ private PemObject(String content) {
+
+ String sanitized = content.replaceAll("\r", "").replaceAll("\n", "");
+ this.content = Base64Utils.decodeFromString(sanitized);
+ }
+
+ /**
+ * Create a{@link PemObject} from PEM {@code content} that is enclosed with
+ * {@code -BEGIN PRIVATE KEY-} and {@code -END PRIVATE KEY-}.
+ *
+ * @param content the PEM content.
+ * @return the {@link PemObject} from PEM {@code content}.
+ */
+ public static PemObject fromKey(String content) {
+
+ Matcher m = KEY_PATTERN.matcher(content);
+ if (!m.find()) {
+ throw new IllegalArgumentException("Could not find a PKCS #8 private key");
+ }
+
+ return new PemObject(m.group(1));
+ }
+
+ /**
+ * Retrieve a {@link RSAPrivateCrtKeySpec}.
+ *
+ * @return the {@link RSAPrivateCrtKeySpec}.
+ */
+ public RSAPrivateCrtKeySpec getRSAKeySpec() {
+
+ try {
+ return KeystoreUtil.getRSAKeySpec(this.content);
+ }
+ catch (IOException e) {
+ throw new IllegalArgumentException("Cannot obtain PrivateKey", e);
+ }
+ }
+}
diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/PcfAuthenticationOptionsUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/PcfAuthenticationOptionsUnitTests.java
new file mode 100644
index 00000000..3db4ab1d
--- /dev/null
+++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/PcfAuthenticationOptionsUnitTests.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2019 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.vault.authentication;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+/**
+ * Unit tests for {@link PcfAuthenticationOptions}.
+ *
+ * @author Mark Paluch
+ */
+class PcfAuthenticationOptionsUnitTests {
+
+ @Test
+ void emptyEnvVariableShouldFailWithMeaningfulMessage() {
+
+ assertThatThrownBy(
+ () -> PcfAuthenticationOptions.builder().role("my-role").build())
+ .isInstanceOf(IllegalStateException.class) //
+ .hasMessageContaining(
+ "Environment variable CF_INSTANCE_CERT not set");
+ }
+}
diff --git a/spring-vault-core/src/test/java/org/springframework/vault/authentication/PcfAuthenticationUnitTests.java b/spring-vault-core/src/test/java/org/springframework/vault/authentication/PcfAuthenticationUnitTests.java
new file mode 100644
index 00000000..bafd3d64
--- /dev/null
+++ b/spring-vault-core/src/test/java/org/springframework/vault/authentication/PcfAuthenticationUnitTests.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2019 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.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.vault.authentication;
+
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.client.MockRestServiceServer;
+import org.springframework.vault.client.VaultClients;
+import org.springframework.vault.client.VaultClients.PrefixAwareUriTemplateHandler;
+import org.springframework.vault.support.VaultToken;
+import org.springframework.web.client.RestTemplate;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.jsonPath;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+
+/**
+ * Unit tests for {@link PcfAuthentication}.
+ *
+ * @author Mark Paluch
+ */
+class PcfAuthenticationUnitTests {
+
+ RestTemplate restTemplate;
+
+ MockRestServiceServer mockRest;
+
+ String instanceKey = "-----BEGIN RSA PRIVATE KEY-----\n"
+ + "MIIEpAIBAAKCAQEAzhDAw7m5EuCcQkT7cesJF9J/0FWeSICLg4F/3R8EpkjPfZSW\n"
+ + "BeIjSs6v+wUjPCdBomZpYnrphYvSdiDrHWIDKrFNcWMFms0t6A0jEyGG/k9xDf6u\n"
+ + "VjDw4Gi4LJ0o0sNK0y9ULgdrViwRkSKNdhZx+34l/aeWyrg9WG6KAdjbPQE2J4Vi\n"
+ + "3x7yJVEh/Ya0uR/UtN/8hB8Makuaz6SRcLvooUO0FXYpy20olA/nlmowCl1PxpVv\n"
+ + "smZZG7qDJGL/P3C3M9YRX4VPXLTiyvEFwIgWNz6QIhX/Enm0q+xyw+gd5hRQzF4Q\n"
+ + "Fs03VrzHsQX9H3GMd/HoqsM1vD+PPfpKI7re7wIDAQABAoIBAQCk83oq8wd4Wf4b\n"
+ + "ejbBWQB9Zk5UCcVbijKjwU0GR2ckaNJXV1LEQOI5ZrwuN02eQFpk0o/3eiZmdaey\n"
+ + "UeWDLssUKLuyUS7SXP4rbCCwlr0F47e/GSia7DBVot4TMHbWR+gkpxU+h0ffwgUJ\n"
+ + "5dvRNGRnifKFWtr1SYgpusqUcfAFovvcbLZ4X+VkV7uazHAbtor5ol2UuRN04Hnu\n"
+ + "i5gxKBvr/j4ULDnZDJZjJKPVyaS9x4ewVJx241mFbE3aOWxRl6QwouqXTqhIs/Lv\n"
+ + "85MR67nuVlEWMToR/sx0/5Xg/BJDHLUCRM5MNx+wD+Fyj6DlJn2A63Ly4HQZZuYG\n"
+ + "Z48BGku5AoGBAOFmlJQITfp5xtu2oy10bwtDElHV3HBAtcJ7OHgu9ZniNNhgZ7ud\n"
+ + "pw9VC/bL8qZ8iToooKA7AgecSmaDeX0qWPgE9uaheaT76x/6Kn3Ue/ZfV2pSrStu\n"
+ + "YlFc5UxG3Z3klAx/Y+DA7rLb2Y0U6olLx5A7Fg+V/feD8mYxnyZy2r/bAoGBAOoK\n"
+ + "NVIyzcv13S7OqiCo4nhF2CcDWekGTzmsFygwvNwiM1CipzFifQQw6Z+0rl1FwxN0\n"
+ + "uGs3x41iTmkVOyASO78Li9aPQHZWhRWQI82689kYcnChQnDZGLfIv/WVxGy3DgKd\n"
+ + "FdJIOSLagTwhUOnZ4kaR6Mj2Jc4RXYjwpoQUJON9AoGBALOqP75rjDSegvs5boJZ\n"
+ + "7/WLJfwjOw4jFn6KF638yHo7zCG5XpY3CSX4hYvYb3dzhzLblYWC45BLbSafn+Q8\n"
+ + "MCSqWF/n0H3I7FdV4i7gg1sUDirK8gvPdgEiygdt6VLlE3mOxX8ualYZViTVyklc\n"
+ + "JRt7bY9I4OI9w6bf4NsV6/XHAoGAISd5Dj/sL2yQ/MSCDUZfbrJWQJCU+BHQv1bF\n"
+ + "oQfmeTjPFCk2jiRpmWJkdh9eZBAx5luulGG+fyTh/rjnO0/Z7uJv2OFKPHldOQTG\n"
+ + "TaqiSKrR62qswte+TKq/psakoNH9xhkCsltQ3MMfc6k0kSwwhda9p1pXWK3VFkUh\n"
+ + "EazY3PECgYAoo8jvvQTKlXBmnVU1R//16fCklJXqYcEeOAO0CgyPCxHuAULK++M/\n"
+ + "HRHd+6FippoH4ppSACEqQO5TwBTYxgOCwOcYZaRDvYZqEbgPNlf3oZ73kRyoIeAK\n"
+ + "zvaXPNUuUEoW4E9Y2M+9SzF+975TTjqwjBgoCIF3xd+xQfgV9vkB6w==\n"
+ + "-----END RSA PRIVATE KEY-----";
+
+ Clock clock = Clock.fixed(Instant.parse("2007-12-03T10:15:30.00Z"), ZoneId.of("UTC"));
+
+ @BeforeEach
+ void before() {
+
+ RestTemplate restTemplate = VaultClients.createRestTemplate();
+ restTemplate.setUriTemplateHandler(new PrefixAwareUriTemplateHandler());
+
+ this.mockRest = MockRestServiceServer.createServer(restTemplate);
+ this.restTemplate = restTemplate;
+ }
+
+ @Test
+ void loginShouldObtainToken() {
+
+ PcfAuthenticationOptions options = PcfAuthenticationOptions.builder()
+ .instanceCertificate(() -> "foo") //
+ .instanceKey(() -> instanceKey) //
+ .role("dev-role") //
+ .clock(clock) //
+ .build();
+
+ PcfAuthentication authentication = new PcfAuthentication(options, restTemplate);
+
+ expectLoginRequest();
+
+ VaultToken login = authentication.login();
+ assertThat(login).isInstanceOf(LoginToken.class);
+ assertThat(login.getToken()).isEqualTo("my-token");
+ }
+
+ @Test
+ void loginWithStepsShouldObtainToken() {
+
+ PcfAuthenticationOptions options = PcfAuthenticationOptions.builder()
+ .instanceCertificate(() -> "foo") //
+ .instanceKey(() -> instanceKey) //
+ .role("dev-role") //
+ .clock(clock) //
+ .build();
+
+ expectLoginRequest();
+
+ AuthenticationStepsExecutor authentication = new AuthenticationStepsExecutor(
+ PcfAuthentication.createAuthenticationSteps(options), restTemplate);
+
+ VaultToken login = authentication.login();
+ assertThat(login).isInstanceOf(LoginToken.class);
+ assertThat(login.getToken()).isEqualTo("my-token");
+ }
+
+ private void expectLoginRequest() {
+
+ mockRest.expect(requestTo("/auth/pcf/login")).andExpect(method(HttpMethod.POST))
+ .andExpect(jsonPath("$.role").value("dev-role"))
+ .andExpect(jsonPath("$.signature").exists())
+ .andExpect(jsonPath("$.cf_instance_cert").value("foo"))
+ .andExpect(jsonPath("$.signing_time").value("2007-12-03T10:15:30Z"))
+ .andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON)
+ .body("{" + "\"auth\":{\"client_token\":\"my-token\"}" + "}"));
+ }
+}
diff --git a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultIntegrationTestConfiguration.java b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultIntegrationTestConfiguration.java
index 28499cf5..38396d02 100644
--- a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultIntegrationTestConfiguration.java
+++ b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultIntegrationTestConfiguration.java
@@ -22,6 +22,7 @@ import org.springframework.vault.client.VaultEndpoint;
import org.springframework.vault.config.AbstractReactiveVaultConfiguration;
import org.springframework.vault.support.SslConfiguration;
import org.springframework.vault.util.Settings;
+import org.springframework.vault.util.TestRestTemplateFactory;
/**
* Test configuration for Vault integration tests.
@@ -34,7 +35,7 @@ public class VaultIntegrationTestConfiguration
@Override
public VaultEndpoint vaultEndpoint() {
- return new VaultEndpoint();
+ return TestRestTemplateFactory.TEST_VAULT_ENDPOINT;
}
@Override
diff --git a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTemplateTransitIntegrationTests.java b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTemplateTransitIntegrationTests.java
index f580bc71..e8105433 100644
--- a/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTemplateTransitIntegrationTests.java
+++ b/spring-vault-core/src/test/java/org/springframework/vault/core/VaultTemplateTransitIntegrationTests.java
@@ -18,7 +18,6 @@ package org.springframework.vault.core;
import java.util.Collections;
import java.util.List;
-import org.apache.commons.codec.binary.Base64;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -27,6 +26,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.util.Base64Utils;
import org.springframework.vault.support.VaultMount;
import org.springframework.vault.support.VaultResponse;
import org.springframework.vault.support.VaultTransitKeyConfiguration;
@@ -103,7 +103,7 @@ class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport {
VaultResponse response = vaultOperations.write("transit/encrypt/mykey",
Collections.singletonMap("plaintext",
- Base64.encodeBase64String("that message is secret".getBytes())));
+ Base64Utils.encodeToString("that message is secret".getBytes())));
assertThat((String) response.getRequiredData().get("ciphertext")).isNotEmpty();
}
@@ -113,13 +113,13 @@ class VaultTemplateTransitIntegrationTests extends IntegrationTestSupport {
VaultResponse response = vaultOperations.write("transit/encrypt/mykey",
Collections.singletonMap("plaintext",
- Base64.encodeBase64String("that message is secret".getBytes())));
+ Base64Utils.encodeToString("that message is secret".getBytes())));
VaultResponse decrypted = vaultOperations.write("transit/decrypt/mykey",
Collections.singletonMap("ciphertext",
response.getRequiredData().get("ciphertext")));
assertThat((String) decrypted.getRequiredData().get("plaintext")).isEqualTo(
- Base64.encodeBase64String("that message is secret".getBytes()));
+ Base64Utils.encodeToString("that message is secret".getBytes()));
}
}
diff --git a/spring-vault-core/src/test/java/org/springframework/vault/util/TestWebClientFactory.java b/spring-vault-core/src/test/java/org/springframework/vault/util/TestWebClientFactory.java
index ba255001..3228c986 100644
--- a/spring-vault-core/src/test/java/org/springframework/vault/util/TestWebClientFactory.java
+++ b/spring-vault-core/src/test/java/org/springframework/vault/util/TestWebClientFactory.java
@@ -29,7 +29,7 @@ import org.springframework.web.reactive.function.client.WebClient;
*/
public class TestWebClientFactory {
- private static final VaultEndpoint TEST_VAULT_ENDPOINT = new VaultEndpoint();
+ private static final VaultEndpoint TEST_VAULT_ENDPOINT = TestRestTemplateFactory.TEST_VAULT_ENDPOINT;
/**
* Create a new {@link WebClient} using the {@link SslConfiguration}. See
diff --git a/spring-vault-dependencies/pom.xml b/spring-vault-dependencies/pom.xml
index 8a1aba94..bad7c6e5 100644
--- a/spring-vault-dependencies/pom.xml
+++ b/spring-vault-dependencies/pom.xml
@@ -66,6 +66,7 @@