Search code examples
sshpipdockerfiledocker-buildkit

Can I use Docker buildkit to provide an ssh key to a non-root user?


I have had trouble using buildkit's RUN --mount=type=ssh as a non-root user.

Using this command:

eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519
DOCKER_BUILDKIT=1 docker build --ssh default=${SSH_AUTH_SOCK} .

And this Dockerfile:

FROM docker.io/apache/airflow
USER root
RUN apt update && apt install -y git openssh-client

# uncommenting this breaks it
#USER airflow

RUN mkdir -m 700 ~/.ssh
RUN ssh-keyscan github.com > ~/.ssh/known_hosts
RUN --mount=type=ssh ssh -vvvT [email protected]

It works. I get output like:

 > [5/5] RUN --mount=type=ssh ssh -vvvT [email protected]:
...
#8 0.931 debug1: Will attempt key: matt@ChoedanKal ED25519 SHA256:2IGNbnSt122LtFaH5Z6u5eQf9B+aG0khsfNUxOKfHJU agent
#8 0.931 debug1: Will attempt key: /root/.ssh/id_rsa
#8 0.931 debug1: Will attempt key: /root/.ssh/id_dsa
#8 0.931 debug1: Will attempt key: /root/.ssh/id_ecdsa
#8 0.931 debug1: Will attempt key: /root/.ssh/id_ecdsa_sk
#8 0.931 debug1: Will attempt key: /root/.ssh/id_ed25519
#8 0.931 debug1: Will attempt key: /root/.ssh/id_ed25519_sk
#8 0.931 debug1: Will attempt key: /root/.ssh/id_xmss
#8 0.917 debug2: pubkey_prepare: done
#8 0.917 debug3: send packet: type 5
#8 0.961 debug3: receive packet: type 7
...
#8 1.056 debug1: Offering public key: matt@ChoedanKal ED25519 SHA256:2IGNbnSt122LtFaH5Z6u5eQf9B+aG0khsfNUxOKfHJU agent
#8 1.056 debug3: send packet: type 50
#8 1.056 debug2: we sent a publickey packet, wait for reply
#8 1.111 debug3: receive packet: type 60
#8 1.111 debug1: Server accepts key: matt@ChoedanKal ED25519 SHA256:2IGNbnSt122LtFaH5Z6u5eQf9B+aG0khsfNUxOKfHJU agent
#8 1.111 debug3: sign_and_send_pubkey: ED25519 SHA256:2IGNbnSt122LtFaH5Z6u5eQf9B+aG0khsfNUxOKfHJU
#8 1.111 debug3: sign_and_send_pubkey: signing using ssh-ed25519 SHA256:2IGNbnSt122LtFaH5Z6u5eQf9B+aG0khsfNUxOKfHJU
#8 1.122 debug3: send packet: type 50
#8 1.176 debug3: receive packet: type 52
#8 1.176 debug1: Authentication succeeded (publickey).
#8 1.176 Authenticated to github.com ([140.82.113.3]:22).
...
#8 1.271 Hi MatrixManAtYrService! You've successfully authenticated, but GitHub does not provide shell access.

But if I include the USER airflow line, it breaks:

 > [5/5] RUN --mount=type=ssh ssh -vvvT [email protected]:
...
#8 0.941 debug1: pubkey_prepare: ssh_get_authentication_socket: Permission denied
#8 0.941 debug1: Will attempt key: /home/airflow/.ssh/id_rsa
#8 0.941 debug1: Will attempt key: /home/airflow/.ssh/id_dsa
#8 0.941 debug1: Will attempt key: /home/airflow/.ssh/id_ecdsa
#8 0.941 debug1: Will attempt key: /home/airflow/.ssh/id_ecdsa_sk
#8 0.941 debug1: Will attempt key: /home/airflow/.ssh/id_ed25519
#8 0.941 debug1: Will attempt key: /home/airflow/.ssh/id_ed25519_sk
#8 0.941 debug1: Will attempt key: /home/airflow/.ssh/id_xmss
#8 0.941 debug2: pubkey_prepare: done
#8 0.941 debug3: send packet: type 5
#8 0.991 debug3: receive packet: type 7
#8 0.991 debug1: SSH2_MSG_EXT_INFO received
#8 0.991 debug1: kex_input_ext_info: server-sig-algs=<[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],ssh-ed25519,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256,ssh-rsa>
#8 1.042 debug3: receive packet: type 6
#8 1.042 debug2: service_accept: ssh-userauth
#8 1.042 debug1: SSH2_MSG_SERVICE_ACCEPT received
#8 1.042 debug3: send packet: type 50
#8 1.092 debug3: receive packet: type 51
#8 1.092 debug1: Authentications that can continue: publickey
#8 1.092 debug3: start over, passed a different list publickey
...
#8 1.092 [email protected]: Permission denied (publickey).

This is probably the crux of it:

ssh_get_authentication_socket: Permission denied

I want to reference the key in a command like:

pip install git+ssh://[email protected]/someuser/somerepo.git

Which is a problem because invoking pip as root is not recommended. I've been able to work around the issue by creating a virtual environment as root, installing the package as root, and then chown -Ring the virtual environment to airflow, but I'd like to know if there's a more direct way.


Solution

  • It turns out, buildkit's --mount syntax takes a uid= parameter.

    So I was able to discover the uid for my non-root user like so:

    $ docker run -it --rm apache/airflow bash -c 'id -u $(whoami)'
        50000
    

    And then adjust my Dockerfile to mount the socket to the ssh agent with that uid as the owner:

    FROM docker.io/apache/airflow
    USER root
    RUN apt update && apt install -y git openssh-client && rm -rf /var/lib/apt/lists/*
    USER airflow
    RUN mkdir -m 700 ~/.ssh
    RUN ssh-keyscan github.com > ~/.ssh/known_hosts
    RUN --mount=type=ssh,uid=50000 ssh -vvvT [email protected]
    

    Following this, I was able to authenticate over ssh with the externally-supplied key, as a non-root user.