Add ClientCertificateAuthenticationOptions.

We now provide ClientCertificateAuthentication to configure the auth mount path.

Closes gh-557.
This commit is contained in:
Mark Paluch
2020-05-19 13:58:44 +02:00
parent 069eafc498
commit 7dc00613e2
4 changed files with 142 additions and 7 deletions

View File

@@ -36,11 +36,11 @@ import static org.springframework.vault.authentication.AuthenticationSteps.HttpR
public class ClientCertificateAuthentication
implements ClientAuthentication, AuthenticationStepsFactory {
private static final String CERT = "cert";
private static final Log logger = LogFactory
.getLog(ClientCertificateAuthentication.class);
private final ClientCertificateAuthenticationOptions options;
private final RestOperations restOperations;
/**
@@ -49,10 +49,25 @@ public class ClientCertificateAuthentication
* @param restOperations must not be {@literal null}.
*/
public ClientCertificateAuthentication(RestOperations restOperations) {
this(ClientCertificateAuthenticationOptions.builder().build(), restOperations);
}
/**
* Create a {@link ClientCertificateAuthentication} using {@link RestOperations}.
*
* @param options must not be {@literal null}.
* @param restOperations must not be {@literal null}.
* @since 2.3
*/
public ClientCertificateAuthentication(ClientCertificateAuthenticationOptions options,
RestOperations restOperations) {
Assert.notNull(options,
"ClientCertificateAuthenticationOptions must not be null");
Assert.notNull(restOperations, "RestOperations must not be null");
this.restOperations = restOperations;
this.options = options;
}
/**
@@ -62,7 +77,26 @@ public class ClientCertificateAuthentication
* @since 2.0
*/
public static AuthenticationSteps createAuthenticationSteps() {
return AuthenticationSteps.just(post(AuthenticationUtil.getLoginPath(CERT)).as(VaultResponse.class));
return createAuthenticationSteps(
ClientCertificateAuthenticationOptions.builder().build());
}
/**
* Creates a {@link AuthenticationSteps} for client certificate authentication.
*
* @param options must not be {@literal null}.
* @return {@link AuthenticationSteps} for client certificate authentication.
* @since 2.3
*/
public static AuthenticationSteps createAuthenticationSteps(
ClientCertificateAuthenticationOptions options) {
Assert.notNull(options,
"ClientCertificateAuthenticationOptions must not be null");
return AuthenticationSteps
.just(post(AuthenticationUtil.getLoginPath(options.getPath()))
.as(VaultResponse.class));
}
@Override
@@ -72,13 +106,14 @@ public class ClientCertificateAuthentication
@Override
public AuthenticationSteps getAuthenticationSteps() {
return createAuthenticationSteps();
return createAuthenticationSteps(options);
}
private VaultToken createTokenUsingTlsCertAuthentication() {
try {
VaultResponse response = restOperations.postForObject(AuthenticationUtil.getLoginPath(CERT),
VaultResponse response = restOperations.postForObject(
AuthenticationUtil.getLoginPath(options.getPath()),
Collections.emptyMap(), VaultResponse.class);
Assert.state(response.getAuth() != null, "Auth field must not be null");

View File

@@ -0,0 +1,92 @@
/*
* Copyright 2020 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.springframework.util.Assert;
/**
* Authentication options for {@link ClientCertificateAuthentication}.
* <p>
* Authentication options provide the path. {@link ClientCertificateAuthenticationOptions}
* can be constructed using {@link #builder()}. Instances of this class are immutable once
* constructed.
*
* @author Mark Paluch
* @since 2.3
* @see ClientCertificateAuthenticationOptions
* @see #builder()
*/
public class ClientCertificateAuthenticationOptions {
public static final String DEFAULT_CERT_PATH = "cert";
/**
* Path of the cert authentication backend mount.
*/
private final String path;
private ClientCertificateAuthenticationOptions(String path) {
this.path = path;
}
/**
* @return a new {@link ClientCertificateAuthenticationOptionsBuilder}.
*/
public static ClientCertificateAuthenticationOptionsBuilder builder() {
return new ClientCertificateAuthenticationOptionsBuilder();
}
/**
* @return the path of the azure authentication backend mount.
*/
public String getPath() {
return path;
}
/**
* Builder for {@link ClientCertificateAuthenticationOptions}.
*/
public static class ClientCertificateAuthenticationOptionsBuilder {
private String path = DEFAULT_CERT_PATH;
ClientCertificateAuthenticationOptionsBuilder() {
}
/**
* Configure the mount path, defaults to {@literal azure}.
*
* @param path must not be empty or {@literal null}.
* @return {@code this} {@link ClientCertificateAuthenticationOptionsBuilder}.
*/
public ClientCertificateAuthenticationOptionsBuilder path(String path) {
Assert.hasText(path, "Path must not be empty");
this.path = path;
return this;
}
/**
* Build a new {@link ClientCertificateAuthenticationOptions} instance.
*
* @return a new {@link ClientCertificateAuthenticationOptions}.
*/
public ClientCertificateAuthenticationOptions build() {
return new ClientCertificateAuthenticationOptions(path);
}
}
}

View File

@@ -60,13 +60,17 @@ class ClientCertificateAuthenticationUnitTests {
@Test
void loginShouldObtainToken() {
mockRest.expect(requestTo("/auth/cert/login")).andExpect(method(HttpMethod.POST))
mockRest.expect(requestTo("/auth/my/path/login"))
.andExpect(method(HttpMethod.POST))
.andRespond(withSuccess().contentType(MediaType.APPLICATION_JSON).body("{"
+ "\"auth\":{\"client_token\":\"my-token\", \"renewable\": true, \"lease_duration\": 10}"
+ "}"));
ClientCertificateAuthenticationOptions options = ClientCertificateAuthenticationOptions
.builder().path("my/path").build();
ClientCertificateAuthentication sut = new ClientCertificateAuthentication(
restTemplate);
options, restTemplate);
VaultToken login = sut.login();

View File

@@ -599,6 +599,10 @@ class AppConfig extends AbstractVaultConfiguration {
@Override
public ClientAuthentication clientAuthentication() {
ClientCertificateAuthenticationOptions options = ClientCertificateAuthenticationOptions.builder()
.path(…).build();
return new ClientCertificateAuthentication(options, restOperations());
}