diff --git a/spring-cloud-config-dependencies/pom.xml b/spring-cloud-config-dependencies/pom.xml
index 5e8ba76a..fbe60054 100644
--- a/spring-cloud-config-dependencies/pom.xml
+++ b/spring-cloud-config-dependencies/pom.xml
@@ -48,6 +48,11 @@
org.eclipse.jgit.junit.http
${jgit.version}
+
+ org.eclipse.jgit
+ org.eclipse.jgit.http.apache
+ ${jgit.version}
+
com.jcraft
jsch
diff --git a/spring-cloud-config-server/pom.xml b/spring-cloud-config-server/pom.xml
index 86ab7029..d6cb96b4 100644
--- a/spring-cloud-config-server/pom.xml
+++ b/spring-cloud-config-server/pom.xml
@@ -51,6 +51,10 @@
org.eclipse.jgit
org.eclipse.jgit
+
+ org.eclipse.jgit
+ org.eclipse.jgit.http.apache
+
org.yaml
snakeyaml
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java
index ad766d58..538d7713 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EnvironmentRepositoryConfiguration.java
@@ -15,20 +15,12 @@
*/
package org.springframework.cloud.config.server.config;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Optional;
-import javax.net.ssl.SSLContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.http.client.HttpClient;
-import org.apache.http.conn.ssl.NoopHostnameVerifier;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.ssl.SSLContextBuilder;
import org.eclipse.jgit.api.TransportConfigCallback;
import org.tmatesoft.svn.core.SVNException;
@@ -47,6 +39,9 @@ import org.springframework.cloud.config.server.environment.CompositeEnvironmentR
import org.springframework.cloud.config.server.environment.ConsulEnvironmentWatch;
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
import org.springframework.cloud.config.server.environment.EnvironmentWatch;
+import org.springframework.cloud.config.server.environment.HttpClientConfigurableHttpConnectionFactory;
+import org.springframework.cloud.config.server.environment.HttpClientVaultRestTemplateFactory;
+import org.springframework.cloud.config.server.environment.ConfigurableHttpConnectionFactory;
import org.springframework.cloud.config.server.environment.JdbcEnvironmentProperties;
import org.springframework.cloud.config.server.environment.JdbcEnvironmentRepository;
import org.springframework.cloud.config.server.environment.JdbcEnvironmentRepositoryFactory;
@@ -70,9 +65,7 @@ import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
-import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.web.client.RestTemplate;
/**
* @author Dave Syer
@@ -124,11 +117,24 @@ public class EnvironmentRepositoryConfiguration {
@Configuration
@ConditionalOnClass(TransportConfigCallback.class)
static class JGitFactoryConfig {
+
@Bean
public MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory(
ConfigurableEnvironment environment, ConfigServerProperties server,
+ Optional jgitHttpConnectionFactory,
Optional customTransportConfigCallback) {
- return new MultipleJGitEnvironmentRepositoryFactory(environment, server, customTransportConfigCallback);
+ return new MultipleJGitEnvironmentRepositoryFactory(environment, server, jgitHttpConnectionFactory,
+ customTransportConfigCallback);
+ }
+ }
+
+ @Configuration
+ @ConditionalOnClass({ HttpClient.class, TransportConfigCallback.class })
+ static class JGitHttpClientConfig {
+
+ @Bean
+ public ConfigurableHttpConnectionFactory httpClientConnectionFactory() {
+ return new HttpClientConfigurableHttpConnectionFactory();
}
}
@@ -144,17 +150,28 @@ public class EnvironmentRepositoryConfiguration {
@Configuration
static class VaultFactoryConfig {
+
@Bean
public VaultEnvironmentRepositoryFactory vaultEnvironmentRepositoryFactory(
ObjectProvider request, EnvironmentWatch watch,
- Optional skipSslValidationRestTemplate) {
- return new VaultEnvironmentRepositoryFactory(request, watch, skipSslValidationRestTemplate);
+ Optional vaultRestTemplateFactory) {
+ return new VaultEnvironmentRepositoryFactory(request, watch, vaultRestTemplateFactory);
+ }
+ }
+
+ @Configuration
+ @ConditionalOnClass(HttpClient.class)
+ static class VaultHttpClientConfig {
+
+ @Bean
+ public VaultEnvironmentRepositoryFactory.VaultRestTemplateFactory vaultRestTemplateFactory() {
+ return new HttpClientVaultRestTemplateFactory();
}
}
@Configuration
@ConditionalOnClass(JdbcTemplate.class)
- static class JdbcCompositeConfig {
+ static class JdbcFactoryConfig {
@Bean
@ConditionalOnBean(JdbcTemplate.class)
public JdbcEnvironmentRepositoryFactory jdbcEnvironmentRepositoryFactory(JdbcTemplate jdbc) {
@@ -171,24 +188,6 @@ public class EnvironmentRepositoryConfiguration {
}
}
- @Bean
- @ConditionalOnClass(HttpClient.class)
- public RestTemplate skipSslValidationRestTemplate() {
- try {
- SSLContext sslContext = new SSLContextBuilder()
- .loadTrustMaterial(null, (certificate, authType) -> true)
- .build();
- CloseableHttpClient httpClient = HttpClients.custom()
- .setSSLContext(sslContext)
- .setSSLHostnameVerifier(new NoopHostnameVerifier())
- .build();
- HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
- requestFactory.setHttpClient(httpClient);
- return new RestTemplate(requestFactory);
- } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
- throw new RuntimeException(e);
- }
- }
}
@Configuration
@@ -206,7 +205,7 @@ class DefaultRepositoryConfiguration {
@Bean
public MultipleJGitEnvironmentRepository defaultEnvironmentRepository(
MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory,
- MultipleJGitEnvironmentProperties environmentProperties) {
+ MultipleJGitEnvironmentProperties environmentProperties) throws Exception {
return gitEnvironmentRepositoryFactory.build(environmentProperties);
}
}
@@ -245,7 +244,8 @@ class VaultRepositoryConfiguration {
@Bean
public VaultEnvironmentRepository vaultEnvironmentRepository(VaultEnvironmentRepositoryFactory factory,
- VaultEnvironmentProperties environmentProperties) {
+ VaultEnvironmentProperties environmentProperties)
+ throws Exception {
return factory.build(environmentProperties);
}
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/ConfigurableHttpConnectionFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/ConfigurableHttpConnectionFactory.java
new file mode 100644
index 00000000..2b162c4f
--- /dev/null
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/ConfigurableHttpConnectionFactory.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.environment;
+
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+
+/**
+ * @author Dylan Roberts
+ */
+public interface ConfigurableHttpConnectionFactory extends HttpConnectionFactory {
+ void addConfiguration(MultipleJGitEnvironmentProperties environmentProperties) throws Exception;
+}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactory.java
new file mode 100644
index 00000000..a163a0ac
--- /dev/null
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactory.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.environment;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.Proxy;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.eclipse.jgit.transport.http.HttpConnection;
+import org.eclipse.jgit.transport.http.apache.HttpClientConnection;
+
+import org.springframework.cloud.config.server.support.HttpClientSupport;
+
+/**
+ * @author Dylan Roberts
+ */
+public class HttpClientConfigurableHttpConnectionFactory implements ConfigurableHttpConnectionFactory {
+
+ private Map httpClientsByUri = new HashMap<>();
+
+ @Override
+ public void addConfiguration(MultipleJGitEnvironmentProperties environmentProperties)
+ throws GeneralSecurityException {
+ addHttpClient(environmentProperties);
+ for (JGitEnvironmentProperties repo : environmentProperties.getRepos().values()) {
+ addHttpClient(repo);
+ }
+ }
+
+ @Override
+ public HttpConnection create(URL url) throws IOException {
+ return create(url, null);
+ }
+
+ @Override
+ public HttpConnection create(URL url, Proxy proxy) throws IOException {
+ return new HttpClientConnection(url.toString(), proxy, lookupHttpClientBuilder(url).build());
+ }
+
+ private void addHttpClient(JGitEnvironmentProperties properties) throws GeneralSecurityException {
+ if (properties.getUri().startsWith("http")) {
+ httpClientsByUri.put(properties.getUri(), HttpClientSupport.builder(properties));
+ }
+ }
+
+ private HttpClientBuilder lookupHttpClientBuilder(URL url) throws MalformedURLException {
+ String spec = url.toString();
+ HttpClientBuilder builder = httpClientsByUri.get(spec);
+ while (builder == null) {
+ spec = spec.substring(0, spec.lastIndexOf(File.separator));
+ builder = httpClientsByUri.get(spec);
+ }
+ return builder;
+ }
+}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientVaultRestTemplateFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientVaultRestTemplateFactory.java
new file mode 100644
index 00000000..dab95a6d
--- /dev/null
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientVaultRestTemplateFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.environment;
+
+import java.security.GeneralSecurityException;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.CloseableHttpClient;
+
+import org.springframework.cloud.config.server.support.HttpClientSupport;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * @author Dylan Roberts
+ */
+public class HttpClientVaultRestTemplateFactory implements VaultEnvironmentRepositoryFactory.VaultRestTemplateFactory {
+
+ @Override
+ public RestTemplate build(VaultEnvironmentProperties environmentProperties) throws GeneralSecurityException {
+ HttpClient httpClient = HttpClientSupport.builder(environmentProperties).build();
+ return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
+ }
+}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentProperties.java
index 5dcacd7c..3598f62b 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentProperties.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentProperties.java
@@ -15,15 +15,20 @@
*/
package org.springframework.cloud.config.server.environment;
+import java.util.HashMap;
+import java.util.Map;
import javax.validation.constraints.Pattern;
+import org.springframework.cloud.config.server.proxy.ProxyHostProperties;
import org.springframework.cloud.config.server.support.AbstractScmAccessorProperties;
+import org.springframework.cloud.config.server.support.HttpEnvironmentRepositoryProperties;
/**
* @author Dylan Roberts
* @author Gareth Clay
*/
-public class JGitEnvironmentProperties extends AbstractScmAccessorProperties {
+public class JGitEnvironmentProperties extends AbstractScmAccessorProperties
+ implements HttpEnvironmentRepositoryProperties {
private static final String DEFAULT_LABEL = "master";
/** Flag to indicate that the repository should be cloned on startup (not on demand). Generally leads to slower startup but faster first query. */
@@ -85,6 +90,11 @@ public class JGitEnvironmentProperties extends AbstractScmAccessorProperties {
*/
private boolean strictHostKeyChecking = true;
+ /**
+ * HTTP proxy configuration.
+ */
+ private Map proxy = new HashMap<>();
+
public JGitEnvironmentProperties() {
super();
setDefaultLabel(DEFAULT_LABEL);
@@ -188,6 +198,7 @@ public class JGitEnvironmentProperties extends AbstractScmAccessorProperties {
this.strictHostKeyChecking = strictHostKeyChecking;
}
+ @Override
public boolean isSkipSslValidation() {
return skipSslValidation;
}
@@ -195,4 +206,13 @@ public class JGitEnvironmentProperties extends AbstractScmAccessorProperties {
public void setSkipSslValidation(boolean skipSslValidation) {
this.skipSslValidation = skipSslValidation;
}
+
+ @Override
+ public Map getProxy() {
+ return proxy;
+ }
+
+ public void setProxy(Map proxy) {
+ this.proxy = proxy;
+ }
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryFactory.java
index a01aaa9b..80f5e922 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryFactory.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryFactory.java
@@ -18,6 +18,7 @@ package org.springframework.cloud.config.server.environment;
import java.util.Optional;
import org.eclipse.jgit.api.TransportConfigCallback;
+import org.eclipse.jgit.transport.HttpTransport;
import org.springframework.cloud.config.server.config.ConfigServerProperties;
import org.springframework.cloud.config.server.ssh.FileBasedSshTransportConfigCallback;
@@ -31,17 +32,33 @@ public class MultipleJGitEnvironmentRepositoryFactory implements EnvironmentRepo
MultipleJGitEnvironmentProperties> {
private ConfigurableEnvironment environment;
private ConfigServerProperties server;
+ private Optional connectionFactory;
private Optional customTransportConfigCallback;
- public MultipleJGitEnvironmentRepositoryFactory(ConfigurableEnvironment environment, ConfigServerProperties server,
- Optional customTransportConfigCallback) {
+ @Deprecated
+ public MultipleJGitEnvironmentRepositoryFactory(ConfigurableEnvironment environment, ConfigServerProperties server,
+ Optional customTransportConfigCallback) {
+ this(environment, server, Optional.empty(), customTransportConfigCallback);
+ }
+
+ public MultipleJGitEnvironmentRepositoryFactory(
+ ConfigurableEnvironment environment, ConfigServerProperties server,
+ Optional connectionFactory,
+ Optional customTransportConfigCallback) {
this.environment = environment;
this.server = server;
+ this.connectionFactory = connectionFactory;
this.customTransportConfigCallback = customTransportConfigCallback;
}
@Override
- public MultipleJGitEnvironmentRepository build(MultipleJGitEnvironmentProperties environmentProperties) {
+ public MultipleJGitEnvironmentRepository build(MultipleJGitEnvironmentProperties environmentProperties)
+ throws Exception {
+ if (connectionFactory.isPresent()) {
+ HttpTransport.setConnectionFactory(connectionFactory.get());
+ connectionFactory.get().addConfiguration(environmentProperties);
+ }
+
MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(environment,
environmentProperties);
repository.setTransportConfigCallback(customTransportConfigCallback
@@ -52,10 +69,11 @@ public class MultipleJGitEnvironmentRepositoryFactory implements EnvironmentRepo
return repository;
}
- private TransportConfigCallback buildTransportConfigCallback(final MultipleJGitEnvironmentProperties gitEnvironmentProperties) {
+ private TransportConfigCallback buildTransportConfigCallback(MultipleJGitEnvironmentProperties gitEnvironmentProperties) {
if (gitEnvironmentProperties.isIgnoreLocalSshSettings()) {
return new PropertiesBasedSshTransportConfigCallback(gitEnvironmentProperties);
}
return new FileBasedSshTransportConfigCallback(gitEnvironmentProperties);
}
+
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java
index 3ae680e1..76dda1fc 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentProperties.java
@@ -15,15 +15,19 @@
*/
package org.springframework.cloud.config.server.environment;
+import java.util.HashMap;
+import java.util.Map;
+
import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties;
+import org.springframework.cloud.config.server.proxy.ProxyHostProperties;
+import org.springframework.cloud.config.server.support.HttpEnvironmentRepositoryProperties;
import org.springframework.core.Ordered;
/**
* @author Dylan Roberts
*/
@ConfigurationProperties("spring.cloud.config.server.vault")
-public class VaultEnvironmentProperties implements EnvironmentRepositoryProperties {
+public class VaultEnvironmentProperties implements HttpEnvironmentRepositoryProperties {
/** Vault host. Defaults to 127.0.0.1. */
private String host = "127.0.0.1";
/** Vault port. Defaults to 8200. */
@@ -41,6 +45,12 @@ public class VaultEnvironmentProperties implements EnvironmentRepositoryProperti
* over an HTTPS connection.
*/
private boolean skipSslValidation = false;
+
+ /**
+ * HTTP proxy configuration.
+ */
+ private Map proxy = new HashMap<>();
+
private int order = Ordered.LOWEST_PRECEDENCE;
public String getHost() {
@@ -91,6 +101,7 @@ public class VaultEnvironmentProperties implements EnvironmentRepositoryProperti
this.profileSeparator = profileSeparator;
}
+ @Override
public boolean isSkipSslValidation() {
return skipSslValidation;
}
@@ -99,6 +110,15 @@ public class VaultEnvironmentProperties implements EnvironmentRepositoryProperti
this.skipSslValidation = skipSslValidation;
}
+ @Override
+ public Map getProxy() {
+ return proxy;
+ }
+
+ public void setProxy(Map proxy) {
+ this.proxy = proxy;
+ }
+
public int getOrder() {
return order;
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentRepositoryFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentRepositoryFactory.java
index 6128d5dd..90659fb5 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentRepositoryFactory.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultEnvironmentRepositoryFactory.java
@@ -28,21 +28,26 @@ public class VaultEnvironmentRepositoryFactory implements EnvironmentRepositoryF
VaultEnvironmentProperties> {
private ObjectProvider request;
private EnvironmentWatch watch;
- private Optional skipSslValidationRestTemplate;
+ private Optional vaultRestTemplateFactory;
public VaultEnvironmentRepositoryFactory(ObjectProvider request, EnvironmentWatch watch,
- Optional skipSslValidationRestTemplate) {
+ Optional vaultRestTemplateFactory) {
this.request = request;
this.watch = watch;
- this.skipSslValidationRestTemplate = skipSslValidationRestTemplate;
+ this.vaultRestTemplateFactory = vaultRestTemplateFactory;
}
@Override
- public VaultEnvironmentRepository build(VaultEnvironmentProperties environmentProperties) {
- if (environmentProperties.isSkipSslValidation() && skipSslValidationRestTemplate.isPresent()) {
- return new VaultEnvironmentRepository(request, watch, skipSslValidationRestTemplate.get(),
- environmentProperties);
+ public VaultEnvironmentRepository build(VaultEnvironmentProperties environmentProperties) throws Exception {
+ if (vaultRestTemplateFactory.isPresent()) {
+ RestTemplate restTemplate = vaultRestTemplateFactory.get().build(environmentProperties);
+ return new VaultEnvironmentRepository(request, watch, restTemplate, environmentProperties);
}
return new VaultEnvironmentRepository(request, watch, new RestTemplate(), environmentProperties);
}
+
+ public interface VaultRestTemplateFactory {
+
+ RestTemplate build(VaultEnvironmentProperties environmentProperties) throws Exception;
+ }
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/ProxyHostCredentialsProvider.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/ProxyHostCredentialsProvider.java
new file mode 100644
index 00000000..a6cfb140
--- /dev/null
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/ProxyHostCredentialsProvider.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.proxy;
+
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+
+/**
+ * @author Dylan Roberts
+ */
+public class ProxyHostCredentialsProvider extends BasicCredentialsProvider {
+
+ public ProxyHostCredentialsProvider(ProxyHostProperties... proxyHostProperties) {
+
+ for (ProxyHostProperties proxy : proxyHostProperties) {
+
+ if (proxy != null && proxy.getUsername() != null && proxy.getPassword() != null) {
+ AuthScope authscope = new AuthScope(proxy.getHost(), proxy.getPort());
+ UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(proxy.getUsername(),
+ proxy.getPassword());
+ setCredentials(authscope, credentials);
+ }
+ }
+ }
+}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/ProxyHostProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/ProxyHostProperties.java
new file mode 100644
index 00000000..67bdee27
--- /dev/null
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/ProxyHostProperties.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.proxy;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public class ProxyHostProperties {
+ private String host;
+ private int port;
+ private String nonProxyHosts;
+ private String username;
+ private String password;
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getNonProxyHosts() {
+ return nonProxyHosts;
+ }
+
+ public void setNonProxyHosts(String nonProxyHosts) {
+ this.nonProxyHosts = nonProxyHosts;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public enum ProxyForScheme {
+ HTTP,
+ HTTPS;
+
+ @JsonCreator
+ public static ProxyForScheme forLowerCaseName(String lowerCaseName) {
+ return ProxyForScheme.valueOf(lowerCaseName.toUpperCase());
+ }
+
+ @JsonValue
+ public String lowercaseName() {
+ return this.name().toLowerCase();
+ }
+ }
+}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/SchemeBasedRoutePlanner.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/SchemeBasedRoutePlanner.java
new file mode 100644
index 00000000..e1d3510e
--- /dev/null
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/proxy/SchemeBasedRoutePlanner.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.proxy;
+
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequest;
+import org.apache.http.impl.conn.DefaultRoutePlanner;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * @author Dylan Roberts
+ */
+public class SchemeBasedRoutePlanner extends DefaultRoutePlanner {
+
+ private final ProxyHostProperties httpsProxy;
+ private final ProxyHostProperties httpProxy;
+
+ public SchemeBasedRoutePlanner(ProxyHostProperties httpsProxy, ProxyHostProperties httpProxy) {
+ super(null);
+ this.httpsProxy = httpsProxy;
+ this.httpProxy = httpProxy;
+ }
+
+ @Override
+ protected HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) {
+ return "https".equals(target.getSchemeName()) ?
+ determineProxy(httpsProxy) :
+ determineProxy(httpProxy);
+ }
+
+ private HttpHost determineProxy(ProxyHostProperties properties) {
+ if (properties == null) {
+ return null;
+ }
+ return new HttpHost(properties.getHost(), properties.getPort());
+ }
+}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java
new file mode 100644
index 00000000..0974e86a
--- /dev/null
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.support;
+
+import java.security.GeneralSecurityException;
+
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContextBuilder;
+
+import org.springframework.cloud.config.server.proxy.ProxyHostCredentialsProvider;
+import org.springframework.cloud.config.server.proxy.ProxyHostProperties;
+import org.springframework.cloud.config.server.proxy.SchemeBasedRoutePlanner;
+import org.springframework.util.CollectionUtils;
+
+/**
+ * @author Dylan Roberts
+ */
+public class HttpClientSupport {
+
+ public static HttpClientBuilder builder(HttpEnvironmentRepositoryProperties environmentProperties)
+ throws GeneralSecurityException {
+ SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
+ HttpClientBuilder httpClientBuilder = HttpClients.custom();
+
+ if (environmentProperties.isSkipSslValidation()) {
+ sslContextBuilder.loadTrustMaterial(null, (certificate, authType) -> true);
+ httpClientBuilder.setSSLHostnameVerifier(new NoopHostnameVerifier());
+ }
+
+ if (!CollectionUtils.isEmpty(environmentProperties.getProxy())) {
+ ProxyHostProperties httpsProxy = environmentProperties.getProxy().get(ProxyHostProperties.ProxyForScheme.HTTPS);
+ ProxyHostProperties httpProxy = environmentProperties.getProxy().get(ProxyHostProperties.ProxyForScheme.HTTP);
+
+ httpClientBuilder.setRoutePlanner(new SchemeBasedRoutePlanner(httpsProxy, httpProxy));
+ httpClientBuilder.setDefaultCredentialsProvider(new ProxyHostCredentialsProvider(httpProxy, httpsProxy));
+ }
+
+ return httpClientBuilder.setSSLContext(sslContextBuilder.build());
+ }
+}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpEnvironmentRepositoryProperties.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpEnvironmentRepositoryProperties.java
new file mode 100644
index 00000000..bb5cc3e0
--- /dev/null
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpEnvironmentRepositoryProperties.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.support;
+
+import java.util.Map;
+
+import org.springframework.cloud.config.server.proxy.ProxyHostProperties;
+import org.springframework.cloud.config.server.support.EnvironmentRepositoryProperties;
+
+/**
+ * @author Dylan Roberts
+ */
+public interface HttpEnvironmentRepositoryProperties extends EnvironmentRepositoryProperties {
+
+ Map getProxy();
+
+ boolean isSkipSslValidation();
+}
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CompositeClasspathTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CompositeClasspathTests.java
index 4bdccf4a..f8ccf98d 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CompositeClasspathTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/CompositeClasspathTests.java
@@ -45,6 +45,26 @@ public class CompositeClasspathTests {
}
}
+ @RunWith(ModifiedClassPathRunner.class)
+ @ClassPathExclusions("httpclient-*.jar")
+ public static class HttpClientTests {
+
+ @Test
+ public void contextLoads() {
+ new WebApplicationContextRunner()
+ .withUserConfiguration(ConfigServerApplication.class)
+ .withPropertyValues("spring.profiles.active:test,composite",
+ "spring.config.name:compositeconfigserver",
+ "spring.cloud.config.server.composite[0].uri:file:./target/repos/config-repo",
+ "spring.cloud.config.server.composite[0].type:git",
+ "spring.cloud.config.server.composite[1].uri:file:///./target/repos/svn-config-repo",
+ "spring.cloud.config.server.composite[1].type:svn")
+ .run(context -> {
+ CompositeUtils.getCompositeTypeList(context.getEnvironment());
+ });
+ }
+ }
+
@RunWith(ModifiedClassPathRunner.class)
@ClassPathExclusions("svnkit-*.jar")
public static class SvnTests {
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/config/HttpClientVaultRestTemplateFactoryTest.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/config/HttpClientVaultRestTemplateFactoryTest.java
new file mode 100644
index 00000000..70853c51
--- /dev/null
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/config/HttpClientVaultRestTemplateFactoryTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.config;
+
+import java.net.UnknownHostException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.springframework.cloud.config.server.environment.HttpClientVaultRestTemplateFactory;
+import org.springframework.cloud.config.server.environment.VaultEnvironmentProperties;
+import org.springframework.cloud.config.server.proxy.ProxyHostProperties;
+import org.springframework.web.client.RestTemplate;
+
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasProperty;
+import static org.hamcrest.Matchers.instanceOf;
+
+/**
+ * @author Dylan Roberts
+ */
+public class HttpClientVaultRestTemplateFactoryTest {
+ private static final ProxyHostProperties AUTHENTICATED_HTTP_PROXY = new ProxyHostProperties();
+ static {
+ AUTHENTICATED_HTTP_PROXY.setHost("http://authenticated.http.proxy");
+ AUTHENTICATED_HTTP_PROXY.setPort(8080);
+ AUTHENTICATED_HTTP_PROXY.setUsername("username");
+ AUTHENTICATED_HTTP_PROXY.setPassword("password");
+ }
+ private static final ProxyHostProperties AUTHENTICATED_HTTPS_PROXY = new ProxyHostProperties();
+ static {
+ AUTHENTICATED_HTTPS_PROXY.setHost("http://authenticated.https.proxy");
+ AUTHENTICATED_HTTPS_PROXY.setPort(8081);
+ AUTHENTICATED_HTTPS_PROXY.setUsername("username2");
+ AUTHENTICATED_HTTPS_PROXY.setPassword("password2");
+ }
+ private static final ProxyHostProperties HTTP_PROXY = new ProxyHostProperties();
+ static {
+ HTTP_PROXY.setHost("http://http.proxy");
+ HTTP_PROXY.setPort(8080);
+ }
+ private static final ProxyHostProperties HTTPS_PROXY = new ProxyHostProperties();
+ static {
+ HTTPS_PROXY.setHost("http://https.proxy");
+ HTTPS_PROXY.setPort(8081);
+ }
+
+ private HttpClientVaultRestTemplateFactory factory;
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Before
+ public void setUp() {
+ factory = new HttpClientVaultRestTemplateFactory();
+ }
+
+ @Test
+ public void authenticatedHttpsProxy() throws Exception {
+ VaultEnvironmentProperties properties = getVaultEnvironmentProperties(null, AUTHENTICATED_HTTPS_PROXY);
+ RestTemplate restTemplate = factory.build(properties);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString(AUTHENTICATED_HTTPS_PROXY.getHost()))));
+
+ restTemplate.getForObject("https://somehost", String.class);
+ }
+
+ @Test
+ public void httpsProxy() throws Exception {
+ VaultEnvironmentProperties properties = getVaultEnvironmentProperties(null, HTTPS_PROXY);
+ RestTemplate restTemplate = factory.build(properties);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString(HTTPS_PROXY.getHost()))));
+
+ restTemplate.getForObject("https://somehost", String.class);
+ }
+
+ @Test
+ public void httpsProxy_notCalled() throws Exception {
+ VaultEnvironmentProperties properties = getVaultEnvironmentProperties(null, HTTPS_PROXY);
+ RestTemplate restTemplate = factory.build(properties);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString("somehost"))));
+
+ restTemplate.getForObject("http://somehost", String.class);
+ }
+
+ @Test
+ public void authenticatedHttpProxy() throws Exception {
+ VaultEnvironmentProperties properties = getVaultEnvironmentProperties(AUTHENTICATED_HTTP_PROXY, null);
+ RestTemplate restTemplate = factory.build(properties);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString(AUTHENTICATED_HTTP_PROXY.getHost()))));
+
+ restTemplate.getForObject("http://somehost", String.class);
+ }
+
+ @Test
+ public void httpProxy() throws Exception {
+ VaultEnvironmentProperties properties = getVaultEnvironmentProperties(HTTP_PROXY, null);
+ RestTemplate restTemplate = factory.build(properties);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString(HTTP_PROXY.getHost()))));
+
+ restTemplate.getForObject("http://somehost", String.class);
+ }
+
+ @Test
+ public void httpProxy_notCalled() throws Exception {
+ VaultEnvironmentProperties properties = getVaultEnvironmentProperties(HTTP_PROXY, null);
+ RestTemplate restTemplate = factory.build(properties);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString("somehost"))));
+
+ restTemplate.getForObject("https://somehost", String.class);
+ }
+
+ private VaultEnvironmentProperties getVaultEnvironmentProperties(ProxyHostProperties httpProxy, ProxyHostProperties httpsProxy) {
+ Map proxyMap = new HashMap<>();
+ proxyMap.put(ProxyHostProperties.ProxyForScheme.HTTP, httpProxy);
+ proxyMap.put(ProxyHostProperties.ProxyForScheme.HTTPS, httpsProxy);
+ VaultEnvironmentProperties properties = new VaultEnvironmentProperties();
+ properties.setProxy(proxyMap);
+ return properties;
+ }
+}
\ No newline at end of file
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryHttpProxyTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryHttpProxyTests.java
new file mode 100644
index 00000000..d7bc11c7
--- /dev/null
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryHttpProxyTests.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2018 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
+ *
+ * http://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.server.environment;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.http.client.HttpClient;
+import org.eclipse.jgit.transport.HttpTransport;
+import org.eclipse.jgit.transport.http.HttpConnection;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.apache.HttpClientConnection;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import org.springframework.boot.WebApplicationType;
+import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.cloud.config.server.config.ConfigServerProperties;
+import org.springframework.cloud.config.server.config.EnvironmentRepositoryConfiguration;
+import org.springframework.cloud.config.server.proxy.ProxyHostProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.test.util.ReflectionTestUtils;
+import org.springframework.web.client.RestTemplate;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasProperty;
+import static org.hamcrest.Matchers.instanceOf;
+
+/**
+ * @author Dylan Roberts
+ */
+public class JGitEnvironmentRepositoryHttpProxyTests {
+ private static final ProxyHostProperties AUTHENTICATED_HTTP_PROXY = new ProxyHostProperties();
+ static {
+ AUTHENTICATED_HTTP_PROXY.setHost("http://authenticated.http.proxy");
+ AUTHENTICATED_HTTP_PROXY.setPort(8080);
+ AUTHENTICATED_HTTP_PROXY.setUsername("username");
+ AUTHENTICATED_HTTP_PROXY.setPassword("password");
+ }
+ private static final ProxyHostProperties AUTHENTICATED_HTTPS_PROXY = new ProxyHostProperties();
+ static {
+ AUTHENTICATED_HTTPS_PROXY.setHost("http://authenticated.https.proxy");
+ AUTHENTICATED_HTTPS_PROXY.setPort(8081);
+ AUTHENTICATED_HTTPS_PROXY.setUsername("username2");
+ AUTHENTICATED_HTTPS_PROXY.setPassword("password2");
+ }
+ private static final ProxyHostProperties HTTP_PROXY = new ProxyHostProperties();
+ static {
+ HTTP_PROXY.setHost("http://http.proxy");
+ HTTP_PROXY.setPort(8080);
+ }
+ private static final ProxyHostProperties HTTPS_PROXY = new ProxyHostProperties();
+ static {
+ HTTPS_PROXY.setHost("http://https.proxy");
+ HTTPS_PROXY.setPort(8081);
+ }
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void authenticatedHttpsProxy() throws Exception {
+ String repoUrl = "https://myrepo/repo.git";
+ new SpringApplicationBuilder(TestConfiguration.class)
+ .web(WebApplicationType.NONE)
+ .properties(gitProperties(repoUrl, null, AUTHENTICATED_HTTPS_PROXY))
+ .run();
+ HttpClient httpClient = getHttpClientForUrl(repoUrl);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString(AUTHENTICATED_HTTPS_PROXY.getHost()))));
+
+ makeRequest(httpClient, "https://somehost");
+ }
+
+ @Test
+ public void httpsProxy() throws Exception {
+ String repoUrl = "https://myrepo/repo.git";
+ new SpringApplicationBuilder(TestConfiguration.class)
+ .web(WebApplicationType.NONE)
+ .properties(gitProperties(repoUrl, null, HTTPS_PROXY))
+ .run();
+ HttpClient httpClient = getHttpClientForUrl(repoUrl);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString(HTTPS_PROXY.getHost()))));
+
+ makeRequest(httpClient, "https://somehost");
+ }
+
+ @Test
+ public void httpsProxy_notCalled() throws Exception {
+ String repoUrl = "https://myrepo/repo.git";
+ new SpringApplicationBuilder(TestConfiguration.class)
+ .web(WebApplicationType.NONE)
+ .properties(gitProperties(repoUrl, null, HTTPS_PROXY))
+ .run();
+ HttpClient httpClient = getHttpClientForUrl(repoUrl);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString("somehost"))));
+
+ makeRequest(httpClient, "http://somehost");
+ }
+
+ @Test
+ public void authenticatedHttpProxy() throws Exception {
+ String repoUrl = "https://myrepo/repo.git";
+ new SpringApplicationBuilder(TestConfiguration.class)
+ .web(WebApplicationType.NONE)
+ .properties(gitProperties(repoUrl, AUTHENTICATED_HTTP_PROXY, null))
+ .run();
+ HttpClient httpClient = getHttpClientForUrl(repoUrl);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString(AUTHENTICATED_HTTP_PROXY.getHost()))));
+
+ makeRequest(httpClient, "http://somehost");
+ }
+
+ @Test
+ public void httpProxy() throws Exception {
+ String repoUrl = "https://myrepo/repo.git";
+ new SpringApplicationBuilder(TestConfiguration.class)
+ .web(WebApplicationType.NONE)
+ .properties(gitProperties(repoUrl, HTTP_PROXY, null))
+ .run();
+ HttpClient httpClient = getHttpClientForUrl(repoUrl);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString(HTTP_PROXY.getHost()))));
+
+ makeRequest(httpClient, "http://somehost");
+ }
+
+ @Test
+ public void httpProxy_notCalled() throws Exception {
+ String repoUrl = "https://myrepo/repo.git";
+ new SpringApplicationBuilder(TestConfiguration.class)
+ .web(WebApplicationType.NONE)
+ .properties(gitProperties(repoUrl, HTTP_PROXY, null))
+ .run();
+ HttpClient httpClient = getHttpClientForUrl(repoUrl);
+ expectedException.expectCause(allOf(
+ instanceOf(UnknownHostException.class),
+ hasProperty("message", containsString("somehost"))));
+
+ makeRequest(httpClient, "https://somehost");
+ }
+
+ private String[] gitProperties(String repoUrl, ProxyHostProperties httpProxy, ProxyHostProperties httpsProxy) {
+ List result = new ArrayList<>();
+ result.add("spring.cloud.config.server.git.uri=" + repoUrl);
+ if (httpProxy != null) {
+ result.addAll(Arrays.asList(
+ "spring.cloud.config.server.git.proxy.http.host=" + httpProxy.getHost(),
+ "spring.cloud.config.server.git.proxy.http.port=" + httpProxy.getPort()
+ ));
+ if (httpProxy.getUsername() != null && httpProxy.getPassword() != null) {
+ result.addAll(Arrays.asList(
+ "spring.cloud.config.server.git.proxy.http.username=" + httpProxy.getUsername(),
+ "spring.cloud.config.server.git.proxy.http.password=" + httpProxy.getPassword()
+ ));
+ }
+ }
+ if (httpsProxy != null) {
+ result.addAll(Arrays.asList(
+ "spring.cloud.config.server.git.proxy.https.host=" + httpsProxy.getHost(),
+ "spring.cloud.config.server.git.proxy.https.port=" + httpsProxy.getPort()
+ ));
+ if (httpsProxy.getUsername() != null && httpsProxy.getPassword() != null) {
+ result.addAll(Arrays.asList(
+ "spring.cloud.config.server.git.proxy.https.username=" + httpsProxy.getUsername(),
+ "spring.cloud.config.server.git.proxy.https.password=" + httpsProxy.getPassword()
+ ));
+ }
+ }
+ return result.toArray(new String[0]);
+ }
+
+ private void makeRequest(HttpClient httpClient, String url) {
+ RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
+ restTemplate.getForObject(url, String.class);
+ }
+
+ private HttpClient getHttpClientForUrl(String repoUrl) throws IOException {
+ HttpConnectionFactory connectionFactory = HttpTransport.getConnectionFactory();
+ HttpConnection httpConnection = connectionFactory.create(new URL(repoUrl));
+ assertThat(httpConnection).isInstanceOf(HttpClientConnection.class);
+ return (HttpClient) ReflectionTestUtils.getField(httpConnection, "client");
+ }
+
+ @Configuration
+ @EnableConfigurationProperties(ConfigServerProperties.class)
+ @Import({ PropertyPlaceholderAutoConfiguration.class, EnvironmentRepositoryConfiguration.class })
+ protected static class TestConfiguration {
+ }
+}
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/VaultEnvironmentRepositoryIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/VaultEnvironmentRepositoryIntegrationTests.java
index 3ea6ebe4..5842de0f 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/VaultEnvironmentRepositoryIntegrationTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/VaultEnvironmentRepositoryIntegrationTests.java
@@ -15,18 +15,10 @@
*/
package org.springframework.cloud.config.server.environment;
-import java.security.KeyManagementException;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
import java.util.Optional;
-import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
import javax.servlet.http.HttpServletRequest;
-import org.apache.http.conn.ssl.NoopHostnameVerifier;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.ssl.SSLContextBuilder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -39,9 +31,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.config.environment.Environment;
-import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.test.context.junit4.SpringRunner;
-import org.springframework.web.client.RestTemplate;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.instanceOf;
@@ -55,10 +45,10 @@ import static org.mockito.Mockito.when;
@SpringBootTest(classes = VaultEnvironmentRepositoryIntegrationTests.TestApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {
- "server.ssl.key-store=classpath:ssl-test.jks",
- "server.ssl.key-store-password=password",
- "server.ssl.key-password=password",
- "server.key-alias=ssl-test"})
+ "server.ssl.key-store=classpath:ssl-test.jks",
+ "server.ssl.key-store-password=password",
+ "server.ssl.key-password=password",
+ "server.key-alias=ssl-test"})
public class VaultEnvironmentRepositoryIntegrationTests {
@LocalServerPort
@@ -68,10 +58,10 @@ public class VaultEnvironmentRepositoryIntegrationTests {
public ExpectedException expectedException = ExpectedException.none();
@Test
- public void withSslValidation() {
+ public void withSslValidation() throws Exception {
VaultEnvironmentRepositoryFactory vaultEnvironmentRepositoryFactory =
new VaultEnvironmentRepositoryFactory(withRequest(), new EnvironmentWatch.Default(),
- Optional.of(skipSslValidationRestTemplate()));
+ Optional.of(new HttpClientVaultRestTemplateFactory()));
VaultEnvironmentRepository vaultEnvironmentRepository =
vaultEnvironmentRepositoryFactory.build(withEnvironmentProperties(false));
expectedException.expectCause(instanceOf(SSLHandshakeException.class));
@@ -80,10 +70,10 @@ public class VaultEnvironmentRepositoryIntegrationTests {
}
@Test
- public void skipSslValidation() {
+ public void skipSslValidation() throws Exception {
VaultEnvironmentRepositoryFactory vaultEnvironmentRepositoryFactory =
new VaultEnvironmentRepositoryFactory(withRequest(), new EnvironmentWatch.Default(),
- Optional.of(skipSslValidationRestTemplate()));
+ Optional.of(new HttpClientVaultRestTemplateFactory()));
VaultEnvironmentRepository vaultEnvironmentRepository =
vaultEnvironmentRepositoryFactory.build(withEnvironmentProperties(true));
@@ -92,23 +82,6 @@ public class VaultEnvironmentRepositoryIntegrationTests {
assertThat(actual).isNotNull();
}
- private RestTemplate skipSslValidationRestTemplate() {
- try {
- SSLContext sslContext = new SSLContextBuilder()
- .loadTrustMaterial(null, (certificate, authType) -> true)
- .build();
- CloseableHttpClient httpClient = HttpClients.custom()
- .setSSLContext(sslContext)
- .setSSLHostnameVerifier(new NoopHostnameVerifier())
- .build();
- HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
- requestFactory.setHttpClient(httpClient);
- return new RestTemplate(requestFactory);
- } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
- throw new RuntimeException(e);
- }
- }
-
private VaultEnvironmentProperties withEnvironmentProperties(boolean skipSslValidation) {
VaultEnvironmentProperties environmentProperties = new VaultEnvironmentProperties();
environmentProperties.setPort(Integer.decode(localServerPort));