Omit Vault namespace header for sys/init and sys/health endpoints
We now no longer add the default namespace header when issuing requests to opsForSys().init()/health(). Closes gh-534.
This commit is contained in:
@@ -233,27 +233,42 @@ public class RestTemplateBuilder {
|
||||
protected RestTemplate createTemplate() {
|
||||
|
||||
ClientHttpRequestFactory requestFactory = this.requestFactory.get();
|
||||
RestTemplateBuilderClientHttpRequestFactoryWrapper wrapper = new RestTemplateBuilderClientHttpRequestFactoryWrapper(
|
||||
requestFactory, new LinkedHashMap<>(defaultHeaders),
|
||||
new LinkedHashSet<>(requestCustomizers));
|
||||
|
||||
return VaultClients.createRestTemplate(endpointProvider, wrapper);
|
||||
LinkedHashMap<String, String> defaultHeaders = new LinkedHashMap<>(
|
||||
this.defaultHeaders);
|
||||
LinkedHashSet<RestTemplateRequestCustomizer<ClientHttpRequest>> requestCustomizers = new LinkedHashSet<>(
|
||||
this.requestCustomizers);
|
||||
|
||||
RestTemplate restTemplate = VaultClients.createRestTemplate(this.endpointProvider,
|
||||
new RestTemplateBuilderClientHttpRequestFactoryWrapper(requestFactory,
|
||||
requestCustomizers));
|
||||
|
||||
restTemplate.getInterceptors()
|
||||
.add((httpRequest, bytes, clientHttpRequestExecution) -> {
|
||||
|
||||
HttpHeaders headers = httpRequest.getHeaders();
|
||||
defaultHeaders.forEach((key, value) -> {
|
||||
if (!headers.containsKey(key)) {
|
||||
headers.add(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
return clientHttpRequestExecution.execute(httpRequest, bytes);
|
||||
});
|
||||
|
||||
return restTemplate;
|
||||
}
|
||||
|
||||
static class RestTemplateBuilderClientHttpRequestFactoryWrapper
|
||||
extends AbstractClientHttpRequestFactoryWrapper {
|
||||
|
||||
private final Map<String, String> defaultHeaders;
|
||||
|
||||
private final Set<RestTemplateRequestCustomizer<ClientHttpRequest>> requestCustomizers;
|
||||
|
||||
RestTemplateBuilderClientHttpRequestFactoryWrapper(
|
||||
ClientHttpRequestFactory requestFactory,
|
||||
Map<String, String> defaultHeaders,
|
||||
Set<RestTemplateRequestCustomizer<ClientHttpRequest>> requestCustomizers) {
|
||||
|
||||
super(requestFactory);
|
||||
this.defaultHeaders = defaultHeaders;
|
||||
this.requestCustomizers = requestCustomizers;
|
||||
}
|
||||
|
||||
@@ -262,15 +277,7 @@ public class RestTemplateBuilder {
|
||||
ClientHttpRequestFactory requestFactory) throws IOException {
|
||||
|
||||
ClientHttpRequest request = requestFactory.createRequest(uri, httpMethod);
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
|
||||
this.defaultHeaders.forEach((key, value) -> {
|
||||
|
||||
if (!headers.containsKey(key)) {
|
||||
headers.add(key, value);
|
||||
}
|
||||
|
||||
});
|
||||
this.requestCustomizers.forEach(it -> it.customize(request));
|
||||
|
||||
return request;
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -39,6 +40,7 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.vault.VaultException;
|
||||
import org.springframework.vault.client.VaultHttpHeaders;
|
||||
import org.springframework.vault.client.VaultResponses;
|
||||
import org.springframework.vault.support.Policy;
|
||||
import org.springframework.vault.support.VaultHealth;
|
||||
@@ -99,15 +101,17 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean isInitialized() {
|
||||
|
||||
return requireResponse(vaultOperations.doWithVault(restOperations -> {
|
||||
return requireResponse(vaultOperations.doWithSession(restOperations -> {
|
||||
|
||||
try {
|
||||
Map<String, Boolean> body = restOperations.getForObject("sys/init",
|
||||
Map.class);
|
||||
ResponseEntity<Map<String, Boolean>> body = (ResponseEntity) restOperations
|
||||
.exchange("sys/init", HttpMethod.GET, emptyNamespace(null),
|
||||
Map.class);
|
||||
|
||||
Assert.state(body != null, "Initialization response must not be null");
|
||||
Assert.state(body.getBody() != null,
|
||||
"Initialization response must not be null");
|
||||
|
||||
return body.get("initialized");
|
||||
return body.getBody().get("initialized");
|
||||
}
|
||||
catch (HttpStatusCodeException e) {
|
||||
throw VaultResponses.buildException(e);
|
||||
@@ -127,7 +131,7 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
try {
|
||||
ResponseEntity<VaultInitializationResponseImpl> exchange = restOperations
|
||||
.exchange("sys/init", HttpMethod.PUT,
|
||||
new HttpEntity<Object>(vaultInitializationRequest),
|
||||
emptyNamespace(vaultInitializationRequest),
|
||||
VaultInitializationResponseImpl.class);
|
||||
|
||||
Assert.state(exchange.getBody() != null,
|
||||
@@ -388,6 +392,12 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> HttpEntity<T> emptyNamespace(@Nullable T body) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(VaultHttpHeaders.VAULT_NAMESPACE, "");
|
||||
return new HttpEntity<>(body, headers);
|
||||
}
|
||||
|
||||
private static class Health implements RestOperationsCallback<VaultHealth> {
|
||||
|
||||
@Override
|
||||
@@ -395,7 +405,8 @@ public class VaultSysTemplate implements VaultSysOperations {
|
||||
|
||||
try {
|
||||
ResponseEntity<VaultHealthImpl> healthResponse = restOperations.exchange(
|
||||
"sys/health", HttpMethod.GET, null, VaultHealthImpl.class);
|
||||
"sys/health", HttpMethod.GET, emptyNamespace(null),
|
||||
VaultHealthImpl.class);
|
||||
return healthResponse.getBody();
|
||||
}
|
||||
catch (RestClientResponseException responseError) {
|
||||
|
||||
@@ -60,22 +60,6 @@ class RestTemplateBuilderUnitTests {
|
||||
assertThat(restTemplate.getErrorHandler()).isSameAs(errorHandler);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyDefaultHeaders() throws IOException {
|
||||
|
||||
RestTemplate restTemplate = RestTemplateBuilder.builder()
|
||||
.endpoint(VaultEndpoint.create("localhost", 8200))
|
||||
.defaultHeader("header", "value").build();
|
||||
|
||||
restTemplate.getInterceptors().clear();
|
||||
|
||||
ClientHttpRequest request = restTemplate.getRequestFactory()
|
||||
.createRequest(URI.create("/"), HttpMethod.GET);
|
||||
|
||||
assertThat(request.getHeaders()).containsEntry("header",
|
||||
Collections.singletonList("value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyRequestCustomizers() throws IOException {
|
||||
|
||||
|
||||
@@ -69,6 +69,12 @@ class VaultNamespaceSecretIntegrationTests extends IntegrationTestSupport {
|
||||
RestTemplateBuilder devRestTemplate;
|
||||
RestTemplateBuilder maketingRestTemplate;
|
||||
|
||||
WebClientBuilder marketingWebClientBuilder = WebClientBuilder.builder()
|
||||
.httpConnector(ClientHttpConnectorFactory.create(new ClientOptions(),
|
||||
Settings.createSslConfiguration()))
|
||||
.endpoint(TestRestTemplateFactory.TEST_VAULT_ENDPOINT)
|
||||
.defaultHeader(VaultHttpHeaders.VAULT_NAMESPACE, "marketing");
|
||||
|
||||
String devToken;
|
||||
String marketingToken;
|
||||
|
||||
@@ -166,14 +172,9 @@ class VaultNamespaceSecretIntegrationTests extends IntegrationTestSupport {
|
||||
VaultTemplate marketing = new VaultTemplate(maketingRestTemplate,
|
||||
new SimpleSessionManager(new TokenAuthentication(marketingToken)));
|
||||
|
||||
WebClientBuilder webClientBuilder = WebClientBuilder.builder()
|
||||
.httpConnector(ClientHttpConnectorFactory.create(new ClientOptions(),
|
||||
Settings.createSslConfiguration()))
|
||||
.endpoint(TestRestTemplateFactory.TEST_VAULT_ENDPOINT)
|
||||
.defaultHeader(VaultHttpHeaders.VAULT_NAMESPACE, "marketing");
|
||||
|
||||
ReactiveVaultTemplate reactiveMarketing = new ReactiveVaultTemplate(
|
||||
webClientBuilder, () -> Mono.just(VaultToken.of(marketingToken)));
|
||||
marketingWebClientBuilder,
|
||||
() -> Mono.just(VaultToken.of(marketingToken)));
|
||||
|
||||
marketing.write("marketing-secrets/my-secret",
|
||||
Collections.singletonMap("key", "marketing"));
|
||||
@@ -187,6 +188,41 @@ class VaultNamespaceSecretIntegrationTests extends IntegrationTestSupport {
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReportInitialized() {
|
||||
|
||||
VaultTemplate marketing = new VaultTemplate(maketingRestTemplate,
|
||||
new SimpleSessionManager(new TokenAuthentication(marketingToken)));
|
||||
|
||||
assertThat(marketing.opsForSys().isInitialized()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReportHealth() {
|
||||
|
||||
VaultTemplate marketing = new VaultTemplate(maketingRestTemplate,
|
||||
new SimpleSessionManager(new TokenAuthentication(marketingToken)));
|
||||
|
||||
assertThat(marketing.opsForSys().health().isInitialized()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReportReactiveInitialized() {
|
||||
|
||||
ReactiveVaultTemplate reactiveMarketing = new ReactiveVaultTemplate(
|
||||
marketingWebClientBuilder,
|
||||
() -> Mono.just(VaultToken.of(marketingToken)));
|
||||
|
||||
reactiveMarketing.doWithSession(webClient -> {
|
||||
return webClient.get().uri("sys/init")
|
||||
.header(VaultHttpHeaders.VAULT_NAMESPACE, "").exchange()
|
||||
.flatMap(it -> it.bodyToMono(Map.class));
|
||||
}).as(StepVerifier::create)
|
||||
.assertNext(
|
||||
actual -> assertThat(actual).containsEntry("initialized", true))
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class NamespaceConfiguration extends AbstractVaultConfiguration {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user