'Docker, how to deal with ssh keys, known_hosts and authorized_keys

In docker, how to scope with the requirement of configuring known_hosts, authorized_keys and ssh connectivity in general, when container have to talk with external systems?

For example, I'm running jenkins container and try to checkout the project from github in job, but connection fails with the error host key verification failed

This could be solved by login into container, connect to github manually and trust the host key when prompted. However this isn't proper solution, as everything needs to be 100% automated (I'm building CI pipeline with ansible and docker). Another (clunky) solution would be to provision the running container with ansible, but this would make things messy and hard to maintain. Jenkins container doesn't even has ssh daemon, and I'm not sure how to ssh into container from other host. Third option would be to use my own Dockerfile extending jenkins image, where ssh is configured, but that would be hardcoding and locking the container to this specific environment.

So what is the correct way with docker to manage (and automate) connectivity with external systems?



Solution 1:[1]

To trust github.com host you can issue this command when you start or build your container:

 ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

This will add github public key to your known hosts file.

Solution 2:[2]

If everything is done in the Dockerfile it's easy. In my Dockerfile:

ARG PRIVATE_SSH_KEY

# Authorize SSH Host
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan example.com > /root/.ssh/known_hosts && \
    # Add the keys and set permissions
    echo "$PRIVATE_SSH_KEY" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa

...do stuff with private key

# Remove SSH keys
RUN rm -rf /root/.ssh/

You need to obviously need to pass the private key as an argument to the building(docker-compose build or docker build).

Solution 3:[3]

This is how I do it, not sure if you will like this solution though. I have a private git repository containing authorized_keys with a collection of public keys. Then, I use ansible to clone this repository and replace authorized_keys:

- git: repo=my_repo dest=my_local_folder force=yes accept_hostkey=yes

- shell: "cp my_local_folder/authorized_keys ~/.ssh/"

Using accept_hostkey is what actually allows me to automate the process (I trust the source, of course).

Solution 4:[4]

One solution is to mount host's ssh keys into docker with following options:

docker run -v /home/<host user>/.ssh:/home/<docker user>/.ssh <image>

This works perfectly for git.

Solution 5:[5]

There is a small trick but git version should be > 2.3

export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
git clone [email protected]:some/another/repo.git

or simply

GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" git clone git@...

you can even point to private key file path like this:

GIT_SSH_COMMAND="ssh -i /path/to/private_key_file -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" git clone git@...

Solution 6:[6]

Try this: Log into the host, then:

sudo mkdir /var/jenkins_home/.ssh/
sudo ssh-keyscan -t rsa github.com >> /var/jenkins_home/.ssh/known_hosts

The Jenkins container sets the home location to the persistent map, as such, running this in the host system will generate the required result.

Solution 7:[7]

Detailed answer to the one provided by @Konstantin Suvorov, if you are going to use a Dockerfile.

In my Dockerfile I just added:

COPY my_rsa /root/.ssh/my_rsa                       # copy rsa key
RUN chmod 600 /root/.ssh/my_rsa                     # make it accessible
RUN apt-get -y install openssh-server               # install openssh
RUN ssh-keyscan my_hostname >> ~/.ssh/known_hosts   # add hostname to known_hosts

Note that "my_hostname" and "my_rsa" are your host-name and your rsa key

This made ssh work in docker without any issues, so I could connect to DBs

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Konstantin Suvorov
Solution 2 basickarl
Solution 3 Xavier Alvarez
Solution 4 Mohammad Azim
Solution 5 Dennis V
Solution 6 Cyberience
Solution 7 Javi