Merge branch 'master' of github.com:spring-cloud/spring-cloud-config
This commit is contained in:
@@ -105,6 +105,7 @@ If there are profile-specific YAML (or properties) files, these are also applied
|
||||
Higher precedence translates to a `PropertySource` listed earlier in the `Environment`.
|
||||
(These same rules apply in a standalone Spring Boot application.)
|
||||
|
||||
You can set spring.cloud.config.server.accept-empty to false so that Server would return a HTTP 404 status, if the application is not found.By default, this flag is set to true.
|
||||
==== Git Backend
|
||||
|
||||
The default implementation of `EnvironmentRepository` uses a Git backend, which is very convenient for managing upgrades and physical
|
||||
|
||||
@@ -233,14 +233,16 @@ public class ConfigClientProperties {
|
||||
String bare = UriComponentsBuilder.fromHttpUrl(uri).userInfo(null).build()
|
||||
.toUriString();
|
||||
result.uri = bare;
|
||||
// handle the password only case
|
||||
|
||||
// if userInfo does not contain a :, then append a : to it
|
||||
if (!userInfo.contains(":")) {
|
||||
userInfo = userInfo + ":";
|
||||
}
|
||||
String[] split = userInfo.split(":");
|
||||
|
||||
int sepIndex=userInfo.indexOf(":");
|
||||
// set username and password from uri
|
||||
result.username = split[0];
|
||||
result.password = split[1];
|
||||
result.username = userInfo.substring(0, sepIndex);
|
||||
result.password = userInfo.substring(sepIndex +1);
|
||||
|
||||
// override password if explicitly set
|
||||
if (explicitCredentials.password != null) {
|
||||
|
||||
@@ -59,7 +59,51 @@ public class ConfigClientPropertiesTests {
|
||||
assertEquals("foo", locator.getUsername());
|
||||
assertEquals("secret", locator.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfNoColonPresentInUriCreds() {
|
||||
locator.setUri("http://foobar@localhost:9999");
|
||||
locator.setPassword("secret");
|
||||
assertEquals("http://localhost:9999", locator.getRawUri());
|
||||
assertEquals("foobar", locator.getUsername());
|
||||
assertEquals("secret", locator.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfColonPresentAtTheEndInUriCreds() {
|
||||
locator.setUri("http://foobar:@localhost:9999");
|
||||
locator.setPassword("secret");
|
||||
assertEquals("http://localhost:9999", locator.getRawUri());
|
||||
assertEquals("foobar", locator.getUsername());
|
||||
assertEquals("secret", locator.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfColonPresentAtTheStartInUriCreds() {
|
||||
locator.setUri("http://:foobar@localhost:9999");
|
||||
assertEquals("http://localhost:9999", locator.getRawUri());
|
||||
assertEquals("", locator.getUsername());
|
||||
assertEquals("foobar", locator.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfColonPresentAtTheStartAndEndInUriCreds() {
|
||||
locator.setUri("http://:foobar:@localhost:9999");
|
||||
assertEquals("http://localhost:9999", locator.getRawUri());
|
||||
assertEquals("", locator.getUsername());
|
||||
assertEquals("foobar:", locator.getPassword());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIfsolonPresentAtTheStartAndEndInUriCreds() {
|
||||
locator.setUri("http:// @localhost:9999");
|
||||
locator.setPassword("secret");
|
||||
assertEquals("http://localhost:9999", locator.getRawUri());
|
||||
assertEquals(" ", locator.getUsername());
|
||||
assertEquals("secret", locator.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changeNameInOverride() {
|
||||
locator.setName("one");
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
<packaging>pom</packaging>
|
||||
<name>spring-cloud-config-dependencies</name>
|
||||
<description>Spring Cloud Config Dependencies</description>
|
||||
<properties>
|
||||
<jgit.version>4.11.0.201803080745-r</jgit.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -38,7 +41,12 @@
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit</artifactId>
|
||||
<version>4.8.0.201706111038-r</version>
|
||||
<version>${jgit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit.junit.http</artifactId>
|
||||
<version>${jgit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.cloud.bus.BusProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
@@ -39,8 +40,8 @@ public class EnvironmentMonitorAutoConfiguration {
|
||||
private List<PropertyPathNotificationExtractor> extractors;
|
||||
|
||||
@Bean
|
||||
public PropertyPathEndpoint propertyPathEndpoint() {
|
||||
return new PropertyPathEndpoint(new CompositePropertyPathNotificationExtractor(this.extractors));
|
||||
public PropertyPathEndpoint propertyPathEndpoint(BusProperties busProperties) {
|
||||
return new PropertyPathEndpoint(new CompositePropertyPathNotificationExtractor(this.extractors), busProperties.getId());
|
||||
}
|
||||
|
||||
@Configuration
|
||||
|
||||
@@ -22,12 +22,10 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.cloud.bus.event.RefreshRemoteApplicationEvent;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -40,31 +38,30 @@ import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.apachecommons.CommonsLog;
|
||||
|
||||
/**
|
||||
* HTTP endpoint for webhooks coming from repository providers.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping(path = "${spring.cloud.config.monitor.endpoint.path:}/monitor")
|
||||
@CommonsLog
|
||||
public class PropertyPathEndpoint
|
||||
implements ApplicationEventPublisherAware, ApplicationContextAware {
|
||||
implements ApplicationEventPublisherAware {
|
||||
|
||||
private static Log log = LogFactory.getLog(PropertyPathEndpoint.class);
|
||||
|
||||
private final PropertyPathNotificationExtractor extractor;
|
||||
private ApplicationEventPublisher applicationEventPublisher;
|
||||
private String busId;
|
||||
|
||||
private String contextId = UUID.randomUUID().toString();
|
||||
public PropertyPathEndpoint(PropertyPathNotificationExtractor extractor, String busId) {
|
||||
this.extractor = extractor;
|
||||
this.busId = busId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
this.contextId = applicationContext.getId();
|
||||
/* for testing */ String getBusId() {
|
||||
return busId;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,7 +86,7 @@ public class PropertyPathEndpoint
|
||||
log.info("Refresh for: " + service);
|
||||
this.applicationEventPublisher
|
||||
.publishEvent(new RefreshRemoteApplicationEvent(this,
|
||||
this.contextId, service));
|
||||
this.busId, service));
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.cloud.config.monitor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -25,11 +24,11 @@ import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoCon
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.bus.BusProperties;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -40,8 +39,9 @@ import static org.junit.Assert.assertEquals;
|
||||
public class EnvironmentMonitorAutoConfigurationTests {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
public void testExtractorsCount() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(
|
||||
BusConfig.class,
|
||||
EnvironmentMonitorAutoConfiguration.class,
|
||||
ServletWebServerFactoryAutoConfiguration.class, ServerProperties.class,
|
||||
PropertyPlaceholderAutoConfiguration.class).properties("server.port=-1")
|
||||
@@ -57,6 +57,7 @@ public class EnvironmentMonitorAutoConfigurationTests {
|
||||
@Test
|
||||
public void testCanAddCustomPropertyPathNotificationExtractor() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(
|
||||
BusConfig.class,
|
||||
CustomPropertyPathNotificationExtractorConfig.class,
|
||||
EnvironmentMonitorAutoConfiguration.class,
|
||||
ServletWebServerFactoryAutoConfiguration.class, ServerProperties.class,
|
||||
@@ -70,18 +71,22 @@ public class EnvironmentMonitorAutoConfigurationTests {
|
||||
context.close();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class BusConfig {
|
||||
|
||||
@Bean
|
||||
public BusProperties busProperties() {
|
||||
return new BusProperties();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class CustomPropertyPathNotificationExtractorConfig {
|
||||
@Bean
|
||||
public PropertyPathNotificationExtractor customNotificationExtractor() {
|
||||
return new PropertyPathNotificationExtractor() {
|
||||
@Override
|
||||
public PropertyPathNotification extract(
|
||||
MultiValueMap<String, String> headers,
|
||||
Map<String, Object> payload) {
|
||||
throw new UnsupportedOperationException("doesn't do anything");
|
||||
}
|
||||
};
|
||||
return (headers, payload) -> {
|
||||
throw new UnsupportedOperationException("doesn't do anything");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class PropertyPathEndpointTests {
|
||||
|
||||
private PropertyPathEndpoint endpoint = new PropertyPathEndpoint(
|
||||
new CompositePropertyPathNotificationExtractor(
|
||||
Collections.<PropertyPathNotificationExtractor> emptyList()));
|
||||
Collections.emptyList()), "abc1");
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
@@ -44,15 +44,20 @@ public class PropertyPathEndpointTests {
|
||||
publisher.refresh();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBusId() {
|
||||
assertEquals("abc1", this.endpoint.getBusId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyByForm() throws Exception {
|
||||
public void testNotifyByForm() {
|
||||
assertEquals(0, this.endpoint
|
||||
.notifyByForm(new HttpHeaders(), new ArrayList<String>()).size());
|
||||
.notifyByForm(new HttpHeaders(), new ArrayList<>()).size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifySeveral() throws Exception {
|
||||
List<String> request = new ArrayList<String>();
|
||||
public void testNotifySeveral() {
|
||||
List<String> request = new ArrayList<>();
|
||||
request.add("/foo/bar.properties");
|
||||
request.add("/application.properties");
|
||||
assertEquals("[bar, *]",
|
||||
@@ -60,56 +65,56 @@ public class PropertyPathEndpointTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyAll() throws Exception {
|
||||
public void testNotifyAll() {
|
||||
assertEquals("[*]",
|
||||
this.endpoint
|
||||
.notifyByPath(new HttpHeaders(), Collections
|
||||
.<String, Object> singletonMap("path", "application.yml"))
|
||||
.singletonMap("path", "application.yml"))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyAllWithProfile() throws Exception {
|
||||
public void testNotifyAllWithProfile() {
|
||||
assertEquals("[*:local]",
|
||||
this.endpoint
|
||||
.notifyByPath(new HttpHeaders(), Collections
|
||||
.<String, Object> singletonMap("path", "application-local.yml"))
|
||||
.singletonMap("path", "application-local.yml"))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOne() throws Exception {
|
||||
public void testNotifyOne() {
|
||||
assertEquals("[foo]",
|
||||
this.endpoint
|
||||
.notifyByPath(new HttpHeaders(), Collections
|
||||
.<String, Object> singletonMap("path", "foo.yml"))
|
||||
.singletonMap("path", "foo.yml"))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOneWithWindowsPath() throws Exception {
|
||||
public void testNotifyOneWithWindowsPath() {
|
||||
assertEquals("[foo]",
|
||||
this.endpoint
|
||||
.notifyByPath(new HttpHeaders(), Collections
|
||||
.<String, Object> singletonMap("path", "C:\\config\\foo.yml"))
|
||||
.singletonMap("path", "C:\\config\\foo.yml"))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyOneWithProfile() throws Exception {
|
||||
public void testNotifyOneWithProfile() {
|
||||
assertEquals("[foo:local, foo-local]",
|
||||
this.endpoint
|
||||
.notifyByPath(new HttpHeaders(), Collections
|
||||
.<String, Object> singletonMap("path", "foo-local.yml"))
|
||||
.singletonMap("path", "foo-local.yml"))
|
||||
.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotifyMultiDash() throws Exception {
|
||||
public void testNotifyMultiDash() {
|
||||
assertEquals("[foo:local-dev, foo-local:dev, foo-local-dev]",
|
||||
this.endpoint
|
||||
.notifyByPath(new HttpHeaders(), Collections
|
||||
.<String, Object> singletonMap("path", "foo-local-dev.yml"))
|
||||
.singletonMap("path", "foo-local-dev.yml"))
|
||||
.toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
server:
|
||||
composite:
|
||||
- type: git
|
||||
uri: ${repo1}
|
||||
- type: git
|
||||
uri: ${repo1}
|
||||
bootstrap: true
|
||||
profiles:
|
||||
active: composite
|
||||
@@ -0,0 +1,88 @@
|
||||
package sample;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.web.server.LocalServerPort;
|
||||
import org.springframework.cloud.config.server.test.ConfigServerTestUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
|
||||
|
||||
/**
|
||||
* Test for gh-975.
|
||||
* org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name
|
||||
* 'vaultEnvironmentRepositoryFactory' defined in
|
||||
* org.springframework.cloud.config.server.config.CompositeRepositoryConfiguration: Unsatisfied dependency
|
||||
* No qualifying bean of type 'javax.servlet.http.HttpServletRequest' available:
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class,
|
||||
// Normally spring.cloud.config.enabled:true is the default but since we have the config
|
||||
// server on the classpath we need to set it explicitly
|
||||
properties = { "spring.cloud.config.enabled:true", "",
|
||||
"management.security.enabled=false", "management.endpoints.web.exposure.include=*" }, webEnvironment = RANDOM_PORT)
|
||||
public class ApplicationBootstrapTests {
|
||||
private static final String BASE_PATH = new WebEndpointProperties().getBasePath();
|
||||
|
||||
private static int configPort = SocketUtils.findAvailableTcpPort();
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
private static ConfigurableApplicationContext server;
|
||||
|
||||
@BeforeClass
|
||||
public static void startConfigServer() throws IOException {
|
||||
System.setProperty("spring.cloud.bootstrap.name", "bootstrapservercomposite");
|
||||
String baseDir = ConfigServerTestUtils
|
||||
.getBaseDirectory("spring-cloud-config-sample");
|
||||
String repo = ConfigServerTestUtils.prepareLocalRepo(baseDir, "target/repos",
|
||||
"config-repo", "target/config");
|
||||
System.setProperty("repo1", repo);
|
||||
server = SpringApplication.run(
|
||||
org.springframework.cloud.config.server.ConfigServerApplication.class,
|
||||
"--server.port=" + configPort, "--spring.config.name=compositeserver",
|
||||
"--repo1=" + repo);
|
||||
System.setProperty("config.port", "" + configPort);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void close() {
|
||||
System.clearProperty("config.port");
|
||||
System.clearProperty("spring.cloud.bootstrap.name");
|
||||
System.clearProperty("repo1");
|
||||
if (server != null) {
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void contextLoads() {
|
||||
Map res = new TestRestTemplate()
|
||||
.getForObject("http://localhost:" + port + BASE_PATH + "/env/info.foo", Map.class);
|
||||
assertThat(res).containsKey("propertySources");
|
||||
Map<String, Object> property = (Map<String,Object>) res.get("property");
|
||||
assertThat(property).containsEntry("value", "bar");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
configPort = 8888;
|
||||
startConfigServer();
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -80,6 +80,11 @@
|
||||
<artifactId>spring-cloud-test-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jgit</groupId>
|
||||
<artifactId>org.eclipse.jgit.junit.http</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2015 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -21,7 +21,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties
|
||||
import org.springframework.cloud.config.client.ConfigClientProperties;
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.cloud.config.server.config.EnvironmentRepositoryConfiguration;
|
||||
import org.springframework.cloud.config.server.config.TransportConfiguration;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentRepositoryPropertySourceLocator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@@ -45,7 +44,7 @@ import org.springframework.util.StringUtils;
|
||||
public class ConfigServerBootstrapConfiguration {
|
||||
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@Import({ EnvironmentRepositoryConfiguration.class, TransportConfiguration.class })
|
||||
@Import({ EnvironmentRepositoryConfiguration.class })
|
||||
protected static class LocalPropertySourceLocatorConfiguration {
|
||||
|
||||
@Autowired
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2016 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -29,7 +29,7 @@ import org.springframework.context.annotation.Import;
|
||||
@ConditionalOnBean(ConfigServerConfiguration.Marker.class)
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@Import({ EnvironmentRepositoryConfiguration.class, CompositeConfiguration.class, ResourceRepositoryConfiguration.class,
|
||||
ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class, TransportConfiguration.class })
|
||||
ConfigServerEncryptionConfiguration.class, ConfigServerMvcConfiguration.class })
|
||||
public class ConfigServerAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ public class ConfigServerMvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
public EnvironmentController environmentController(EnvironmentRepository envRepository, ConfigServerProperties server) {
|
||||
EnvironmentController controller = new EnvironmentController(encrypted(envRepository, server), this.objectMapper);
|
||||
controller.setStripDocumentFromYaml(server.isStripDocumentFromYaml());
|
||||
controller.setAcceptEmpty(server.isAcceptEmpty());
|
||||
return controller;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,10 @@ public class ConfigServerProperties {
|
||||
* should be returned in "native" form.
|
||||
*/
|
||||
private boolean stripDocumentFromYaml = true;
|
||||
/**
|
||||
* Flag to indicate that If HTTP 404 needs to be sent if Application is not Found
|
||||
*/
|
||||
private boolean acceptEmpty = true;
|
||||
|
||||
/**
|
||||
* Default application name when incoming requests do not have a specific one.
|
||||
@@ -115,7 +119,14 @@ public class ConfigServerProperties {
|
||||
public void setStripDocumentFromYaml(boolean stripDocumentFromYaml) {
|
||||
this.stripDocumentFromYaml = stripDocumentFromYaml;
|
||||
}
|
||||
|
||||
public boolean isAcceptEmpty() {
|
||||
return this.acceptEmpty;
|
||||
}
|
||||
|
||||
public void setAcceptEmpty(boolean acceptEmpty) {
|
||||
this.acceptEmpty = acceptEmpty;
|
||||
}
|
||||
public String getDefaultApplicationName() {
|
||||
return this.defaultApplicationName;
|
||||
}
|
||||
|
||||
@@ -17,12 +17,12 @@ package org.springframework.cloud.config.server.config;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.tmatesoft.svn.core.SVNException;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
@@ -113,14 +113,14 @@ class DefaultRepositoryConfiguration {
|
||||
private ConfigServerProperties server;
|
||||
|
||||
@Autowired(required = false)
|
||||
private TransportConfigCallback transportConfigCallback;
|
||||
private TransportConfigCallback customTransportConfigCallback;
|
||||
|
||||
@Bean
|
||||
public MultipleJGitEnvironmentRepository defaultEnvironmentRepository(
|
||||
MultipleJGitEnvironmentProperties environmentProperties) {
|
||||
MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory =
|
||||
new MultipleJGitEnvironmentRepositoryFactory(environment, server,
|
||||
Optional.ofNullable(transportConfigCallback));
|
||||
Optional.ofNullable(customTransportConfigCallback));
|
||||
return gitEnvironmentRepositoryFactory.build(environmentProperties);
|
||||
}
|
||||
}
|
||||
@@ -169,7 +169,7 @@ class SvnRepositoryConfiguration {
|
||||
@Profile("vault")
|
||||
class VaultRepositoryConfiguration {
|
||||
@Bean
|
||||
public VaultEnvironmentRepository vaultEnvironmentRepository(HttpServletRequest request, EnvironmentWatch watch,
|
||||
public VaultEnvironmentRepository vaultEnvironmentRepository(ObjectProvider<HttpServletRequest> request, EnvironmentWatch watch,
|
||||
VaultEnvironmentProperties environmentProperties) {
|
||||
return new VaultEnvironmentRepositoryFactory(request, watch).build(environmentProperties);
|
||||
}
|
||||
@@ -198,8 +198,8 @@ class CompositeRepositoryConfiguration {
|
||||
@Bean
|
||||
public MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory(
|
||||
ConfigurableEnvironment environment, ConfigServerProperties server,
|
||||
Optional<TransportConfigCallback> transportConfigCallback) {
|
||||
return new MultipleJGitEnvironmentRepositoryFactory(environment, server, transportConfigCallback);
|
||||
Optional<TransportConfigCallback> customTransportConfigCallback) {
|
||||
return new MultipleJGitEnvironmentRepositoryFactory(environment, server, customTransportConfigCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ class CompositeRepositoryConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public VaultEnvironmentRepositoryFactory vaultEnvironmentRepositoryFactory(HttpServletRequest request,
|
||||
public VaultEnvironmentRepositoryFactory vaultEnvironmentRepositoryFactory(ObjectProvider<HttpServletRequest> request,
|
||||
EnvironmentWatch watch) {
|
||||
return new VaultEnvironmentRepositoryFactory(request, watch);
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015-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 com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.Session;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.eclipse.jgit.transport.*;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.ssh.PropertyBasedSshSessionFactory;
|
||||
import org.springframework.cloud.config.server.ssh.SshUriProperties;
|
||||
import org.springframework.cloud.config.server.ssh.SshUriPropertyProcessor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Configure a callback to set up a property based SSH settings before running a transport command (such as clone or fetch)
|
||||
*
|
||||
* @author Ollie Hughes
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(TransportConfigCallback.class)
|
||||
@EnableConfigurationProperties(SshUriProperties.class)
|
||||
public class TransportConfiguration {
|
||||
|
||||
@ConditionalOnMissingBean(TransportConfigCallback.class)
|
||||
@Bean
|
||||
public TransportConfigCallback propertiesBasedSshTransportCallback(final SshUriProperties sshUriProperties) {
|
||||
if(sshUriProperties.isIgnoreLocalSshSettings()) {
|
||||
return new PropertiesBasedSshTransportConfigCallback(sshUriProperties);
|
||||
}
|
||||
else return new FileBasedSshTransportConfigCallback(sshUriProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure JGit transport command to use a SSH session factory that is configured using properties defined
|
||||
* in {@link SshUriProperties}
|
||||
*/
|
||||
public static class PropertiesBasedSshTransportConfigCallback implements TransportConfigCallback {
|
||||
|
||||
private SshUriProperties sshUriProperties;
|
||||
|
||||
public PropertiesBasedSshTransportConfigCallback(SshUriProperties sshUriProperties) {
|
||||
this.sshUriProperties = sshUriProperties;
|
||||
}
|
||||
|
||||
public SshUriProperties getSshUriProperties() {
|
||||
return sshUriProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Transport transport) {
|
||||
if (transport instanceof SshTransport) {
|
||||
SshTransport sshTransport = (SshTransport) transport;
|
||||
sshTransport.setSshSessionFactory(
|
||||
new PropertyBasedSshSessionFactory(
|
||||
new SshUriPropertyProcessor(sshUriProperties).getSshKeysByHostname(), new JSch()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure JGit transport command to use a default SSH session factory based on local machines SSH config.
|
||||
* Allow strict host key checking to be set.
|
||||
*/
|
||||
public static class FileBasedSshTransportConfigCallback implements TransportConfigCallback {
|
||||
|
||||
private SshUriProperties sshUriProperties;
|
||||
|
||||
public FileBasedSshTransportConfigCallback(SshUriProperties sshUriProperties) {
|
||||
this.sshUriProperties = sshUriProperties;
|
||||
}
|
||||
|
||||
public SshUriProperties getSshUriProperties() {
|
||||
return sshUriProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Transport transport) {
|
||||
SshSessionFactory.setInstance(new JschConfigSessionFactory() {
|
||||
@Override
|
||||
protected void configure(OpenSshConfig.Host hc, Session session) {
|
||||
session.setConfig("StrictHostKeyChecking",
|
||||
sshUriProperties.isStrictHostKeyChecking() ? "yes" : "no");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,7 @@ public class EnvironmentController {
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
private boolean stripDocument = true;
|
||||
private boolean acceptEmpty = true;
|
||||
|
||||
public EnvironmentController(EnvironmentRepository repository) {
|
||||
this(repository, new ObjectMapper());
|
||||
@@ -90,6 +91,15 @@ public class EnvironmentController {
|
||||
this.stripDocument = stripDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag to indicate that If HTTP 404 needs to be sent if Application is not Found
|
||||
*
|
||||
* @param acceptEmpty the flag to set
|
||||
*/
|
||||
public void setAcceptEmpty(boolean acceptEmpty) {
|
||||
this.acceptEmpty = acceptEmpty;
|
||||
}
|
||||
|
||||
@RequestMapping("/{name}/{profiles:.*[^-].*}")
|
||||
public Environment defaultLabel(@PathVariable String name,
|
||||
@PathVariable String profiles) {
|
||||
@@ -110,6 +120,9 @@ public class EnvironmentController {
|
||||
label = label.replace("(_)", "/");
|
||||
}
|
||||
Environment environment = this.repository.findOne(name, profiles, label);
|
||||
if(!acceptEmpty && (environment == null || environment.getPropertySources().isEmpty())){
|
||||
throw new EnvironmentNotFoundException("Profile Not found");
|
||||
}
|
||||
return environment;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* @author Chids
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "Application Not Found")
|
||||
public class EnvironmentNotFoundException extends RuntimeException {
|
||||
|
||||
public EnvironmentNotFoundException(String string) {
|
||||
super(string);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,19 +15,76 @@
|
||||
*/
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import org.springframework.cloud.config.server.support.AbstractScmAccessorProperties;
|
||||
|
||||
/**
|
||||
* @author Dylan Roberts
|
||||
* @author Gareth Clay
|
||||
*/
|
||||
public class JGitEnvironmentProperties extends AbstractScmAccessorProperties {
|
||||
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. */
|
||||
private boolean cloneOnStart = false;
|
||||
|
||||
/** Flag to indicate that the repository should force pull. If true discard any local changes and take from remote repository. */
|
||||
private boolean forcePull;
|
||||
|
||||
/** Timeout (in seconds) for obtaining HTTP or SSH connection (if applicable), defaults to 5 seconds. */
|
||||
private int timeout = 5;
|
||||
|
||||
/** Flag to indicate that the branch should be deleted locally if it's origin tracked branch was removed. */
|
||||
private boolean deleteUntrackedBranches = false;
|
||||
|
||||
/**
|
||||
* Flag to indicate that SSL certificate validation should be bypassed when
|
||||
* communicating with a repository served over an HTTPS connection.
|
||||
*/
|
||||
private boolean skipSslValidation = false;
|
||||
|
||||
/**
|
||||
* Time (in seconds) between refresh of the git repository
|
||||
*/
|
||||
private int refreshRate = 0;
|
||||
|
||||
/**
|
||||
* Valid SSH private key. Must be set if ignoreLocalSshSettings is true and Git URI is SSH format.
|
||||
*/
|
||||
private String privateKey;
|
||||
|
||||
/**
|
||||
* One of ssh-dss, ssh-rsa, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384, or ecdsa-sha2-nistp521. Must be set if hostKey is also set.
|
||||
*/
|
||||
private String hostKeyAlgorithm;
|
||||
|
||||
/**
|
||||
* Valid SSH host key. Must be set if hostKeyAlgorithm is also set.
|
||||
*/
|
||||
private String hostKey;
|
||||
|
||||
/**
|
||||
* Location of custom .known_hosts file.
|
||||
*/
|
||||
private String knownHostsFile;
|
||||
|
||||
/**
|
||||
* Override server authentication method order. This should allow for evading login prompts if server has keyboard-interactive authentication before the publickey method.
|
||||
*/
|
||||
@Pattern(regexp = "([\\w -]+,)*([\\w -]+)")
|
||||
private String preferredAuthentications;
|
||||
|
||||
/**
|
||||
* If true, use property-based instead of file-based SSH config.
|
||||
*/
|
||||
private boolean ignoreLocalSshSettings;
|
||||
|
||||
/**
|
||||
* If false, ignore errors with host key
|
||||
*/
|
||||
private boolean strictHostKeyChecking = true;
|
||||
|
||||
public JGitEnvironmentProperties() {
|
||||
super();
|
||||
setDefaultLabel(DEFAULT_LABEL);
|
||||
@@ -64,4 +121,78 @@ public class JGitEnvironmentProperties extends AbstractScmAccessorProperties {
|
||||
public void setDeleteUntrackedBranches(boolean deleteUntrackedBranches) {
|
||||
this.deleteUntrackedBranches = deleteUntrackedBranches;
|
||||
}
|
||||
|
||||
public int getRefreshRate() {
|
||||
return refreshRate;
|
||||
}
|
||||
|
||||
public void setRefreshRate(int refreshRate) {
|
||||
this.refreshRate = refreshRate;
|
||||
}
|
||||
|
||||
public String getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public void setPrivateKey(String privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public String getHostKeyAlgorithm() {
|
||||
return hostKeyAlgorithm;
|
||||
}
|
||||
|
||||
public void setHostKeyAlgorithm(String hostKeyAlgorithm) {
|
||||
this.hostKeyAlgorithm = hostKeyAlgorithm;
|
||||
}
|
||||
|
||||
public String getHostKey() {
|
||||
return hostKey;
|
||||
}
|
||||
|
||||
public void setHostKey(String hostKey) {
|
||||
this.hostKey = hostKey;
|
||||
}
|
||||
|
||||
public String getKnownHostsFile() {
|
||||
return knownHostsFile;
|
||||
}
|
||||
|
||||
public void setKnownHostsFile(String knownHostsFile) {
|
||||
this.knownHostsFile = knownHostsFile;
|
||||
}
|
||||
|
||||
public String getPreferredAuthentications() {
|
||||
return preferredAuthentications;
|
||||
}
|
||||
|
||||
public void setPreferredAuthentications(String preferredAuthentications) {
|
||||
this.preferredAuthentications = preferredAuthentications;
|
||||
}
|
||||
|
||||
public boolean isIgnoreLocalSshSettings() {
|
||||
return ignoreLocalSshSettings;
|
||||
}
|
||||
|
||||
public void setIgnoreLocalSshSettings(boolean ignoreLocalSshSettings) {
|
||||
this.ignoreLocalSshSettings = ignoreLocalSshSettings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStrictHostKeyChecking() {
|
||||
return strictHostKeyChecking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStrictHostKeyChecking(boolean strictHostKeyChecking) {
|
||||
this.strictHostKeyChecking = strictHostKeyChecking;
|
||||
}
|
||||
|
||||
public boolean isSkipSslValidation() {
|
||||
return skipSslValidation;
|
||||
}
|
||||
|
||||
public void setSkipSslValidation(boolean skipSslValidation) {
|
||||
this.skipSslValidation = skipSslValidation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,19 +54,18 @@ import org.eclipse.jgit.transport.ReceiveCommand;
|
||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||
import org.eclipse.jgit.transport.TagOpt;
|
||||
import org.eclipse.jgit.transport.TrackingRefUpdate;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.eclipse.jgit.util.FileUtils;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cloud.config.server.support.PassphraseCredentialsProvider;
|
||||
import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.eclipse.jgit.transport.ReceiveCommand.Type.DELETE;
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* An {@link EnvironmentRepository} backed by a single git repository.
|
||||
@@ -76,6 +75,7 @@ import static org.springframework.util.StringUtils.hasText;
|
||||
* @author Marcos Barbero
|
||||
* @author Daniel Lavoie
|
||||
* @author Ryan Lynch
|
||||
* @author Gareth Clay
|
||||
*/
|
||||
public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
implements EnvironmentRepository, SearchPathLocator, InitializingBean {
|
||||
@@ -90,6 +90,16 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
*/
|
||||
private int timeout;
|
||||
|
||||
/**
|
||||
* Time (in seconds) between refresh of the git repository
|
||||
*/
|
||||
private int refreshRate = 0;
|
||||
|
||||
/**
|
||||
* Time of the last refresh of the git repository
|
||||
*/
|
||||
private long lastRefresh;
|
||||
|
||||
/**
|
||||
* Flag to indicate that the repository should be cloned on startup (not on demand).
|
||||
* Generally leads to slower startup but faster first query.
|
||||
@@ -101,9 +111,10 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
private String defaultLabel;
|
||||
|
||||
/**
|
||||
* The credentials provider to use to connect to the Git repository.
|
||||
* Factory used to create the credentials provider to use to connect to the Git
|
||||
* repository.
|
||||
*/
|
||||
private CredentialsProvider gitCredentialsProvider;
|
||||
private GitCredentialsProviderFactory gitCredentialsProviderFactory = new GitCredentialsProviderFactory();
|
||||
|
||||
/**
|
||||
* Transport configuration callback for JGit commands.
|
||||
@@ -122,6 +133,12 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
*/
|
||||
private boolean deleteUntrackedBranches;
|
||||
|
||||
/**
|
||||
* Flag to indicate that SSL certificate validation should be bypassed when
|
||||
* communicating with a repository served over an HTTPS connection.
|
||||
*/
|
||||
private boolean skipSslValidation;
|
||||
|
||||
public JGitEnvironmentRepository(ConfigurableEnvironment environment, JGitEnvironmentProperties properties) {
|
||||
super(environment, properties);
|
||||
this.cloneOnStart = properties.isCloneOnStart();
|
||||
@@ -129,6 +146,8 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
this.forcePull = properties.isForcePull();
|
||||
this.timeout = properties.getTimeout();
|
||||
this.deleteUntrackedBranches = properties.isDeleteUntrackedBranches();
|
||||
this.refreshRate = properties.getRefreshRate();
|
||||
this.skipSslValidation = properties.isSkipSslValidation();
|
||||
}
|
||||
|
||||
public boolean isCloneOnStart() {
|
||||
@@ -147,6 +166,15 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
this.timeout = timeout;
|
||||
}
|
||||
|
||||
public int getRefreshRate() {
|
||||
return refreshRate;
|
||||
}
|
||||
|
||||
public void setRefreshRate(int refreshRate) {
|
||||
this.refreshRate = refreshRate;
|
||||
}
|
||||
|
||||
|
||||
public TransportConfigCallback getTransportConfigCallback() {
|
||||
return transportConfigCallback;
|
||||
}
|
||||
@@ -164,6 +192,11 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
this.gitFactory = gitFactory;
|
||||
}
|
||||
|
||||
public void setGitCredentialsProviderFactory(
|
||||
GitCredentialsProviderFactory gitCredentialsProviderFactory) {
|
||||
this.gitCredentialsProviderFactory = gitCredentialsProviderFactory;
|
||||
}
|
||||
|
||||
public String getDefaultLabel() {
|
||||
return this.defaultLabel;
|
||||
}
|
||||
@@ -188,6 +221,14 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
this.deleteUntrackedBranches = deleteUntrackedBranches;
|
||||
}
|
||||
|
||||
public boolean isSkipSslValidation() {
|
||||
return skipSslValidation;
|
||||
}
|
||||
|
||||
public void setSkipSslValidation(boolean skipSslValidation) {
|
||||
this.skipSslValidation = skipSslValidation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Locations getLocations(String application, String profile,
|
||||
String label) {
|
||||
@@ -349,6 +390,11 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
|
||||
protected boolean shouldPull(Git git) throws GitAPIException {
|
||||
boolean shouldPull;
|
||||
|
||||
if (this.refreshRate > 0 && System.currentTimeMillis() - this.lastRefresh < (this.refreshRate * 1000)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Status gitStatus = git.status().call();
|
||||
boolean isWorkingTreeClean = gitStatus.isClean();
|
||||
String originUrl = git.getRepository().getConfig().getString("remote", "origin",
|
||||
@@ -394,6 +440,9 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
fetch.setRemote("origin");
|
||||
fetch.setTagOpt(TagOpt.FETCH_TAGS);
|
||||
fetch.setRemoveDeletedRefs(deleteUntrackedBranches);
|
||||
if (this.refreshRate > 0) {
|
||||
this.setLastRefresh(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
configureCommand(fetch);
|
||||
try {
|
||||
@@ -555,19 +604,8 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
|
||||
private CredentialsProvider getCredentialsProvider() {
|
||||
if (this.gitCredentialsProvider != null) {
|
||||
return this.gitCredentialsProvider;
|
||||
}
|
||||
|
||||
if (hasText(getUsername()) && hasText(getPassword())) {
|
||||
return new UsernamePasswordCredentialsProvider(getUsername(), getPassword());
|
||||
}
|
||||
|
||||
if (hasText(getPassphrase())) {
|
||||
return new PassphraseCredentialsProvider(getPassphrase());
|
||||
}
|
||||
|
||||
return null;
|
||||
return this.gitCredentialsProviderFactory.createFor(this.getUri(), getUsername(),
|
||||
getPassword(), getPassphrase(), isSkipSslValidation());
|
||||
}
|
||||
|
||||
private boolean isClean(Git git, String label) {
|
||||
@@ -621,6 +659,14 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
}
|
||||
}
|
||||
|
||||
public void setLastRefresh(long lastRefresh) {
|
||||
this.lastRefresh = lastRefresh;
|
||||
}
|
||||
|
||||
public long getLastRefresh() {
|
||||
return lastRefresh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the static method calls to {@link org.eclipse.jgit.api.Git} and
|
||||
* {@link org.eclipse.jgit.api.CloneCommand} allowing for easier unit testing.
|
||||
@@ -637,18 +683,4 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
|
||||
return command;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the gitCredentialsProvider
|
||||
*/
|
||||
public CredentialsProvider getGitCredentialsProvider() {
|
||||
return gitCredentialsProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param gitCredentialsProvider the gitCredentialsProvider to set
|
||||
*/
|
||||
public void setGitCredentialsProvider(CredentialsProvider gitCredentialsProvider) {
|
||||
this.gitCredentialsProvider = gitCredentialsProvider;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public class JdbcEnvironmentProperties implements EnvironmentRepositoryPropertie
|
||||
private static final String DEFAULT_SQL = "SELECT KEY, VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?";
|
||||
|
||||
private int order = Ordered.LOWEST_PRECEDENCE - 10;
|
||||
/** SQL used to query database for keys and values */
|
||||
private String sql = DEFAULT_SQL;
|
||||
|
||||
public int getOrder() {
|
||||
|
||||
@@ -19,12 +19,25 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.ssh.HostKeyAlgoSupported;
|
||||
import org.springframework.cloud.config.server.ssh.HostKeyAndAlgoBothExist;
|
||||
import org.springframework.cloud.config.server.ssh.KnownHostsFileIsValid;
|
||||
import org.springframework.cloud.config.server.ssh.PrivateKeyIsValid;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* @author Dylan Roberts
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.git")
|
||||
@Validated
|
||||
@PrivateKeyIsValid
|
||||
@HostKeyAndAlgoBothExist
|
||||
@HostKeyAlgoSupported
|
||||
@KnownHostsFileIsValid
|
||||
public class MultipleJGitEnvironmentProperties extends JGitEnvironmentProperties {
|
||||
/**
|
||||
* Map of repository identifier to location and other properties.
|
||||
*/
|
||||
private Map<String, PatternMatchingJGitEnvironmentProperties> repos = new LinkedHashMap<>();
|
||||
|
||||
public Map<String, PatternMatchingJGitEnvironmentProperties> getRepos() {
|
||||
@@ -36,7 +49,13 @@ public class MultipleJGitEnvironmentProperties extends JGitEnvironmentProperties
|
||||
}
|
||||
|
||||
public static class PatternMatchingJGitEnvironmentProperties extends JGitEnvironmentProperties {
|
||||
/**
|
||||
* Pattern to match on application name and profiles.
|
||||
*/
|
||||
private String[] pattern = new String[0];
|
||||
/**
|
||||
* Name of repository (same as map key by default).
|
||||
*/
|
||||
private String name;
|
||||
|
||||
public String[] getPattern() {
|
||||
|
||||
@@ -27,7 +27,6 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -44,6 +43,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Andy Chan (iceycake)
|
||||
* @author Dave Syer
|
||||
* @author Gareth Clay
|
||||
*
|
||||
*/
|
||||
public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository {
|
||||
@@ -66,9 +66,6 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
GitCredentialsProviderFactory credentialFactory = new GitCredentialsProviderFactory();
|
||||
super.setGitCredentialsProvider(credentialFactory.createFor(getUri(),
|
||||
getUsername(), getPassword(), getPassphrase()));
|
||||
super.afterPropertiesSet();
|
||||
for (String name : this.repos.keySet()) {
|
||||
PatternMatchingJGitEnvironmentRepository repo = this.repos.get(name);
|
||||
@@ -85,18 +82,21 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository
|
||||
if (getTimeout() != 0 && repo.getTimeout() == 0) {
|
||||
repo.setTimeout(getTimeout());
|
||||
}
|
||||
if (getRefreshRate() != 0 && repo.getRefreshRate() == 0) {
|
||||
repo.setRefreshRate(getRefreshRate());
|
||||
}
|
||||
String user = repo.getUsername();
|
||||
String pass = repo.getPassword();
|
||||
String passphrase = repo.getPassphrase();
|
||||
if (user == null) {
|
||||
user = getUsername();
|
||||
pass = getPassword();
|
||||
repo.setUsername(getUsername());
|
||||
repo.setPassword(getPassword());
|
||||
}
|
||||
if (passphrase == null) {
|
||||
passphrase = getPassphrase();
|
||||
repo.setPassphrase(getPassphrase());
|
||||
}
|
||||
if (isSkipSslValidation()) {
|
||||
repo.setSkipSslValidation(true);
|
||||
}
|
||||
repo.setGitCredentialsProvider(
|
||||
credentialFactory.createFor(repo.getUri(), user, pass, passphrase));
|
||||
repo.afterPropertiesSet();
|
||||
}
|
||||
if (!getBasedir().exists() &&
|
||||
|
||||
@@ -20,6 +20,8 @@ import java.util.Optional;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
|
||||
import org.springframework.cloud.config.server.config.ConfigServerProperties;
|
||||
import org.springframework.cloud.config.server.ssh.FileBasedSshTransportConfigCallback;
|
||||
import org.springframework.cloud.config.server.ssh.PropertiesBasedSshTransportConfigCallback;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
|
||||
/**
|
||||
@@ -29,23 +31,31 @@ public class MultipleJGitEnvironmentRepositoryFactory implements EnvironmentRepo
|
||||
MultipleJGitEnvironmentProperties> {
|
||||
private ConfigurableEnvironment environment;
|
||||
private ConfigServerProperties server;
|
||||
private Optional<TransportConfigCallback> transportConfigCallback;
|
||||
private Optional<TransportConfigCallback> customTransportConfigCallback;
|
||||
|
||||
public MultipleJGitEnvironmentRepositoryFactory(ConfigurableEnvironment environment, ConfigServerProperties server,
|
||||
Optional<TransportConfigCallback> transportConfigCallback) {
|
||||
Optional<TransportConfigCallback> customTransportConfigCallback) {
|
||||
this.environment = environment;
|
||||
this.server = server;
|
||||
this.transportConfigCallback = transportConfigCallback;
|
||||
this.customTransportConfigCallback = customTransportConfigCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultipleJGitEnvironmentRepository build(MultipleJGitEnvironmentProperties environmentProperties) {
|
||||
MultipleJGitEnvironmentRepository repository = new MultipleJGitEnvironmentRepository(environment,
|
||||
environmentProperties);
|
||||
repository.setTransportConfigCallback(transportConfigCallback.orElse(null));
|
||||
repository.setTransportConfigCallback(customTransportConfigCallback
|
||||
.orElse(buildTransportConfigCallback(environmentProperties)));
|
||||
if (server.getDefaultLabel() != null) {
|
||||
repository.setDefaultLabel(server.getDefaultLabel());
|
||||
}
|
||||
return repository;
|
||||
}
|
||||
|
||||
private TransportConfigCallback buildTransportConfigCallback(final MultipleJGitEnvironmentProperties gitEnvironmentProperties) {
|
||||
if (gitEnvironmentProperties.isIgnoreLocalSshSettings()) {
|
||||
return new PropertiesBasedSshTransportConfigCallback(gitEnvironmentProperties);
|
||||
}
|
||||
return new FileBasedSshTransportConfigCallback(gitEnvironmentProperties);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,23 @@ import org.springframework.core.Ordered;
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.native")
|
||||
public class NativeEnvironmentProperties implements EnvironmentRepositoryProperties {
|
||||
/**
|
||||
* Flag to determine how to handle exceptions during decryption (default false).
|
||||
*/
|
||||
private Boolean failOnError = false;
|
||||
/**
|
||||
* Flag to determine whether label locations should be added.
|
||||
*/
|
||||
private Boolean addLabelLocations = true;
|
||||
private String defaultLabel = "master";
|
||||
/**
|
||||
* Locations to search for configuration files. Defaults to the same as a Spring Boot
|
||||
* app so [classpath:/,classpath:/config/,file:./,file:./config/].
|
||||
*/
|
||||
private String[] searchLocations = new String[0];
|
||||
/**
|
||||
* Version string to be reported for native repository
|
||||
*/
|
||||
private String version;
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
|
||||
@@ -24,11 +24,17 @@ import org.springframework.core.Ordered;
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.vault")
|
||||
public class VaultEnvironmentProperties implements EnvironmentRepositoryProperties {
|
||||
/** Vault host. Defaults to 127.0.0.1. */
|
||||
private String host = "127.0.0.1";
|
||||
/** Vault port. Defaults to 8200. */
|
||||
private Integer port = 8200;
|
||||
/** Vault scheme. Defaults to http. */
|
||||
private String scheme = "http";
|
||||
/** Vault backend. Defaults to secret. */
|
||||
private String backend = "secret";
|
||||
/** The key in vault shared by all applications. Defaults to application. Set to empty to disable. */
|
||||
private String defaultKey = "application";
|
||||
/** Vault profile separator. Defaults to comma. */
|
||||
private String profileSeparator = ",";
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
|
||||
@@ -20,15 +20,18 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonRawValue;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
@@ -61,7 +64,8 @@ public class VaultEnvironmentRepository implements EnvironmentRepository, Ordere
|
||||
private String host;
|
||||
|
||||
/** Vault port. Defaults to 8200. */
|
||||
@Range(min = 1, max = 65535)
|
||||
@Min(1)
|
||||
@Max(65535)
|
||||
private int port;
|
||||
|
||||
/** Vault scheme. Defaults to http. */
|
||||
@@ -83,11 +87,11 @@ public class VaultEnvironmentRepository implements EnvironmentRepository, Ordere
|
||||
private RestTemplate rest;
|
||||
|
||||
// TODO: move to watchState:String on findOne?
|
||||
private HttpServletRequest request;
|
||||
private ObjectProvider<HttpServletRequest> request;
|
||||
|
||||
private EnvironmentWatch watch;
|
||||
|
||||
public VaultEnvironmentRepository(HttpServletRequest request, EnvironmentWatch watch, RestTemplate rest,
|
||||
public VaultEnvironmentRepository(ObjectProvider<HttpServletRequest> request, EnvironmentWatch watch, RestTemplate rest,
|
||||
VaultEnvironmentProperties properties) {
|
||||
this.request = request;
|
||||
this.watch = watch;
|
||||
@@ -104,7 +108,12 @@ public class VaultEnvironmentRepository implements EnvironmentRepository, Ordere
|
||||
@Override
|
||||
public Environment findOne(String application, String profile, String label) {
|
||||
|
||||
String state = request.getHeader(STATE_HEADER);
|
||||
HttpServletRequest servletRequest = request.getIfAvailable();
|
||||
if (servletRequest == null) {
|
||||
throw new IllegalStateException("No HttpServletRequest available");
|
||||
}
|
||||
|
||||
String state = servletRequest.getHeader(STATE_HEADER);
|
||||
String newState = this.watch.watch(state);
|
||||
|
||||
String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
|
||||
@@ -116,7 +125,7 @@ public class VaultEnvironmentRepository implements EnvironmentRepository, Ordere
|
||||
|
||||
for (String key : keys) {
|
||||
// read raw 'data' key from vault
|
||||
String data = read(key);
|
||||
String data = read(servletRequest, key);
|
||||
if (data != null) {
|
||||
// data is in json format of which, yaml is a superset, so parse
|
||||
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
|
||||
@@ -162,12 +171,12 @@ public class VaultEnvironmentRepository implements EnvironmentRepository, Ordere
|
||||
}
|
||||
}
|
||||
|
||||
String read(String key) {
|
||||
String read(HttpServletRequest servletRequest, String key) {
|
||||
String url = String.format("%s://%s:%s/v1/{backend}/{key}", this.scheme, this.host, this.port);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
String token = request.getHeader(TOKEN_HEADER);
|
||||
String token = servletRequest.getHeader(TOKEN_HEADER);
|
||||
if (!StringUtils.hasLength(token)) {
|
||||
throw new IllegalArgumentException("Missing required header: " + TOKEN_HEADER);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
@@ -24,10 +25,10 @@ import org.springframework.web.client.RestTemplate;
|
||||
*/
|
||||
public class VaultEnvironmentRepositoryFactory implements EnvironmentRepositoryFactory<VaultEnvironmentRepository,
|
||||
VaultEnvironmentProperties> {
|
||||
private HttpServletRequest request;
|
||||
private ObjectProvider<HttpServletRequest> request;
|
||||
private EnvironmentWatch watch;
|
||||
|
||||
public VaultEnvironmentRepositoryFactory(HttpServletRequest request, EnvironmentWatch watch) {
|
||||
public VaultEnvironmentRepositoryFactory(ObjectProvider<HttpServletRequest> request, EnvironmentWatch watch) {
|
||||
this.request = request;
|
||||
this.watch = watch;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.ssh;
|
||||
|
||||
import com.jcraft.jsch.Session;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
||||
import org.eclipse.jgit.transport.OpenSshConfig;
|
||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||
import org.eclipse.jgit.transport.Transport;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
|
||||
/**
|
||||
* Configure JGit transport command to use a default SSH session factory based on local machines SSH config.
|
||||
* Allow strict host key checking to be set.
|
||||
*/
|
||||
public class FileBasedSshTransportConfigCallback implements TransportConfigCallback {
|
||||
|
||||
private MultipleJGitEnvironmentProperties sshUriProperties;
|
||||
|
||||
public FileBasedSshTransportConfigCallback(MultipleJGitEnvironmentProperties sshUriProperties) {
|
||||
this.sshUriProperties = sshUriProperties;
|
||||
}
|
||||
|
||||
public MultipleJGitEnvironmentProperties getSshUriProperties() {
|
||||
return sshUriProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Transport transport) {
|
||||
SshSessionFactory.setInstance(new JschConfigSessionFactory() {
|
||||
@Override
|
||||
protected void configure(OpenSshConfig.Host hc, Session session) {
|
||||
session.setConfig("StrictHostKeyChecking",
|
||||
sshUriProperties.isStrictHostKeyChecking() ? "yes" : "no");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import java.util.Set;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import static java.lang.String.format;
|
||||
@@ -30,14 +32,14 @@ import static org.springframework.cloud.config.server.ssh.SshPropertyValidator.i
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* JSR-303 Cross Field validator that ensures that a {@link SshUriProperties} bean for the constraints:
|
||||
* JSR-303 Cross Field validator that ensures that a {@link MultipleJGitEnvironmentProperties} bean for the constraints:
|
||||
* - If host key algo is supported
|
||||
*
|
||||
* Beans annotated with {@link HostKeyAlgoSupported} and {@link Validated} will have the constraints applied.
|
||||
*
|
||||
* @author Ollie Hughes
|
||||
*/
|
||||
public class HostKeyAlgoSupportedValidator implements ConstraintValidator<HostKeyAlgoSupported, SshUriProperties> {
|
||||
public class HostKeyAlgoSupportedValidator implements ConstraintValidator<HostKeyAlgoSupported, MultipleJGitEnvironmentProperties> {
|
||||
private static final String GIT_PROPERTY_PREFIX = "spring.cloud.config.server.git.";
|
||||
private final SshPropertyValidator sshPropertyValidator = new SshPropertyValidator();
|
||||
private static final Set<String> VALID_HOST_KEY_ALGORITHMS = new LinkedHashSet<>(Arrays.asList(
|
||||
@@ -49,12 +51,12 @@ public class HostKeyAlgoSupportedValidator implements ConstraintValidator<HostKe
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(SshUriProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
public boolean isValid(MultipleJGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
Set<Boolean> validationResults = new HashSet<>();
|
||||
List<SshUri> extractedProperties = sshPropertyValidator.extractRepoProperties(sshUriProperties);
|
||||
List<JGitEnvironmentProperties> extractedProperties = sshPropertyValidator.extractRepoProperties(sshUriProperties);
|
||||
|
||||
for (SshUri extractedProperty : extractedProperties) {
|
||||
for (JGitEnvironmentProperties extractedProperty : extractedProperties) {
|
||||
if (sshUriProperties.isIgnoreLocalSshSettings() && isSshUri(extractedProperty.getUri())) {
|
||||
validationResults.add(isHostKeySpecifiedWhenAlgorithmSet(extractedProperty, context));
|
||||
}
|
||||
@@ -62,7 +64,7 @@ public class HostKeyAlgoSupportedValidator implements ConstraintValidator<HostKe
|
||||
return !validationResults.contains(false);
|
||||
}
|
||||
|
||||
private boolean isHostKeySpecifiedWhenAlgorithmSet(SshUri sshUriProperties, ConstraintValidatorContext context) {
|
||||
private boolean isHostKeySpecifiedWhenAlgorithmSet(JGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
if (hasText(sshUriProperties.getHostKeyAlgorithm())
|
||||
&& !VALID_HOST_KEY_ALGORITHMS.contains(sshUriProperties.getHostKeyAlgorithm())) {
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import java.util.Set;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import static java.lang.String.format;
|
||||
@@ -28,7 +30,7 @@ import static org.springframework.cloud.config.server.ssh.SshPropertyValidator.i
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* JSR-303 Cross Field validator that ensures that a {@link SshUriProperties} bean for the constraints:
|
||||
* JSR-303 Cross Field validator that ensures that a {@link MultipleJGitEnvironmentProperties} bean for the constraints:
|
||||
* - If host key is set then host key algo must also be set
|
||||
* - If host key algo is set then host key must also be set
|
||||
*
|
||||
@@ -36,7 +38,7 @@ import static org.springframework.util.StringUtils.hasText;
|
||||
*
|
||||
* @author Ollie Hughes
|
||||
*/
|
||||
public class HostKeyAndAlgoBothExistValidator implements ConstraintValidator<HostKeyAndAlgoBothExist, SshUriProperties> {
|
||||
public class HostKeyAndAlgoBothExistValidator implements ConstraintValidator<HostKeyAndAlgoBothExist, MultipleJGitEnvironmentProperties> {
|
||||
private static final String GIT_PROPERTY_PREFIX = "spring.cloud.config.server.git.";
|
||||
private final SshPropertyValidator sshPropertyValidator = new SshPropertyValidator();
|
||||
|
||||
@@ -46,11 +48,11 @@ public class HostKeyAndAlgoBothExistValidator implements ConstraintValidator<Hos
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(SshUriProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
public boolean isValid(MultipleJGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
Set<Boolean> validationResults = new HashSet<>();
|
||||
List<SshUri> extractedProperties = sshPropertyValidator.extractRepoProperties(sshUriProperties);
|
||||
List<JGitEnvironmentProperties> extractedProperties = sshPropertyValidator.extractRepoProperties(sshUriProperties);
|
||||
|
||||
for (SshUri extractedProperty : extractedProperties) {
|
||||
for (JGitEnvironmentProperties extractedProperty : extractedProperties) {
|
||||
if (sshUriProperties.isIgnoreLocalSshSettings() && isSshUri(extractedProperty.getUri())) {
|
||||
validationResults.add(
|
||||
isAlgorithmSpecifiedWhenHostKeySet(extractedProperty, context)
|
||||
@@ -60,7 +62,7 @@ public class HostKeyAndAlgoBothExistValidator implements ConstraintValidator<Hos
|
||||
return !validationResults.contains(false);
|
||||
}
|
||||
|
||||
private boolean isHostKeySpecifiedWhenAlgorithmSet(SshUri sshUriProperties, ConstraintValidatorContext context) {
|
||||
private boolean isHostKeySpecifiedWhenAlgorithmSet(JGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
if (hasText(sshUriProperties.getHostKeyAlgorithm()) && !hasText(sshUriProperties.getHostKey())) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
context.buildConstraintViolationWithTemplate(
|
||||
@@ -71,7 +73,7 @@ public class HostKeyAndAlgoBothExistValidator implements ConstraintValidator<Hos
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isAlgorithmSpecifiedWhenHostKeySet(SshUri sshUriProperties, ConstraintValidatorContext context) {
|
||||
private boolean isAlgorithmSpecifiedWhenHostKeySet(JGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
if (hasText(sshUriProperties.getHostKey()) && !hasText(sshUriProperties.getHostKeyAlgorithm())) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
context.buildConstraintViolationWithTemplate(
|
||||
|
||||
@@ -16,23 +16,24 @@
|
||||
|
||||
package org.springframework.cloud.config.server.ssh;
|
||||
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.io.File;
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import java.io.File;
|
||||
|
||||
import static java.lang.String.*;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
/**
|
||||
* JSR-303 Cross Field validator that ensures that a {@link SshUriProperties} bean for the constraints:
|
||||
* JSR-303 Cross Field validator that ensures that a {@link MultipleJGitEnvironmentProperties} bean for the constraints:
|
||||
* - Verifies that known hosts file exists
|
||||
* <p>
|
||||
* Beans annotated with {@link KnownHostsFileIsValid} and {@link Validated} will have the constraints applied.
|
||||
*
|
||||
* @author Edgars Jasmans
|
||||
*/
|
||||
public class KnownHostsFileValidator implements ConstraintValidator<KnownHostsFileIsValid, SshUriProperties> {
|
||||
public class KnownHostsFileValidator implements ConstraintValidator<KnownHostsFileIsValid, MultipleJGitEnvironmentProperties> {
|
||||
|
||||
@Override
|
||||
public void initialize(KnownHostsFileIsValid knownHostsFileIsValid) {
|
||||
@@ -40,7 +41,7 @@ public class KnownHostsFileValidator implements ConstraintValidator<KnownHostsFi
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(SshUriProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
public boolean isValid(MultipleJGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
String knownHostsFile = sshUriProperties.getKnownHostsFile();
|
||||
if (knownHostsFile != null && !new File(knownHostsFile).exists()) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
|
||||
@@ -25,6 +25,8 @@ import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.JSchException;
|
||||
import com.jcraft.jsch.KeyPair;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import static java.lang.String.format;
|
||||
@@ -32,14 +34,14 @@ import static org.springframework.cloud.config.server.ssh.SshPropertyValidator.i
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* JSR-303 Cross Field validator that ensures that an {@link SshUriProperties} bean for the constraints:
|
||||
* JSR-303 Cross Field validator that ensures that an {@link MultipleJGitEnvironmentProperties} bean for the constraints:
|
||||
* - Private key is present and can be correctly parsed using {@link com.jcraft.jsch.KeyPair}
|
||||
*
|
||||
* Beans annotated with {@link PrivateKeyValidator} and {@link Validated} will have the constraints applied.
|
||||
*
|
||||
* @author Ollie Hughes
|
||||
*/
|
||||
public class PrivateKeyValidator implements ConstraintValidator<PrivateKeyIsValid, SshUriProperties> {
|
||||
public class PrivateKeyValidator implements ConstraintValidator<PrivateKeyIsValid, MultipleJGitEnvironmentProperties> {
|
||||
private static final String GIT_PROPERTY_PREFIX = "spring.cloud.config.server.git.";
|
||||
private final SshPropertyValidator sshPropertyValidator = new SshPropertyValidator();
|
||||
|
||||
@@ -49,12 +51,12 @@ public class PrivateKeyValidator implements ConstraintValidator<PrivateKeyIsVali
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(SshUriProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
public boolean isValid(MultipleJGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
Set<Boolean> validationResults = new HashSet<>();
|
||||
List<SshUri> extractedProperties = sshPropertyValidator.extractRepoProperties(sshUriProperties);
|
||||
List<JGitEnvironmentProperties> extractedProperties = sshPropertyValidator.extractRepoProperties(sshUriProperties);
|
||||
|
||||
for (SshUri extractedProperty : extractedProperties) {
|
||||
for (JGitEnvironmentProperties extractedProperty : extractedProperties) {
|
||||
if (extractedProperty.isIgnoreLocalSshSettings() && isSshUri(extractedProperty.getUri())) {
|
||||
validationResults.add(
|
||||
isPrivateKeyPresent(extractedProperty, context)
|
||||
@@ -65,7 +67,7 @@ public class PrivateKeyValidator implements ConstraintValidator<PrivateKeyIsVali
|
||||
|
||||
}
|
||||
|
||||
private boolean isPrivateKeyPresent(SshUri sshUriProperties, ConstraintValidatorContext context) {
|
||||
private boolean isPrivateKeyPresent(JGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
if (!hasText(sshUriProperties.getPrivateKey())) {
|
||||
context.buildConstraintViolationWithTemplate(
|
||||
format("Property '%sprivateKey' must be set when '%signoreLocalSshSettings' is specified", GIT_PROPERTY_PREFIX, GIT_PROPERTY_PREFIX))
|
||||
@@ -75,7 +77,7 @@ public class PrivateKeyValidator implements ConstraintValidator<PrivateKeyIsVali
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isPrivateKeyFormatCorrect(SshUri sshUriProperties, ConstraintValidatorContext context) {
|
||||
private boolean isPrivateKeyFormatCorrect(JGitEnvironmentProperties sshUriProperties, ConstraintValidatorContext context) {
|
||||
try {
|
||||
KeyPair.load(new JSch(), sshUriProperties.getPrivateKey().getBytes(), null);
|
||||
return true;
|
||||
|
||||
@@ -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.ssh;
|
||||
|
||||
import com.jcraft.jsch.JSch;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.eclipse.jgit.transport.SshTransport;
|
||||
import org.eclipse.jgit.transport.Transport;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
|
||||
/**
|
||||
* Configure JGit transport command to use a SSH session factory that is configured using properties defined
|
||||
* in {@link MultipleJGitEnvironmentProperties}
|
||||
*/
|
||||
public class PropertiesBasedSshTransportConfigCallback implements TransportConfigCallback {
|
||||
|
||||
private MultipleJGitEnvironmentProperties sshUriProperties;
|
||||
|
||||
public PropertiesBasedSshTransportConfigCallback(MultipleJGitEnvironmentProperties sshUriProperties) {
|
||||
this.sshUriProperties = sshUriProperties;
|
||||
}
|
||||
|
||||
public MultipleJGitEnvironmentProperties getSshUriProperties() {
|
||||
return sshUriProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Transport transport) {
|
||||
if (transport instanceof SshTransport) {
|
||||
SshTransport sshTransport = (SshTransport) transport;
|
||||
sshTransport.setSshSessionFactory(
|
||||
new PropertyBasedSshSessionFactory(
|
||||
new SshUriPropertyProcessor(sshUriProperties).getSshKeysByHostname(), new JSch()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 - 2017 the original author or authors.
|
||||
* Copyright 2015 - 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.
|
||||
@@ -26,6 +26,8 @@ import org.eclipse.jgit.transport.OpenSshConfig.Host;
|
||||
import org.eclipse.jgit.util.Base64;
|
||||
import org.eclipse.jgit.util.FS;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
|
||||
/**
|
||||
* In a cloud environment local SSH config files such as `.known_hosts` may not be suitable for providing
|
||||
* configuration settings due to ephemeral filesystems. This flag enables SSH config to be provided as application
|
||||
@@ -40,17 +42,17 @@ public class PropertyBasedSshSessionFactory extends JschConfigSessionFactory {
|
||||
private static final String YES_OPTION = "yes";
|
||||
private static final String NO_OPTION = "no";
|
||||
private static final String SERVER_HOST_KEY = "server_host_key";
|
||||
private final Map<String, SshUri> sshKeysByHostname;
|
||||
private final Map<String, JGitEnvironmentProperties> sshKeysByHostname;
|
||||
private final JSch jSch;
|
||||
|
||||
public PropertyBasedSshSessionFactory(Map<String, SshUri> sshKeysByHostname, JSch jSch) {
|
||||
public PropertyBasedSshSessionFactory(Map<String, JGitEnvironmentProperties> sshKeysByHostname, JSch jSch) {
|
||||
this.sshKeysByHostname = sshKeysByHostname;
|
||||
this.jSch = jSch;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(Host hc, Session session) {
|
||||
SshUri sshProperties = sshKeysByHostname.get(hc.getHostName());
|
||||
JGitEnvironmentProperties sshProperties = sshKeysByHostname.get(hc.getHostName());
|
||||
String hostKeyAlgorithm = sshProperties.getHostKeyAlgorithm();
|
||||
if (hostKeyAlgorithm != null) {
|
||||
session.setConfig(SERVER_HOST_KEY, hostKeyAlgorithm);
|
||||
@@ -69,7 +71,7 @@ public class PropertyBasedSshSessionFactory extends JschConfigSessionFactory {
|
||||
@Override
|
||||
protected Session createSession(Host hc, String user, String host, int port, FS fs) throws JSchException {
|
||||
if (sshKeysByHostname.containsKey(host)) {
|
||||
SshUri sshUriProperties = sshKeysByHostname.get(host);
|
||||
JGitEnvironmentProperties sshUriProperties = sshKeysByHostname.get(host);
|
||||
jSch.addIdentity(host, sshUriProperties.getPrivateKey().getBytes(), null, null);
|
||||
if (sshUriProperties.getKnownHostsFile() != null) {
|
||||
jSch.setKnownHosts(sshUriProperties.getKnownHostsFile());
|
||||
|
||||
@@ -24,6 +24,8 @@ import java.util.Map;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
@@ -34,7 +36,7 @@ import static org.springframework.util.StringUtils.hasText;
|
||||
* @author Ollie Hughes
|
||||
*/
|
||||
@Component
|
||||
@EnableConfigurationProperties(SshUriProperties.class)
|
||||
@EnableConfigurationProperties(MultipleJGitEnvironmentProperties.class)
|
||||
public class SshPropertyValidator {
|
||||
|
||||
protected static boolean isSshUri(Object uri) {
|
||||
@@ -55,10 +57,10 @@ public class SshPropertyValidator {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected List<SshUri> extractRepoProperties(SshUriProperties sshUriProperties) {
|
||||
List<SshUri> allRepoProperties = new ArrayList<>();
|
||||
protected List<JGitEnvironmentProperties> extractRepoProperties(MultipleJGitEnvironmentProperties sshUriProperties) {
|
||||
List<JGitEnvironmentProperties> allRepoProperties = new ArrayList<>();
|
||||
allRepoProperties.add(sshUriProperties);
|
||||
Map<String, SshUriProperties.SshUriNestedRepoProperties> repos = sshUriProperties.getRepos();
|
||||
Map<String, MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties> repos = sshUriProperties.getRepos();
|
||||
if (repos != null) {
|
||||
allRepoProperties.addAll(repos.values());
|
||||
}
|
||||
|
||||
@@ -1,215 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 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.ssh;
|
||||
|
||||
import org.springframework.cloud.config.server.ssh.SshUriProperties.SshUriNestedRepoProperties;
|
||||
|
||||
import javax.validation.constraints.Pattern;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Base class that contains configuration properties for Git SSH properties
|
||||
*
|
||||
* @author Ollie Hughes
|
||||
*/
|
||||
public abstract class SshUri {
|
||||
private String privateKey;
|
||||
private String uri;
|
||||
private String hostKeyAlgorithm;
|
||||
private String hostKey;
|
||||
private String knownHostsFile;
|
||||
@Pattern(regexp = "([\\w -]+,)*([\\w -]+)")
|
||||
private String preferredAuthentications;
|
||||
private boolean ignoreLocalSshSettings;
|
||||
private boolean strictHostKeyChecking = true;
|
||||
|
||||
public static SshUriPropertiesBuilder builder() {
|
||||
return new SshUriPropertiesBuilder();
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
public String getHostKeyAlgorithm() {
|
||||
return this.hostKeyAlgorithm;
|
||||
}
|
||||
|
||||
public String getHostKey() {
|
||||
return this.hostKey;
|
||||
}
|
||||
|
||||
public String getKnownHostsFile() {
|
||||
return this.knownHostsFile;
|
||||
}
|
||||
|
||||
public String getPreferredAuthentications() {
|
||||
return this.preferredAuthentications;
|
||||
}
|
||||
|
||||
public String getPrivateKey() {
|
||||
return this.privateKey;
|
||||
}
|
||||
|
||||
public boolean isIgnoreLocalSshSettings() {
|
||||
return this.ignoreLocalSshSettings;
|
||||
}
|
||||
|
||||
public boolean isStrictHostKeyChecking() {
|
||||
return this.strictHostKeyChecking;
|
||||
}
|
||||
|
||||
public void setUri(String uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public void setHostKeyAlgorithm(String hostKeyAlgorithm) {
|
||||
this.hostKeyAlgorithm = hostKeyAlgorithm;
|
||||
}
|
||||
|
||||
public void setHostKey(String hostKey) {
|
||||
this.hostKey = hostKey;
|
||||
}
|
||||
|
||||
public void setKnownHostsFile(String knownHostsFile) {
|
||||
this.knownHostsFile = knownHostsFile;
|
||||
}
|
||||
|
||||
public void setPreferredAuthentications(String preferredAuthentications) {
|
||||
this.preferredAuthentications = preferredAuthentications;
|
||||
}
|
||||
|
||||
public void setPrivateKey(String privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public void setIgnoreLocalSshSettings(boolean ignoreLocalSshSettings) {
|
||||
this.ignoreLocalSshSettings = ignoreLocalSshSettings;
|
||||
}
|
||||
|
||||
public void setStrictHostKeyChecking(boolean strictHostKeyChecking) {
|
||||
this.strictHostKeyChecking = strictHostKeyChecking;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "org.springframework.cloud.config.server.ssh.SshUriProperties(uri=" + this.getUri()
|
||||
+ " hostKeyAlgorithm=" + this.getHostKeyAlgorithm()
|
||||
+ ", hostKey=" + this.getHostKey()
|
||||
+ ", privateKey=" + this.getPrivateKey()
|
||||
+ ", ignoreLocalSshSettings=" + this.isIgnoreLocalSshSettings()
|
||||
+ ", knownHostsFile=" + this.getKnownHostsFile()
|
||||
+ ", preferredAuthentications=" + this.getPreferredAuthentications()
|
||||
+ ", strictHostKeyChecking=" + this.isStrictHostKeyChecking() + ",)";
|
||||
}
|
||||
|
||||
public static class SshUriPropertiesBuilder {
|
||||
private String uri;
|
||||
private String hostKeyAlgorithm;
|
||||
private String hostKey;
|
||||
private String privateKey;
|
||||
private String knownHostsFile;
|
||||
private String preferredAuthentications;
|
||||
private boolean ignoreLocalSshSettings;
|
||||
private boolean strictHostKeyChecking = true;
|
||||
private Map<String, SshUriNestedRepoProperties> repos = new LinkedHashMap<>();
|
||||
|
||||
SshUriPropertiesBuilder() {
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder uri(String uri) {
|
||||
this.uri = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder hostKeyAlgorithm(String hostKeyAlgorithm) {
|
||||
this.hostKeyAlgorithm = hostKeyAlgorithm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder hostKey(String hostKey) {
|
||||
this.hostKey = hostKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder privateKey(String privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder knownHostsFile(String knownHostsFile) {
|
||||
this.knownHostsFile = knownHostsFile;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder preferredAuthentications(String preferredAuthentications) {
|
||||
this.preferredAuthentications = preferredAuthentications;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder ignoreLocalSshSettings(boolean ignoreLocalSshSettings) {
|
||||
this.ignoreLocalSshSettings = ignoreLocalSshSettings;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder strictHostKeyChecking(boolean strictHostKeyChecking) {
|
||||
this.strictHostKeyChecking = strictHostKeyChecking;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUri.SshUriPropertiesBuilder repos(Map<String, SshUriNestedRepoProperties> repos) {
|
||||
this.repos = repos;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SshUriProperties build() {
|
||||
SshUriProperties sshUriProperties = new SshUriProperties();
|
||||
sshUriProperties.setRepos(repos);
|
||||
build(sshUriProperties);
|
||||
return sshUriProperties;
|
||||
}
|
||||
|
||||
public SshUriNestedRepoProperties buildAsNestedRepo() {
|
||||
SshUriNestedRepoProperties sshUriNestedRepoProperties = new SshUriNestedRepoProperties();
|
||||
build(sshUriNestedRepoProperties);
|
||||
return sshUriNestedRepoProperties;
|
||||
}
|
||||
|
||||
private void build(SshUri sshUriNestedRepoProperties) {
|
||||
sshUriNestedRepoProperties.setUri(uri);
|
||||
sshUriNestedRepoProperties.setHostKeyAlgorithm(hostKeyAlgorithm);
|
||||
sshUriNestedRepoProperties.setHostKey(hostKey);
|
||||
sshUriNestedRepoProperties.setPrivateKey(privateKey);
|
||||
sshUriNestedRepoProperties.setKnownHostsFile(knownHostsFile);
|
||||
sshUriNestedRepoProperties.setPreferredAuthentications(preferredAuthentications);
|
||||
sshUriNestedRepoProperties.setIgnoreLocalSshSettings(ignoreLocalSshSettings);
|
||||
sshUriNestedRepoProperties.setStrictHostKeyChecking(strictHostKeyChecking);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "org.springframework.cloud.config.server.ssh.SshUriProperties.SshUriPropertiesBuilder(uri=" + this.uri
|
||||
+ "hostKeyAlgorithm=" + this.hostKeyAlgorithm
|
||||
+ ", hostKey=" + this.hostKey
|
||||
+ ", privateKey=" + this.privateKey
|
||||
+ ", knownHostsFile=" + this.knownHostsFile
|
||||
+ ", preferredAuthentications=" + this.preferredAuthentications
|
||||
+ ", ignoreLocalSshSettings=" + this.ignoreLocalSshSettings
|
||||
+ ", strictHostKeyChecking=" + this.strictHostKeyChecking
|
||||
+ ", repos=" + this.repos + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 - 2017 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.ssh;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
/**
|
||||
* Data container for property based SSH config
|
||||
*
|
||||
* @author Ollie Hughes
|
||||
*/
|
||||
@ConfigurationProperties("spring.cloud.config.server.git")
|
||||
@Validated
|
||||
@PrivateKeyIsValid
|
||||
@HostKeyAndAlgoBothExist
|
||||
@HostKeyAlgoSupported
|
||||
@KnownHostsFileIsValid
|
||||
public class SshUriProperties extends SshUri {
|
||||
|
||||
private Map<String, SshUriProperties.SshUriNestedRepoProperties> repos = new LinkedHashMap<>();
|
||||
|
||||
public Map<String, SshUriProperties.SshUriNestedRepoProperties> getRepos() {
|
||||
return this.repos;
|
||||
}
|
||||
|
||||
public void setRepos(Map<String, SshUriNestedRepoProperties> repos) {
|
||||
this.repos = repos;
|
||||
}
|
||||
|
||||
public void addRepo(String repoName, SshUriProperties.SshUriNestedRepoProperties properties) {
|
||||
this.repos.put(repoName, properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + "{repos=" + repos + "}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Differentiate between sets of properties that are defined in nested Git repos.
|
||||
* This is to prevent boot from guarding against a potential infinite deserialization of nested properties.
|
||||
* This sub class differentiates from {@link SshUriProperties} as it does not contain the self mao
|
||||
*/
|
||||
public static class SshUriNestedRepoProperties extends SshUri {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-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.
|
||||
@@ -21,7 +21,9 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.springframework.cloud.config.server.ssh.SshUriProperties.SshUriNestedRepoProperties;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
|
||||
import static org.springframework.cloud.config.server.ssh.SshPropertyValidator.isSshUri;
|
||||
|
||||
@@ -32,25 +34,25 @@ import static org.springframework.cloud.config.server.ssh.SshPropertyValidator.i
|
||||
*/
|
||||
public class SshUriPropertyProcessor {
|
||||
|
||||
private final SshUriProperties sshUriProperties;
|
||||
private final MultipleJGitEnvironmentProperties sshUriProperties;
|
||||
|
||||
public SshUriPropertyProcessor(SshUriProperties sshUriProperties) {
|
||||
public SshUriPropertyProcessor(MultipleJGitEnvironmentProperties sshUriProperties) {
|
||||
this.sshUriProperties = sshUriProperties;
|
||||
}
|
||||
|
||||
public Map<String, SshUri> getSshKeysByHostname() {
|
||||
public Map<String, JGitEnvironmentProperties> getSshKeysByHostname() {
|
||||
return extractNestedProperties(sshUriProperties);
|
||||
}
|
||||
|
||||
private Map<String, SshUri> extractNestedProperties(SshUriProperties uriProperties) {
|
||||
Map<String, SshUri> sshUriPropertyMap = new HashMap<>();
|
||||
private Map<String, JGitEnvironmentProperties> extractNestedProperties(MultipleJGitEnvironmentProperties uriProperties) {
|
||||
Map<String, JGitEnvironmentProperties> sshUriPropertyMap = new HashMap<>();
|
||||
String parentUri = uriProperties.getUri();
|
||||
if (isSshUri(parentUri) && getHostname(parentUri) != null) {
|
||||
sshUriPropertyMap.put(getHostname(parentUri), uriProperties);
|
||||
}
|
||||
Map<String, SshUriNestedRepoProperties> repos = uriProperties.getRepos();
|
||||
Map<String, MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties> repos = uriProperties.getRepos();
|
||||
if(repos != null) {
|
||||
for (SshUriNestedRepoProperties repoProperties : repos.values()) {
|
||||
for (MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties repoProperties : repos.values()) {
|
||||
String repoUri = repoProperties.getUri();
|
||||
if (isSshUri(repoUri) && getHostname(repoUri) != null) {
|
||||
sshUriPropertyMap.put(getHostname(repoUri), repoProperties);
|
||||
|
||||
@@ -25,14 +25,39 @@ import org.springframework.core.Ordered;
|
||||
public class AbstractScmAccessorProperties implements EnvironmentRepositoryProperties {
|
||||
static final String[] DEFAULT_LOCATIONS = new String[] { "/" };
|
||||
|
||||
/**
|
||||
* URI of remote repository.
|
||||
*/
|
||||
private String uri;
|
||||
/**
|
||||
* Base directory for local working copy of repository.
|
||||
*/
|
||||
private File basedir;
|
||||
/**
|
||||
* Search paths to use within local working copy. By default searches only the root.
|
||||
*/
|
||||
private String[] searchPaths = DEFAULT_LOCATIONS.clone();;
|
||||
/**
|
||||
* Username for authentication with remote repository.
|
||||
*/
|
||||
private String username;
|
||||
/**
|
||||
* Password for authentication with remote repository.
|
||||
*/
|
||||
private String password;
|
||||
/**
|
||||
* Passphrase for unlocking your ssh private key.
|
||||
*/
|
||||
private String passphrase;
|
||||
/**
|
||||
* Reject incoming SSH host keys from remote servers not in the known host list.
|
||||
*/
|
||||
private boolean strictHostKeyChecking = true;
|
||||
|
||||
/** The order of the environment repository. */
|
||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
/** The default label to be used with the remore repository */
|
||||
private String defaultLabel;
|
||||
|
||||
public String getUri() {
|
||||
|
||||
@@ -16,19 +16,21 @@
|
||||
|
||||
package org.springframework.cloud.config.server.support;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.springframework.util.StringUtils.hasText;
|
||||
|
||||
/**
|
||||
* A CredentialsProvider factory for Git repositories. Can handle AWS CodeCommit
|
||||
* A CredentialsProvider factory for Git repositories. Can handle AWS CodeCommit
|
||||
* repositories and other repositories with username/password.
|
||||
*
|
||||
* @author Don Laidlaw
|
||||
* @author Gareth Clay
|
||||
*
|
||||
*/
|
||||
public class GitCredentialsProviderFactory {
|
||||
@@ -41,20 +43,43 @@ public class GitCredentialsProviderFactory {
|
||||
* Enabled by default.
|
||||
*/
|
||||
protected boolean awsCodeCommitEnabled = true;
|
||||
|
||||
|
||||
/**
|
||||
* Search for a credential provider that will handle the specified URI. If
|
||||
* not found, and the username has text, then create a default using the
|
||||
* provided username and password. Otherwise null.
|
||||
* Search for a credential provider that will handle the specified URI. If not found,
|
||||
* and the username or passphrase has text, then create a default using the provided
|
||||
* username and password or passphrase. Otherwise null.
|
||||
* @param uri the URI of the repository (cannot be null)
|
||||
* @param username the username provided for the repository (may be null)
|
||||
* @param password the password provided for the repository (may be null)
|
||||
* @param passphrase the passphrase to unlock the ssh private key (may be null)
|
||||
* @return the first matched credentials provider or the default or null.
|
||||
* @deprecated in favour of {@link #createFor(String, String, String, String, boolean)}
|
||||
*/
|
||||
public CredentialsProvider createFor(String uri,
|
||||
String username, String password, String passphrase) {
|
||||
@Deprecated
|
||||
public CredentialsProvider createFor(String uri, String username, String password,
|
||||
String passphrase) {
|
||||
return createFor(uri, username, password, passphrase, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a credential provider that will handle the specified URI. If not found,
|
||||
* and the username or passphrase has text, then create a default using the provided
|
||||
* username and password or passphrase.
|
||||
*
|
||||
* If skipSslValidation is true and the URI has an https scheme, the default credential
|
||||
* provider's behaviour is modified to suppress any SSL validation errors that occur
|
||||
* when communicating via the URI.
|
||||
*
|
||||
* Otherwise null.
|
||||
* @param uri the URI of the repository (cannot be null)
|
||||
* @param username the username provided for the repository (may be null)
|
||||
* @param password the password provided for the repository (may be null)
|
||||
* @param passphrase the passphrase to unlock the ssh private key (may be null)
|
||||
* @param skipSslValidation whether to skip SSL validation when connecting via HTTPS
|
||||
* @return the first matched credentials provider or the default or null.
|
||||
*/
|
||||
public CredentialsProvider createFor(String uri, String username, String password,
|
||||
String passphrase, boolean skipSslValidation) {
|
||||
CredentialsProvider provider = null;
|
||||
if (awsAvailable() && AwsCodeCommitCredentialProvider.canHandle(uri)) {
|
||||
logger.debug("Constructing AwsCodeCommitCredentialProvider for URI " + uri);
|
||||
@@ -72,10 +97,15 @@ public class GitCredentialsProviderFactory {
|
||||
provider = new PassphraseCredentialsProvider(passphrase);
|
||||
}
|
||||
|
||||
if (skipSslValidation && GitSkipSslValidationCredentialsProvider.canHandle(uri)) {
|
||||
logger.debug("Constructing GitSkipSslValidationCredentialsProvider for URI "
|
||||
+ uri);
|
||||
provider = new GitSkipSslValidationCredentialsProvider(provider);
|
||||
}
|
||||
else {
|
||||
logger.debug("No credentials provider required for URI " + uri);
|
||||
}
|
||||
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
|
||||
import org.eclipse.jgit.internal.JGitText;
|
||||
import org.eclipse.jgit.transport.CredentialItem;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
|
||||
/**
|
||||
* A {@link CredentialsProvider} that will ignore any SSL validation errors that occur.
|
||||
* This is primarily intended as a convenience for testing scenarios where self-signed
|
||||
* certificates are being used.
|
||||
*
|
||||
* This class can be used as a decorator for another CredentialsProvider, adding SSL
|
||||
* validation skipping behaviour to a repository that also requires authentication, for
|
||||
* example.
|
||||
*
|
||||
* @author Gareth Clay
|
||||
*/
|
||||
public class GitSkipSslValidationCredentialsProvider extends CredentialsProvider {
|
||||
|
||||
private final CredentialsProvider delegate;
|
||||
|
||||
public GitSkipSslValidationCredentialsProvider(CredentialsProvider delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* This provider can handle uris like https://github.com/org/repo
|
||||
*/
|
||||
public static boolean canHandle(String uri) {
|
||||
return uri != null && uri.toLowerCase().startsWith("https://");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInteractive() {
|
||||
return (delegate != null) && delegate.isInteractive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(CredentialItem... items) {
|
||||
List<CredentialItem> unprocessedItems = new ArrayList<>();
|
||||
|
||||
for (CredentialItem item : items) {
|
||||
if (item instanceof CredentialItem.InformationalMessage
|
||||
&& item.getPromptText() != null && item.getPromptText()
|
||||
.contains(JGitText.get().sslFailureTrustExplanation))
|
||||
continue;
|
||||
|
||||
if (item instanceof CredentialItem.YesNoType && item.getPromptText() != null
|
||||
&& (item.getPromptText().equals(JGitText.get().sslTrustNow)
|
||||
|| item.getPromptText()
|
||||
.startsWith(stripFormattingPlaceholders(
|
||||
JGitText.get().sslTrustForRepo))
|
||||
|| item.getPromptText()
|
||||
.equals(JGitText.get().sslTrustAlways)))
|
||||
continue;
|
||||
|
||||
unprocessedItems.add(item);
|
||||
}
|
||||
|
||||
return unprocessedItems.isEmpty() || (delegate != null
|
||||
&& delegate.supports(unprocessedItems.toArray(new CredentialItem[0])));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get(URIish uri, CredentialItem... items)
|
||||
throws UnsupportedCredentialItem {
|
||||
List<CredentialItem> unprocessedItems = new ArrayList<>();
|
||||
|
||||
for (CredentialItem item : items) {
|
||||
if (item instanceof CredentialItem.YesNoType) {
|
||||
CredentialItem.YesNoType yesNoItem = (CredentialItem.YesNoType) item;
|
||||
String prompt = yesNoItem.getPromptText();
|
||||
if (prompt == null) {
|
||||
unprocessedItems.add(item);
|
||||
}
|
||||
else if (prompt.equals(JGitText.get().sslTrustNow) || prompt.startsWith(
|
||||
stripFormattingPlaceholders(JGitText.get().sslTrustForRepo))) {
|
||||
yesNoItem.setValue(true);
|
||||
}
|
||||
else if (prompt.equals(JGitText.get().sslTrustAlways)) {
|
||||
yesNoItem.setValue(false);
|
||||
}
|
||||
else {
|
||||
unprocessedItems.add(item);
|
||||
}
|
||||
}
|
||||
else if (!item.getPromptText()
|
||||
.contains(JGitText.get().sslFailureTrustExplanation)) {
|
||||
unprocessedItems.add(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (unprocessedItems.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
if (delegate != null) {
|
||||
return delegate.get(uri, unprocessedItems.toArray(new CredentialItem[0]));
|
||||
}
|
||||
throw new UnsupportedCredentialItem(uri,
|
||||
unprocessedItems.size() + " credential items not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(URIish uri) {
|
||||
if (delegate != null) {
|
||||
delegate.reset(uri);
|
||||
}
|
||||
}
|
||||
|
||||
private static String stripFormattingPlaceholders(String string) {
|
||||
return string.replaceAll("\\s*\\{\\d}\\s*", "");
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
* Copyright 2013-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.
|
||||
@@ -24,7 +24,6 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||
import org.springframework.cloud.config.server.config.ConfigServerHealthIndicatorTests;
|
||||
import org.springframework.cloud.config.server.config.CustomCompositeEnvironmentRepositoryTests;
|
||||
import org.springframework.cloud.config.server.config.CustomEnvironmentRepositoryTests;
|
||||
import org.springframework.cloud.config.server.config.TransportConfigurationTest;
|
||||
import org.springframework.cloud.config.server.credentials.AwsCodeCommitCredentialsProviderTests;
|
||||
import org.springframework.cloud.config.server.credentials.GitCredentialsProviderFactoryTests;
|
||||
import org.springframework.cloud.config.server.encryption.CipherEnvironmentEncryptorTests;
|
||||
@@ -108,7 +107,6 @@ import org.springframework.cloud.config.server.ssh.SshUriPropertyProcessorTest;
|
||||
ConfigServerHealthIndicatorTests.class,
|
||||
CustomCompositeEnvironmentRepositoryTests.class,
|
||||
CustomEnvironmentRepositoryTests.class,
|
||||
TransportConfigurationTest.class,
|
||||
BootstrapConfigServerIntegrationTests.class,
|
||||
})
|
||||
@Ignore
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-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.
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.config.server;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.jcraft.jsch.Session;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.eclipse.jgit.transport.JschConfigSessionFactory;
|
||||
@@ -25,20 +28,22 @@ import org.eclipse.jgit.util.FS;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.config.server.config.TransportConfiguration;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentRepository;
|
||||
import org.springframework.cloud.config.server.ssh.FileBasedSshTransportConfigCallback;
|
||||
import org.springframework.cloud.config.server.ssh.PropertiesBasedSshTransportConfigCallback;
|
||||
import org.springframework.cloud.config.server.ssh.SshPropertyValidator;
|
||||
import org.springframework.cloud.config.server.ssh.SshUriProperties;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -49,124 +54,251 @@ import static org.mockito.Mockito.verify;
|
||||
*/
|
||||
public class TransportConfigurationIntegrationTests {
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, TransportConfiguration.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.config.name:ssh/ssh-private-key-block",})
|
||||
@ActiveProfiles({"test", "git"})
|
||||
public static class PropertyBasedCallbackTest {
|
||||
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {"spring.config.name:ssh/ssh-private-key-block"})
|
||||
@ActiveProfiles({"test", "git"})
|
||||
public static class StaticTest {
|
||||
|
||||
@Test
|
||||
public void propertyBasedTransportCallbackIsConfigured() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(TransportConfiguration.PropertiesBasedSshTransportConfigCallback.class)));
|
||||
}
|
||||
}
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, TransportConfiguration.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.config.name:ssh/ssh-private-key-newline"
|
||||
})
|
||||
@ActiveProfiles({"test", "git"})
|
||||
public static class PrivateKeyPropertyWithLineBreaks {
|
||||
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void privateKeyPropertyWithLineBreaks() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(TransportConfiguration.PropertiesBasedSshTransportConfigCallback.class)));
|
||||
|
||||
TransportConfiguration.PropertiesBasedSshTransportConfigCallback configCallback =
|
||||
(TransportConfiguration.PropertiesBasedSshTransportConfigCallback) transportConfigCallback;
|
||||
assertThat(configCallback.getSshUriProperties().getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_1)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, TransportConfiguration.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.config.name:ssh/ssh-nested-settings"
|
||||
})
|
||||
@ActiveProfiles({"test", "git"})
|
||||
public static class SshPropertiesWithinNestedRepo {
|
||||
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void sshPropertiesWithinNestedRepo() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(TransportConfiguration.PropertiesBasedSshTransportConfigCallback.class)));
|
||||
|
||||
TransportConfiguration.PropertiesBasedSshTransportConfigCallback configCallback =
|
||||
(TransportConfiguration.PropertiesBasedSshTransportConfigCallback) transportConfigCallback;
|
||||
SshUriProperties sshUriProperties = configCallback.getSshUriProperties();
|
||||
assertThat(sshUriProperties.getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_1)));
|
||||
|
||||
assertThat(sshUriProperties.getRepos().get("repo1"), is(notNullValue()));
|
||||
assertThat(sshUriProperties.getRepos().get("repo1").getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_2)));
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, TransportConfiguration.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.cloud.config.server.git.uri=git@gitserver.com:team/repo.git",
|
||||
"spring.cloud.config.server.git.ignoreLocalSshSettings=false",})
|
||||
@ActiveProfiles({"test", "git"})
|
||||
public static class FileBasedCallbackTest {
|
||||
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void fileBasedTransportCallbackIsConfigured() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(TransportConfiguration.FileBasedSshTransportConfigCallback.class)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void strictHostKeyCheckShouldCheck() throws Exception {
|
||||
String uri = "git+ssh://git@somegitserver/somegitrepo";
|
||||
SshSessionFactory.setInstance(null);
|
||||
jGitEnvironmentRepository.setUri(uri);
|
||||
jGitEnvironmentRepository.setBasedir(new File("./mybasedir"));
|
||||
assertTrue(jGitEnvironmentRepository.isStrictHostKeyChecking());
|
||||
jGitEnvironmentRepository.setCloneOnStart(true);
|
||||
try {
|
||||
// this will throw but we don't care about connecting.
|
||||
jGitEnvironmentRepository.afterPropertiesSet();
|
||||
} catch (Exception e) {
|
||||
final OpenSshConfig.Host hc = OpenSshConfig.get(FS.detect()).lookup("github.com");
|
||||
JschConfigSessionFactory factory = (JschConfigSessionFactory) SshSessionFactory.getInstance();
|
||||
// There's no public method that can be used to inspect the ssh
|
||||
// configuration, so we'll reflect
|
||||
// the configure method to allow us to check that the config
|
||||
// property is set as expected.
|
||||
Method configure = factory.getClass().getDeclaredMethod("configure", OpenSshConfig.Host.class,
|
||||
Session.class);
|
||||
configure.setAccessible(true);
|
||||
Session session = mock(Session.class);
|
||||
ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
|
||||
configure.invoke(factory, hc, session);
|
||||
verify(session).setConfig(keyCaptor.capture(), valueCaptor.capture());
|
||||
configure.setAccessible(false);
|
||||
assertTrue("yes".equals(valueCaptor.getValue()));
|
||||
@Test
|
||||
public void propertyBasedTransportCallbackIsConfigured() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(PropertiesBasedSshTransportConfigCallback.class)));
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {"spring.config.name:ssh/ssh-private-key-block-list"})
|
||||
@ActiveProfiles({"test", "composite"})
|
||||
public static class ListTest {
|
||||
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void propertyBasedTransportCallbackIsConfigured() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(PropertiesBasedSshTransportConfigCallback.class)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class PrivateKeyPropertyWithLineBreaks {
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.config.name:ssh/ssh-private-key-newline"
|
||||
})
|
||||
@ActiveProfiles({"test", "git"})
|
||||
public static class StaticTest {
|
||||
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void privateKeyPropertyWithLineBreaks() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(PropertiesBasedSshTransportConfigCallback.class)));
|
||||
|
||||
PropertiesBasedSshTransportConfigCallback configCallback =
|
||||
(PropertiesBasedSshTransportConfigCallback) transportConfigCallback;
|
||||
assertThat(configCallback.getSshUriProperties().getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_1)));
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.config.name:ssh/ssh-private-key-newline-list"
|
||||
})
|
||||
@ActiveProfiles({"test", "composite"})
|
||||
public static class ListTest {
|
||||
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void privateKeyPropertyWithLineBreaks() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(PropertiesBasedSshTransportConfigCallback.class)));
|
||||
|
||||
PropertiesBasedSshTransportConfigCallback configCallback =
|
||||
(PropertiesBasedSshTransportConfigCallback) transportConfigCallback;
|
||||
assertThat(configCallback.getSshUriProperties().getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_1)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class SshPropertiesWithinNestedRepo {
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.config.name:ssh/ssh-nested-settings"
|
||||
})
|
||||
@ActiveProfiles({"test", "git"})
|
||||
public static class StaticTest {
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void sshPropertiesWithinNestedRepo() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(PropertiesBasedSshTransportConfigCallback.class)));
|
||||
|
||||
PropertiesBasedSshTransportConfigCallback configCallback =
|
||||
(PropertiesBasedSshTransportConfigCallback) transportConfigCallback;
|
||||
MultipleJGitEnvironmentProperties sshUriProperties = configCallback.getSshUriProperties();
|
||||
assertThat(sshUriProperties.getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_1)));
|
||||
|
||||
assertThat(sshUriProperties.getRepos().get("repo1"), is(notNullValue()));
|
||||
assertThat(sshUriProperties.getRepos().get("repo1").getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_2)));
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.config.name:ssh/ssh-nested-settings-list"
|
||||
})
|
||||
@ActiveProfiles({"test", "composite"})
|
||||
public static class ListTest {
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void sshPropertiesWithinNestedRepo() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(PropertiesBasedSshTransportConfigCallback.class)));
|
||||
|
||||
PropertiesBasedSshTransportConfigCallback configCallback =
|
||||
(PropertiesBasedSshTransportConfigCallback) transportConfigCallback;
|
||||
MultipleJGitEnvironmentProperties sshUriProperties = configCallback.getSshUriProperties();
|
||||
assertThat(sshUriProperties.getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_1)));
|
||||
|
||||
assertThat(sshUriProperties.getRepos().get("repo1"), is(notNullValue()));
|
||||
assertThat(sshUriProperties.getRepos().get("repo1").getPrivateKey(), is(equalTo(TestProperties.TEST_PRIVATE_KEY_2)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class FileBasedCallbackTest {
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.cloud.config.server.git.uri=git@gitserver.com:team/repo.git",
|
||||
"spring.cloud.config.server.git.ignoreLocalSshSettings=false",})
|
||||
@ActiveProfiles({"test", "git"})
|
||||
public static class StaticTest {
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void fileBasedTransportCallbackIsConfigured() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(FileBasedSshTransportConfigCallback.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void strictHostKeyCheckShouldCheck() throws Exception {
|
||||
String uri = "git+ssh://git@somegitserver/somegitrepo";
|
||||
SshSessionFactory.setInstance(null);
|
||||
jGitEnvironmentRepository.setUri(uri);
|
||||
jGitEnvironmentRepository.setBasedir(new File("./mybasedir"));
|
||||
assertTrue(jGitEnvironmentRepository.isStrictHostKeyChecking());
|
||||
jGitEnvironmentRepository.setCloneOnStart(true);
|
||||
try {
|
||||
// this will throw but we don't care about connecting.
|
||||
jGitEnvironmentRepository.afterPropertiesSet();
|
||||
} catch (Exception e) {
|
||||
final OpenSshConfig.Host hc = OpenSshConfig.get(FS.detect()).lookup("github.com");
|
||||
JschConfigSessionFactory factory = (JschConfigSessionFactory) SshSessionFactory.getInstance();
|
||||
// There's no public method that can be used to inspect the ssh
|
||||
// configuration, so we'll reflect
|
||||
// the configure method to allow us to check that the config
|
||||
// property is set as expected.
|
||||
Method configure = factory.getClass().getDeclaredMethod("configure", OpenSshConfig.Host.class,
|
||||
Session.class);
|
||||
configure.setAccessible(true);
|
||||
Session session = mock(Session.class);
|
||||
ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
|
||||
configure.invoke(factory, hc, session);
|
||||
verify(session).setConfig(keyCaptor.capture(), valueCaptor.capture());
|
||||
configure.setAccessible(false);
|
||||
assertTrue("yes".equals(valueCaptor.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = {ConfigServerApplication.class, SshPropertyValidator.class},
|
||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
|
||||
properties = {
|
||||
"spring.cloud.config.server.composite[0].type=git",
|
||||
"spring.cloud.config.server.composite[0].uri=git@gitserver.com:team/repo.git",
|
||||
"spring.cloud.config.server.composite[0].ignoreLocalSshSettings=false",})
|
||||
@ActiveProfiles({"test", "composite"})
|
||||
public static class ListTest {
|
||||
@Autowired
|
||||
private MultipleJGitEnvironmentRepository jGitEnvironmentRepository;
|
||||
|
||||
@Test
|
||||
public void fileBasedTransportCallbackIsConfigured() throws Exception {
|
||||
TransportConfigCallback transportConfigCallback = jGitEnvironmentRepository.getTransportConfigCallback();
|
||||
assertThat(transportConfigCallback, is(instanceOf(FileBasedSshTransportConfigCallback.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void strictHostKeyCheckShouldCheck() throws Exception {
|
||||
String uri = "git+ssh://git@somegitserver/somegitrepo";
|
||||
SshSessionFactory.setInstance(null);
|
||||
jGitEnvironmentRepository.setUri(uri);
|
||||
jGitEnvironmentRepository.setBasedir(new File("./mybasedir"));
|
||||
assertTrue(jGitEnvironmentRepository.isStrictHostKeyChecking());
|
||||
jGitEnvironmentRepository.setCloneOnStart(true);
|
||||
try {
|
||||
// this will throw but we don't care about connecting.
|
||||
jGitEnvironmentRepository.afterPropertiesSet();
|
||||
} catch (Exception e) {
|
||||
final OpenSshConfig.Host hc = OpenSshConfig.get(FS.detect()).lookup("github.com");
|
||||
JschConfigSessionFactory factory = (JschConfigSessionFactory) SshSessionFactory.getInstance();
|
||||
// There's no public method that can be used to inspect the ssh
|
||||
// configuration, so we'll reflect
|
||||
// the configure method to allow us to check that the config
|
||||
// property is set as expected.
|
||||
Method configure = factory.getClass().getDeclaredMethod("configure", OpenSshConfig.Host.class,
|
||||
Session.class);
|
||||
configure.setAccessible(true);
|
||||
Session session = mock(Session.class);
|
||||
ArgumentCaptor<String> keyCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<String> valueCaptor = ArgumentCaptor.forClass(String.class);
|
||||
configure.invoke(factory, hc, session);
|
||||
verify(session).setConfig(keyCaptor.capture(), valueCaptor.capture());
|
||||
configure.setAccessible(false);
|
||||
assertTrue("yes".equals(valueCaptor.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class TestProperties {
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 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 org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.config.server.ssh.SshUri;
|
||||
import org.springframework.cloud.config.server.ssh.SshUriProperties;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
/**
|
||||
* @author Ollie Hughes
|
||||
*/
|
||||
public class TransportConfigurationTest {
|
||||
@Test
|
||||
public void propertiesBasedSshTransportCallbackCreated() throws Exception {
|
||||
SshUriProperties ignoreLocalSettings = SshUri.builder()
|
||||
.uri("user@gitrepo.com:proj/repo")
|
||||
.ignoreLocalSshSettings(true)
|
||||
.build();
|
||||
TransportConfiguration transportConfiguration = new TransportConfiguration();
|
||||
TransportConfigCallback transportConfigCallback = transportConfiguration.propertiesBasedSshTransportCallback(ignoreLocalSettings);
|
||||
assertThat(transportConfigCallback, is(instanceOf(TransportConfiguration.PropertiesBasedSshTransportConfigCallback.class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileBasedSshTransportCallbackCreated() throws Exception {
|
||||
SshUriProperties dontIgnoreLocalSettings = SshUri.builder()
|
||||
.uri("user@gitrepo.com:proj/repo")
|
||||
.ignoreLocalSshSettings(false)
|
||||
.build();
|
||||
|
||||
TransportConfiguration transportConfiguration = new TransportConfiguration();
|
||||
TransportConfigCallback transportConfigCallback = transportConfiguration.propertiesBasedSshTransportCallback(dontIgnoreLocalSettings);
|
||||
assertThat(transportConfigCallback, is(instanceOf(TransportConfiguration.FileBasedSshTransportConfigCallback.class)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,16 +18,16 @@ package org.springframework.cloud.config.server.credentials;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
|
||||
import com.amazonaws.auth.AWSCredentialsProvider;
|
||||
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
|
||||
import org.eclipse.jgit.transport.CredentialItem;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.config.server.support.AwsCodeCommitCredentialProvider;
|
||||
import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory;
|
||||
|
||||
import com.amazonaws.auth.AWSCredentialsProvider;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -56,7 +56,7 @@ public class AwsCodeCommitCredentialsProviderTests {
|
||||
public void init() {
|
||||
GitCredentialsProviderFactory factory = new GitCredentialsProviderFactory();
|
||||
provider = (AwsCodeCommitCredentialProvider)
|
||||
factory.createFor(AWS_REPO, USER, PASSWORD, null);
|
||||
factory.createFor(AWS_REPO, USER, PASSWORD, null, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -116,7 +116,7 @@ public class AwsCodeCommitCredentialsProviderTests {
|
||||
public void testUriWithCurlyBracesReturnsTrue() throws UnsupportedCredentialItem, URISyntaxException {
|
||||
GitCredentialsProviderFactory factory = new GitCredentialsProviderFactory();
|
||||
provider = (AwsCodeCommitCredentialProvider)
|
||||
factory.createFor(CURLY_BRACES_REPO, USER, PASSWORD, null);
|
||||
factory.createFor(CURLY_BRACES_REPO, USER, PASSWORD, null, false);
|
||||
CredentialItem[] credentialItems = makeCredentialItems();
|
||||
assertTrue(provider.get(new URIish(CURLY_BRACES_REPO), credentialItems));
|
||||
}
|
||||
|
||||
@@ -20,9 +20,11 @@ import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.config.server.support.AwsCodeCommitCredentialProvider;
|
||||
import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory;
|
||||
import org.springframework.cloud.config.server.support.PassphraseCredentialsProvider;
|
||||
import org.springframework.cloud.config.server.support.GitSkipSslValidationCredentialsProvider;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -32,13 +34,14 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author don laidlaw
|
||||
*
|
||||
* @author Gareth Clay
|
||||
*/
|
||||
public class GitCredentialsProviderFactoryTests {
|
||||
private static final String PASSWORD = "secret";
|
||||
private static final String USER = "test";
|
||||
private static final String FILE_REPO = "file:///home/user/repo";
|
||||
private static final String GIT_REPO = "https://github.com/spring-cloud/spring-cloud-config-test";
|
||||
private static final String HTTPS_GIT_REPO = "https://github.com/spring-cloud/spring-cloud-config-test";
|
||||
private static final String SSH_GIT_REPO = "git@github.com:spring-cloud/spring-cloud-config-test.git";
|
||||
private static final String AWS_REPO = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/test";
|
||||
|
||||
private GitCredentialsProviderFactory factory;
|
||||
@@ -50,33 +53,62 @@ public class GitCredentialsProviderFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testCreateForFileNoUsernameIsNull() {
|
||||
CredentialsProvider provider = factory.createFor(FILE_REPO, null, null, null);
|
||||
CredentialsProvider provider = factory.createFor(FILE_REPO, null, null, null,
|
||||
false);
|
||||
assertNull(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateForFileWithUsername() {
|
||||
CredentialsProvider provider = factory.createFor(FILE_REPO, USER, PASSWORD, null);
|
||||
CredentialsProvider provider = factory.createFor(FILE_REPO, USER, PASSWORD, null,
|
||||
false);
|
||||
assertNotNull(provider);
|
||||
assertTrue(provider instanceof UsernamePasswordCredentialsProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateForServerNoUsernameIsNull() {
|
||||
CredentialsProvider provider = factory.createFor(GIT_REPO, null, null, null);
|
||||
CredentialsProvider provider = factory.createFor(HTTPS_GIT_REPO, null, null, null,
|
||||
false);
|
||||
assertNull(provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateForServerWithUsername() {
|
||||
CredentialsProvider provider = factory.createFor(GIT_REPO, USER, PASSWORD, null);
|
||||
CredentialsProvider provider = factory.createFor(HTTPS_GIT_REPO, USER, PASSWORD,
|
||||
null, false);
|
||||
assertNotNull(provider);
|
||||
assertTrue(provider instanceof UsernamePasswordCredentialsProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateForHttpsServerWithSkipSslValidation() {
|
||||
CredentialsProvider provider = factory.createFor(HTTPS_GIT_REPO, USER, PASSWORD,
|
||||
null, true);
|
||||
assertNotNull(provider);
|
||||
assertTrue(provider instanceof GitSkipSslValidationCredentialsProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateForHttpsServerWithoutSpecifyingSkipSslValidation() {
|
||||
CredentialsProvider provider = factory.createFor(HTTPS_GIT_REPO, USER, PASSWORD, null);
|
||||
assertNotNull(provider);
|
||||
assertTrue("deprecated createFor() should not enable ssl validation skipping",
|
||||
provider instanceof UsernamePasswordCredentialsProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateForSshServerWithSkipSslValidation() {
|
||||
CredentialsProvider provider = factory.createFor(SSH_GIT_REPO, USER, PASSWORD,
|
||||
null, true);
|
||||
assertNotNull(provider);
|
||||
assertTrue(provider instanceof UsernamePasswordCredentialsProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateForAwsNoUsername() {
|
||||
CredentialsProvider provider = factory.createFor(AWS_REPO, null, null, null);
|
||||
CredentialsProvider provider = factory.createFor(AWS_REPO, null, null, null,
|
||||
false);
|
||||
assertNotNull(provider);
|
||||
assertTrue(provider instanceof AwsCodeCommitCredentialProvider);
|
||||
AwsCodeCommitCredentialProvider aws = (AwsCodeCommitCredentialProvider) provider;
|
||||
@@ -86,7 +118,8 @@ public class GitCredentialsProviderFactoryTests {
|
||||
|
||||
@Test
|
||||
public void testCreateForAwsWithUsername() {
|
||||
CredentialsProvider provider = factory.createFor(AWS_REPO, USER, PASSWORD, null);
|
||||
CredentialsProvider provider = factory.createFor(AWS_REPO, USER, PASSWORD, null,
|
||||
false);
|
||||
assertNotNull(provider);
|
||||
assertTrue(provider instanceof AwsCodeCommitCredentialProvider);
|
||||
AwsCodeCommitCredentialProvider aws = (AwsCodeCommitCredentialProvider) provider;
|
||||
@@ -97,20 +130,21 @@ public class GitCredentialsProviderFactoryTests {
|
||||
@Test
|
||||
public void testCreateForAwsDisabled() {
|
||||
factory.setAwsCodeCommitEnabled(false);
|
||||
CredentialsProvider provider = factory.createFor(AWS_REPO, null, null, null);
|
||||
CredentialsProvider provider = factory.createFor(AWS_REPO, null, null, null,
|
||||
false);
|
||||
assertNull(provider);
|
||||
provider = factory.createFor(AWS_REPO, USER, PASSWORD, null);
|
||||
provider = factory.createFor(AWS_REPO, USER, PASSWORD, null, false);
|
||||
assertNotNull(provider);
|
||||
assertTrue(provider instanceof UsernamePasswordCredentialsProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreatePassphraseCredentialProvider() {
|
||||
CredentialsProvider provider = factory.createFor(GIT_REPO, null, null, PASSWORD);
|
||||
CredentialsProvider provider = factory.createFor(HTTPS_GIT_REPO, null, null,
|
||||
PASSWORD, false);
|
||||
assertNotNull(provider);
|
||||
assertTrue(provider instanceof PassphraseCredentialsProvider);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsAwsCodeCommitEnabled() {
|
||||
|
||||
@@ -16,16 +16,17 @@
|
||||
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.util.HashMap;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.environment.PropertySource;
|
||||
import org.springframework.cloud.config.server.environment.EnvironmentControllerIntegrationTests.ControllerConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -52,23 +53,26 @@ public class EnvironmentControllerIntegrationTests {
|
||||
private MockMvc mvc;
|
||||
@Autowired
|
||||
private EnvironmentRepository repository;
|
||||
|
||||
private Environment environment = new Environment("foo", "default");
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
Mockito.reset(this.repository);
|
||||
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
|
||||
environment.add(new PropertySource("foo", new HashMap<>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentNoLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", null)).thenReturn(new Environment("foo", "default"));
|
||||
Mockito.when(this.repository.findOne("foo", "default", null)).thenReturn(this.environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default")).andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo", "default", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertiesNoLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", null)).thenReturn(new Environment("foo", "default"));
|
||||
Mockito.when(this.repository.findOne("foo", "default", null)).thenReturn(this.environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo-default.properties"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo", "default", null);
|
||||
@@ -76,7 +80,7 @@ public class EnvironmentControllerIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void propertiesLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "label")).thenReturn(new Environment("foo", "default"));
|
||||
Mockito.when(this.repository.findOne("foo", "default", "label")).thenReturn(this.environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label/foo-default.properties"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo", "default", "label");
|
||||
@@ -84,8 +88,10 @@ public class EnvironmentControllerIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void propertiesLabelWhenApplicationNameContainsHyphen() throws Exception {
|
||||
Environment environment = new Environment("foo-bar", "default");
|
||||
environment.add(new PropertySource("foo", new HashMap<>()));
|
||||
Mockito.when(this.repository.findOne("foo-bar", "default", "label"))
|
||||
.thenReturn(new Environment("foo-bar", "default"));
|
||||
.thenReturn(this.environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label/foo-bar-default.properties"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo-bar", "default", "label");
|
||||
@@ -93,8 +99,9 @@ public class EnvironmentControllerIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void propertiesLabelWithSlash() throws Exception {
|
||||
|
||||
Mockito.when(this.repository.findOne("foo", "default", "label/spam"))
|
||||
.thenReturn(new Environment("foo", "default"));
|
||||
.thenReturn(this.environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/label(_)spam/foo-default.properties"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
Mockito.verify(this.repository).findOne("foo", "default", "label/spam");
|
||||
@@ -103,7 +110,7 @@ public class EnvironmentControllerIntegrationTests {
|
||||
@Test
|
||||
public void environmentWithLabel() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "awesome"))
|
||||
.thenReturn(new Environment("foo", "default"));
|
||||
.thenReturn(this.environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/awesome"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
}
|
||||
@@ -126,7 +133,7 @@ public class EnvironmentControllerIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void environmentWithLabelContainingPeriod() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "1.0.0")).thenReturn(new Environment("foo", "default"));
|
||||
Mockito.when(this.repository.findOne("foo", "default", "1.0.0")).thenReturn(this.environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/1.0.0"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
}
|
||||
@@ -134,7 +141,7 @@ public class EnvironmentControllerIntegrationTests {
|
||||
@Test
|
||||
public void environmentWithLabelContainingSlash() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo", "default", "feature/puff"))
|
||||
.thenReturn(new Environment("foo", "default"));
|
||||
.thenReturn(this.environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo/default/feature(_)puff"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("\"propertySources\":")));
|
||||
@@ -142,8 +149,10 @@ public class EnvironmentControllerIntegrationTests {
|
||||
|
||||
@Test
|
||||
public void environmentWithApplicationContainingSlash() throws Exception {
|
||||
Environment environment = new Environment("foo/app", "default");
|
||||
environment.add(new PropertySource("foo", new HashMap<>()));
|
||||
Mockito.when(this.repository.findOne("foo/app", "default", null))
|
||||
.thenReturn(new Environment("foo/app", "default"));
|
||||
.thenReturn(environment);
|
||||
this.mvc.perform(MockMvcRequestBuilders.get("/foo(_)app/default"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk())
|
||||
.andExpect(MockMvcResultMatchers.content().string(Matchers.containsString("\"propertySources\":")));
|
||||
|
||||
@@ -65,6 +65,7 @@ public class EnvironmentControllerTests {
|
||||
@Before
|
||||
public void init() {
|
||||
this.controller = new EnvironmentController(this.repository);
|
||||
environment.add(new PropertySource("foo", new HashMap<>()));
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -195,27 +196,47 @@ public class EnvironmentControllerTests {
|
||||
assertThat(environment.getProfiles(), equalTo(new String[] { "master" }));
|
||||
assertThat(environment.getLabel(), equalTo("master"));
|
||||
assertThat(environment.getVersion(), nullValue());
|
||||
assertThat(environment.getPropertySources(), hasSize(2));
|
||||
assertThat(environment.getPropertySources(), hasSize(3));
|
||||
assertThat(environment.getPropertySources().get(0).getName(), equalTo("two"));
|
||||
assertThat(environment.getPropertySources().get(0).getSource().entrySet(),
|
||||
hasSize(2));
|
||||
assertThat(environment.getPropertySources().get(1).getName(), equalTo("one"));
|
||||
assertThat(environment.getPropertySources().get(1).getSource().entrySet(),
|
||||
assertThat(environment.getPropertySources().get(2).getName(), equalTo("one"));
|
||||
assertThat(environment.getPropertySources().get(2).getSource().entrySet(),
|
||||
hasSize(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameWithSlash() {
|
||||
this.controller.labelled("foo(_)spam", "bar", "two");
|
||||
|
||||
Mockito.verify(this.repository).findOne("foo/spam", "bar", "two");
|
||||
}
|
||||
Mockito.when(this.repository.findOne("foo/spam", "bar", "two")).thenReturn(this.environment);
|
||||
|
||||
Environment returnedEnvironment = this.controller.labelled("foo(_)spam", "bar", "two");
|
||||
|
||||
assertEquals(this.environment.getLabel(), returnedEnvironment.getLabel());
|
||||
assertEquals(this.environment.getName(), returnedEnvironment.getName());
|
||||
|
||||
}
|
||||
@Test(expected=EnvironmentNotFoundException.class)
|
||||
public void testEnvironmentNotFound() {
|
||||
this.controller.setAcceptEmpty(false);
|
||||
this.controller.labelled("foo", "bar", null);
|
||||
}
|
||||
@Test
|
||||
public void testwithValidEnvironment() {
|
||||
Mockito.when(this.repository.findOne("foo", "bar",null))
|
||||
.thenReturn(this.environment);
|
||||
Environment environment = this.controller.labelled("foo", "bar", null);
|
||||
assertThat(environment, not(nullValue()));
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testLabelWithSlash() {
|
||||
this.controller.labelled("foo", "bar", "two(_)spam");
|
||||
|
||||
Mockito.verify(this.repository).findOne("foo", "bar", "two/spam");
|
||||
Mockito.when(this.repository.findOne("foo", "bar", "two/spam")).thenReturn(this.environment);
|
||||
|
||||
Environment returnedEnvironment = this.controller.labelled("foo", "bar", "two(_)spam");
|
||||
|
||||
assertEquals(this.environment.getLabel(), returnedEnvironment.getLabel());
|
||||
assertEquals(this.environment.getName(), returnedEnvironment.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -491,6 +512,15 @@ public class EnvironmentControllerTests {
|
||||
mvc.perform(MockMvcRequestBuilders.get("/foo/bar/other"))
|
||||
.andExpect(MockMvcResultMatchers.status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void environmentMissing() throws Exception {
|
||||
Mockito.when(this.repository.findOne("foo1", "notfound", null))
|
||||
.thenThrow(new EnvironmentNotFoundException("Missing Environment"));
|
||||
MockMvc mvc = MockMvcBuilders.standaloneSetup(this.controller).build();
|
||||
mvc.perform(MockMvcRequestBuilders.get("/foo1/notfound"))
|
||||
.andExpect(MockMvcResultMatchers.status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingForYaml() throws Exception {
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* 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.net.URL;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jgit.internal.storage.file.FileRepository;
|
||||
import org.eclipse.jgit.junit.http.SimpleHttpServer;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
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.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
public class JGitEnvironmentRepositorySslTests {
|
||||
|
||||
private static SimpleHttpServer server;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception {
|
||||
URL repoUrl = JGitEnvironmentRepositorySslTests.class
|
||||
.getResource("/test1-config-repo/git");
|
||||
Repository repo = new FileRepository(new File(repoUrl.toURI()));
|
||||
server = new SimpleHttpServer(repo, true);
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardown() throws Exception {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test(expected = CertificateException.class)
|
||||
public void selfSignedCertIsRejected() throws Throwable {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(
|
||||
TestConfiguration.class).properties(configServerProperties())
|
||||
.web(WebApplicationType.NONE).run();
|
||||
|
||||
JGitEnvironmentRepository repository = context
|
||||
.getBean(JGitEnvironmentRepository.class);
|
||||
|
||||
try {
|
||||
repository.findOne("bar", "staging", "master");
|
||||
}
|
||||
catch (Throwable e) {
|
||||
while (e.getCause() != null) {
|
||||
e = e.getCause();
|
||||
if (e instanceof CertificateException)
|
||||
break;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selfSignedCertWithSkipSslValidationIsAccepted() {
|
||||
ConfigurableApplicationContext context = new SpringApplicationBuilder(
|
||||
TestConfiguration.class)
|
||||
.properties(configServerProperties(
|
||||
"spring.cloud.config.server.git.skipSslValidation=true"))
|
||||
.web(WebApplicationType.NONE).run();
|
||||
|
||||
JGitEnvironmentRepository repository = context
|
||||
.getBean(JGitEnvironmentRepository.class);
|
||||
repository.findOne("bar", "staging", "master");
|
||||
}
|
||||
|
||||
private static String[] configServerProperties(String... extraProperties) {
|
||||
List<String> properties = new ArrayList<>(Arrays.asList(extraProperties));
|
||||
properties.add("spring.cloud.config.server.git.uri=" + server.getSecureUri());
|
||||
properties.add("spring.cloud.config.server.git.username=agitter");
|
||||
properties.add("spring.cloud.config.server.git.password=letmein");
|
||||
return properties.toArray(new String[0]);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ConfigServerProperties.class)
|
||||
@Import({ PropertyPlaceholderAutoConfiguration.class,
|
||||
EnvironmentRepositoryConfiguration.class })
|
||||
static class TestConfiguration {
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,6 @@ import org.eclipse.jgit.api.StatusCommand;
|
||||
import org.eclipse.jgit.api.TransportConfigCallback;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
||||
import org.eclipse.jgit.api.errors.NoMessageException;
|
||||
import org.eclipse.jgit.api.errors.NotMergedException;
|
||||
import org.eclipse.jgit.api.errors.TransportException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
@@ -60,17 +59,17 @@ import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.support.AwsCodeCommitCredentialProvider;
|
||||
import org.springframework.cloud.config.server.support.GitCredentialsProviderFactory;
|
||||
import org.springframework.cloud.config.server.support.GitSkipSslValidationCredentialsProvider;
|
||||
import org.springframework.cloud.config.server.support.PassphraseCredentialsProvider;
|
||||
import org.springframework.cloud.config.server.test.ConfigServerTestUtils;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.AdditionalMatchers.aryEq;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
@@ -82,7 +81,7 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @author Gareth Clay
|
||||
*/
|
||||
public class JGitEnvironmentRepositoryTests {
|
||||
|
||||
@@ -332,6 +331,70 @@ public class JGitEnvironmentRepositoryTests {
|
||||
assertThat("shouldPull was false", shouldPull, is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldNotRefresh() throws Exception {
|
||||
Git git = mock(Git.class);
|
||||
StatusCommand statusCommand = mock(StatusCommand.class);
|
||||
Status status = mock(Status.class);
|
||||
Repository repository = mock(Repository.class);
|
||||
StoredConfig storedConfig = mock(StoredConfig.class);
|
||||
|
||||
when(git.status()).thenReturn(statusCommand);
|
||||
when(git.getRepository()).thenReturn(repository);
|
||||
when(repository.getConfig()).thenReturn(storedConfig);
|
||||
when(storedConfig.getString("remote", "origin", "url")).thenReturn("http://example/git");
|
||||
when(statusCommand.call()).thenReturn(status);
|
||||
when(status.isClean()).thenReturn(true);
|
||||
|
||||
JGitEnvironmentProperties properties = new JGitEnvironmentProperties();
|
||||
properties.setRefreshRate(2);
|
||||
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment, properties);
|
||||
|
||||
repo.setLastRefresh(System.currentTimeMillis() - 5000);
|
||||
|
||||
boolean shouldPull = repo.shouldPull(git);
|
||||
|
||||
assertThat("shouldPull was false", shouldPull, is(true));
|
||||
|
||||
repo.setRefreshRate(30);
|
||||
|
||||
shouldPull = repo.shouldPull(git);
|
||||
|
||||
assertThat("shouldPull was true", shouldPull, is(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldUpdateLastRefresh() throws Exception {
|
||||
Git git = mock(Git.class);
|
||||
StatusCommand statusCommand = mock(StatusCommand.class);
|
||||
Status status = mock(Status.class);
|
||||
Repository repository = mock(Repository.class);
|
||||
StoredConfig storedConfig = mock(StoredConfig.class);
|
||||
FetchCommand fetchCommand = mock(FetchCommand.class);
|
||||
FetchResult fetchResult = mock(FetchResult.class);
|
||||
|
||||
when(git.status()).thenReturn(statusCommand);
|
||||
when(git.getRepository()).thenReturn(repository);
|
||||
when(fetchCommand.call()).thenReturn(fetchResult);
|
||||
when(git.fetch()).thenReturn(fetchCommand);
|
||||
when(repository.getConfig()).thenReturn(storedConfig);
|
||||
when(storedConfig.getString("remote", "origin", "url")).thenReturn("http://example/git");
|
||||
when(statusCommand.call()).thenReturn(status);
|
||||
when(status.isClean()).thenReturn(true);
|
||||
|
||||
JGitEnvironmentProperties properties = new JGitEnvironmentProperties();
|
||||
properties.setRefreshRate(1000);
|
||||
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment, properties);
|
||||
|
||||
repo.setLastRefresh(0);
|
||||
repo.fetch(git, "master");
|
||||
|
||||
long timeDiff = System.currentTimeMillis() - repo.getLastRefresh();
|
||||
|
||||
assertThat("time difference ("+timeDiff+") was longer than 1 second", timeDiff < 1000L, is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFetchException() throws Exception {
|
||||
|
||||
@@ -617,7 +680,6 @@ public class JGitEnvironmentRepositoryTests {
|
||||
public void gitCredentialsProviderFactoryCreatesPassphraseProvider() throws Exception {
|
||||
final String passphrase = "mypassphrase";
|
||||
final String gitUri = "git+ssh://git@somegitserver/somegitrepo";
|
||||
GitCredentialsProviderFactory credentialsFactory = new GitCredentialsProviderFactory();
|
||||
Git mockGit = mock(Git.class);
|
||||
MockCloneCommand mockCloneCommand = new MockCloneCommand(mockGit);
|
||||
|
||||
@@ -626,7 +688,7 @@ public class JGitEnvironmentRepositoryTests {
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri(gitUri);
|
||||
envRepository.setBasedir(new File("./mybasedir"));
|
||||
envRepository.setGitCredentialsProvider(credentialsFactory.createFor(gitUri, null, null, passphrase));
|
||||
envRepository.setPassphrase(passphrase);
|
||||
envRepository.setCloneOnStart(true);
|
||||
envRepository.afterPropertiesSet();
|
||||
|
||||
@@ -646,7 +708,6 @@ public class JGitEnvironmentRepositoryTests {
|
||||
|
||||
@Test
|
||||
public void gitCredentialsProviderFactoryCreatesUsernamePasswordProvider() throws Exception {
|
||||
GitCredentialsProviderFactory credentialsFactory = new GitCredentialsProviderFactory();
|
||||
Git mockGit = mock(Git.class);
|
||||
MockCloneCommand mockCloneCommand = new MockCloneCommand(mockGit);
|
||||
final String username = "someuser";
|
||||
@@ -657,8 +718,8 @@ public class JGitEnvironmentRepositoryTests {
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri("git+ssh://git@somegitserver/somegitrepo");
|
||||
envRepository.setBasedir(new File("./mybasedir"));
|
||||
envRepository.setGitCredentialsProvider(
|
||||
credentialsFactory.createFor(envRepository.getUri(), username, password, null));
|
||||
envRepository.setUsername(username);
|
||||
envRepository.setPassword(password);
|
||||
envRepository.setCloneOnStart(true);
|
||||
envRepository.afterPropertiesSet();
|
||||
|
||||
@@ -678,7 +739,6 @@ public class JGitEnvironmentRepositoryTests {
|
||||
|
||||
@Test
|
||||
public void gitCredentialsProviderFactoryCreatesAwsCodeCommitProvider() throws Exception {
|
||||
GitCredentialsProviderFactory credentialsFactory = new GitCredentialsProviderFactory();
|
||||
Git mockGit = mock(Git.class);
|
||||
MockCloneCommand mockCloneCommand = new MockCloneCommand(mockGit);
|
||||
final String awsUri = "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/test";
|
||||
@@ -687,12 +747,44 @@ public class JGitEnvironmentRepositoryTests {
|
||||
new JGitEnvironmentProperties());
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri(awsUri);
|
||||
envRepository.setGitCredentialsProvider(credentialsFactory.createFor(envRepository.getUri(), null, null, null));
|
||||
envRepository.setCloneOnStart(true);
|
||||
envRepository.afterPropertiesSet();
|
||||
|
||||
assertTrue(mockCloneCommand.getCredentialsProvider() instanceof AwsCodeCommitCredentialProvider);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gitCredentialsProviderFactoryCreatesSkipSslValidationProvider()
|
||||
throws Exception {
|
||||
Git mockGit = mock(Git.class);
|
||||
MockCloneCommand mockCloneCommand = new MockCloneCommand(mockGit);
|
||||
final String username = "someuser";
|
||||
final String password = "mypassword";
|
||||
|
||||
JGitEnvironmentRepository envRepository = new JGitEnvironmentRepository(
|
||||
this.environment, new JGitEnvironmentProperties());
|
||||
envRepository.setGitFactory(new MockGitFactory(mockGit, mockCloneCommand));
|
||||
envRepository.setUri("https://somegitserver/somegitrepo");
|
||||
envRepository.setBasedir(new File("./mybasedir"));
|
||||
envRepository.setUsername(username);
|
||||
envRepository.setPassword(password);
|
||||
envRepository.setSkipSslValidation(true);
|
||||
envRepository.setCloneOnStart(true);
|
||||
envRepository.afterPropertiesSet();
|
||||
|
||||
CredentialsProvider provider = mockCloneCommand.getCredentialsProvider();
|
||||
|
||||
assertTrue(provider instanceof GitSkipSslValidationCredentialsProvider);
|
||||
|
||||
CredentialItem.Username usernameCredential = new CredentialItem.Username();
|
||||
CredentialItem.Password passwordCredential = new CredentialItem.Password();
|
||||
assertTrue(provider.supports(usernameCredential));
|
||||
assertTrue(provider.supports(passwordCredential));
|
||||
|
||||
provider.get(new URIish(), usernameCredential);
|
||||
assertEquals(usernameCredential.getValue(), username);
|
||||
provider.get(new URIish(), passwordCredential);
|
||||
assertEquals(String.valueOf(passwordCredential.getValue()), password);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -105,6 +105,26 @@ public class MultipleJGitEnvironmentRepositoryIntegrationTests {
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingRepoWithRefreshRate() throws IOException {
|
||||
String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
String test1RepoUri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo");
|
||||
|
||||
Map<String, Object> repoMapping = new LinkedHashMap<String, Object>();
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].pattern", "*test1*");
|
||||
repoMapping.put("spring.cloud.config.server.git.repos[test1].uri", test1RepoUri);
|
||||
repoMapping.put("spring.cloud.config.server.git.refresh-rate", "30");
|
||||
this.context = new SpringApplicationBuilder(TestConfiguration.class).web(WebApplicationType.NONE)
|
||||
.properties("spring.cloud.config.server.git.uri:" + defaultRepoUri)
|
||||
.properties(repoMapping).run();
|
||||
EnvironmentRepository repository = this.context
|
||||
.getBean(EnvironmentRepository.class);
|
||||
repository.findOne("test1-svc", "staging", "master");
|
||||
Environment environment = repository.findOne("test1-svc", "staging", "master");
|
||||
assertEquals(2, environment.getPropertySources().size());
|
||||
assertEquals(((MultipleJGitEnvironmentRepository) repository).getRepos().get("test1").getRefreshRate(), 30);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mappingRepoWithProfile() throws IOException {
|
||||
String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.springframework.core.env.StandardEnvironment;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -46,6 +47,7 @@ import static org.mockito.Mockito.when;
|
||||
* @author Andy Chan (iceycake)
|
||||
* @author Dave Syer
|
||||
* @author Spencer Gibb
|
||||
* @author Gareth Clay
|
||||
*
|
||||
*/
|
||||
public class MultipleJGitEnvironmentRepositoryTests {
|
||||
@@ -204,6 +206,85 @@ public class MultipleJGitEnvironmentRepositoryTests {
|
||||
assertEquals(repo2.getTransportConfigCallback(), mockCallback2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setCorrectCredentials() throws Exception {
|
||||
final String repo1Username = "repo1-username";
|
||||
final String repo1Password = "repo1-password";
|
||||
final String repo2Passphrase = "repo2-passphrase";
|
||||
final String multiRepoUsername = "multi-repo-username";
|
||||
final String multiRepoPassword = "multi-repo-password";
|
||||
final String multiRepoPassphrase = "multi-repo-passphrase";
|
||||
PatternMatchingJGitEnvironmentRepository repo1 = createRepository("test1",
|
||||
"*test1*", "test1Uri");
|
||||
repo1.setUsername(repo1Username);
|
||||
repo1.setPassword(repo1Password);
|
||||
PatternMatchingJGitEnvironmentRepository repo2 = createRepository("test2",
|
||||
"*test2*", "test2Uri");
|
||||
repo2.setPassphrase(repo2Passphrase);
|
||||
|
||||
Map<String, PatternMatchingJGitEnvironmentRepository> repos = new HashMap<>();
|
||||
repos.put("test1", repo1);
|
||||
repos.put("test2", repo2);
|
||||
|
||||
this.repository.setRepos(repos);
|
||||
this.repository.setUsername(multiRepoUsername);
|
||||
this.repository.setPassword(multiRepoPassword);
|
||||
this.repository.setPassphrase(multiRepoPassphrase);
|
||||
this.repository.afterPropertiesSet();
|
||||
|
||||
assertEquals("Repo1 has its own username which should not be overwritten",
|
||||
repo1.getUsername(), repo1Username);
|
||||
assertEquals("Repo1 has its own password which should not be overwritten",
|
||||
repo1.getPassword(), repo1Password);
|
||||
assertEquals(
|
||||
"Repo1 did not specify a passphrase so this should have been copied from the multi repo",
|
||||
repo1.getPassphrase(), multiRepoPassphrase);
|
||||
assertEquals(
|
||||
"Repo2 did not specify a username so this should have been copied from the multi repo",
|
||||
repo2.getUsername(), multiRepoUsername);
|
||||
assertEquals(
|
||||
"Repo2 did not specify a username so this should have been copied from the multi repo",
|
||||
repo2.getPassword(), multiRepoPassword);
|
||||
assertEquals(
|
||||
"Repo2 has its own passphrase which should not have been overwritten",
|
||||
repo2.getPassphrase(), repo2Passphrase);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setSkipSslValidation() throws Exception {
|
||||
final boolean repo1SkipSslValidation = false;
|
||||
final boolean repo2SkipSslValidation = true;
|
||||
PatternMatchingJGitEnvironmentRepository repo1 = createRepository("test1",
|
||||
"*test1*", "test1Uri");
|
||||
repo1.setSkipSslValidation(repo1SkipSslValidation);
|
||||
PatternMatchingJGitEnvironmentRepository repo2 = createRepository("test2",
|
||||
"*test2*", "test2Uri");
|
||||
repo2.setSkipSslValidation(repo2SkipSslValidation);
|
||||
|
||||
Map<String, PatternMatchingJGitEnvironmentRepository> repos = new HashMap<>();
|
||||
repos.put("test1", repo1);
|
||||
repos.put("test2", repo2);
|
||||
|
||||
this.repository.setRepos(repos);
|
||||
this.repository.setSkipSslValidation(false);
|
||||
this.repository.afterPropertiesSet();
|
||||
assertFalse(
|
||||
"If skip SSL validation is false at multi-repo level, then per-repo settings take priority",
|
||||
repo1.isSkipSslValidation());
|
||||
assertTrue(
|
||||
"If skip SSL validation is false at multi-repo level, then per-repo settings take priority",
|
||||
repo2.isSkipSslValidation());
|
||||
|
||||
this.repository.setSkipSslValidation(true);
|
||||
this.repository.afterPropertiesSet();
|
||||
assertTrue(
|
||||
"If explicitly set to skip SSL validation at the multi-repo level, then apply same setting to sub-repos",
|
||||
repo1.isSkipSslValidation());
|
||||
assertTrue(
|
||||
"If explicitly set to skip SSL validation at the multi-repo level, then apply same setting to sub-repos",
|
||||
repo2.isSkipSslValidation());
|
||||
}
|
||||
|
||||
@Test
|
||||
// test for gh-700
|
||||
public void basedirCreatedIfNotExists() throws Exception {
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package org.springframework.cloud.config.server.environment;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.cloud.config.environment.Environment;
|
||||
import org.springframework.cloud.config.server.environment.VaultEnvironmentRepository.VaultResponse;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
@@ -17,6 +19,10 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
@@ -27,133 +33,170 @@ public class VaultEnvironmentRepositoryTests {
|
||||
@Before
|
||||
public void init() {}
|
||||
|
||||
@Test
|
||||
public void testFindOneNoDefaultKey() throws IOException {
|
||||
MockHttpServletRequest configRequest = new MockHttpServletRequest();
|
||||
configRequest.addHeader("X-CONFIG-TOKEN", "mytoken");
|
||||
RestTemplate rest = Mockito.mock(RestTemplate.class);
|
||||
|
||||
ResponseEntity<VaultEnvironmentRepository.VaultResponse> myAppResp = Mockito.mock(ResponseEntity.class);
|
||||
Mockito.when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultEnvironmentRepository.VaultResponse myAppVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
|
||||
Mockito.when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
|
||||
Mockito.when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
|
||||
Mockito.eq("secret"), Mockito.eq("myapp"))).thenReturn(myAppResp);
|
||||
|
||||
ResponseEntity<VaultEnvironmentRepository.VaultResponse> appResp = Mockito.mock(ResponseEntity.class);
|
||||
Mockito.when(appResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultEnvironmentRepository.VaultResponse appVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
|
||||
Mockito.when(appVaultResp.getData()).thenReturn("{\"def-foo\":\"def-bar\"}");
|
||||
Mockito.when(appResp.getBody()).thenReturn(appVaultResp);
|
||||
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
|
||||
Mockito.eq("secret"), Mockito.eq("application"))).thenReturn(appResp);
|
||||
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(configRequest, new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
|
||||
Environment e = repo.findOne("myapp", null, null);
|
||||
assertEquals("Name should be the same as the application argument", "myapp", e.getName());
|
||||
assertEquals("Properties for specified application and default application with key 'application' should be returned", 2, e.getPropertySources().size());
|
||||
Map<String, String> firstResult = new HashMap<String, String>();
|
||||
firstResult.put("foo", "bar");
|
||||
assertEquals("Properties for specified application should be returned in priority position", firstResult, e.getPropertySources().get(0).getSource());
|
||||
|
||||
Map<String, String> secondResult = new HashMap<String, String>();
|
||||
secondResult.put("def-foo", "def-bar");
|
||||
assertEquals("Properties for default application with key 'application' should be returned in second position", secondResult, e.getPropertySources().get(1).getSource());
|
||||
@SuppressWarnings("unchecked")
|
||||
private ObjectProvider<HttpServletRequest> mockProvide(HttpServletRequest request) {
|
||||
ObjectProvider<HttpServletRequest> objectProvider = mock(ObjectProvider.class);
|
||||
when(objectProvider.getIfAvailable()).thenReturn(request);
|
||||
return objectProvider;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneDefaultKeySetAndDifferentToApplication() throws IOException {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testFindOneNoDefaultKey() {
|
||||
MockHttpServletRequest configRequest = new MockHttpServletRequest();
|
||||
configRequest.addHeader("X-CONFIG-TOKEN", "mytoken");
|
||||
RestTemplate rest = Mockito.mock(RestTemplate.class);
|
||||
|
||||
ResponseEntity<VaultEnvironmentRepository.VaultResponse> myAppResp = Mockito.mock(ResponseEntity.class);
|
||||
Mockito.when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultEnvironmentRepository.VaultResponse myAppVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
|
||||
Mockito.when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
|
||||
Mockito.when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
|
||||
Mockito.eq("secret"), Mockito.eq("myapp"))).thenReturn(myAppResp);
|
||||
RestTemplate rest = mock(RestTemplate.class);
|
||||
|
||||
ResponseEntity<VaultEnvironmentRepository.VaultResponse> myDefaultKeyResp = Mockito.mock(ResponseEntity.class);
|
||||
Mockito.when(myDefaultKeyResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultEnvironmentRepository.VaultResponse myDefaultKeyVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
|
||||
Mockito.when(myDefaultKeyVaultResp.getData()).thenReturn("{\"def-foo\":\"def-bar\"}");
|
||||
Mockito.when(myDefaultKeyResp.getBody()).thenReturn(myDefaultKeyVaultResp);
|
||||
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
|
||||
Mockito.eq("secret"), Mockito.eq("mydefaultkey"))).thenReturn(myDefaultKeyResp);
|
||||
ResponseEntity<VaultResponse> myAppResp = mock(ResponseEntity.class);
|
||||
when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse myAppVaultResp = mock(VaultResponse.class);
|
||||
when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
|
||||
when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
eq(HttpMethod.GET), any(HttpEntity.class), eq(VaultResponse.class),
|
||||
eq("secret"), eq("myapp"))).thenReturn(myAppResp);
|
||||
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(configRequest, new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
ResponseEntity<VaultResponse> appResp = mock(ResponseEntity.class);
|
||||
when(appResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse appVaultResp = mock(VaultResponse.class);
|
||||
when(appVaultResp.getData()).thenReturn("{\"def-foo\":\"def-bar\"}");
|
||||
when(appResp.getBody()).thenReturn(appVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
eq(HttpMethod.GET), any(HttpEntity.class), eq(VaultResponse.class),
|
||||
eq("secret"), eq("application"))).thenReturn(appResp);
|
||||
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(mockProvide(configRequest),
|
||||
new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
|
||||
Environment e = repo.findOne("myapp", null, null);
|
||||
assertEquals("Name should be the same as the application argument", "myapp", e.getName());
|
||||
assertEquals("Properties for specified application and default application with key 'application' should be returned",
|
||||
2, e.getPropertySources().size());
|
||||
Map<String, String> firstResult = new HashMap<String, String>();
|
||||
firstResult.put("foo", "bar");
|
||||
assertEquals("Properties for specified application should be returned in priority position",
|
||||
firstResult, e.getPropertySources().get(0).getSource());
|
||||
|
||||
Map<String, String> secondResult = new HashMap<String, String>();
|
||||
secondResult.put("def-foo", "def-bar");
|
||||
assertEquals("Properties for default application with key 'application' should be returned in second position",
|
||||
secondResult, e.getPropertySources().get(1).getSource());
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testFindOneDefaultKeySetAndDifferentToApplication() {
|
||||
MockHttpServletRequest configRequest = new MockHttpServletRequest();
|
||||
configRequest.addHeader("X-CONFIG-TOKEN", "mytoken");
|
||||
RestTemplate rest = mock(RestTemplate.class);
|
||||
|
||||
ResponseEntity<VaultResponse> myAppResp = mock(ResponseEntity.class);
|
||||
when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse myAppVaultResp = mock(VaultResponse.class);
|
||||
when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
|
||||
when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
eq(HttpMethod.GET), any(HttpEntity.class), eq(VaultResponse.class),
|
||||
eq("secret"), eq("myapp"))).thenReturn(myAppResp);
|
||||
|
||||
ResponseEntity<VaultResponse> myDefaultKeyResp = mock(ResponseEntity.class);
|
||||
when(myDefaultKeyResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse myDefaultKeyVaultResp = mock(VaultResponse.class);
|
||||
when(myDefaultKeyVaultResp.getData()).thenReturn("{\"def-foo\":\"def-bar\"}");
|
||||
when(myDefaultKeyResp.getBody()).thenReturn(myDefaultKeyVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
eq(HttpMethod.GET), any(HttpEntity.class), eq(VaultResponse.class),
|
||||
eq("secret"), eq("mydefaultkey"))).thenReturn(myDefaultKeyResp);
|
||||
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(mockProvide(configRequest),
|
||||
new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
repo.setDefaultKey("mydefaultkey");
|
||||
|
||||
Environment e = repo.findOne("myapp", null, null);
|
||||
assertEquals("Name should be the same as the application argument", "myapp", e.getName());
|
||||
assertEquals("Properties for specified application and default application with key 'mydefaultkey' should be returned", 2, e.getPropertySources().size());
|
||||
assertEquals("Properties for specified application and default application with key 'mydefaultkey' should be returned",
|
||||
2, e.getPropertySources().size());
|
||||
|
||||
Map<String, String> firstResult = new HashMap<String, String>();
|
||||
firstResult.put("foo", "bar");
|
||||
assertEquals("Properties for specified application should be returned in priority position", firstResult, e.getPropertySources().get(0).getSource());
|
||||
assertEquals("Properties for specified application should be returned in priority position",
|
||||
firstResult, e.getPropertySources().get(0).getSource());
|
||||
|
||||
Map<String, String> secondResult = new HashMap<String, String>();
|
||||
secondResult.put("def-foo", "def-bar");
|
||||
assertEquals("Properties for default application with key 'mydefaultkey' should be returned in second position", secondResult, e.getPropertySources().get(1).getSource());
|
||||
assertEquals("Properties for default application with key 'mydefaultkey' should be returned in second position",
|
||||
secondResult, e.getPropertySources().get(1).getSource());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindOneDefaultKeySetAndEqualToApplication() throws IOException {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testFindOneDefaultKeySetAndEqualToApplication() {
|
||||
MockHttpServletRequest configRequest = new MockHttpServletRequest();
|
||||
configRequest.addHeader("X-CONFIG-TOKEN", "mytoken");
|
||||
RestTemplate rest = Mockito.mock(RestTemplate.class);
|
||||
RestTemplate rest = mock(RestTemplate.class);
|
||||
|
||||
ResponseEntity<VaultEnvironmentRepository.VaultResponse> myAppResp = Mockito.mock(ResponseEntity.class);
|
||||
Mockito.when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultEnvironmentRepository.VaultResponse myAppVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
|
||||
Mockito.when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
|
||||
Mockito.when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
|
||||
Mockito.eq("secret"), Mockito.eq("myapp"))).thenReturn(myAppResp);
|
||||
ResponseEntity<VaultResponse> myAppResp = mock(ResponseEntity.class);
|
||||
when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse myAppVaultResp = mock(VaultResponse.class);
|
||||
when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
|
||||
when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
eq(HttpMethod.GET), any(HttpEntity.class), eq(VaultResponse.class),
|
||||
eq("secret"), eq("myapp"))).thenReturn(myAppResp);
|
||||
|
||||
ResponseEntity<VaultEnvironmentRepository.VaultResponse> appResp = Mockito.mock(ResponseEntity.class);
|
||||
Mockito.when(appResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultEnvironmentRepository.VaultResponse appVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
|
||||
Mockito.when(appVaultResp.getData()).thenReturn("{\"def-foo\":\"def-bar\"}");
|
||||
Mockito.when(appResp.getBody()).thenReturn(appVaultResp);
|
||||
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
|
||||
Mockito.eq("secret"), Mockito.eq("application"))).thenReturn(appResp);
|
||||
ResponseEntity<VaultResponse> appResp = mock(ResponseEntity.class);
|
||||
when(appResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse appVaultResp = mock(VaultResponse.class);
|
||||
when(appVaultResp.getData()).thenReturn("{\"def-foo\":\"def-bar\"}");
|
||||
when(appResp.getBody()).thenReturn(appVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
eq(HttpMethod.GET), any(HttpEntity.class), eq(VaultResponse.class),
|
||||
eq("secret"), eq("application"))).thenReturn(appResp);
|
||||
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(configRequest, new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(mockProvide(configRequest),
|
||||
new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
repo.setDefaultKey("myapp");
|
||||
|
||||
Environment e = repo.findOne("myapp", null, null);
|
||||
assertEquals("Name should be the same as the application argument", "myapp", e.getName());
|
||||
assertEquals("Only properties for specified application should be returned", 1, e.getPropertySources().size());
|
||||
assertEquals("Name should be the same as the application argument",
|
||||
"myapp", e.getName());
|
||||
assertEquals("Only properties for specified application should be returned",
|
||||
1, e.getPropertySources().size());
|
||||
|
||||
Map<String, String> result = new HashMap<String, String>();
|
||||
result.put("foo", "bar");
|
||||
assertEquals("Properties should be returned for specified application", result, e.getPropertySources().get(0).getSource());
|
||||
assertEquals("Properties should be returned for specified application",
|
||||
result, e.getPropertySources().get(0).getSource());
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void missingConfigToken() throws IOException {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void missingConfigToken() {
|
||||
MockHttpServletRequest configRequest = new MockHttpServletRequest();
|
||||
RestTemplate rest = Mockito.mock(RestTemplate.class);
|
||||
ResponseEntity<VaultEnvironmentRepository.VaultResponse> myAppResp = Mockito.mock(ResponseEntity.class);
|
||||
Mockito.when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultEnvironmentRepository.VaultResponse myAppVaultResp = Mockito.mock(VaultEnvironmentRepository.VaultResponse.class);
|
||||
Mockito.when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
|
||||
Mockito.when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
Mockito.when(rest.exchange(Mockito.eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
Mockito.eq(HttpMethod.GET), Mockito.any(HttpEntity.class), Mockito.eq(VaultEnvironmentRepository.VaultResponse.class),
|
||||
Mockito.eq("secret"), Mockito.eq("myapp"))).thenReturn(myAppResp);
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(configRequest, new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
RestTemplate rest = mock(RestTemplate.class);
|
||||
ResponseEntity<VaultResponse> myAppResp = mock(ResponseEntity.class);
|
||||
when(myAppResp.getStatusCode()).thenReturn(HttpStatus.OK);
|
||||
VaultResponse myAppVaultResp = mock(VaultResponse.class);
|
||||
when(myAppVaultResp.getData()).thenReturn("{\"foo\":\"bar\"}");
|
||||
when(myAppResp.getBody()).thenReturn(myAppVaultResp);
|
||||
when(rest.exchange(eq("http://127.0.0.1:8200/v1/{backend}/{key}"),
|
||||
eq(HttpMethod.GET), any(HttpEntity.class), eq(VaultResponse.class),
|
||||
eq("secret"), eq("myapp"))).thenReturn(myAppResp);
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(mockProvide(configRequest),
|
||||
new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
repo.findOne("myapp", null, null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
@SuppressWarnings("unchecked")
|
||||
public void missingHttpRequest() {
|
||||
ObjectProvider<HttpServletRequest> objectProvider = mock(ObjectProvider.class);
|
||||
when(objectProvider.getIfAvailable()).thenReturn(null);
|
||||
|
||||
RestTemplate rest = mock(RestTemplate.class);
|
||||
VaultEnvironmentRepository repo = new VaultEnvironmentRepository(objectProvider,
|
||||
new EnvironmentWatch.Default(), rest, new VaultEnvironmentProperties());
|
||||
repo.findOne("myapp", null, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 - 2017 the original author or authors.
|
||||
* Copyright 2015 - 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.
|
||||
@@ -22,6 +22,10 @@ import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.jcraft.jsch.HostKey;
|
||||
import com.jcraft.jsch.HostKeyRepository;
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.Session;
|
||||
import org.eclipse.jgit.transport.OpenSshConfig.Host;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
@@ -29,19 +33,11 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import com.jcraft.jsch.HostKey;
|
||||
import com.jcraft.jsch.HostKeyRepository;
|
||||
import com.jcraft.jsch.JSch;
|
||||
import com.jcraft.jsch.Session;
|
||||
|
||||
import static org.mockito.Matchers.isNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static org.mockito.Matchers.isNull;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
@@ -70,10 +66,9 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
|
||||
@Test
|
||||
public void strictHostKeyCheckingIsOptional() {
|
||||
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
|
||||
.uri("ssh://gitlab.example.local:3322/somerepo.git")
|
||||
.privateKey(PRIVATE_KEY)
|
||||
.build();
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("ssh://gitlab.example.local:3322/somerepo.git");
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
setupSessionFactory(sshKey);
|
||||
|
||||
factory.configure(hc, session);
|
||||
@@ -84,11 +79,10 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
|
||||
@Test
|
||||
public void strictHostKeyCheckingIsUsed() {
|
||||
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
|
||||
.uri("ssh://gitlab.example.local:3322/somerepo.git")
|
||||
.hostKey(HOST_KEY)
|
||||
.privateKey(PRIVATE_KEY)
|
||||
.build();
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("ssh://gitlab.example.local:3322/somerepo.git");
|
||||
sshKey.setHostKey(HOST_KEY);
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
setupSessionFactory(sshKey);
|
||||
|
||||
factory.configure(hc, session);
|
||||
@@ -99,12 +93,11 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
|
||||
@Test
|
||||
public void hostKeyAlgorithmIsSpecified() {
|
||||
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
|
||||
.uri("ssh://gitlab.example.local:3322/somerepo.git")
|
||||
.hostKeyAlgorithm(HOST_KEY_ALGORITHM)
|
||||
.hostKey(HOST_KEY)
|
||||
.privateKey(PRIVATE_KEY)
|
||||
.build();
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("ssh://gitlab.example.local:3322/somerepo.git");
|
||||
sshKey.setHostKeyAlgorithm(HOST_KEY_ALGORITHM);
|
||||
sshKey.setHostKey(HOST_KEY);
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
setupSessionFactory(sshKey);
|
||||
|
||||
factory.configure(hc, session);
|
||||
@@ -115,10 +108,9 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
|
||||
@Test
|
||||
public void privateKeyIsUsed() throws Exception {
|
||||
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
|
||||
.uri("git@gitlab.example.local:someorg/somerepo.git")
|
||||
.privateKey(PRIVATE_KEY)
|
||||
.build();
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("git@gitlab.example.local:someorg/somerepo.git");
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
setupSessionFactory(sshKey);
|
||||
|
||||
factory.createSession(hc, null, SshUriPropertyProcessor.getHostname(sshKey.getUri()), 22, null);
|
||||
@@ -127,11 +119,10 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
|
||||
@Test
|
||||
public void hostKeyIsUsed() throws Exception {
|
||||
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
|
||||
.uri("git@gitlab.example.local:someorg/somerepo.git")
|
||||
.hostKey(HOST_KEY)
|
||||
.privateKey(PRIVATE_KEY)
|
||||
.build();
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("git@gitlab.example.local:someorg/somerepo.git");
|
||||
sshKey.setHostKey(HOST_KEY);
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
setupSessionFactory(sshKey);
|
||||
|
||||
factory.createSession(hc, null, SshUriPropertyProcessor.getHostname(sshKey.getUri()), 22, null);
|
||||
@@ -144,11 +135,10 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
|
||||
@Test
|
||||
public void preferredAuthenticationsIsSpecified() {
|
||||
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
|
||||
.uri("ssh://gitlab.example.local:3322/somerepo.git")
|
||||
.privateKey(PRIVATE_KEY)
|
||||
.preferredAuthentications("password,keyboard-interactive")
|
||||
.build();
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("ssh://gitlab.example.local:3322/somerepo.git");
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
sshKey.setPreferredAuthentications("password,keyboard-interactive");
|
||||
setupSessionFactory(sshKey);
|
||||
|
||||
factory.configure(hc, session);
|
||||
@@ -159,11 +149,10 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
|
||||
@Test
|
||||
public void customKnownHostsFileIsUsed() throws Exception {
|
||||
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
|
||||
.uri("git@gitlab.example.local:someorg/somerepo.git")
|
||||
.privateKey(PRIVATE_KEY)
|
||||
.knownHostsFile("/ssh/known_hosts")
|
||||
.build();
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("git@gitlab.example.local:someorg/somerepo.git");
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
sshKey.setKnownHostsFile("/ssh/known_hosts");
|
||||
setupSessionFactory(sshKey);
|
||||
|
||||
factory.createSession(hc, null, SshUriPropertyProcessor.getHostname(sshKey.getUri()), 22, null);
|
||||
@@ -173,8 +162,8 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
Assert.assertEquals("/ssh/known_hosts", captor.getValue());
|
||||
}
|
||||
|
||||
private void setupSessionFactory(SshUri sshKey) {
|
||||
Map<String, SshUri> sshKeysByHostname = new HashMap<>();
|
||||
private void setupSessionFactory(JGitEnvironmentProperties sshKey) {
|
||||
Map<String, JGitEnvironmentProperties> sshKeysByHostname = new HashMap<>();
|
||||
sshKeysByHostname.put(SshUriPropertyProcessor.getHostname(sshKey.getUri()), sshKey);
|
||||
factory = new PropertyBasedSshSessionFactory(sshKeysByHostname, jSch) ;
|
||||
when(hc.getHostName()).thenReturn(SshUriPropertyProcessor.getHostname(sshKey.getUri()));
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
|
||||
package org.springframework.cloud.config.server.ssh;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Set;
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.Validation;
|
||||
import javax.validation.Validator;
|
||||
import javax.validation.ValidatorFactory;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
@@ -76,119 +78,102 @@ public class SshPropertyValidatorTest {
|
||||
|
||||
@Test
|
||||
public void supportedParametersSuccesful() throws Exception {
|
||||
SshUriProperties validSettings = SshUri.builder()
|
||||
.uri(SSH_URI)
|
||||
.ignoreLocalSshSettings(true)
|
||||
.privateKey(VALID_PRIVATE_KEY)
|
||||
.hostKey(VALID_HOST_KEY)
|
||||
.hostKeyAlgorithm("ssh-rsa")
|
||||
.build();
|
||||
MultipleJGitEnvironmentProperties validSettings = new MultipleJGitEnvironmentProperties();
|
||||
validSettings.setUri(SSH_URI);
|
||||
validSettings.setIgnoreLocalSshSettings(true);
|
||||
validSettings.setPrivateKey(VALID_PRIVATE_KEY);
|
||||
validSettings.setHostKey(VALID_HOST_KEY);
|
||||
validSettings.setHostKeyAlgorithm("ssh-rsa");
|
||||
|
||||
Set<ConstraintViolation<SshUriProperties>> constraintViolations = validator.validate(validSettings);
|
||||
Set<ConstraintViolation<MultipleJGitEnvironmentProperties>> constraintViolations = validator.validate(validSettings);
|
||||
assertThat(constraintViolations, hasSize(0));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidPrivateKeyFails() throws Exception {
|
||||
MultipleJGitEnvironmentProperties invalidKey = new MultipleJGitEnvironmentProperties();
|
||||
invalidKey.setUri(SSH_URI);
|
||||
invalidKey.setIgnoreLocalSshSettings(true);
|
||||
invalidKey.setPrivateKey("invalid_key");
|
||||
|
||||
SshUriProperties invalidKey = SshUri.builder()
|
||||
.uri(SSH_URI)
|
||||
.ignoreLocalSshSettings(true)
|
||||
.privateKey("invalid_key")
|
||||
.build();
|
||||
|
||||
Set<ConstraintViolation<SshUriProperties>> constraintViolations = validator.validate(invalidKey);
|
||||
Set<ConstraintViolation<MultipleJGitEnvironmentProperties>> constraintViolations = validator.validate(invalidKey);
|
||||
assertThat(constraintViolations, hasSize(1));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingPrivateKeyFails() throws Exception {
|
||||
MultipleJGitEnvironmentProperties missingKey = new MultipleJGitEnvironmentProperties();
|
||||
missingKey.setUri(SSH_URI);
|
||||
missingKey.setIgnoreLocalSshSettings(true);
|
||||
|
||||
SshUriProperties missingKey = SshUri.builder()
|
||||
.uri(SSH_URI)
|
||||
.ignoreLocalSshSettings(true)
|
||||
.build();
|
||||
|
||||
Set<ConstraintViolation<SshUriProperties>> constraintViolations = validator.validate(missingKey);
|
||||
Set<ConstraintViolation<MultipleJGitEnvironmentProperties>> constraintViolations = validator.validate(missingKey);
|
||||
assertThat(constraintViolations, hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostKeyWithMissingAlgoFails() throws Exception {
|
||||
MultipleJGitEnvironmentProperties missingAlgo = new MultipleJGitEnvironmentProperties();
|
||||
missingAlgo.setUri(SSH_URI);
|
||||
missingAlgo.setIgnoreLocalSshSettings(true);
|
||||
missingAlgo.setPrivateKey(VALID_PRIVATE_KEY);
|
||||
missingAlgo.setHostKey("some_host");
|
||||
|
||||
SshUriProperties missingAlgo = SshUri.builder()
|
||||
.uri(SSH_URI)
|
||||
.ignoreLocalSshSettings(true)
|
||||
.privateKey(VALID_PRIVATE_KEY)
|
||||
.hostKey("some_host")
|
||||
.build();
|
||||
|
||||
Set<ConstraintViolation<SshUriProperties>> constraintViolations = validator.validate(missingAlgo);
|
||||
Set<ConstraintViolation<MultipleJGitEnvironmentProperties>> constraintViolations = validator.validate(missingAlgo);
|
||||
assertThat(constraintViolations, hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void algoWithMissingHostKeyFails() throws Exception {
|
||||
MultipleJGitEnvironmentProperties missingHostKey = new MultipleJGitEnvironmentProperties();
|
||||
missingHostKey.setUri(SSH_URI);
|
||||
missingHostKey.setIgnoreLocalSshSettings(true);
|
||||
missingHostKey.setPrivateKey(VALID_PRIVATE_KEY);
|
||||
missingHostKey.setHostKeyAlgorithm("ssh-rsa");
|
||||
|
||||
SshUriProperties missingHostKey = SshUri.builder()
|
||||
.uri(SSH_URI)
|
||||
.ignoreLocalSshSettings(true)
|
||||
.privateKey(VALID_PRIVATE_KEY)
|
||||
.hostKeyAlgorithm("ssh-rsa")
|
||||
.build();
|
||||
|
||||
Set<ConstraintViolation<SshUriProperties>> constraintViolations = validator.validate(missingHostKey);
|
||||
Set<ConstraintViolation<MultipleJGitEnvironmentProperties>> constraintViolations = validator.validate(missingHostKey);
|
||||
assertThat(constraintViolations, hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unsupportedAlgoFails() throws Exception {
|
||||
MultipleJGitEnvironmentProperties unsupportedAlgo = new MultipleJGitEnvironmentProperties();
|
||||
unsupportedAlgo.setUri(SSH_URI);
|
||||
unsupportedAlgo.setIgnoreLocalSshSettings(true);
|
||||
unsupportedAlgo.setPrivateKey(VALID_PRIVATE_KEY);
|
||||
unsupportedAlgo.setHostKey("some_host_key");
|
||||
unsupportedAlgo.setHostKeyAlgorithm("unsupported");
|
||||
|
||||
SshUriProperties unsupportedAlgo = SshUri.builder()
|
||||
.uri(SSH_URI)
|
||||
.ignoreLocalSshSettings(true)
|
||||
.privateKey(VALID_PRIVATE_KEY)
|
||||
.hostKey("some_host_key")
|
||||
.hostKeyAlgorithm("unsupported")
|
||||
.build();
|
||||
|
||||
Set<ConstraintViolation<SshUriProperties>> constraintViolations = validator.validate(unsupportedAlgo);
|
||||
Set<ConstraintViolation<MultipleJGitEnvironmentProperties>> constraintViolations = validator.validate(unsupportedAlgo);
|
||||
assertThat(constraintViolations, hasSize(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validatorNotRunIfIgnoreLocalSettingsFalse() throws Exception {
|
||||
MultipleJGitEnvironmentProperties useLocal = new MultipleJGitEnvironmentProperties();
|
||||
useLocal.setUri(SSH_URI);
|
||||
useLocal.setIgnoreLocalSshSettings(false);
|
||||
useLocal.setPrivateKey("invalid_key");
|
||||
|
||||
SshUriProperties useLocal = (SshUri.builder()
|
||||
.uri(SSH_URI)
|
||||
.ignoreLocalSshSettings(false)
|
||||
.privateKey("invalid_key")
|
||||
.build());
|
||||
|
||||
Set<ConstraintViolation<SshUriProperties>> constraintViolations = validator.validate(useLocal);
|
||||
Set<ConstraintViolation<MultipleJGitEnvironmentProperties>> constraintViolations = validator.validate(useLocal);
|
||||
assertThat(constraintViolations, hasSize(0));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validatorNotRunIfHttpsUri() throws Exception {
|
||||
MultipleJGitEnvironmentProperties httpsUri = new MultipleJGitEnvironmentProperties();
|
||||
httpsUri.setUri("https://somerepo.com/team/project.git");
|
||||
httpsUri.setIgnoreLocalSshSettings(true);
|
||||
httpsUri.setPrivateKey("invalid_key");
|
||||
|
||||
SshUriProperties httpsUri = (SshUri.builder()
|
||||
.uri("https://somerepo.com/team/project.git")
|
||||
.ignoreLocalSshSettings(true)
|
||||
.privateKey("invalid_key")
|
||||
.build());
|
||||
|
||||
Set<ConstraintViolation<SshUriProperties>> constraintViolations = validator.validate(httpsUri);
|
||||
Set<ConstraintViolation<MultipleJGitEnvironmentProperties>> constraintViolations = validator.validate(httpsUri);
|
||||
assertThat(constraintViolations, hasSize(0));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preferredAuthenticationsIsValidated() throws Exception {
|
||||
SshUriProperties sshUriProperties = new SshUriProperties();
|
||||
MultipleJGitEnvironmentProperties sshUriProperties = new MultipleJGitEnvironmentProperties();
|
||||
assertThat(validator.validate(sshUriProperties), hasSize(0));
|
||||
|
||||
sshUriProperties.setPreferredAuthentications("keyboard-interactive, public-key ,kerberos");
|
||||
@@ -200,7 +185,7 @@ public class SshPropertyValidatorTest {
|
||||
|
||||
@Test
|
||||
public void knowHostsFileIsValidated() throws Exception {
|
||||
SshUriProperties sshUriProperties = new SshUriProperties();
|
||||
MultipleJGitEnvironmentProperties sshUriProperties = new MultipleJGitEnvironmentProperties();
|
||||
assertThat(validator.validate(sshUriProperties), hasSize(0));
|
||||
|
||||
sshUriProperties.setKnownHostsFile("non-existing.file");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015 - 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.
|
||||
@@ -18,13 +18,19 @@ package org.springframework.cloud.config.server.ssh;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.jgit.transport.SshSessionFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.cloud.config.server.ssh.SshUriProperties.SshUriNestedRepoProperties;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
import org.springframework.cloud.config.server.environment.MultipleJGitEnvironmentProperties;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
@@ -54,43 +60,45 @@ public class SshUriPropertyProcessorTest {
|
||||
@Test
|
||||
public void testSingleSshUriProperties() {
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(mainRepoPropertiesFixture());
|
||||
Map<String, SshUri> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
Map<String, JGitEnvironmentProperties> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
|
||||
assertThat(sshKeysByHostname.values(), hasSize(1));
|
||||
|
||||
SshUri sshKey = sshKeysByHostname.get(HOST1);
|
||||
JGitEnvironmentProperties sshKey = sshKeysByHostname.get(HOST1);
|
||||
assertMainRepo(sshKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleSshUriPropertiess() {
|
||||
SshUriProperties sshUriProperties = mainRepoPropertiesFixture();
|
||||
addRepoProperties(sshUriProperties, SshUri.builder()
|
||||
.uri(URI2)
|
||||
.privateKey(PRIVATE_KEY2)
|
||||
.buildAsNestedRepo(), "repo2");
|
||||
addRepoProperties(sshUriProperties, SshUri.builder()
|
||||
.uri(URI3)
|
||||
.privateKey(PRIVATE_KEY3)
|
||||
.buildAsNestedRepo(), "repo3");
|
||||
MultipleJGitEnvironmentProperties sshUriProperties = mainRepoPropertiesFixture();
|
||||
MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties nestedSshUriProperties1 =
|
||||
new MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties();
|
||||
nestedSshUriProperties1.setUri(URI2);
|
||||
nestedSshUriProperties1.setPrivateKey(PRIVATE_KEY2);
|
||||
MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties nestedSshUriProperties2 =
|
||||
new MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties();
|
||||
nestedSshUriProperties2.setUri(URI3);
|
||||
nestedSshUriProperties2.setPrivateKey(PRIVATE_KEY3);
|
||||
addRepoProperties(sshUriProperties, nestedSshUriProperties1, "repo2");
|
||||
addRepoProperties(sshUriProperties, nestedSshUriProperties2, "repo3");
|
||||
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(sshUriProperties);
|
||||
|
||||
Map<String, SshUri> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
Map<String, JGitEnvironmentProperties> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
|
||||
assertThat(sshKeysByHostname.values(), hasSize(3));
|
||||
|
||||
SshUri sshKey1 = sshKeysByHostname.get(HOST1);
|
||||
JGitEnvironmentProperties sshKey1 = sshKeysByHostname.get(HOST1);
|
||||
assertMainRepo(sshKey1);
|
||||
|
||||
SshUri sshKey2 = sshKeysByHostname.get(HOST2);
|
||||
JGitEnvironmentProperties sshKey2 = sshKeysByHostname.get(HOST2);
|
||||
|
||||
assertThat(SshUriPropertyProcessor.getHostname(sshKey2.getUri()), is(equalTo(HOST2)));
|
||||
assertThat(sshKey2.getHostKeyAlgorithm(), is(nullValue()));
|
||||
assertThat(sshKey2.getHostKey(), is(nullValue()));
|
||||
assertThat(sshKey2.getPrivateKey(), is(equalTo(PRIVATE_KEY2)));
|
||||
|
||||
SshUri sshKey3 = sshKeysByHostname.get(HOST3);
|
||||
JGitEnvironmentProperties sshKey3 = sshKeysByHostname.get(HOST3);
|
||||
|
||||
assertThat(SshUriPropertyProcessor.getHostname(sshKey3.getUri()), is(equalTo(HOST3)));
|
||||
assertThat(sshKey3.getHostKeyAlgorithm(), is(nullValue()));
|
||||
@@ -100,58 +108,62 @@ public class SshUriPropertyProcessorTest {
|
||||
|
||||
@Test
|
||||
public void testSameHostnameDifferentKeysFirstOneWins() {
|
||||
SshUriProperties sshUriProperties = mainRepoPropertiesFixture();
|
||||
addRepoProperties(sshUriProperties, SshUri.builder().uri(URI1)
|
||||
.privateKey(PRIVATE_KEY1)
|
||||
.hostKey(HOST_KEY1)
|
||||
.hostKeyAlgorithm(ALGO1)
|
||||
.buildAsNestedRepo(), "repo2");
|
||||
MultipleJGitEnvironmentProperties sshUriProperties = mainRepoPropertiesFixture();
|
||||
MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties nestedSshUriProperties = new MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties();
|
||||
nestedSshUriProperties.setUri(URI1);
|
||||
nestedSshUriProperties.setPrivateKey(PRIVATE_KEY1);
|
||||
nestedSshUriProperties.setHostKey(HOST_KEY1);
|
||||
nestedSshUriProperties.setHostKeyAlgorithm(ALGO1);
|
||||
addRepoProperties(sshUriProperties, nestedSshUriProperties, "repo2");
|
||||
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(sshUriProperties);
|
||||
Map<String, SshUri> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
Map<String, JGitEnvironmentProperties> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
|
||||
assertThat(sshKeysByHostname.values(), hasSize(1));
|
||||
|
||||
SshUri sshKey = sshKeysByHostname.get(HOST1);
|
||||
JGitEnvironmentProperties sshKey = sshKeysByHostname.get(HOST1);
|
||||
assertMainRepo(sshKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSshUriProperties() {
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(new SshUriProperties());
|
||||
Map<String, SshUri> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(new MultipleJGitEnvironmentProperties());
|
||||
Map<String, JGitEnvironmentProperties> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
assertThat(sshKeysByHostname.values(), hasSize(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidUriDoesNotAddEntry() {
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(SshUri.builder().uri("invalid_uri").build());
|
||||
Map<String, SshUri> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
MultipleJGitEnvironmentProperties sshUriProperties = new MultipleJGitEnvironmentProperties();
|
||||
sshUriProperties.setUri("invalid_uri");
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(sshUriProperties);
|
||||
Map<String, JGitEnvironmentProperties> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
assertThat(sshKeysByHostname.values(), hasSize(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpsUriDoesNotAddEntry() {
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(SshUri.builder().uri("https://user@github.com/proj/repo.git").build());
|
||||
Map<String, SshUri> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
MultipleJGitEnvironmentProperties sshUriProperties = new MultipleJGitEnvironmentProperties();
|
||||
sshUriProperties.setUri("https://user@github.com/proj/repo.git");
|
||||
SshUriPropertyProcessor sshUriPropertyProcessor = new SshUriPropertyProcessor(sshUriProperties);
|
||||
Map<String, JGitEnvironmentProperties> sshKeysByHostname = sshUriPropertyProcessor.getSshKeysByHostname();
|
||||
assertThat(sshKeysByHostname.values(), hasSize(0));
|
||||
}
|
||||
|
||||
private SshUriProperties mainRepoPropertiesFixture() {
|
||||
|
||||
return SshUri.builder()
|
||||
.uri(URI1)
|
||||
.hostKeyAlgorithm(ALGO1)
|
||||
.hostKey(HOST_KEY1)
|
||||
.privateKey(PRIVATE_KEY1)
|
||||
.build();
|
||||
private MultipleJGitEnvironmentProperties mainRepoPropertiesFixture() {
|
||||
MultipleJGitEnvironmentProperties result = new MultipleJGitEnvironmentProperties();
|
||||
result.setUri(URI1);
|
||||
result.setHostKeyAlgorithm(ALGO1);
|
||||
result.setHostKey(HOST_KEY1);
|
||||
result.setPrivateKey(PRIVATE_KEY1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addRepoProperties(SshUriProperties mainRepoProperties, SshUriNestedRepoProperties repoProperties, String repoName) {
|
||||
mainRepoProperties.addRepo(repoName, repoProperties);
|
||||
private void addRepoProperties(MultipleJGitEnvironmentProperties mainRepoProperties, MultipleJGitEnvironmentProperties.PatternMatchingJGitEnvironmentProperties repoProperties, String repoName) {
|
||||
mainRepoProperties.getRepos().put(repoName, repoProperties);
|
||||
}
|
||||
|
||||
private void assertMainRepo(SshUri sshKey) {
|
||||
private void assertMainRepo(JGitEnvironmentProperties sshKey) {
|
||||
assertThat(sshKey, is(notNullValue()));
|
||||
assertThat(SshUriPropertyProcessor.getHostname(sshKey.getUri()), is(equalTo(HOST1)));
|
||||
assertThat(sshKey.getHostKeyAlgorithm(), is(equalTo(ALGO1)));
|
||||
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* 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.net.URISyntaxException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.jgit.errors.UnsupportedCredentialItem;
|
||||
import org.eclipse.jgit.internal.JGitText;
|
||||
import org.eclipse.jgit.transport.CredentialItem;
|
||||
import org.eclipse.jgit.transport.CredentialsProvider;
|
||||
import org.eclipse.jgit.transport.URIish;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Gareth Clay
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GitSkipSslValidationCredentialsProviderTest {
|
||||
|
||||
@Mock
|
||||
private CredentialsProvider mockDelegateCredentialsProvider;
|
||||
private GitSkipSslValidationCredentialsProvider skipSslValidationCredentialsProvider;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanHandle() {
|
||||
assertTrue("GitSkipSslValidationCredentialsProvider only handles HTTPS uris",
|
||||
GitSkipSslValidationCredentialsProvider
|
||||
.canHandle("https://github.com/org/repo"));
|
||||
assertFalse("GitSkipSslValidationCredentialsProvider only handles HTTPS uris",
|
||||
GitSkipSslValidationCredentialsProvider
|
||||
.canHandle("git@github.com:org/repo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsInteractive() {
|
||||
assertFalse(
|
||||
"GitSkipSslValidationCredentialsProvider with no delegate requires no user interaction",
|
||||
skipSslValidationCredentialsProvider.isInteractive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsInteractiveWithDelegate() {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
mockDelegateCredentialsProvider);
|
||||
|
||||
when(mockDelegateCredentialsProvider.isInteractive()).thenReturn(true);
|
||||
|
||||
assertTrue(
|
||||
"With a delegate provider, isInteractive value depends on the delegate",
|
||||
skipSslValidationCredentialsProvider.isInteractive());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupportsSslFailureInformationalMessage() {
|
||||
CredentialItem informationalMessage = new CredentialItem.InformationalMessage(
|
||||
"text " + JGitText.get().sslFailureTrustExplanation + " more text");
|
||||
assertTrue(
|
||||
"GitSkipSslValidationCredentialsProvider should always support SSL failure InformationalMessage",
|
||||
skipSslValidationCredentialsProvider.supports(informationalMessage));
|
||||
|
||||
informationalMessage = new CredentialItem.InformationalMessage("unrelated");
|
||||
assertFalse(
|
||||
"GitSkipSslValidationCredentialsProvider should not support unrelated InformationalMessage items",
|
||||
skipSslValidationCredentialsProvider.supports(informationalMessage));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupportsSslFailureInformationalMessageWithDelegate() {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
mockDelegateCredentialsProvider);
|
||||
|
||||
testSupportsSslFailureInformationalMessage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupportsSslValidationYesNoTypes() {
|
||||
CredentialItem yesNoType = new CredentialItem.YesNoType(
|
||||
JGitText.get().sslTrustNow);
|
||||
assertTrue(
|
||||
"GitSkipSslValidationCredentialsProvider should always support the trust now YesNoType item",
|
||||
skipSslValidationCredentialsProvider.supports(yesNoType));
|
||||
|
||||
yesNoType = new CredentialItem.YesNoType(
|
||||
MessageFormat.format(JGitText.get().sslTrustForRepo, "/a/path.git"));
|
||||
assertTrue(
|
||||
"GitSkipSslValidationCredentialsProvider should always support the trust repo YesNoType item",
|
||||
skipSslValidationCredentialsProvider.supports(yesNoType));
|
||||
|
||||
yesNoType = new CredentialItem.YesNoType(JGitText.get().sslTrustAlways);
|
||||
assertTrue(
|
||||
"GitSkipSslValidationCredentialsProvider should always support the trust always YesNoType item",
|
||||
skipSslValidationCredentialsProvider.supports(yesNoType));
|
||||
|
||||
yesNoType = new CredentialItem.YesNoType("unrelated");
|
||||
assertFalse(
|
||||
"GitSkipSslValidationCredentialsProvider should not support unrelated YesNoType items",
|
||||
skipSslValidationCredentialsProvider.supports(yesNoType));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupportsYesNoTypeWithDelegate() {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
mockDelegateCredentialsProvider);
|
||||
|
||||
testSupportsSslValidationYesNoTypes();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupportsUnrelatedCredentialItemTypes() {
|
||||
CredentialItem usernameCredentialItem = new CredentialItem.Username();
|
||||
|
||||
boolean supportsItems = skipSslValidationCredentialsProvider
|
||||
.supports(usernameCredentialItem);
|
||||
|
||||
assertFalse(
|
||||
"Credential item types not related to SSL validation skipping should not be supported",
|
||||
supportsItems);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupportsUnrelatedCredentialItemTypesWithDelegate() {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
mockDelegateCredentialsProvider);
|
||||
CredentialItem usernameCredentialItem = new CredentialItem.Username();
|
||||
|
||||
when(mockDelegateCredentialsProvider.supports(usernameCredentialItem))
|
||||
.thenReturn(true);
|
||||
|
||||
boolean supportsItems = skipSslValidationCredentialsProvider
|
||||
.supports(usernameCredentialItem);
|
||||
|
||||
assertTrue(
|
||||
"GitSkipSslValidationCredentialsProvider must support the types supported by its delegate CredentialsProvider",
|
||||
supportsItems);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedCredentialItem.class)
|
||||
public void testGetUnrelatedCredentialItemTypes() throws URISyntaxException {
|
||||
URIish uri = new URIish("https://example.com/repo.git");
|
||||
CredentialItem usernameCredentialItem = new CredentialItem.Username();
|
||||
CredentialItem passwordCredentialItem = new CredentialItem.Password();
|
||||
|
||||
skipSslValidationCredentialsProvider.get(uri, usernameCredentialItem,
|
||||
passwordCredentialItem);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUnrelatedCredentialItemTypesWithDelegate()
|
||||
throws URISyntaxException {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
mockDelegateCredentialsProvider);
|
||||
URIish uri = new URIish("https://example.com/repo.git");
|
||||
CredentialItem usernameCredentialItem = new CredentialItem.Username();
|
||||
CredentialItem passwordCredentialItem = new CredentialItem.Password();
|
||||
|
||||
when(mockDelegateCredentialsProvider.get(uri, usernameCredentialItem,
|
||||
passwordCredentialItem)).thenReturn(true);
|
||||
|
||||
boolean getSuccessful = skipSslValidationCredentialsProvider.get(uri,
|
||||
usernameCredentialItem, passwordCredentialItem);
|
||||
|
||||
assertTrue(
|
||||
"GitSkipSslValidationCredentialsProvider must successfully get the types supported by its delegate CredentialsProvider",
|
||||
getSuccessful);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSslTrustItems() throws URISyntaxException {
|
||||
URIish uri = new URIish("https://example.com/repo.git");
|
||||
CredentialItem message = new CredentialItem.InformationalMessage(
|
||||
JGitText.get().sslFailureTrustExplanation);
|
||||
CredentialItem.YesNoType trustNow = new CredentialItem.YesNoType(
|
||||
JGitText.get().sslTrustNow);
|
||||
CredentialItem.YesNoType trustAlways = new CredentialItem.YesNoType(
|
||||
JGitText.get().sslTrustAlways);
|
||||
|
||||
boolean getSuccessful = skipSslValidationCredentialsProvider.get(uri, message,
|
||||
trustNow, trustAlways);
|
||||
|
||||
assertTrue(
|
||||
"SkipSSlValidationCredentialsProvider must successfully get the types required for SSL validation skipping",
|
||||
getSuccessful);
|
||||
assertTrue(
|
||||
"SkipSSlValidationCredentialsProvider should trust the current repo operation",
|
||||
trustNow.getValue());
|
||||
assertFalse("We should not globally skip all SSL validation",
|
||||
trustAlways.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSslTrustItemsWithDelegate() throws URISyntaxException {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
mockDelegateCredentialsProvider);
|
||||
|
||||
testGetSslTrustItems();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSslTrustItemsWithLocalRepo() throws URISyntaxException {
|
||||
URIish uri = new URIish("https://example.com/repo.git");
|
||||
CredentialItem message = new CredentialItem.InformationalMessage(
|
||||
JGitText.get().sslFailureTrustExplanation);
|
||||
CredentialItem.YesNoType trustNow = new CredentialItem.YesNoType(
|
||||
JGitText.get().sslTrustNow);
|
||||
CredentialItem.YesNoType trustForRepo = new CredentialItem.YesNoType(
|
||||
JGitText.get().sslTrustForRepo);
|
||||
CredentialItem.YesNoType trustAlways = new CredentialItem.YesNoType(
|
||||
JGitText.get().sslTrustAlways);
|
||||
|
||||
boolean getSuccessful = skipSslValidationCredentialsProvider.get(uri, message,
|
||||
trustNow, trustForRepo, trustAlways);
|
||||
|
||||
assertTrue(
|
||||
"SkipSSlValidationCredentialsProvider must successfully get the types required for SSL validation skipping",
|
||||
getSuccessful);
|
||||
assertTrue(
|
||||
"SkipSSlValidationCredentialsProvider should trust the current repo operation",
|
||||
trustNow.getValue());
|
||||
assertTrue("Future operations on this repository should also be trusted",
|
||||
trustForRepo.getValue());
|
||||
assertFalse("We should not globally skip all SSL validation",
|
||||
trustAlways.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSslTrustItemsWithLocalRepoAndDelegate() throws URISyntaxException {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
mockDelegateCredentialsProvider);
|
||||
|
||||
testGetSslTrustItemsWithLocalRepo();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReset() throws URISyntaxException {
|
||||
URIish uri = new URIish("https://example.com/repo.git");
|
||||
|
||||
skipSslValidationCredentialsProvider.reset(uri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResetWithDelegate() throws URISyntaxException {
|
||||
this.skipSslValidationCredentialsProvider = new GitSkipSslValidationCredentialsProvider(
|
||||
mockDelegateCredentialsProvider);
|
||||
URIish uri = new URIish("https://example.com/repo.git");
|
||||
|
||||
skipSslValidationCredentialsProvider.reset(uri);
|
||||
|
||||
verify(mockDelegateCredentialsProvider).reset(uri);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
server:
|
||||
composite:
|
||||
- type: git
|
||||
uri: git@gitserver.com:team/repo1.git
|
||||
ignoreLocalSshSettings: true
|
||||
privateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAoqyz6YaYMTr7L8GLPSQpAQXaM04gRx4CCsGK2kfLQdw4BlqI\nyyxp38YcuZG9cUDBAxby+K2TKmwHaC1R61QTwbPuCRdIPrDwRz+FLoegm3iDLCmn\nuP6rjZDneYsqfU1KSdrOwIbCnONfDdvYL/vnZC/o8DDMlk5Orw2SfHkT3pq0o8km\nayBwN4Sf3bpyWTY0oZcmNeSCCoIdE59k8Pa7/t9bwY9caLj05C3DEsjucc7Ei/Eq\nTOyGyobtXwaya5CqKLUHes74Poz1aEP/yVFdUud91uezd8ZK1P1t5/ZKA3R6aHir\n+diDJ2/GQ2tD511FW46yw+EtBUJTO6ADVv4UnQIDAQABAoIBAF+5qwEfX82QfKFk\njfADqFFexUDtl1biFKeJrpC2MKhn01wByH9uejrhFKQqW8UaKroLthyZ34DWIyGt\nlDnHGv0gSVF2LuAdNLdobJGt49e4+c9yD61vxzm97Eh8mRs08SM2q/VlF35E2fmI\nxdWusUImYzd8L9e+6tRd8zZl9UhG5vR5XIstKqxC6S0g79aAt0hasE4Gw1FKOf2V\n4mlL15atjQSKCPdOicuyc4zpjAtU1A9AfF51iG8oOUuJebPW8tCftfOQxaeGFgMG\n7M9aai1KzXR6M5IBAKEv31yBvz/SHTneP7oZXNLeC1GIR420PKybmeZdNK8BbEAu\n3reKgm0CgYEA03Sx8JoF5UBsIvFPpP1fjSlTgKryM5EJR6KQtj5e4YfyxccJepN8\nq4MrqDfNKleG/a1acEtDMhBNovU7Usp2QIP7zpAeioHBOhmE5WSieZGc3icOGWWq\nmRkdulSONruqWKv76ZoluxftekE03bDhZDNlcCgmrslEKB/ufHd2oc8CgYEAxPFa\nlKOdSeiYFV5CtvO8Ro8em6rGpSsVz4qkPxbeBqUDCb9KXHhq6YrhRxOIfQJKfT7M\nZFCn8ArJXKgOGu+KsvwIErFHF9g2jJMG4DOUTpkQgi2yveihFxcmz/AltyVXgrnv\nZWQbAerH77pdKKhNivLGgEv72GYawdYjYNjemdMCgYA2kEMmMahZyrDcp2YEzfit\nBT/t0K6kzcUWPgWXcSqsiZcEn+J7RbmCzFskkhmX1nQX23adyV3yejB+X0dKisHO\nzf/ZAmlPFkJVCqa3RquCMSfIT02dEhXeYZPBM/Zqeyxuqxpa4hLgX0FBLbhFiFHw\nuC5xrXql2XuD2xF//peXEwKBgQC+pa28Cg7vRxxCQzduB9CQtWc55j3aEjVQ7bNF\n54sS/5ZLT0Ra8677WZfuyDfuW9NkHvCZg4Ku2qJG8eCFrrGjxlrCTZ62tHVJ6+JS\nE1xUIdRbUIWhVZrr0VufG6hG/P0T7Y6Tpi6G0pKtvMkF3LcD9TS3adboix8H2ZXx\n4L7MRQKBgQC0OO3qqNXOjIVYWOoqXLybOY/Wqu9lxCAgGyCYaMcstnBI7W0MZTBr\n/syluvGsaFc1sE7MMGOOzKi1tF4YvDmSnzA/R1nmaPguuD9fOA+w7Pwkv5vLvuJq\n2U7EeNwxq1I1L3Ag6E7wH4BHLHd4TKaZR6agFkn8oomz71yZPGjuZQ==\n-----END RSA PRIVATE KEY-----"
|
||||
repos:
|
||||
repo1:
|
||||
uri: git@gitserver.com:team/repo2.git
|
||||
hostKey: someHostKey
|
||||
hostKeyAlgorithm: ssh-rsa
|
||||
privateKey: |
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpgIBAAKCAQEAx4UbaDzY5xjW6hc9jwN0mX33XpTDVW9WqHp5AKaRbtAC3DqX
|
||||
IXFMPgw3K45jxRb93f8tv9vL3rD9CUG1Gv4FM+o7ds7FRES5RTjv2RT/JVNJCoqF
|
||||
ol8+ngLqRZCyBtQN7zYByWMRirPGoDUqdPYrj2yq+ObBBNhg5N+hOwKjjpzdj2Ud
|
||||
1l7R+wxIqmJo1IYyy16xS8WsjyQuyC0lL456qkd5BDZ0Ag8j2X9H9D5220Ln7s9i
|
||||
oezTipXipS7p7Jekf3Ywx6abJwOmB0rX79dV4qiNcGgzATnG1PkXxqt76VhcGa0W
|
||||
DDVHEEYGbSQ6hIGSh0I7BQun0aLRZojfE3gqHQIDAQABAoIBAQCZmGrk8BK6tXCd
|
||||
fY6yTiKxFzwb38IQP0ojIUWNrq0+9Xt+NsypviLHkXfXXCKKU4zUHeIGVRq5MN9b
|
||||
BO56/RrcQHHOoJdUWuOV2qMqJvPUtC0CpGkD+valhfD75MxoXU7s3FK7yjxy3rsG
|
||||
EmfA6tHV8/4a5umo5TqSd2YTm5B19AhRqiuUVI1wTB41DjULUGiMYrnYrhzQlVvj
|
||||
5MjnKTlYu3V8PoYDfv1GmxPPh6vlpafXEeEYN8VB97e5x3DGHjZ5UrurAmTLTdO8
|
||||
+AahyoKsIY612TkkQthJlt7FJAwnCGMgY6podzzvzICLFmmTXYiZ/28I4BX/mOSe
|
||||
pZVnfRixAoGBAO6Uiwt40/PKs53mCEWngslSCsh9oGAaLTf/XdvMns5VmuyyAyKG
|
||||
ti8Ol5wqBMi4GIUzjbgUvSUt+IowIrG3f5tN85wpjQ1UGVcpTnl5Qo9xaS1PFScQ
|
||||
xrtWZ9eNj2TsIAMp/svJsyGG3OibxfnuAIpSXNQiJPwRlW3irzpGgVx/AoGBANYW
|
||||
dnhshUcEHMJi3aXwR12OTDnaLoanVGLwLnkqLSYUZA7ZegpKq90UAuBdcEfgdpyi
|
||||
PhKpeaeIiAaNnFo8m9aoTKr+7I6/uMTlwrVnfrsVTZv3orxjwQV20YIBCVRKD1uX
|
||||
VhE0ozPZxwwKSPAFocpyWpGHGreGF1AIYBE9UBtjAoGBAI8bfPgJpyFyMiGBjO6z
|
||||
FwlJc/xlFqDusrcHL7abW5qq0L4v3R+FrJw3ZYufzLTVcKfdj6GelwJJO+8wBm+R
|
||||
gTKYJItEhT48duLIfTDyIpHGVm9+I1MGhh5zKuCqIhxIYr9jHloBB7kRm0rPvYY4
|
||||
VAykcNgyDvtAVODP+4m6JvhjAoGBALbtTqErKN47V0+JJpapLnF0KxGrqeGIjIRV
|
||||
cYA6V4WYGr7NeIfesecfOC356PyhgPfpcVyEztwlvwTKb3RzIT1TZN8fH4YBr6Ee
|
||||
KTbTjefRFhVUjQqnucAvfGi29f+9oE3Ei9f7wA+H35ocF6JvTYUsHNMIO/3gZ38N
|
||||
CPjyCMa9AoGBAMhsITNe3QcbsXAbdUR00dDsIFVROzyFJ2m40i4KCRM35bC/BIBs
|
||||
q0TY3we+ERB40U8Z2BvU61QuwaunJ2+uGadHo58VSVdggqAo0BSkH58innKKt96J
|
||||
69pcVH/4rmLbXdcmNYGm6iu+MlPQk4BUZknHSmVHIFdJ0EPupVaQ8RHT
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -0,0 +1,36 @@
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
server:
|
||||
composite:
|
||||
- type: git
|
||||
uri: git@gitserver.com:team/repo.git
|
||||
ignoreLocalSshSettings: true
|
||||
privateKey: |
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAoqyz6YaYMTr7L8GLPSQpAQXaM04gRx4CCsGK2kfLQdw4BlqI
|
||||
yyxp38YcuZG9cUDBAxby+K2TKmwHaC1Wf1QTwbPuCRdIPrDwRz+FLoegm3iDLCmn
|
||||
uP6rjZDneYsqfU1sSdrOwIbCnONfDdvYL/vnZC/o8DDMlk5Orw2SfHkT3pq0o8km
|
||||
ayBwN4Sf3bpyWTY0oZcmNeSCCoIdE59k8Pa7/t9bwY9caLj05C3DEsjucc7Ei/Eq
|
||||
TOyGyobtXwaya5CqKLUHes74Poz1aEP/yVFdUud91uezd8ZK1P1t5/ZKA3R6aHir
|
||||
+diDJ2/GQ2tD511FW46yw+EtBUJTO6ADVv4UnQIDAQABAoIBAF+5qwEfX82QfKFk
|
||||
jfADqFFexUDtl1biFKeJrpC2MKhn01wByH9uejrhFKQqW8UaKroLthyZ34DWIyGt
|
||||
lDnHGv0gSVF2LuAdNLdobJGt49e4+c9yD61vxzm97Eh8mRs08SM2q/VlF35E2fmI
|
||||
xdWusUImYzd8L9e+6tRd8zZl9UhG5vR5XIstKqxC6S0g79aAt0hasE4Gw1FKOf2V
|
||||
4mlL15atjQSKCPdOicuyc4zpjAtU1A9AfF51iG8oOUuJebPW8tCftfOQxaeGFgMG
|
||||
7M9aai1KzXR6M5IBAKEv31yBvz/SHTneP7oZXNLeC1GIR420PKybmeZdNK8BbEAu
|
||||
3reKgm0CgYEA03Sx8JgF5UBsIvFPpP1fjSlTgKryM5EJR6KQtj5e4YfyxccJepN8
|
||||
q4MrqDfNKleG/a1acEtDMhBNovU7Usp2QIP7zpAeioHBOhmE5WSieZGc3icOGWWq
|
||||
mRkdulSONruqWKv76ZoluxftekE03bDhZDNlcCgmrslEKB/ufHd2oc8CgYEAxPFa
|
||||
lKOdSeiYFV5CtvO8Ro8em6rGpSsVz4qkPxbeBqUDCb9KXHhq6YrhRxOIfQJKfT7M
|
||||
ZFCn8ArJXKgOGu+KsvwIErFHF9g2jJMG4DOUTpkQgi2yveihFxcmz/AltyVXgrnv
|
||||
ZWQbAerH77pdKKhNivLGgEv72GYawdYjYNjemdMCgYA2kEMmMahZyrDcp2YEzfit
|
||||
BT/t0K6kzcUWPgWXcSqsiZcEn+J7RbmCzFskkhmX1nQX23adyV3yejB+X0dKisHO
|
||||
zf/ZAmlPFkJVCqa3RquCMSfIT02dEhXeYZPBM/Zqeyxuqxpa4hLgX0FBLbhFiFHw
|
||||
uC5xrXql2XuD2xF//peXEwKBgQC+pa28Cg7vRxxCQzduB9CQtWc55j3aEjVQ7bNF
|
||||
54sS/5ZLT0Ra8677WZfuyDfuW9NkHvCZg4Ku2qJG8eCFrrGjxlrCTZ62tHVJ6+JS
|
||||
E1xUIdRbUIWhVZrr0VufG6hG/P0T7Y6Tpi6G0pKtvMkF3LcD9TS3adboix8H2ZXx
|
||||
4L7MRQKBgQC0OO3qqNXOjIVYWOoqXLybOY/Wqu9lxCAgGyCYaMcstnBI7W0MZTBr
|
||||
/syluvGsaFc1sE7MMGOOzKi1tF4YvDmSnzA/R1nmaPguuD9fOA+w7Pwkv5vLvuJq
|
||||
2U7EeNwxq1I1L3Ag6E7wH4BHLHd4TKaZR6agFkn8oomz71yZPGjuZQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -0,0 +1,11 @@
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
server:
|
||||
composite:
|
||||
- type: git
|
||||
uri: git@gitserver.com:team/repo.git
|
||||
ignoreLocalSshSettings: true
|
||||
privateKey: "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAoqyz6YaYMTr7L8GLPSQpAQXaM04gRx4CCsGK2kfLQdw4BlqI\nyyxp38YcuZG9cUDBAxby+K2TKmwHaC1R61QTwbPuCRdIPrDwRz+FLoegm3iDLCmn\nuP6rjZDneYsqfU1KSdrOwIbCnONfDdvYL/vnZC/o8DDMlk5Orw2SfHkT3pq0o8km\nayBwN4Sf3bpyWTY0oZcmNeSCCoIdE59k8Pa7/t9bwY9caLj05C3DEsjucc7Ei/Eq\nTOyGyobtXwaya5CqKLUHes74Poz1aEP/yVFdUud91uezd8ZK1P1t5/ZKA3R6aHir\n+diDJ2/GQ2tD511FW46yw+EtBUJTO6ADVv4UnQIDAQABAoIBAF+5qwEfX82QfKFk\njfADqFFexUDtl1biFKeJrpC2MKhn01wByH9uejrhFKQqW8UaKroLthyZ34DWIyGt\nlDnHGv0gSVF2LuAdNLdobJGt49e4+c9yD61vxzm97Eh8mRs08SM2q/VlF35E2fmI\nxdWusUImYzd8L9e+6tRd8zZl9UhG5vR5XIstKqxC6S0g79aAt0hasE4Gw1FKOf2V\n4mlL15atjQSKCPdOicuyc4zpjAtU1A9AfF51iG8oOUuJebPW8tCftfOQxaeGFgMG\n7M9aai1KzXR6M5IBAKEv31yBvz/SHTneP7oZXNLeC1GIR420PKybmeZdNK8BbEAu\n3reKgm0CgYEA03Sx8JoF5UBsIvFPpP1fjSlTgKryM5EJR6KQtj5e4YfyxccJepN8\nq4MrqDfNKleG/a1acEtDMhBNovU7Usp2QIP7zpAeioHBOhmE5WSieZGc3icOGWWq\nmRkdulSONruqWKv76ZoluxftekE03bDhZDNlcCgmrslEKB/ufHd2oc8CgYEAxPFa\nlKOdSeiYFV5CtvO8Ro8em6rGpSsVz4qkPxbeBqUDCb9KXHhq6YrhRxOIfQJKfT7M\nZFCn8ArJXKgOGu+KsvwIErFHF9g2jJMG4DOUTpkQgi2yveihFxcmz/AltyVXgrnv\nZWQbAerH77pdKKhNivLGgEv72GYawdYjYNjemdMCgYA2kEMmMahZyrDcp2YEzfit\nBT/t0K6kzcUWPgWXcSqsiZcEn+J7RbmCzFskkhmX1nQX23adyV3yejB+X0dKisHO\nzf/ZAmlPFkJVCqa3RquCMSfIT02dEhXeYZPBM/Zqeyxuqxpa4hLgX0FBLbhFiFHw\nuC5xrXql2XuD2xF//peXEwKBgQC+pa28Cg7vRxxCQzduB9CQtWc55j3aEjVQ7bNF\n54sS/5ZLT0Ra8677WZfuyDfuW9NkHvCZg4Ku2qJG8eCFrrGjxlrCTZ62tHVJ6+JS\nE1xUIdRbUIWhVZrr0VufG6hG/P0T7Y6Tpi6G0pKtvMkF3LcD9TS3adboix8H2ZXx\n4L7MRQKBgQC0OO3qqNXOjIVYWOoqXLybOY/Wqu9lxCAgGyCYaMcstnBI7W0MZTBr\n/syluvGsaFc1sE7MMGOOzKi1tF4YvDmSnzA/R1nmaPguuD9fOA+w7Pwkv5vLvuJq\n2U7EeNwxq1I1L3Ag6E7wH4BHLHd4TKaZR6agFkn8oomz71yZPGjuZQ==\n-----END RSA PRIVATE KEY-----"
|
||||
hostKey: somekey
|
||||
hostKeyAlgorithm: ssh-rsa
|
||||
@@ -0,0 +1 @@
|
||||
4e1f25bbdca5765e279b436b5b02d05b1654515c refs/heads/master
|
||||
Reference in New Issue
Block a user