6

I try to clone a test project from GitLab using a Dockerfile and an SSH key pair: ssh-keygen -t rsa -P "". The private key is passwordless, the public key is published at the GitLab account.

This can be quickly tested by anyone else, just open an account on GitLab and publish your SSH public key, and add a new empty project to clone.

Without Docker, using ssh -i C:\path\to\my\private_key\id_rsa [email protected], it works. Without Docker, cloning the project also works.

I load the private key in the Dockerfile and delete it in the end. Not important, but for all who see a security risk here: I delete the key pair directly after usage, both on client and server. I only try to get around the password entry for the user account when cloning, since that does not seem to work during the run of a Dockerfile, and would be the real security risk as it could leave the password in the logs.

Start: Go to the Dockerfile directory, paste the private key "id_rsa" in a new ".ssh" subfolder. Then:

docker build -t NEW_IMAGENAME . --build-arg ssh_prv_key="$(cat ./.ssh/id_rsa)"

Working code up to now:

FROM vcatechnology/linux-mint:18.2
ARG ssh_prv_key
RUN apt-get update && \
    apt upgrade -y && \
    apt-get install -y git  
RUN apt-get install -y openssh-client # openssh-server
RUN mkdir /root/.ssh/
RUN echo "Host *\n  User git\n  HostName gitlab.com\n  AddKeysToAgent yes\n  IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config
RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa

RUN ssh-keyscan -t rsa -H gitlab.com >> /root/.ssh/known_hosts
RUN ssh -o StrictHostKeyChecking=no [email protected] || true
RUN eval "$(ssh-agent -s)"
RUN chmod 666 /dev/tty

Which leads to:

docker build -t CONTAINERNAME . --build-arg ssh_prv_key="$(cat /.ssh/id_rsa)"
[+] Building 254.9s (14/17)
 => [internal] load build definition from Dockerfile                                                                                                                                                                                    0.0s
 => => transferring dockerfile: 6.84kB                                                                                                                                                                                                  0.0s
 => [internal] load .dockerignore                                                                                                                                                                                                       0.0s
 => => transferring context: 2B                                                                                                                                                                                                         0.0s
 => [internal] load metadata for docker.io/vcatechnology/linux-mint:18.2                                                                                                                                                                0.8s
 => CACHED [ 1/14] FROM docker.io/vcatechnology/linux-mint:18.2@sha256:0557a4999d43c0c622f3a57c3db5b13536024fb5999ecf4f03c6ffec0e4fdb47                                                                                                 0.0s
 => [ 2/14] RUN apt-get update &&  apt upgrade -y &&  apt-get install -y git                                                                                                                                                          244.3s
 => [ 3/14] RUN apt-get install -y openssh-client # openssh-server                                                                                                                                                                      3.1s
 => [ 4/14] RUN mkdir /root/.ssh/                                                                                                                                                                                                       0.6s
 => [ 5/14] RUN echo "Host *\n  User git\n  HostName gitlab.com\n  AddKeysToAgent yes\n  IdentityFile /root/.ssh/id_rsa" >> /etc/ssh/ssh_config                                                                                         0.6s
 => [ 6/14] RUN echo "$(cat /.ssh/id_rsa)" > /root/.ssh/id_rsa &&     chmod 600 /root/.ssh/id_rsa                                                                                                                                       0.6s
 => [ 7/14] RUN ssh-keyscan -t rsa -H gitlab.com >> /root/.ssh/known_hosts                                                                                                                                                              1.3s
 => [ 8/14] RUN ssh -o StrictHostKeyChecking=no [email protected] || true                                                                                                                                                                  1.6s
 => [ 9/14] RUN eval "$(ssh-agent -s)"                                                                                                                                                                                                  0.6s
 => [10/14] RUN chmod 666 /dev/tty                                                                                                                                                                                                      0.6s

The last steps after this working code in the Dockerfile would be as follows, though each of the first three lines stops the script up to now:

