From d79b54f4204649e9e4f68becae3b237521f5998e Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Fri, 3 Feb 2017 19:49:56 +0100 Subject: [PATCH 01/11] Volume-based approach (WIP) --- Dockerfile | 10 +++++----- Makefile | 2 +- docker-entrypoint.sh | 5 +++++ pinata-build-sshd.sh | 1 - pinata-ssh-forward.sh | 16 +++++++++++----- pinata-ssh-mount.sh | 4 +--- ssh-find-agent.sh | 9 --------- ssh-forward-agent.sh | 4 ++++ 8 files changed, 27 insertions(+), 24 deletions(-) create mode 100755 docker-entrypoint.sh delete mode 100755 ssh-find-agent.sh create mode 100755 ssh-forward-agent.sh diff --git a/Dockerfile b/Dockerfile index 09e82d4..20c5327 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,12 @@ FROM alpine MAINTAINER Anil Madhavapeddy -RUN apk update && apk add openssh && \ - apk add --update --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ tini +RUN apk update && apk add openssh socat RUN mkdir /root/.ssh && \ chmod 700 /root/.ssh && \ ssh-keygen -A -COPY ssh-find-agent.sh /root/ssh-find-agent.sh +COPY ssh-forward-agent.sh /root/ssh-forward-agent.sh +COPY docker-entrypoint.sh / EXPOSE 22 -VOLUME ["/root/.ssh/authorized_keys"] -ENTRYPOINT ["/usr/bin/tini","--"] +VOLUME ["/ssh-agent"] +ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["/usr/sbin/sshd","-D"] diff --git a/Makefile b/Makefile index 49c0488..038f634 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ install: @mkdir -p $(PREFIX)/share/pinata-ssh-agent cp Dockerfile $(PREFIX)/share/pinata-ssh-agent cp ssh-build.sh $(PREFIX)/share/pinata-ssh-agent/ssh-build - cp ssh-find-agent.sh $(PREFIX)/share/pinata-ssh-agent/ssh-find-agent.sh + cp ssh-forward-agent.sh $(PREFIX)/share/pinata-ssh-agent/ssh-forward-agent.sh @mkdir -p $(BINDIR) cp pinata-build-sshd.sh $(BINDIR)/pinata-build-sshd cp pinata-ssh-forward.sh $(BINDIR)/pinata-ssh-forward diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100755 index 0000000..09d23df --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,5 @@ +#!/bin/sh +set -e +cp /tmp/.pinata-sshd/authorized_keys /root/.ssh/authorized_keys +chown root:root /root/.ssh/authorized_keys +exec "$@" diff --git a/pinata-build-sshd.sh b/pinata-build-sshd.sh index 23e9a85..99b6e0d 100755 --- a/pinata-build-sshd.sh +++ b/pinata-build-sshd.sh @@ -1,4 +1,3 @@ #!/bin/sh -cd /usr/local/share/pinata-ssh-agent docker build -t pinata-sshd . diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index 4b236d4..7ad3244 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -1,4 +1,5 @@ -#!/bin/sh -e +#!/bin/sh +set -e IMAGE_NAME=pinata-sshd CONTAINER_NAME=pinata-sshd @@ -9,17 +10,22 @@ docker rm -f ${CONTAINER_NAME} >/dev/null 2>&1 || true rm -rf ${LOCAL_STATE} mkdir -p ${LOCAL_STATE} +ssh-add -L >${LOCAL_STATE}/authorized_keys + docker run --name ${CONTAINER_NAME} \ - -v ~/.ssh/id_rsa.pub:/root/.ssh/authorized_keys \ - -v ${LOCAL_STATE}:/tmp \ + -v ${LOCAL_STATE}:/tmp/.pinata-sshd \ -d -p ${LOCAL_PORT}:22 ${IMAGE_NAME} > /dev/null -IP=`docker inspect --format '{{(index (index .NetworkSettings.Ports "22/tcp") 0).HostIp }}' ${CONTAINER_NAME}` +if [ "${DOCKER_HOST}" ]; then + IP=$(echo $DOCKER_HOST | awk -F '//' '{print $2}' | awk -F ':' '{print $1}') +else + IP=127.0.0.1 +fi ssh-keyscan -p ${LOCAL_PORT} ${IP} > ${LOCAL_STATE}/known_hosts 2>/dev/null ssh -f -o "UserKnownHostsFile=${LOCAL_STATE}/known_hosts" \ -A -p ${LOCAL_PORT} root@${IP} \ - /root/ssh-find-agent.sh + /root/ssh-forward-agent.sh echo 'Agent forwarding successfully started.' echo 'Run "pinata-ssh-mount" to get a command-line fragment that' diff --git a/pinata-ssh-mount.sh b/pinata-ssh-mount.sh index 9835091..9a8dad0 100755 --- a/pinata-ssh-mount.sh +++ b/pinata-ssh-mount.sh @@ -1,5 +1,3 @@ #!/bin/sh -LOCAL_STATE=~/.pinata-sshd -AGENT=`cat ${LOCAL_STATE}/agent_socket_path | sed -e 's,/tmp/,,g'` -echo "-v ${LOCAL_STATE}/$AGENT:/tmp/ssh-agent.sock --env SSH_AUTH_SOCK=/tmp/ssh-agent.sock" +echo "--volumes-from pinata-sshd --env SSH_AUTH_SOCK=/ssh-agent/ssh-agent.sock" diff --git a/ssh-find-agent.sh b/ssh-find-agent.sh deleted file mode 100755 index 9dfb677..0000000 --- a/ssh-find-agent.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -e -# Log the location of the SSH agent to a file - -finish() { - rm -f /tmp/agent_socket_path -} -trap finish EXIT -echo $SSH_AUTH_SOCK > /tmp/agent_socket_path -tail -f /dev/null diff --git a/ssh-forward-agent.sh b/ssh-forward-agent.sh new file mode 100755 index 0000000..d3fe0a7 --- /dev/null +++ b/ssh-forward-agent.sh @@ -0,0 +1,4 @@ +#!/bin/sh -e +# Forward SSH agent socket to a well-known location + +socat UNIX-LISTEN:/ssh-agent/ssh-agent.sock,fork UNIX-CONNECT:$SSH_AUTH_SOCK From 186366c470841fa7bdb17b82af910166fcdd55d0 Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Sun, 5 Feb 2017 04:36:49 +0100 Subject: [PATCH 02/11] Make pinata-ssh-mount fish compatible --- pinata-ssh-mount.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pinata-ssh-mount.sh b/pinata-ssh-mount.sh index 9a8dad0..0d65a4e 100755 --- a/pinata-ssh-mount.sh +++ b/pinata-ssh-mount.sh @@ -1,3 +1,4 @@ #!/bin/sh -echo "--volumes-from pinata-sshd --env SSH_AUTH_SOCK=/ssh-agent/ssh-agent.sock" +echo "--volumes-from=pinata-sshd" +echo "--env=SSH_AUTH_SOCK=/ssh-agent/ssh-agent.sock" From 2ba664c04c62a0e746a24b128c36d28862c3df12 Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Sun, 5 Feb 2017 13:40:49 +0100 Subject: [PATCH 03/11] Inject authorized keys via env instead of volume --- docker-entrypoint.sh | 2 +- pinata-ssh-forward.sh | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 09d23df..6a23658 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,5 +1,5 @@ #!/bin/sh set -e -cp /tmp/.pinata-sshd/authorized_keys /root/.ssh/authorized_keys +echo $AUTHORIZED_KEYS | base64 -d >/root/.ssh/authorized_keys chown root:root /root/.ssh/authorized_keys exec "$@" diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index 7ad3244..b389a59 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -5,15 +5,14 @@ IMAGE_NAME=pinata-sshd CONTAINER_NAME=pinata-sshd LOCAL_STATE=~/.pinata-sshd LOCAL_PORT=2244 +AUTHORIZED_KEYS=$(ssh-add -L | base64 -w0) docker rm -f ${CONTAINER_NAME} >/dev/null 2>&1 || true rm -rf ${LOCAL_STATE} mkdir -p ${LOCAL_STATE} -ssh-add -L >${LOCAL_STATE}/authorized_keys - docker run --name ${CONTAINER_NAME} \ - -v ${LOCAL_STATE}:/tmp/.pinata-sshd \ + -e AUTHORIZED_KEYS="${AUTHORIZED_KEYS}" \ -d -p ${LOCAL_PORT}:22 ${IMAGE_NAME} > /dev/null if [ "${DOCKER_HOST}" ]; then From 01524e42c11403c824eadb9f927c3f175565ec7c Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Sun, 5 Feb 2017 13:58:56 +0100 Subject: [PATCH 04/11] Use temp file for known hosts --- pinata-ssh-forward.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index b389a59..e5d431f 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -3,13 +3,13 @@ set -e IMAGE_NAME=pinata-sshd CONTAINER_NAME=pinata-sshd -LOCAL_STATE=~/.pinata-sshd LOCAL_PORT=2244 AUTHORIZED_KEYS=$(ssh-add -L | base64 -w0) +KNOWN_HOSTS_FILE=$(mktemp) + +trap "rm ${KNOWN_HOSTS_FILE}" EXIT docker rm -f ${CONTAINER_NAME} >/dev/null 2>&1 || true -rm -rf ${LOCAL_STATE} -mkdir -p ${LOCAL_STATE} docker run --name ${CONTAINER_NAME} \ -e AUTHORIZED_KEYS="${AUTHORIZED_KEYS}" \ @@ -20,9 +20,9 @@ if [ "${DOCKER_HOST}" ]; then else IP=127.0.0.1 fi -ssh-keyscan -p ${LOCAL_PORT} ${IP} > ${LOCAL_STATE}/known_hosts 2>/dev/null +ssh-keyscan -p ${LOCAL_PORT} ${IP} > ${KNOWN_HOSTS_FILE} 2>/dev/null -ssh -f -o "UserKnownHostsFile=${LOCAL_STATE}/known_hosts" \ +ssh -f -o "UserKnownHostsFile=${KNOWN_HOSTS_FILE}" \ -A -p ${LOCAL_PORT} root@${IP} \ /root/ssh-forward-agent.sh From d615ba5d2893b592694524156cede98b75b96a15 Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Sun, 5 Feb 2017 14:14:04 +0100 Subject: [PATCH 05/11] Rename LOCAL_* variables to HOST_* (because that's what it is now) --- pinata-ssh-forward.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index e5d431f..1544909 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -3,7 +3,7 @@ set -e IMAGE_NAME=pinata-sshd CONTAINER_NAME=pinata-sshd -LOCAL_PORT=2244 +HOST_PORT=2244 AUTHORIZED_KEYS=$(ssh-add -L | base64 -w0) KNOWN_HOSTS_FILE=$(mktemp) @@ -13,17 +13,17 @@ docker rm -f ${CONTAINER_NAME} >/dev/null 2>&1 || true docker run --name ${CONTAINER_NAME} \ -e AUTHORIZED_KEYS="${AUTHORIZED_KEYS}" \ - -d -p ${LOCAL_PORT}:22 ${IMAGE_NAME} > /dev/null + -d -p ${HOST_PORT}:22 ${IMAGE_NAME} > /dev/null if [ "${DOCKER_HOST}" ]; then - IP=$(echo $DOCKER_HOST | awk -F '//' '{print $2}' | awk -F ':' '{print $1}') + HOST_IP=$(echo $DOCKER_HOST | awk -F '//' '{print $2}' | awk -F ':' '{print $1}') else - IP=127.0.0.1 + HOST_IP=127.0.0.1 fi -ssh-keyscan -p ${LOCAL_PORT} ${IP} > ${KNOWN_HOSTS_FILE} 2>/dev/null +ssh-keyscan -p ${HOST_PORT} ${HOST_IP} > ${KNOWN_HOSTS_FILE} 2>/dev/null ssh -f -o "UserKnownHostsFile=${KNOWN_HOSTS_FILE}" \ - -A -p ${LOCAL_PORT} root@${IP} \ + -A -p ${HOST_PORT} root@${HOST_IP} \ /root/ssh-forward-agent.sh echo 'Agent forwarding successfully started.' From 979dd6a4e73e34856f813f16b3acc55cfba8c06a Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Mon, 6 Feb 2017 23:54:34 +0100 Subject: [PATCH 06/11] Make agent socket accessible by all --- ssh-forward-agent.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ssh-forward-agent.sh b/ssh-forward-agent.sh index d3fe0a7..9d07372 100755 --- a/ssh-forward-agent.sh +++ b/ssh-forward-agent.sh @@ -2,3 +2,4 @@ # Forward SSH agent socket to a well-known location socat UNIX-LISTEN:/ssh-agent/ssh-agent.sock,fork UNIX-CONNECT:$SSH_AUTH_SOCK +chmod 777 /ssh-agent/ssh-agent.sock From 2b35f4fe82071c4adb73dc74bac9537527dba8bc Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Tue, 7 Feb 2017 00:47:18 +0100 Subject: [PATCH 07/11] Make ssh-agent a named volume --- pinata-ssh-forward.sh | 4 ++++ pinata-ssh-mount.sh | 2 +- ssh-forward-agent.sh | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index 1544909..6544faf 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -3,6 +3,7 @@ set -e IMAGE_NAME=pinata-sshd CONTAINER_NAME=pinata-sshd +VOLUME_NAME=ssh-agent HOST_PORT=2244 AUTHORIZED_KEYS=$(ssh-add -L | base64 -w0) KNOWN_HOSTS_FILE=$(mktemp) @@ -11,8 +12,11 @@ trap "rm ${KNOWN_HOSTS_FILE}" EXIT docker rm -f ${CONTAINER_NAME} >/dev/null 2>&1 || true +docker volume create ${VOLUME_NAME} + docker run --name ${CONTAINER_NAME} \ -e AUTHORIZED_KEYS="${AUTHORIZED_KEYS}" \ + -v ${VOLUME_NAME}:/ssh-agent \ -d -p ${HOST_PORT}:22 ${IMAGE_NAME} > /dev/null if [ "${DOCKER_HOST}" ]; then diff --git a/pinata-ssh-mount.sh b/pinata-ssh-mount.sh index 0d65a4e..3a70aae 100755 --- a/pinata-ssh-mount.sh +++ b/pinata-ssh-mount.sh @@ -1,4 +1,4 @@ #!/bin/sh -echo "--volumes-from=pinata-sshd" +echo "--volume=ssh-agent:/ssh-agent" echo "--env=SSH_AUTH_SOCK=/ssh-agent/ssh-agent.sock" diff --git a/ssh-forward-agent.sh b/ssh-forward-agent.sh index 9d07372..0022f40 100755 --- a/ssh-forward-agent.sh +++ b/ssh-forward-agent.sh @@ -1,5 +1,6 @@ #!/bin/sh -e # Forward SSH agent socket to a well-known location +FORWARDED_SOCKET=/ssh-agent/ssh-agent.sock -socat UNIX-LISTEN:/ssh-agent/ssh-agent.sock,fork UNIX-CONNECT:$SSH_AUTH_SOCK -chmod 777 /ssh-agent/ssh-agent.sock +rm -f ${FORWARDED_SOCKET} +socat UNIX-LISTEN:${FORWARDED_SOCKET},fork,mode=777 UNIX-CONNECT:${SSH_AUTH_SOCK} From e79d9cad577f7864f04961764a425e09feebc11b Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Tue, 7 Feb 2017 17:46:42 +0100 Subject: [PATCH 08/11] Fix for new volume create syntax --- pinata-ssh-forward.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index 6544faf..a46e776 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -12,7 +12,7 @@ trap "rm ${KNOWN_HOSTS_FILE}" EXIT docker rm -f ${CONTAINER_NAME} >/dev/null 2>&1 || true -docker volume create ${VOLUME_NAME} +docker volume create --name ${VOLUME_NAME} docker run --name ${CONTAINER_NAME} \ -e AUTHORIZED_KEYS="${AUTHORIZED_KEYS}" \ From d4fca3abf0a75127720788cf22fc66216773b4f4 Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Wed, 8 Feb 2017 08:44:07 +0100 Subject: [PATCH 09/11] Work around missing base64 option on OSX --- pinata-ssh-forward.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index a46e776..b489c83 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -5,7 +5,7 @@ IMAGE_NAME=pinata-sshd CONTAINER_NAME=pinata-sshd VOLUME_NAME=ssh-agent HOST_PORT=2244 -AUTHORIZED_KEYS=$(ssh-add -L | base64 -w0) +AUTHORIZED_KEYS=$(ssh-add -L | base64 | tr -d '\n') KNOWN_HOSTS_FILE=$(mktemp) trap "rm ${KNOWN_HOSTS_FILE}" EXIT From dfc7673ef1335d1aca3b01e6333c1ddba51e5bab Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Tue, 14 Feb 2017 22:56:57 +0100 Subject: [PATCH 10/11] Use mktemp syntax compatible with Yosemite --- pinata-ssh-forward.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index b489c83..ca8d922 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -6,7 +6,7 @@ CONTAINER_NAME=pinata-sshd VOLUME_NAME=ssh-agent HOST_PORT=2244 AUTHORIZED_KEYS=$(ssh-add -L | base64 | tr -d '\n') -KNOWN_HOSTS_FILE=$(mktemp) +KNOWN_HOSTS_FILE=$(mktemp -t dsaf.XXX) trap "rm ${KNOWN_HOSTS_FILE}" EXIT From cd9b12b2a2c7ac3b0cb6b72d20ad311a6ec25327 Mon Sep 17 00:00:00 2001 From: Martin Honermeyer Date: Tue, 14 Feb 2017 23:51:29 +0100 Subject: [PATCH 11/11] Generate SSH host key during container startup FIXME Find a way to ensure sshd is ready without waiting an arbitrary second. --- Dockerfile | 3 +-- docker-entrypoint.sh | 4 ++++ pinata-ssh-forward.sh | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 20c5327..e29a90d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,7 @@ FROM alpine MAINTAINER Anil Madhavapeddy RUN apk update && apk add openssh socat RUN mkdir /root/.ssh && \ - chmod 700 /root/.ssh && \ - ssh-keygen -A + chmod 700 /root/.ssh COPY ssh-forward-agent.sh /root/ssh-forward-agent.sh COPY docker-entrypoint.sh / EXPOSE 22 diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 6a23658..f55b510 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,5 +1,9 @@ #!/bin/sh set -e + echo $AUTHORIZED_KEYS | base64 -d >/root/.ssh/authorized_keys chown root:root /root/.ssh/authorized_keys + +ssh-keygen -A + exec "$@" diff --git a/pinata-ssh-forward.sh b/pinata-ssh-forward.sh index ca8d922..f99fa03 100755 --- a/pinata-ssh-forward.sh +++ b/pinata-ssh-forward.sh @@ -24,6 +24,11 @@ if [ "${DOCKER_HOST}" ]; then else HOST_IP=127.0.0.1 fi + +# FIXME Find a way to get rid of this additional 1s wait +sleep 1 +while [ 1 ] && ! nc -z -w5 ${HOST_IP} ${HOST_PORT}; do sleep 0.1; done + ssh-keyscan -p ${HOST_PORT} ${HOST_IP} > ${KNOWN_HOSTS_FILE} 2>/dev/null ssh -f -o "UserKnownHostsFile=${KNOWN_HOSTS_FILE}" \