From 1a1dd1cbe018c899beb9fb7a95c4fc67b9e13b2c Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Wed, 18 Dec 2019 16:07:30 -0800 Subject: [PATCH] e2e: Add test for SSH This requires having a docker image for git-over-ssh. --- Makefile | 3 +++ _test_tools/sshd/Dockerfile | 39 +++++++++++++++++++++++++++ _test_tools/sshd/README.md | 52 ++++++++++++++++++++++++++++++++++++ _test_tools/sshd/sshd.sh | 14 ++++++++++ _test_tools/sshd/sshd_config | 12 +++++++++ test_e2e.sh | 42 +++++++++++++++++++++++++++++ 6 files changed, 162 insertions(+) create mode 100644 _test_tools/sshd/Dockerfile create mode 100644 _test_tools/sshd/README.md create mode 100755 _test_tools/sshd/sshd.sh create mode 100644 _test_tools/sshd/sshd_config diff --git a/Makefile b/Makefile index b4dfb4a..6602863 100644 --- a/Makefile +++ b/Makefile @@ -177,6 +177,9 @@ test: $(BUILD_DIRS) " @./test_e2e.sh +test-tools: + @docker build -t $(REGISTRY)/test/test-sshd _test_tools/sshd + $(BUILD_DIRS): @mkdir -p $@ diff --git a/_test_tools/sshd/Dockerfile b/_test_tools/sshd/Dockerfile new file mode 100644 index 0000000..31efc1a --- /dev/null +++ b/_test_tools/sshd/Dockerfile @@ -0,0 +1,39 @@ +# Stolen from https://github.com/linuxkit/linuxkit/tree/master/pkg/sshd/ + +FROM alpine AS base + +RUN mkdir -p /out/etc/apk && cp -r /etc/apk/* /out/etc/apk/ +RUN apk add --no-cache --initdb -p /out \ + alpine-baselayout \ + apk-tools \ + busybox \ + ca-certificates \ + git \ + musl \ + openssh-server \ + tini \ + util-linux \ + wireguard-tools \ + && true + +############### + +FROM scratch + +ENTRYPOINT [] +WORKDIR / + +COPY --from=base /out/ / + +RUN mkdir -p /etc/ssh && rm /etc/motd +COPY sshd_config /etc/ssh/ +COPY sshd.sh / + +# Callers should mount a .ssh directory here. Our sshd.sh will copy it and +# manage permissions. +VOLUME /dot_ssh + +# Callers can SSH as user "test" +RUN echo "test:x:65533:65533::/home/test:/usr/bin/git-shell" >> /etc/passwd + +CMD ["/sbin/tini", "/sshd.sh"] diff --git a/_test_tools/sshd/README.md b/_test_tools/sshd/README.md new file mode 100644 index 0000000..3e0e316 --- /dev/null +++ b/_test_tools/sshd/README.md @@ -0,0 +1,52 @@ +# An SSHD for tests git-over-ssh + +DO NOT USE THIS FOR ANYTHING BUT TESTING GIT OVER SSH!!! + +## How to use it + +Build yourself a test image. We use example.com so you can't accidentally push +it. + +``` +$ docker build -t example.com/test/test-sshd . +...lots of output... +Successfully tagged example.com/test/test-sshd:latest +``` + +Generate keys for a fake user named "test". + +``` +$ mkdir -p dot_ssh + +$ ssh-keygen -f dot_ssh/id_test -P "" +Generating public/private rsa key pair. +Your identification has been saved in dot_ssh/id_test. +Your public key has been saved in dot_ssh/id_test.pub. +...lots of output... + +$ cat dot_ssh/id_test.pub > dot_ssh/authorized_keys +``` + +Run it. + +``` +$ docker run -d -v $(pwd)/dot_ssh:/dot_ssh:ro example.com/test/test-sshd +6d05b4111b03c66907031e3cd7587763f0e4fab6c50fac33c4a8284732b448ae +``` + +Find your IP. + +``` +$ docker inspect 6d05b4111b03c66907031e3cd7587763f0e4fab6c50fac33c4a8284732b448ae | jq -r .[0].NetworkSettings.IPAddress +192.168.1.2 +``` + +SSH to it. + +``` +$ ssh -i dot_ssh/id_test -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null test@192.168.9.2 +Warning: Permanently added '192.168.9.2' (ECDSA) to the list of known hosts. +fatal: Interactive git shell is not enabled. +hint: ~/git-shell-commands should exist and have read and execute access. +Connection to 192.168.9.2 closed. +``` diff --git a/_test_tools/sshd/sshd.sh b/_test_tools/sshd/sshd.sh new file mode 100755 index 0000000..757f5fe --- /dev/null +++ b/_test_tools/sshd/sshd.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +KEYS=$(find /etc/ssh -name 'ssh_host_*_key') +[ -z "$KEYS" ] && ssh-keygen -A >/dev/null 2>/dev/null + +# Copy creds for the test user, so we don't have to bake them into the image +# and so users don't have to manage permissions. +mkdir -p /home/test/.ssh +cp -a /dot_ssh/* /home/test/.ssh +chown -R test /home/test/.ssh +chmod 0700 /home/test/.ssh +chmod 0600 /home/test/.ssh/* + +exec /usr/sbin/sshd -D -e diff --git a/_test_tools/sshd/sshd_config b/_test_tools/sshd/sshd_config new file mode 100644 index 0000000..65a0a2a --- /dev/null +++ b/_test_tools/sshd/sshd_config @@ -0,0 +1,12 @@ +# This is the sshd server system-wide configuration file. See +# sshd_config(5) for more information. + +# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2 +# but this is overridden so installations will only check .ssh/authorized_keys +AuthorizedKeysFile .ssh/authorized_keys + +# To disable tunneled clear text passwords, change to no here! +PasswordAuthentication no + +# Change to no to disable s/key passwords +ChallengeResponseAuthentication no diff --git a/test_e2e.sh b/test_e2e.sh index a7118e1..8e3ba81 100755 --- a/test_e2e.sh +++ b/test_e2e.sh @@ -66,6 +66,7 @@ function freencport() { # Build it make container REGISTRY=e2e VERSION=$(make -s version) +make test-tools REGISTRY=e2e RUNID="${RANDOM}${RANDOM}" DIR="" @@ -95,6 +96,12 @@ function clean_root() { mkdir -p "$ROOT" } +# Init SSH for test cases. +DOT_SSH="$DIR/dot_ssh" +mkdir -p "$DOT_SSH" +ssh-keygen -f "$DOT_SSH/id_test" -P "" >/dev/null +cat "$DOT_SSH/id_test.pub" > "$DOT_SSH/authorized_keys" + function finish() { if [ $? -ne 0 ]; then echo "The directory $DIR was not removed as it contains"\ @@ -118,8 +125,10 @@ function GIT_SYNC() { -v "$DIR":"$DIR":rw \ -v "$(pwd)/slow_git.sh":"$SLOW_GIT":ro \ -v "$(pwd)/askpass_git.sh":"$ASKPASS_GIT":ro \ + -v "$DOT_SSH/id_test":"/etc/git-secret/ssh":ro \ --env XDG_CONFIG_HOME=$DIR \ e2e/git-sync:$(make -s version)__$(go env GOOS)_$(go env GOARCH) \ + --add-user \ "$@" } @@ -963,5 +972,38 @@ fi rm -rf $SUBMODULE pass +############################################## +# Test SSH +############################################## +testcase "ssh" +echo "$TESTCASE" > "$REPO"/file +# Run a git-over-SSH server +CTR=$(docker run \ + -d \ + --rm \ + --label git-sync-e2e="$RUNID" \ + -v "$DOT_SSH":/dot_ssh:ro \ + -v "$REPO":/src:ro \ + e2e/test/test-sshd) +IP=$(docker inspect "$CTR" | jq -r .[0].NetworkSettings.IPAddress) +git -C "$REPO" commit -qam "$TESTCASE" +GIT_SYNC \ + --logtostderr \ + --v=5 \ + --one-time \ + --ssh \ + --ssh-known-hosts=false \ + --repo="test@$IP:/src" \ + --branch=master \ + --rev=HEAD \ + --root="$ROOT" \ + --dest="link" \ + > "$DIR"/log."$TESTCASE" 2>&1 +assert_link_exists "$ROOT"/link +assert_file_exists "$ROOT"/link/file +assert_file_eq "$ROOT"/link/file "$TESTCASE" +# Wrap up +pass + echo "cleaning up $DIR" rm -rf "$DIR"