Issue
Request
This docker command injects my ssh key and username into a container, connects that container to a remote host, and then runs: echo hello world
on the host:
docker run --rm \
-e "host=the.host" \
-e "user=my.user.name" \
-v "/home/me/.ssh/id_rsa:/key" \
ubuntu:18.04 /bin/bash -c \
'apt update && apt install -y ssh \
&& ssh -o StrictHostKeyChecking=no $user@$host -i /key
echo hello world'
I want the command to be able to connect to the remote host, but I don't want it to be able to cat /key
and see my ssh key.
What changes can I make to achieve this?
Context
I'm writing a test runner. My code is responsible for determining which tests can be run against which hosts, but the test itself might not be written by me (it gets pulled in from a git repo when my test runner starts up).
I am not worried about my colleagues abusing the server with their test code because that abuse would be visible in source control. They are semi-trusted in this case. I am worried about somebody writing a test which causes my ssh key to appear in log output somewhere.
Ideally, I would set up the ssh connection first, then create the container--somehow granting it access to the connection, but not the key.
Solution
The feature I needed was SSH Multiplexing which I learned about here
This file goes in the docker image at ~/.ssh.config
Host foo
ControlMaster auto
ControlPath ~/.ssh/cm_socket/%r@%h:%p
And this file goes on the host:
Host foo
HostName foo.bar.com
User my.username
IdentityFile /path/to/key
IdentitiesOnly yes
ControlMaster auto
ControlPath ~/.ssh/cm_socket/%r@%h:%p
I called the image keylesssh
, so this command creates a container which doesn't have the key, but does have the folder which will contain a socket if there is an existing connection.
docker run --rm \
-v "/home/matt/.ssh/cm_socket:/root/.ssh/cm_socket" \
keylesssh /bin/bash -c 'ssh dev1 hostname'
It comes together like this:
- I open an ssh connection from the machine that is hosting the docker daemon to the remote host
- SSH will creates a socket and put it in ~/.ssh/cm_socket with a predictable name
- I create a container, sharing that folder with it
- The container tries to ssh to the host, notices that the socket exists, and uses the existing connection without authenticating--no key required
- Once the test has finished running, the container shuts down
- When my code notices the container shutting down, I kill the master ssh connection
I know it works because the hostname
command resolves the hostname of the remote server, not of the container or of the docker host.
Answered By - MatrixManAtYrService