Skip to content

Commit

Permalink
feature: add host key information for better host key verification
Browse files Browse the repository at this point in the history
  • Loading branch information
sparsick committed Aug 30, 2023
1 parent 74a6718 commit 645812e
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import java.io.IOException;
import java.net.URI;
import java.util.Base64;

/**
* Container for a plain Git Server based on the Docker image "rockstorm/git-server".
Expand All @@ -18,6 +19,7 @@ public class GitServerContainer extends GenericContainer<GitServerContainer> {
private static DockerImageName DEFAULT_DOCKER_IMAGE_NAME = DockerImageName.parse("rockstorm/git-server");
private String gitRepoName = "testRepo";
private SshIdentity sshClientIdentity;
private SshHostKey hostKey;

/**
*
Expand Down Expand Up @@ -100,6 +102,11 @@ protected void containerIsStarted(InspectContainerResponse containerInfo) {
execInContainer("mkdir", "-p", gitRepoPath);
execInContainer("git", "init", "--bare", gitRepoPath);
execInContainer("chown", "-R", "git:git", "/srv");

ExecResult result = execInContainer("cat", "/etc/ssh/ssh_host_ecdsa_key.pub");
String[] catResult = result.getStdout().split(" ");
hostKey = new SshHostKey("localhost", Base64.getDecoder().decode(catResult[1]));

} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
Expand Down Expand Up @@ -127,4 +134,13 @@ public String getGitPassword() {
public SshIdentity getSshClientIdentity() {
return sshClientIdentity;
}

/**
* Return the public host key information.
*
* @return public host key
*/
public SshHostKey getHostKey() {
return hostKey;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.github.sparsick.testcontainers.gitserver;

import java.util.Objects;


/**
* Value object for SSH Host key information.
*/
public class SshHostKey {

private String hostname;
private byte[] key;

/**
* SSH Host Key information
* @param hostname host
* @param key keystring
*/
public SshHostKey(String hostname, byte[] key) {
this.key = key;
this.hostname = hostname;
}

/**
* Public key of the host key.
*
* @return key string
*/
public byte[] getKey() {
return key;
}

/**
* Name of the host
*
* @return name of the host
*/
public String getHostname() {
return hostname;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SshHostKey)) return false;
SshHostKey hostKey = (SshHostKey) o;
return Objects.equals(key, hostKey.key) && Objects.equals(hostname, hostKey.hostname);
}

@Override
public int hashCode() {
return Objects.hash(key, hostname);
}

@Override
public String toString() {
return "HostKey{" +
"key='" + key + '\'' +
", hostname='" + hostname + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.github.sparsick.testcontainers.gitserver;

import com.jcraft.jsch.HostKey;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
Expand Down Expand Up @@ -138,11 +139,7 @@ void pubKeyAuth(GitServerVersions gitServer) {
@Override
protected JSch createDefaultJSch(FS fs ) throws JSchException {
JSch defaultJSch = super.createDefaultJSch( fs );
SshIdentity sshIdentity = containerUnderTest.getSshClientIdentity();
byte[] privateKey = sshIdentity.getPrivateKey();
byte[] publicKey = sshIdentity.getPublicKey();
byte[] passphrase = sshIdentity.getPassphrase();
defaultJSch.addIdentity("git-server", privateKey, publicKey, passphrase);
configureSshIdentity(defaultJSch, containerUnderTest);
return defaultJSch;
}
@Override
Expand All @@ -154,4 +151,50 @@ protected void configure(OpenSshConfig.Host hc, Session session) {
.call()
);
}

@ParameterizedTest
@EnumSource(GitServerVersions.class)
void strictHostKeyVerifivation(GitServerVersions gitServer) {
var containerUnderTest = new GitServerContainer(gitServer.getDockerImageName()).withSshKeyAuth();

containerUnderTest.start();

URI gitRepoURI = containerUnderTest.getGitRepoURIAsSSH();

assertThatNoException().isThrownBy(() ->
Git.cloneRepository()
.setURI(gitRepoURI.toString())
.setDirectory(tempDir)
.setBranch("main")
.setTransportConfigCallback(transport -> {
var sshTransport = (SshTransport) transport;
sshTransport.setSshSessionFactory(new JschConfigSessionFactory() {

@Override
protected JSch createDefaultJSch(FS fs ) throws JSchException {
JSch defaultJSch = super.createDefaultJSch( fs );
configureSshIdentity(defaultJSch, containerUnderTest);
configureHostKeyRepository(defaultJSch, containerUnderTest);
return defaultJSch;
}
});
})
.call()
);
}

private void configureSshIdentity(JSch defaultJSch, GitServerContainer containerUnderTest) throws JSchException {
SshIdentity sshIdentity = containerUnderTest.getSshClientIdentity();
byte[] privateKey = sshIdentity.getPrivateKey();
byte[] publicKey = sshIdentity.getPublicKey();
byte[] passphrase = sshIdentity.getPassphrase();
defaultJSch.addIdentity("git-server", privateKey, publicKey, passphrase);
}

private void configureHostKeyRepository(JSch defaultJSch, GitServerContainer containerUnderTest) throws JSchException {
SshHostKey hostKey = containerUnderTest.getHostKey();
String host = hostKey.getHostname();
byte[] key = hostKey.getKey();
defaultJSch.getHostKeyRepository().add(new HostKey(host, key), null);
}
}

0 comments on commit 645812e

Please sign in to comment.