Adds support for Tls to config data.

Moves common setup to new ConfigClientRequestTemplateFactory class that was replicated between two implementations.

Fixes gh-1689
This commit is contained in:
spencergibb
2021-03-12 18:31:25 -05:00
parent 35f219c296
commit 4010a7cf7c
8 changed files with 245 additions and 167 deletions

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2013-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.cloud.config.client.tls;
public class ConfigClientConfigDataTlsTests extends ConfigClientTlsTests {
@Override
protected TlsConfigClientRunner createConfigClient(boolean optional) {
String importValue = "configserver:";
if (optional) {
importValue = "optional:" + importValue;
}
return new TlsConfigClientRunner(TestApp.class, server, "spring.config.import", importValue);
}
@Override
protected TlsConfigClientRunner createConfigClient() {
return new TlsConfigClientRunner(TestApp.class, server, "spring.config.import", "optional:configserver:");
}
}

View File

@@ -30,7 +30,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ConfigClientTlsTests extends AbstractTlsSetup {
private static TlsConfigServerRunner server;
protected static TlsConfigServerRunner server;
@BeforeClass
public static void setupAll() throws Exception {
@@ -95,7 +95,7 @@ public class ConfigClientTlsTests extends AbstractTlsSetup {
@Test(expected = IllegalStateException.class)
public void wrongPasswordCauseFailure() {
TlsConfigClientRunner client = createConfigClient();
TlsConfigClientRunner client = createConfigClient(false);
enableTlsClient(client);
client.setKeyStore(clientCert, WRONG_PASSWORD, WRONG_PASSWORD);
client.start();
@@ -103,7 +103,7 @@ public class ConfigClientTlsTests extends AbstractTlsSetup {
@Test(expected = IllegalStateException.class)
public void nonExistKeyStoreCauseFailure() {
TlsConfigClientRunner client = createConfigClient();
TlsConfigClientRunner client = createConfigClient(false);
enableTlsClient(client);
client.setKeyStore(new File("nonExistFile"));
client.start();
@@ -119,7 +119,15 @@ public class ConfigClientTlsTests extends AbstractTlsSetup {
}
}
private TlsConfigClientRunner createConfigClient() {
protected TlsConfigClientRunner createConfigClient(boolean optional) {
TlsConfigClientRunner runner = createConfigClient();
if (!optional) {
runner.property("spring.cloud.config.fail-fast", "true");
}
return runner;
}
protected TlsConfigClientRunner createConfigClient() {
return new TlsConfigClientRunner(TestApp.class, server);
}

View File

@@ -21,11 +21,15 @@ import java.io.File;
public class TlsConfigClientRunner extends AppRunner {
public TlsConfigClientRunner(Class<?> appClass, AppRunner server) {
this(appClass, server, "spring.config.use-legacy-processing", "true");
}
public TlsConfigClientRunner(Class<?> appClass, AppRunner server, String importKey, String importValue) {
super(appClass);
property("spring.cloud.config.uri", server.root());
property("spring.cloud.config.enabled", "true");
property("spring.config.use-legacy-processing", "true");
property(importKey, importValue);
}
public void enableTls() {

View File

@@ -0,0 +1,151 @@
/*
* Copyright 2013-2021 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.cloud.config.client;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.SSLContext;
import org.apache.commons.logging.Log;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.cloud.configuration.SSLContextFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.util.Base64Utils;
import org.springframework.web.client.RestTemplate;
import static org.springframework.cloud.config.client.ConfigClientProperties.AUTHORIZATION;
public class ConfigClientRequestTemplateFactory {
private final Log log;
private final ConfigClientProperties properties;
public ConfigClientRequestTemplateFactory(Log log, ConfigClientProperties properties) {
this.log = log;
this.properties = properties;
}
public Log getLog() {
return this.log;
}
public ConfigClientProperties getProperties() {
return this.properties;
}
public RestTemplate create() {
if (properties.getRequestReadTimeout() < 0) {
throw new IllegalStateException("Invalid Value for Read Timeout set.");
}
if (properties.getRequestConnectTimeout() < 0) {
throw new IllegalStateException("Invalid Value for Connect Timeout set.");
}
ClientHttpRequestFactory requestFactory = createHttpRequestFactory(properties);
RestTemplate template = new RestTemplate(requestFactory);
Map<String, String> headers = new HashMap<>(properties.getHeaders());
headers.remove(AUTHORIZATION); // To avoid redundant addition of header
if (!headers.isEmpty()) {
template.setInterceptors(Arrays.asList(new GenericRequestHeaderInterceptor(headers)));
}
return template;
}
private ClientHttpRequestFactory createHttpRequestFactory(ConfigClientProperties client) {
if (client.getTls().isEnabled()) {
try {
SSLContextFactory factory = new SSLContextFactory(client.getTls());
SSLContext sslContext = factory.createSSLContext();
HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpComponentsClientHttpRequestFactory result = new HttpComponentsClientHttpRequestFactory(httpClient);
result.setReadTimeout(client.getRequestReadTimeout());
result.setConnectTimeout(client.getRequestConnectTimeout());
return result;
}
catch (GeneralSecurityException | IOException ex) {
log.error(ex);
throw new IllegalStateException("Failed to create config client with TLS.", ex);
}
}
SimpleClientHttpRequestFactory result = new SimpleClientHttpRequestFactory();
result.setReadTimeout(client.getRequestReadTimeout());
result.setConnectTimeout(client.getRequestConnectTimeout());
return result;
}
public void addAuthorizationToken(HttpHeaders httpHeaders, String username, String password) {
String authorization = properties.getHeaders().get(AUTHORIZATION);
if (password != null && authorization != null) {
throw new IllegalStateException("You must set either 'password' or 'authorization'");
}
if (password != null) {
byte[] token = Base64Utils.encode((username + ":" + password).getBytes());
httpHeaders.add("Authorization", "Basic " + new String(token));
}
else if (authorization != null) {
httpHeaders.add("Authorization", authorization);
}
}
/**
* Adds the provided headers to the request.
*/
public static class GenericRequestHeaderInterceptor implements ClientHttpRequestInterceptor {
private final Map<String, String> headers;
public GenericRequestHeaderInterceptor(Map<String, String> headers) {
this.headers = headers;
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
for (Map.Entry<String, String> header : this.headers.entrySet()) {
request.getHeaders().add(header.getKey(), header.getValue());
}
return execution.execute(request, body);
}
protected Map<String, String> getHeaders() {
return this.headers;
}
}
}

View File

@@ -46,14 +46,12 @@ import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;
import static org.springframework.cloud.config.client.ConfigClientProperties.AUTHORIZATION;
import static org.springframework.cloud.config.client.ConfigClientProperties.STATE_HEADER;
import static org.springframework.cloud.config.client.ConfigClientProperties.TOKEN_HEADER;
@@ -240,6 +238,9 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader<ConfigServ
ResponseEntity<Environment> response = null;
List<MediaType> acceptHeader = Collections.singletonList(MediaType.parseMediaType(properties.getMediaType()));
ConfigClientRequestTemplateFactory requestTemplateFactory = context.getBootstrapContext()
.get(ConfigClientRequestTemplateFactory.class);
for (int i = 0; i < noOfUrls; i++) {
ConfigClientProperties.Credentials credentials = properties.getCredentials(i);
String uri = credentials.getUri();
@@ -251,7 +252,7 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader<ConfigServ
try {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptHeader);
addAuthorizationToken(properties, headers, username, password);
requestTemplateFactory.addAuthorizationToken(headers, username, password);
if (StringUtils.hasText(token)) {
headers.add(TOKEN_HEADER, token);
}
@@ -288,22 +289,9 @@ public class ConfigServerConfigDataLoader implements ConfigDataLoader<ConfigServ
return null;
}
@Deprecated
protected void addAuthorizationToken(ConfigClientProperties configClientProperties, HttpHeaders httpHeaders,
String username, String password) {
String authorization = configClientProperties.getHeaders().get(AUTHORIZATION);
if (password != null && authorization != null) {
throw new IllegalStateException("You must set either 'password' or 'authorization'");
}
if (password != null) {
byte[] token = Base64Utils.encode((username + ":" + password).getBytes());
httpHeaders.add("Authorization", "Basic " + new String(token));
}
else if (authorization != null) {
httpHeaders.add("Authorization", authorization);
}
}
}

View File

@@ -18,9 +18,7 @@ package org.springframework.cloud.config.client;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
@@ -38,12 +36,10 @@ import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.core.Ordered;
import org.springframework.core.log.LogMessage;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.retry.support.RetryTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import static org.springframework.cloud.config.client.ConfigClientProperties.AUTHORIZATION;
import static org.springframework.cloud.config.client.ConfigClientProperties.CONFIG_DISCOVERY_ENABLED;
public class ConfigServerConfigDataLocationResolver
@@ -84,27 +80,9 @@ public class ConfigServerConfigDataLocationResolver
return context.getBootstrapContext().getOrElse(BindHandler.class, null);
}
@Deprecated
protected RestTemplate createRestTemplate(ConfigClientProperties properties) {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
if (properties.getRequestReadTimeout() < 0) {
throw new IllegalStateException("Invalid Value for Read Timeout set.");
}
if (properties.getRequestConnectTimeout() < 0) {
throw new IllegalStateException("Invalid Value for Connect Timeout set.");
}
requestFactory.setReadTimeout(properties.getRequestReadTimeout());
requestFactory.setConnectTimeout(properties.getRequestConnectTimeout());
RestTemplate template = new RestTemplate(requestFactory);
Map<String, String> headers = new HashMap<>(properties.getHeaders());
if (headers.containsKey(AUTHORIZATION)) {
headers.remove(AUTHORIZATION); // To avoid redundant addition of header
}
if (!headers.isEmpty()) {
template.setInterceptors(Collections
.singletonList(new ConfigServicePropertySourceLocator.GenericRequestHeaderInterceptor(headers)));
}
return template;
return null;
}
protected Log getLog() {
@@ -147,9 +125,17 @@ public class ConfigServerConfigDataLocationResolver
bootstrapContext.addCloseListener(event -> event.getApplicationContext().getBeanFactory().registerSingleton(
"configDataConfigClientProperties", event.getBootstrapContext().get(ConfigClientProperties.class)));
bootstrapContext.registerIfAbsent(ConfigClientRequestTemplateFactory.class,
context -> new ConfigClientRequestTemplateFactory(log, context.get(ConfigClientProperties.class)));
bootstrapContext.registerIfAbsent(RestTemplate.class, context -> {
ConfigClientProperties props = context.get(ConfigClientProperties.class);
return createRestTemplate(props);
ConfigClientRequestTemplateFactory factory = context.get(ConfigClientRequestTemplateFactory.class);
RestTemplate restTemplate = createRestTemplate(factory.getProperties());
if (restTemplate != null) {
// shouldn't normally happen
return restTemplate;
}
return factory.create();
});
boolean discoveryEnabled = resolverContext.getBinder()

View File

@@ -16,8 +16,6 @@
package org.springframework.cloud.config.client;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -25,14 +23,9 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.net.ssl.SSLContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.origin.Origin;
@@ -42,33 +35,23 @@ import org.springframework.cloud.bootstrap.support.OriginTrackedCompositePropert
import org.springframework.cloud.config.client.ConfigClientProperties.Credentials;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.environment.PropertySource;
import org.springframework.cloud.configuration.SSLContextFactory;
import org.springframework.core.annotation.Order;
import org.springframework.core.env.CompositePropertySource;
import org.springframework.core.env.MapPropertySource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.retry.annotation.Retryable;
import org.springframework.util.Assert;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;
import org.springframework.web.client.RestTemplate;
import static org.springframework.cloud.config.client.ConfigClientProperties.AUTHORIZATION;
import static org.springframework.cloud.config.client.ConfigClientProperties.STATE_HEADER;
import static org.springframework.cloud.config.client.ConfigClientProperties.TOKEN_HEADER;
@@ -95,7 +78,9 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
public org.springframework.core.env.PropertySource<?> locate(org.springframework.core.env.Environment environment) {
ConfigClientProperties properties = this.defaultProperties.override(environment);
CompositePropertySource composite = new OriginTrackedCompositePropertySource("configService");
RestTemplate restTemplate = this.restTemplate == null ? getSecureRestTemplate(properties) : this.restTemplate;
ConfigClientRequestTemplateFactory requestTemplateFactory = new ConfigClientRequestTemplateFactory(logger,
properties);
Exception error = null;
String errorBody = null;
try {
@@ -106,7 +91,7 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
String state = ConfigClientStateHolder.getState();
// Try all the labels until one works
for (String label : labels) {
Environment result = getRemoteEnvironment(restTemplate, properties, label.trim(), state);
Environment result = getRemoteEnvironment(requestTemplateFactory, label.trim(), state);
if (result != null) {
log(result);
@@ -209,8 +194,10 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
}
}
private Environment getRemoteEnvironment(RestTemplate restTemplate, ConfigClientProperties properties, String label,
private Environment getRemoteEnvironment(ConfigClientRequestTemplateFactory requestTemplateFactory, String label,
String state) {
RestTemplate restTemplate = this.restTemplate == null ? requestTemplateFactory.create() : this.restTemplate;
ConfigClientProperties properties = requestTemplateFactory.getProperties();
String path = "/{name}/{profile}";
String name = properties.getName();
String profile = properties.getProfile();
@@ -241,7 +228,7 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
try {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptHeader);
addAuthorizationToken(properties, headers, username, password);
requestTemplateFactory.addAuthorizationToken(headers, username, password);
if (StringUtils.hasText(token)) {
headers.add(TOKEN_HEADER, token);
}
@@ -282,93 +269,15 @@ public class ConfigServicePropertySourceLocator implements PropertySourceLocator
this.restTemplate = restTemplate;
}
private RestTemplate getSecureRestTemplate(ConfigClientProperties client) {
if (client.getRequestReadTimeout() < 0) {
throw new IllegalStateException("Invalid Value for Read Timeout set.");
}
if (client.getRequestConnectTimeout() < 0) {
throw new IllegalStateException("Invalid Value for Connect Timeout set.");
}
ClientHttpRequestFactory requestFactory = createHttpRquestFactory(client);
RestTemplate template = new RestTemplate(requestFactory);
Map<String, String> headers = new HashMap<>(client.getHeaders());
if (headers.containsKey(AUTHORIZATION)) {
headers.remove(AUTHORIZATION); // To avoid redundant addition of header
}
if (!headers.isEmpty()) {
template.setInterceptors(
Arrays.<ClientHttpRequestInterceptor>asList(new GenericRequestHeaderInterceptor(headers)));
}
return template;
}
private ClientHttpRequestFactory createHttpRquestFactory(ConfigClientProperties client) {
if (client.getTls().isEnabled()) {
try {
SSLContextFactory factory = new SSLContextFactory(client.getTls());
SSLContext sslContext = factory.createSSLContext();
HttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
HttpComponentsClientHttpRequestFactory result = new HttpComponentsClientHttpRequestFactory(httpClient);
result.setReadTimeout(client.getRequestReadTimeout());
result.setConnectTimeout(client.getRequestConnectTimeout());
return result;
}
catch (GeneralSecurityException | IOException ex) {
logger.error(ex);
throw new IllegalStateException("Failed to create config client with TLS.", ex);
}
}
SimpleClientHttpRequestFactory result = new SimpleClientHttpRequestFactory();
result.setReadTimeout(client.getRequestReadTimeout());
result.setConnectTimeout(client.getRequestConnectTimeout());
return result;
}
private void addAuthorizationToken(ConfigClientProperties configClientProperties, HttpHeaders httpHeaders,
String username, String password) {
String authorization = configClientProperties.getHeaders().get(AUTHORIZATION);
if (password != null && authorization != null) {
throw new IllegalStateException("You must set either 'password' or 'authorization'");
}
if (password != null) {
byte[] token = Base64Utils.encode((username + ":" + password).getBytes());
httpHeaders.add("Authorization", "Basic " + new String(token));
}
else if (authorization != null) {
httpHeaders.add("Authorization", authorization);
}
}
/**
* Adds the provided headers to the request.
*/
public static class GenericRequestHeaderInterceptor implements ClientHttpRequestInterceptor {
private final Map<String, String> headers;
@Deprecated
public static class GenericRequestHeaderInterceptor
extends ConfigClientRequestTemplateFactory.GenericRequestHeaderInterceptor {
public GenericRequestHeaderInterceptor(Map<String, String> headers) {
this.headers = headers;
}
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
for (Entry<String, String> header : this.headers.entrySet()) {
request.getHeaders().add(header.getKey(), header.getValue());
}
return execution.execute(request, body);
}
protected Map<String, String> getHeaders() {
return this.headers;
super(headers);
}
}

View File

@@ -25,6 +25,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.LogFactory;
import org.hamcrest.core.IsInstanceOf;
import org.junit.Rule;
import org.junit.Test;
@@ -34,7 +35,7 @@ import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.GenericRequestHeaderInterceptor;
import org.springframework.cloud.config.client.ConfigClientRequestTemplateFactory.GenericRequestHeaderInterceptor;
import org.springframework.cloud.config.environment.Environment;
import org.springframework.cloud.config.environment.PropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
@@ -51,7 +52,6 @@ import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
@@ -227,8 +227,7 @@ public class ConfigServicePropertySourceLocatorTests {
byte[] body = new byte[] {};
Map<String, String> headers = new HashMap<>();
headers.put("X-Example-Version", "2.1");
new ConfigServicePropertySourceLocator.GenericRequestHeaderInterceptor(headers).intercept(request, body,
execution);
new GenericRequestHeaderInterceptor(headers).intercept(request, body, execution);
Mockito.verify(execution).execute(request, body);
assertThat(request.getHeaders().getFirst("X-Example-Version")).isEqualTo("2.1");
}
@@ -237,10 +236,9 @@ public class ConfigServicePropertySourceLocatorTests {
public void shouldAddAuthorizationHeaderWhenPasswordSet() {
HttpHeaders headers = new HttpHeaders();
ConfigClientProperties defaults = new ConfigClientProperties(this.environment);
this.locator = new ConfigServicePropertySourceLocator(defaults);
String username = "user";
String password = "pass";
ReflectionTestUtils.invokeMethod(this.locator, "addAuthorizationToken", defaults, headers, username, password);
factory(defaults).addAuthorizationToken(headers, username, password);
assertThat(headers).hasSize(1);
}
@@ -249,10 +247,9 @@ public class ConfigServicePropertySourceLocatorTests {
HttpHeaders headers = new HttpHeaders();
ConfigClientProperties defaults = new ConfigClientProperties(this.environment);
defaults.getHeaders().put(AUTHORIZATION, "Basic dXNlcm5hbWU6cGFzc3dvcmQNCg==");
this.locator = new ConfigServicePropertySourceLocator(defaults);
String username = "user";
String password = null;
ReflectionTestUtils.invokeMethod(this.locator, "addAuthorizationToken", defaults, headers, username, password);
factory(defaults).addAuthorizationToken(headers, username, password);
assertThat(headers).hasSize(1);
}
@@ -261,32 +258,29 @@ public class ConfigServicePropertySourceLocatorTests {
HttpHeaders headers = new HttpHeaders();
ConfigClientProperties defaults = new ConfigClientProperties(this.environment);
defaults.getHeaders().put(AUTHORIZATION, "Basic dXNlcm5hbWU6cGFzc3dvcmQNCg==");
this.locator = new ConfigServicePropertySourceLocator(defaults);
String username = "user";
String password = "pass";
this.expected.expect(IllegalStateException.class);
this.expected.expectMessage("You must set either 'password' or 'authorization'");
ReflectionTestUtils.invokeMethod(this.locator, "addAuthorizationToken", defaults, headers, username, password);
factory(defaults).addAuthorizationToken(headers, username, password);
}
@Test
public void shouldThrowExceptionWhenNegativeReadTimeoutSet() {
ConfigClientProperties defaults = new ConfigClientProperties(this.environment);
defaults.setRequestReadTimeout(-1);
this.locator = new ConfigServicePropertySourceLocator(defaults);
this.expected.expect(IllegalStateException.class);
this.expected.expectMessage("Invalid Value for Read Timeout set.");
ReflectionTestUtils.invokeMethod(this.locator, "getSecureRestTemplate", defaults);
factory(defaults).create();
}
@Test
public void shouldThrowExceptionWhenNegativeConnectTimeoutSet() {
ConfigClientProperties defaults = new ConfigClientProperties(this.environment);
defaults.setRequestConnectTimeout(-1);
this.locator = new ConfigServicePropertySourceLocator(defaults);
this.expected.expect(IllegalStateException.class);
this.expected.expectMessage("Invalid Value for Connect Timeout set.");
ReflectionTestUtils.invokeMethod(this.locator, "getSecureRestTemplate", defaults);
factory(defaults).create();
}
@Test
@@ -294,8 +288,7 @@ public class ConfigServicePropertySourceLocatorTests {
ConfigClientProperties defaults = new ConfigClientProperties(this.environment);
defaults.getHeaders().put(AUTHORIZATION, "Basic dXNlcm5hbWU6cGFzc3dvcmQNCg==");
defaults.getHeaders().put("key", "value");
this.locator = new ConfigServicePropertySourceLocator(defaults);
RestTemplate restTemplate = ReflectionTestUtils.invokeMethod(this.locator, "getSecureRestTemplate", defaults);
RestTemplate restTemplate = factory(defaults).create();
Iterator<ClientHttpRequestInterceptor> iterator = restTemplate.getInterceptors().iterator();
while (iterator.hasNext()) {
GenericRequestHeaderInterceptor genericRequestHeaderInterceptor = (GenericRequestHeaderInterceptor) iterator
@@ -304,6 +297,10 @@ public class ConfigServicePropertySourceLocatorTests {
}
}
private ConfigClientRequestTemplateFactory factory(ConfigClientProperties properties) {
return new ConfigClientRequestTemplateFactory(LogFactory.getLog(getClass()), properties);
}
@SuppressWarnings({ "unchecked", "raw" })
@Test
public void shouldPreserveOrder() {