RUN ssh-add /root/.ssh/id_rsa
RUN ssh -tti /root/.ssh/id_rsa [email protected]
RUN git clone [email protected]:GITLAB_USERNAME/test.git
RUN rm -r /root/.ssh
  1. If RUN ssh-add /root/.ssh/id_rsa comes directly after the last working code:

      => ERROR [11/14] RUN ssh-add /root/.ssh/id_rsa                                                                                                                                                                                         0.6s
     ------
      > [11/14] RUN ssh-add /root/.ssh/id_rsa:
     #14 0.579 Could not open a connection to your authentication agent.
     ------
     executor failed running [/bin/sh -c ssh-add /root/.ssh/id_rsa]: exit code: 2
    

The error Could not open a connection to your authentication agent. is famous, see Could not open a connection to your authentication agent. But I could not solve it with that thread.

  1. If RUN ssh -tti /root/.ssh/id_rsa [email protected] comes directly after the last working code:

     #14 1.545 Permission denied (publickey,keyboard-interactive).
     ------
     executor failed running [/bin/sh -c ssh -tti /root/.ssh/id_rsa [email protected]]: exit code: 255
    
  2. If RUN git clone [email protected]:GITLAB_USERNAME/test.git comes directly after the last working code:

     #16 0.450 Cloning into 'test'...
     #16 1.466 Permission denied (publickey,keyboard-interactive).
     #16 1.467 fatal: Could not read from remote repository.
     #16 1.467
     #16 1.467 Please make sure you have the correct access rights
     #16 1.467 and the repository exists.
     ------
     executor failed running [/bin/sh -c git clone [email protected]:GITLAB_USERNAME/test.git]: exit code: 128
    

