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:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user