Adding ssh proxy capability (#1054)

Adding the capability to configure a proxy host and port for ssh git
repo connections.
This commit is contained in:
bisigc
2018-06-27 15:56:30 +02:00
committed by Ryan Baxter
parent dbf29ad12c
commit 496412bd8e
4 changed files with 88 additions and 3 deletions

View File

@@ -445,6 +445,12 @@ Example:
|*hostKeyAlgorithm*
|One of `ssh-dss, ssh-rsa, ecdsa-sha2-nistp256, ecdsa-sha2-nistp384 ,ecdsa-sha2-nistp521`. Must be set if `hostKey` is also set
|*proxyHost*
|Hostname for the ssh proxy connection. Is optional and used only when `ignoreLocalSshSettings` is true
|*proxyPort*
|Port for the ssh proxy connection. Must be set if `proxyHost` is also set
|*strictHostKeyChecking*
|`true` or `false`. If false, ignore errors with host key

View File

@@ -15,16 +15,18 @@
*/
package org.springframework.cloud.config.server.ssh;
import java.util.Map;
import com.jcraft.jsch.HostKey;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.ProxyHTTP;
import com.jcraft.jsch.Session;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig.Host;
import org.eclipse.jgit.util.Base64;
import org.eclipse.jgit.util.FS;
import org.springframework.util.Assert;
import java.util.Map;
/**
* In a cloud environment local SSH config files such as `.known_hosts` may not be suitable for providing
@@ -64,6 +66,12 @@ public class PropertyBasedSshSessionFactory extends JschConfigSessionFactory {
if (preferredAuthentications != null) {
session.setConfig(PREFERRED_AUTHENTICATIONS, preferredAuthentications);
}
String proxyHost = sshProperties.getProxyHost();
if (proxyHost != null) {
Integer proxyPort = sshProperties.getProxyPort();
Assert.notNull(proxyPort, "Property proxyPort is required, since proxyHost is set.");
session.setProxy(new ProxyHTTP(proxyHost, proxyPort));
}
}
@Override

View File

@@ -37,6 +37,8 @@ public abstract class SshUri {
private String preferredAuthentications;
private boolean ignoreLocalSshSettings;
private boolean strictHostKeyChecking = true;
private String proxyHost;
private Integer proxyPort;
public static SshUriPropertiesBuilder builder() {
return new SshUriPropertiesBuilder();
@@ -106,6 +108,22 @@ public abstract class SshUri {
this.strictHostKeyChecking = strictHostKeyChecking;
}
public String getProxyHost() {
return proxyHost;
}
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
public Integer getProxyPort() {
return proxyPort;
}
public void setProxyPort(Integer proxyPort) {
this.proxyPort = proxyPort;
}
public String toString() {
return "org.springframework.cloud.config.server.ssh.SshUriProperties(uri=" + this.getUri()
+ " hostKeyAlgorithm=" + this.getHostKeyAlgorithm()
@@ -114,7 +132,9 @@ public abstract class SshUri {
+ ", ignoreLocalSshSettings=" + this.isIgnoreLocalSshSettings()
+ ", knownHostsFile=" + this.getKnownHostsFile()
+ ", preferredAuthentications=" + this.getPreferredAuthentications()
+ ", strictHostKeyChecking=" + this.isStrictHostKeyChecking() + ",)";
+ ", strictHostKeyChecking=" + this.isStrictHostKeyChecking()
+ ", proxyHost=" + this.getProxyHost()
+ ", proxyPort=" + this.getProxyPort() + ",)";
}
public static class SshUriPropertiesBuilder {
@@ -126,6 +146,8 @@ public abstract class SshUri {
private String preferredAuthentications;
private boolean ignoreLocalSshSettings;
private boolean strictHostKeyChecking = true;
private String proxyHost;
private Integer proxyPort;
private Map<String, SshUriNestedRepoProperties> repos = new LinkedHashMap<>();
SshUriPropertiesBuilder() {
@@ -171,6 +193,16 @@ public abstract class SshUri {
return this;
}
public SshUri.SshUriPropertiesBuilder proxyHost(String proxyHost) {
this.proxyHost = proxyHost;
return this;
}
public SshUri.SshUriPropertiesBuilder proxyPort(Integer proxyPort) {
this.proxyPort = proxyPort;
return this;
}
public SshUri.SshUriPropertiesBuilder repos(Map<String, SshUriNestedRepoProperties> repos) {
this.repos = repos;
return this;
@@ -198,6 +230,8 @@ public abstract class SshUri {
sshUriNestedRepoProperties.setPreferredAuthentications(preferredAuthentications);
sshUriNestedRepoProperties.setIgnoreLocalSshSettings(ignoreLocalSshSettings);
sshUriNestedRepoProperties.setStrictHostKeyChecking(strictHostKeyChecking);
sshUriNestedRepoProperties.setProxyHost(proxyHost);
sshUriNestedRepoProperties.setProxyPort(proxyPort);
}
public String toString() {
@@ -209,6 +243,8 @@ public abstract class SshUri {
+ ", preferredAuthentications=" + this.preferredAuthentications
+ ", ignoreLocalSshSettings=" + this.ignoreLocalSshSettings
+ ", strictHostKeyChecking=" + this.strictHostKeyChecking
+ ", proxyHost=" + this.proxyHost
+ ", proxyPort=" + this.proxyPort
+ ", repos=" + this.repos + ")";
}
}

View File

@@ -16,6 +16,7 @@
package org.springframework.cloud.config.server.ssh;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -35,6 +36,7 @@ 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.ProxyHTTP;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
@@ -169,6 +171,39 @@ public class PropertyBasedSshSessionFactoryTest {
Assert.assertEquals("/ssh/known_hosts", captor.getValue());
}
@Test
public void proxyHostIsSet() {
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
.uri("git@gitlab.example.local:someorg/somerepo.git")
.privateKey(PRIVATE_KEY)
.hostKey(HOST_KEY)
.hostKeyAlgorithm(HOST_KEY_ALGORITHM)
.proxyHost("localhost")
.proxyPort(8080)
.build();
setupSessionFactory(sshKey);
factory.configure(hc, session);
ArgumentCaptor<ProxyHTTP> captor = ArgumentCaptor.forClass(ProxyHTTP.class);
verify(session).setProxy(captor.capture());
Assert.assertNotNull(captor.getValue());
}
@Test(expected = IllegalArgumentException.class)
public void proxyPortIsMissing() {
SshUri sshKey = new SshUriProperties.SshUriPropertiesBuilder()
.uri("git@gitlab.example.local:someorg/somerepo.git")
.privateKey(PRIVATE_KEY)
.hostKey(HOST_KEY)
.hostKeyAlgorithm(HOST_KEY_ALGORITHM)
.proxyHost("localhost")
.build();
setupSessionFactory(sshKey);
factory.configure(hc, session);
}
private void setupSessionFactory(SshUri sshKey) {
Map<String, SshUri> sshKeysByHostname = new HashMap<>();
sshKeysByHostname.put(SshUriPropertyProcessor.getHostname(sshKey.getUri()), sshKey);