Thus, ssh obviously needs the "ssh-add" that adds the private key to the "ssh-agent" to know the private key on the client at all, and I guess it also needs the ssh -tti /root/.ssh/id_rsa [email protected] to let ssh know the way to the server.

  1. If RUN ssh -Tvvv [email protected] (the -T avoids Pseudo-terminal will not be allocated because stdin is not a terminal) comes directly after the last working code (this is not needed in the final Dockerfile, it is just a check):

      => ERROR [12/12] RUN ssh -Tvvv [email protected]                                                                                                                                                                                          1.2s
     ------
      > [12/12] RUN ssh -Tvvv [email protected]:
     #16 0.376 OpenSSH_7.2p2 Ubuntu-4ubuntu2.10, OpenSSL 1.0.2g  1 Mar 2016
     #16 0.376 debug1: Reading configuration data /etc/ssh/ssh_config
     #16 0.376 debug1: /etc/ssh/ssh_config line 19: Applying options for *
     #16 0.376 debug1: /etc/ssh/ssh_config line 57: Applying options for *
     #16 0.376 debug2: resolving "gitlab.com" port 22
     #16 0.397 debug2: ssh_connect_direct: needpriv 0
     #16 0.397 debug1: Connecting to gitlab.com [172.65.251.78] port 22.
     #16 0.450 debug1: Connection established.
     #16 0.450 debug1: permanently_set_uid: 0/0
     #16 0.450 debug1: key_load_public: No such file or directory
     #16 0.450 debug1: identity file /root/.ssh/id_rsa type -1
     #16 0.450 debug1: key_load_public: No such file or directory
     #16 0.450 debug1: identity file /root/.ssh/id_rsa-cert type -1
     #16 0.451 debug1: Enabling compatibility mode for protocol 2.0
     #16 0.451 debug1: Local version string SSH-2.0-OpenSSH_7.2p2 Ubuntu-4ubuntu2.10
     #16 0.977 debug1: Remote protocol version 2.0, remote software version OpenSSH_7.9p1 Debian-10+deb10u2
     #16 0.977 debug1: match: OpenSSH_7.9p1 Debian-10+deb10u2 pat OpenSSH* compat 0x04000000
     #16 0.977 debug2: fd 3 setting O_NONBLOCK
     #16 0.977 debug1: Authenticating to gitlab.com:22 as 'git'
     #16 0.977 debug3: hostkeys_foreach: reading file "/root/.ssh/known_hosts"
     #16 0.977 debug3: send packet: type 20
     #16 0.977 debug1: SSH2_MSG_KEXINIT sent
     #16 0.994 debug3: receive packet: type 20
     #16 0.994 debug1: SSH2_MSG_KEXINIT received
     #16 0.994 debug2: local client KEXINIT proposal
     #16 0.994 debug2: KEX algorithms: [email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,ext-info-c
     #16 0.994 debug2: host key algorithms: [email protected],[email protected],[email protected],[email protected],[email protected],ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa
     #16 0.994 debug2: ciphers ctos: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected],aes128-cbc,aes192-cbc,aes256-cbc,3des-cbc
     #16 0.994 debug2: ciphers stoc: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected],aes128-cbc,aes192-cbc,aes256-cbc,3des-cbc
     #16 0.994 debug2: MACs ctos: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
     #16 0.994 debug2: MACs stoc: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
     #16 0.994 debug2: compression ctos: none,[email protected],zlib
     #16 0.994 debug2: compression stoc: none,[email protected],zlib
     #16 0.994 debug2: languages ctos:
     #16 0.994 debug2: languages stoc:
     #16 0.994 debug2: first_kex_follows 0
     #16 0.994 debug2: reserved 0
     #16 0.994 debug2: peer server KEXINIT proposal
     #16 0.994 debug2: KEX algorithms: curve25519-sha256,[email protected],ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1
     #16 0.994 debug2: host key algorithms: rsa-sha2-512,rsa-sha2-256,ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519
     #16 0.994 debug2: ciphers ctos: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
     #16 0.994 debug2: ciphers stoc: [email protected],aes128-ctr,aes192-ctr,aes256-ctr,[email protected],[email protected]
     #16 0.994 debug2: MACs ctos: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
     #16 0.994 debug2: MACs stoc: [email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],hmac-sha2-256,hmac-sha2-512,hmac-sha1
     #16 0.994 debug2: compression ctos: none,[email protected]
     #16 0.994 debug2: compression stoc: none,[email protected]
     #16 0.994 debug2: languages ctos:
     #16 0.994 debug2: languages stoc:
     #16 0.994 debug2: first_kex_follows 0
     #16 0.994 debug2: reserved 0
     #16 0.994 debug1: kex: algorithm: [email protected]
     #16 0.994 debug1: kex: host key algorithm: ecdsa-sha2-nistp256
     #16 0.994 debug1: kex: server->client cipher: [email protected] MAC: <implicit> compression: none
     #16 0.994 debug1: kex: client->server cipher: [email protected] MAC: <implicit> compression: none
     #16 1.014 debug3: send packet: type 30
     #16 1.014 debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
     #16 1.182 debug3: receive packet: type 31
     #16 1.185 debug1: Server host key: ecdsa-sha2-nistp256 SHA256:HbW3g8zUjNSksFbqTiUWPWg2Bq1x8xdGUrliXFzSnUw
     #16 1.186 debug3: hostkeys_foreach: reading file "/root/.ssh/known_hosts"
     #16 1.187 debug3: hostkeys_foreach: reading file "/root/.ssh/known_hosts"
     #16 1.187 debug1: read_passphrase: can't open /dev/tty: No such device or address
     #16 1.188 Host key verification failed.
     ------
     executor failed running [/bin/sh -c ssh -Tvvv [email protected]]: exit code: 255    
    

I have tried a lot, but up to now, I could not solve the error read_passphrase: can't open /dev/tty: No such device or address. The file exists, else I could not change its rights to 666, using chmod 666 /dev/tty. I guess that a terminal is required just for entering an empty password.

