Merge branch '3.1.x'
This commit is contained in:
@@ -22,18 +22,13 @@ import java.util.Map;
|
||||
import org.eclipse.jgit.annotations.NonNull;
|
||||
import org.eclipse.jgit.internal.transport.ssh.OpenSshConfigFile;
|
||||
import org.eclipse.jgit.transport.SshConfigStore;
|
||||
import org.eclipse.jgit.transport.SshConstants;
|
||||
import org.eclipse.jgit.transport.sshd.SshdSessionFactory;
|
||||
|
||||
import org.springframework.cloud.config.server.environment.JGitEnvironmentProperties;
|
||||
|
||||
public class FileBasedSshSessionFactory extends SshdSessionFactory {
|
||||
|
||||
private static final String STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";
|
||||
|
||||
private static final String YES_OPTION = "yes";
|
||||
|
||||
private static final String NO_OPTION = "no";
|
||||
|
||||
private final Map<String, JGitEnvironmentProperties> sshKeysByHostname;
|
||||
|
||||
public FileBasedSshSessionFactory(Map<String, JGitEnvironmentProperties> sshKeysByHostname) {
|
||||
@@ -54,8 +49,8 @@ public class FileBasedSshSessionFactory extends SshdSessionFactory {
|
||||
return hostEntry;
|
||||
}
|
||||
|
||||
hostEntry.setValue(STRICT_HOST_KEY_CHECKING,
|
||||
sshProperties.isStrictHostKeyChecking() ? YES_OPTION : NO_OPTION);
|
||||
hostEntry.setValue(SshConstants.STRICT_HOST_KEY_CHECKING,
|
||||
sshProperties.isStrictHostKeyChecking() ? SshConstants.YES : SshConstants.NO);
|
||||
|
||||
return hostEntry;
|
||||
}
|
||||
|
||||
@@ -61,14 +61,6 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
|
||||
private static final String STRICT_HOST_KEY_CHECKING = "StrictHostKeyChecking";
|
||||
|
||||
private static final String PREFERRED_AUTHENTICATIONS = "PreferredAuthentications";
|
||||
|
||||
private static final String YES_OPTION = "yes";
|
||||
|
||||
private static final String NO_OPTION = "no";
|
||||
|
||||
private final Map<String, JGitEnvironmentProperties> sshKeysByHostname;
|
||||
|
||||
public PropertyBasedSshSessionFactory(Map<String, JGitEnvironmentProperties> sshKeysByHostname) {
|
||||
@@ -103,20 +95,17 @@ public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
|
||||
private OpenSshConfigFile.HostEntry updateIfNeeded(OpenSshConfigFile.HostEntry hostEntry, String hostName) {
|
||||
JGitEnvironmentProperties sshProperties = sshKeysByHostname.get(hostName);
|
||||
if (sshProperties == null) {
|
||||
return hostEntry;
|
||||
}
|
||||
|
||||
if (sshProperties.getHostKey() == null || !sshProperties.isStrictHostKeyChecking()) {
|
||||
hostEntry.setValue(STRICT_HOST_KEY_CHECKING, NO_OPTION);
|
||||
hostEntry.setValue(SshConstants.STRICT_HOST_KEY_CHECKING, SshConstants.NO);
|
||||
}
|
||||
else {
|
||||
hostEntry.setValue(STRICT_HOST_KEY_CHECKING, YES_OPTION);
|
||||
hostEntry.setValue(SshConstants.STRICT_HOST_KEY_CHECKING, SshConstants.YES);
|
||||
}
|
||||
|
||||
String preferredAuthentications = sshProperties.getPreferredAuthentications();
|
||||
if (preferredAuthentications != null) {
|
||||
hostEntry.setValue(PREFERRED_AUTHENTICATIONS, preferredAuthentications);
|
||||
hostEntry.setValue(SshConstants.PREFERRED_AUTHENTICATIONS, preferredAuthentications);
|
||||
}
|
||||
return hostEntry;
|
||||
}
|
||||
@@ -136,10 +125,7 @@ public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
public List<PublicKey> lookup(String connectAddress, InetSocketAddress remoteAddress,
|
||||
Configuration config) {
|
||||
|
||||
JGitEnvironmentProperties sshProperties = sshKeysByHostname.get(remoteAddress.getHostName());
|
||||
if (sshProperties == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
JGitEnvironmentProperties sshProperties = findEnvironmentProperties(sshKeysByHostname, remoteAddress);
|
||||
|
||||
List<Path> knownHostFiles = getKnownHostFiles(sshProperties);
|
||||
List<PublicKey> publicKeys = new OpenSshServerKeyDatabase(false, knownHostFiles).lookup(connectAddress,
|
||||
@@ -156,7 +142,8 @@ public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
@Override
|
||||
public boolean accept(String connectAddress, InetSocketAddress remoteAddress, PublicKey serverKey,
|
||||
Configuration config, CredentialsProvider provider) {
|
||||
if (isNotStrictHostKeyChecking(remoteAddress.getHostName())) {
|
||||
|
||||
if (config.getStrictHostKeyChecking() == Configuration.StrictHostKeyChecking.ACCEPT_ANY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -165,14 +152,6 @@ public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
return KeyUtils.findMatchingKey(serverKey, knownServerKeys) != null;
|
||||
}
|
||||
|
||||
private boolean isNotStrictHostKeyChecking(String hostName) {
|
||||
JGitEnvironmentProperties sshProperties = sshKeysByHostname.get(hostName);
|
||||
if (sshProperties == null) {
|
||||
return false;
|
||||
}
|
||||
return !sshProperties.isStrictHostKeyChecking();
|
||||
}
|
||||
|
||||
private PublicKey getHostKey(JGitEnvironmentProperties sshProperties) {
|
||||
String hostKey = sshProperties.getHostKey();
|
||||
String hostKeyAlgorithm = sshProperties.getHostKeyAlgorithm();
|
||||
@@ -206,6 +185,18 @@ public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
return new SingleKeyIdentityProvider(sshKeysByHostname);
|
||||
}
|
||||
|
||||
private static JGitEnvironmentProperties findEnvironmentProperties(
|
||||
Map<String, JGitEnvironmentProperties> sshKeysByHostname, InetSocketAddress socketAddress) {
|
||||
|
||||
JGitEnvironmentProperties sshProperties = sshKeysByHostname.get(socketAddress.getHostString());
|
||||
|
||||
if (sshProperties == null && socketAddress.getAddress() != null) {
|
||||
sshProperties = sshKeysByHostname.get(socketAddress.getAddress().getHostAddress());
|
||||
}
|
||||
|
||||
return sshProperties;
|
||||
}
|
||||
|
||||
private final static class SingleKeyIdentityProvider implements KeyIdentityProvider, Iterable<KeyPair> {
|
||||
|
||||
private final Map<String, JGitEnvironmentProperties> sshKeysByHostname;
|
||||
@@ -221,11 +212,10 @@ public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
|
||||
@Override
|
||||
public Iterable<KeyPair> loadKeys(SessionContext session) throws IOException, GeneralSecurityException {
|
||||
SshdSocketAddress remoteAddress = SshdSocketAddress.toSshdSocketAddress(session.getRemoteAddress());
|
||||
JGitEnvironmentProperties sshProperties = sshKeysByHostname.get(remoteAddress.getHostName());
|
||||
InetSocketAddress remoteAddress = SshdSocketAddress.toInetSocketAddress(session.getRemoteAddress());
|
||||
JGitEnvironmentProperties sshProperties = findEnvironmentProperties(sshKeysByHostname, remoteAddress);
|
||||
|
||||
return sshProperties == null ? Collections.emptyList()
|
||||
: KeyPairUtils.load(session, sshProperties.getPrivateKey(), sshProperties.getPassphrase());
|
||||
return KeyPairUtils.load(session, sshProperties.getPrivateKey(), sshProperties.getPassphrase());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -240,7 +230,8 @@ public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
|
||||
@Override
|
||||
public ProxyData get(InetSocketAddress remoteAddress) {
|
||||
JGitEnvironmentProperties sshProperties = sshKeysByHostname.get(remoteAddress.getHostName());
|
||||
JGitEnvironmentProperties sshProperties = findEnvironmentProperties(sshKeysByHostname, remoteAddress);
|
||||
|
||||
ProxyHostProperties proxyHostProperties = sshProperties.getProxy()
|
||||
.get(ProxyHostProperties.ProxyForScheme.HTTP);
|
||||
|
||||
@@ -250,8 +241,10 @@ public class PropertyBasedSshSessionFactory extends SshdSessionFactory {
|
||||
|
||||
Proxy proxy = new Proxy(Proxy.Type.HTTP,
|
||||
new InetSocketAddress(proxyHostProperties.getHost(), proxyHostProperties.getPort()));
|
||||
return new ProxyData(proxy, proxyHostProperties.getUsername(),
|
||||
proxyHostProperties.getPassword().toCharArray());
|
||||
|
||||
char[] proxyPassword = proxyHostProperties.getPassword() != null
|
||||
? proxyHostProperties.getPassword().toCharArray() : null;
|
||||
return new ProxyData(proxy, proxyHostProperties.getUsername(), proxyPassword);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyPair;
|
||||
@@ -54,6 +55,7 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -121,16 +123,10 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
public void sshConfigIsUsedForRelevantHostOnly() {
|
||||
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);
|
||||
PublicKey configuredKey = toPublicKey(HOST_KEY, HOST_KEY_ALGORITHM);
|
||||
|
||||
SshConfigStore.HostConfig sshConfig = getSshHostConfig("another.host");
|
||||
|
||||
assertThat(sshConfig.getValue("StrictHostKeyChecking")).isNull();
|
||||
assertThat(isKnownKeyForHost(configuredKey, "another.host")).isFalse();
|
||||
assertThatThrownBy(() -> getSshHostConfig("another.host")).isInstanceOf(NullPointerException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -161,6 +157,19 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
assertThat(privateKey).isEqualTo(toPrivateKey(PRIVATE_KEY, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void privateKeyIsUsedWithRepoIp() {
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("git@127.0.0.1:someorg/somerepo.git");
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
setupSessionFactory(sshKey);
|
||||
|
||||
PrivateKey privateKey = getSshPrivateKey("gitlab.example.local");
|
||||
|
||||
assertThat(privateKey).isNotNull();
|
||||
assertThat(privateKey).isEqualTo(toPrivateKey(PRIVATE_KEY, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void privateKeyWithPassphraseIsUsed() {
|
||||
String keyWithPassphrase = getResourceAsString("/ssh/key-with-passphrase");
|
||||
@@ -183,6 +192,24 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
sshKey.setUri("git@gitlab.example.local:someorg/somerepo.git");
|
||||
sshKey.setHostKeyAlgorithm(HOST_KEY_ALGORITHM);
|
||||
sshKey.setHostKey(HOST_KEY);
|
||||
sshKey.setStrictHostKeyChecking(true);
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
setupSessionFactory(sshKey);
|
||||
PublicKey configuredKey = toPublicKey(HOST_KEY, HOST_KEY_ALGORITHM);
|
||||
|
||||
PublicKey knownHostKey = getSshHostKey("gitlab.example.local");
|
||||
|
||||
assertThat(knownHostKey).isNotNull();
|
||||
assertThat(knownHostKey).isEqualTo(configuredKey);
|
||||
assertThat(isKnownKeyForHost(configuredKey, "gitlab.example.local")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hostKeyIsUsedWithRepoIp() {
|
||||
JGitEnvironmentProperties sshKey = new JGitEnvironmentProperties();
|
||||
sshKey.setUri("git@127.0.0.1:someorg/somerepo.git");
|
||||
sshKey.setHostKeyAlgorithm(HOST_KEY_ALGORITHM);
|
||||
sshKey.setHostKey(HOST_KEY);
|
||||
sshKey.setPrivateKey(PRIVATE_KEY);
|
||||
setupSessionFactory(sshKey);
|
||||
PublicKey configuredKey = toPublicKey(HOST_KEY, HOST_KEY_ALGORITHM);
|
||||
@@ -241,6 +268,7 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
|
||||
ProxyData proxyData = getSshProxyData("gitlab.example.local");
|
||||
|
||||
assertThat(proxyData).isNotNull();
|
||||
assertThat(proxyData.getUser()).isEqualTo("user");
|
||||
assertThat(new String(proxyData.getPassword())).isEqualTo("password");
|
||||
assertThat(proxyData.getProxy().type().toString()).isEqualTo("HTTP");
|
||||
@@ -251,11 +279,28 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
public void defaultSshConfigIsSet() {
|
||||
setupSessionFactory(new JGitEnvironmentProperties());
|
||||
|
||||
SshConfigStore.HostConfig sshConfig = getDefaultSshHostConfig("host.name", 123, "user.name");
|
||||
assertThatThrownBy(() -> getDefaultSshHostConfig("host.name", 123, "user.name"))
|
||||
.isInstanceOf(NullPointerException.class);
|
||||
}
|
||||
|
||||
assertThat(sshConfig.getValue("HostName")).isEqualTo("host.name");
|
||||
assertThat(sshConfig.getValue("Port")).isEqualTo("123");
|
||||
assertThat(sshConfig.getValue("User")).isEqualTo("user.name");
|
||||
@Test
|
||||
public void proxySettingsIsUsedWithRepoIp() {
|
||||
JGitEnvironmentProperties sshProperties = new JGitEnvironmentProperties();
|
||||
sshProperties.setUri("ssh://127.0.0.1:3322/somerepo.git");
|
||||
sshProperties.setPrivateKey(PRIVATE_KEY);
|
||||
Map<ProxyHostProperties.ProxyForScheme, ProxyHostProperties> map = new HashMap<>();
|
||||
ProxyHostProperties proxyHostProperties = new ProxyHostProperties();
|
||||
proxyHostProperties.setHost("host.domain");
|
||||
proxyHostProperties.setPort(8080);
|
||||
map.put(ProxyHostProperties.ProxyForScheme.HTTP, proxyHostProperties);
|
||||
sshProperties.setProxy(map);
|
||||
setupSessionFactory(sshProperties);
|
||||
|
||||
ProxyData proxyData = getSshProxyData("gitlab.example.local");
|
||||
|
||||
assertThat(proxyData).isNotNull();
|
||||
assertThat(proxyData.getProxy().type().toString()).isEqualTo("HTTP");
|
||||
assertThat(proxyData.getProxy().address().toString()).containsPattern("host\\.domain.*:8080");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -271,7 +316,7 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
proxies.setAccessible(true);
|
||||
ProxyDataFactory proxyDataFactory = (ProxyDataFactory) proxies.get(factory);
|
||||
proxies.setAccessible(false);
|
||||
return proxyDataFactory.get(new InetSocketAddress(hostname, 22));
|
||||
return proxyDataFactory.get(setupSocketAddress(hostname));
|
||||
}
|
||||
catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -299,9 +344,10 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
}
|
||||
}
|
||||
|
||||
private PrivateKey getSshPrivateKey(String hostName) {
|
||||
private PrivateKey getSshPrivateKey(String hostname) {
|
||||
InetSocketAddress address = setupSocketAddress(hostname);
|
||||
SessionContext session = mock(SessionContext.class);
|
||||
when(session.getRemoteAddress()).thenReturn(new InetSocketAddress(hostName, 22));
|
||||
when(session.getRemoteAddress()).thenReturn(address);
|
||||
|
||||
List<KeyPair> kayPairs;
|
||||
try {
|
||||
@@ -317,22 +363,22 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
return kayPairs.isEmpty() ? null : kayPairs.get(0).getPrivate();
|
||||
}
|
||||
|
||||
private PublicKey getSshHostKey(String hostName) {
|
||||
InetSocketAddress address = new InetSocketAddress(hostName, 22);
|
||||
private PublicKey getSshHostKey(String hostname) {
|
||||
InetSocketAddress address = setupSocketAddress(hostname);
|
||||
List<PublicKey> publicKeys = factory.getServerKeyDatabase(null, null).lookup("address", address,
|
||||
mock(ServerKeyDatabase.Configuration.class));
|
||||
|
||||
return publicKeys.isEmpty() ? null : publicKeys.get(0);
|
||||
}
|
||||
|
||||
private boolean isKnownKeyForHost(PublicKey publicKey, String hostName) {
|
||||
InetSocketAddress address = new InetSocketAddress(hostName, 22);
|
||||
private boolean isKnownKeyForHost(PublicKey publicKey, String hostname) {
|
||||
InetSocketAddress address = setupSocketAddress(hostname);
|
||||
return factory.getServerKeyDatabase(null, null).accept("address", address, publicKey,
|
||||
mock(ServerKeyDatabase.Configuration.class), null);
|
||||
}
|
||||
|
||||
private SshConfigStore.HostConfig getSshHostConfig(String hostName) {
|
||||
return factory.createSshConfigStore(new File("dummy"), new File("dummy"), "localUserName").lookup(hostName, 22,
|
||||
private SshConfigStore.HostConfig getSshHostConfig(String hostname) {
|
||||
return factory.createSshConfigStore(new File("dummy"), new File("dummy"), "localUserName").lookup(hostname, 22,
|
||||
"userName");
|
||||
}
|
||||
|
||||
@@ -347,4 +393,17 @@ public class PropertyBasedSshSessionFactoryTest {
|
||||
this.factory = new PropertyBasedSshSessionFactory(sshKeysByHostname);
|
||||
}
|
||||
|
||||
private InetSocketAddress setupSocketAddress(String hostname) {
|
||||
InetAddress address = mock(InetAddress.class);
|
||||
when(address.getHostAddress()).thenReturn("127.0.0.1");
|
||||
|
||||
InetSocketAddress socketAddress = mock(InetSocketAddress.class);
|
||||
when(socketAddress.getAddress()).thenReturn(address);
|
||||
when(socketAddress.getHostString()).thenReturn(hostname);
|
||||
when(socketAddress.getHostName()).thenReturn(hostname);
|
||||
when(socketAddress.getPort()).thenReturn(22);
|
||||
|
||||
return socketAddress;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user