What to change to clone a repo from GitLab with a passwordless SSH key pair, using just one Dockerfile?

If there is no chance to do this in just one Dockerfile, an accepted workaround would be a docker-compose file; this is not the favoured answer, though.

EDITED: The needed path and file can be found when looking into the container.

(The start was: docker build -t . --build-arg ssh_prv_key="$(cat ./.ssh/id_rsa)", until the end of the working code only!)
docker run -d -it --name test_bash -d NEW_IMAGENAME:latest
docker exec -it test_bash bash
cd root/.ssh;ls

The last command shows the id_rsa and the known_hosts.

d3cbc35351fd / # cd root/.ssh;ls
id_rsa  known_hosts

And if I run d3cbc35351fd .ssh # ssh -Tvvv [email protected] inside the container, I am asked for the password:

Enter passphrase for key '/root/.ssh/id_rsa':
debug2: bad passphrase given, try again...
Enter passphrase for key '/root/.ssh/id_rsa':
debug2: bad passphrase given, try again...
Enter passphrase for key '/root/.ssh/id_rsa':
debug2: no passphrase given, try next key

This is a try with "", '' and just pressing enter, they all do not work.

If I cannot use SSH in the Dockerfile and neither in the container of that Dockerfile' image, I wonder whether cloning a repo out of a Dockerfile or container is possible at all. I guess that suppressing the password entry will be the next big step to solve this, but even that might not solve it entirely, since I have already tried entering an empty password in the container, to no avail.

6
  • 1
    From your log :read_passphrase: .... I suppose the real cause of read_passphrase is that the key isn't be accepted. You should try to docker run into the container and try it there and verify that the private key is stored correct. And add more verbosity by ssh -vvv [email protected]
    – jeb
    Commented Mar 15, 2021 at 7:30
  • @jeb Thanks, I changed to -vvv parameter, see the edited answer. You are right, the /root is empty in the container, obviously, there is no /root/.ssh/id_rsa either, then. There is, though, a green-marked /tmp/ssh-TI6EWavBoyJC folder with the file agent.8 in it. (the steps: docker run -it --name test_bash -d MYIMAGE:latest, then docker exec -it test_bash /bin/bash, cd root, ls) Commented Mar 15, 2021 at 11:55
  • Try it with mkdir -p /root/.ssh && chmod 700 /root/.ssh
    – jeb
    Commented Mar 15, 2021 at 12:21
  • Is it necessary to git clone while building the image? Or is it possible to clone while running the container?
    – jeb
    Commented Mar 15, 2021 at 12:29
  • @jeb I tried it with 700, to no avail. I also tried COPY id_rsa (with "id_rsa" in the same folder as the Dockerfile) instead of echo "$ssh_prv_key" . git clone should happen inside the Dockerfile, I just want to have an installation of everything in one go, without adding another step of cloning. If that is not possible, I will go over to a docker-compose approach where the cloning is done only after the main image was built. If that is not possible again, I would do the cloning manually, then I would just use my password and no key pair would be used. Commented Mar 15, 2021 at 12:48

3 Answers 3

3

If you want to get rid of the private key in the image for security reasons, or if you need more information, see Using SSH keys inside docker container with a more thorough answer.


The main error is caused by the

echo "$ssh_prv_key" > /root/.ssh/id_rsa

which passes a wrongly formatted ssh_prv_key, as just one line, although the private key needs many lines. The idea is from Add private key to ssh-agent in docker file that hints at Gitlab CI/Docker: ssh-add keeps asking for passphrase.

--> Thus, do not use RUN echo ... for the private key, instead, use COPY ...!!!

Another small error is RUN ssh -o StrictHostKeyChecking=no [email protected] || true, which does not work, but

both

RUN echo "Host *\n\t StrictHostKeyChecking no" >> /etc/ssh/ssh_config

and

RUN ssh-keyscan -t rsa -H gitlab.com >> /root/.ssh/known_hosts 

work and reach the same aim, choose just one of the two.

Another step is to drop ssh-agent and ssh-add. Both are only needed if you have a password, see Add private key to ssh-agent in docker file.

This is working now.

The Dockerfile looks as follows:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y git
RUN mkdir -p /root/.ssh && chmod 700 /root/.ssh
COPY /.ssh/id_rsa /root/.ssh/id_rsa
RUN chmod 600 /root/.ssh/id_rsa
RUN ssh-keyscan -t rsa -H gitlab.com >> /root/.ssh/known_hosts
RUN git clone [email protected]:GITLAB_USERNAME/test.git
RUN rm -r /root/.ssh

To create the image from the Dockerfile:

  • Go to the directory of the Dockerfile.

  • Paste your private key "id_rsa" (or whatever name you have, then change the code of course) in a new subfolder "/.ssh/" (or paste it in the Dockerfile directory and change the code to COPY id_rsa /root/.ssh/id_rsa).

  • Start (Do not forget the "." at the end, which is the build context):

    docker build -t test .
    
2

The ssh-agent doesn't work as expected in the build process, but you don't need it at all.

I build a minimal sample that works

FROM ubuntu:latest
ARG ssh_prv_key

RUN apt-get update \
&& apt-get install -y git

RUN mkdir -p /root/.ssh &&  chmod 700 /root/.ssh

RUN echo "$ssh_prv_key" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa

# Check if the key was successfully copied
# RUN cat -n /root/.ssh/id_rsa

# Dummy ssh to store the host into known_hosts
# The expected output is something like: 
# Hi <user>! You've successfully authenticated, but GitHub does not provide shell access.
RUN ssh -T -o StrictHostKeyChecking=no [email protected] || true

RUN git clone ssh://[email protected]/<myrepo>
8
  • This gives me: => ERROR [7/7] RUN git clone [email protected]:USERNAME/test.git 1.2s ------ > [7/7] RUN git clone [email protected]:USERNAME/test.git: #10 0.475 Cloning into 'key_test'... #10 1.109 Host key verification failed. #10 1.110 fatal: Could not read from remote repository. #10 1.110 #10 1.110 Please make sure you have the correct access rights #10 1.110 and the repository exists. Commented Mar 15, 2021 at 15:14
  • @questionto42 [email protected]:USERNAME The :USERNAME looks strange here, does it work in the host system?
    – jeb
    Commented Mar 15, 2021 at 15:16
  • I use USERNAME as a placeholder for my real GitLab username here. On the host: ssh -i id_rsa [email protected] leads to PTY allocation request failed on channel 0 Welcome to GitLab, @USERNAME! Connection to gitlab.com closed. And git clone [email protected]:USERNAME/test.git clones the empty repo. Commented Mar 15, 2021 at 15:18
  • This is just the "Copy URL" that you get in GitLab when you are in the repo and click on the clone button (and choose SSH). It should be the right URL to ssh the repo. Would it not be logical again that this is the same issue of the needed password entry for a private key that does not have a password? I am not using GitHub, but GitLab, perhaps that is also the issue? Commented Mar 15, 2021 at 15:22
  • @questionto42 The error is at Host key verification failed, the host key should already stored in ~/.ssh/known_hosts, by the step 6/7 ssh -T -o StrictHostKeyChecking=no [email protected]
    – jeb
    Commented Mar 15, 2021 at 15:27
1

In my case the error read_passphrase: can't open /dev/tty: No such device or address was caused by ssh prompting for permission to add a new host. As per this answer add to your ssh config

StrictHostKeyChecking no

In case your ssh client supports it use accept-new instead of no for security.

1
  • RUN echo "Host *\n\t StrictHostKeyChecking no" >> /etc/ssh/ssh_config is already mentioned in another answer. Using accept-new is new, though. Commented Oct 12, 2021 at 20:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .