-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to use ssh-agent from devcontainer CLI ? #441
Comments
Curious as well, there seems to be tons of old documentation on how to do this (https://stackoverflow.com/questions/43418188/ssh-agent-forwarding-during-docker-build) but it appears there is more modern (still old) tooling with |
The ssh-agent forwarding is part of the Dev Containers extension and not part of the Dev Containers CLI. You could mount the ssh-agent's socket and then point SSH_AUTH_SOCK at it. |
Strangely when I did mount the ssh-auth-socket to let's say /tmp/ssh-agent.socket and then set SSH_AUTH_SOCK to /tmp/ssh-agent.socket, I could confirm the mount was done and the env was set, but ssh-add was still unable to talk to the ssh-agent itself. I then start a ssh-agent within the devcontainer itself telling it to use /tmp/ssh-agent.socket and ssh-add was happy but still not finding any of my key which I had in my how ssh-agent. The other issue, is that when I did so, within vscode things stop working, because the SSH_AUTH_SOCK got converted to "." instead of the real SSH_AUTH_SOCK value, even thougth the dev conatiners extension is able to find that value propery. |
and docker-compose.yml:
If I do that in a docker container it works, but when I do it via the devcontainer cli it doesn't work. Anyway it would be really nice for devcontainer teams to align and provide an example on how to use ssh-agent in devcontainer CLI in a way compatible with VSCode that is compatible with all OS/remote or not, etc. as it doesn't seem that easy to get working. |
You only need to run an ssh-agent on your local machine (where the private keys are), not inside the container. Note that "runArgs" doesn't apply to Docker Compose. I can't get it to work on Mac right now, maybe this has changed. Another option would be to mount |
@chrmarti I would prefer the option of ssh-agent because getting access to the key doesn't get you access to the passphrase to unlock the key which then raises another challenge. It also simplifies cases where the key to use may not be in the .ssh, some users prefer to use a different folder to make it harder to attackers to find those, etc. when I do not start the ssh-agent within the container, even thought the socket is mounted, ssh-add simply fail to connect to it and report an error. I am using VSCode on Windows, then connect to Linux via Remote-SSH and use devcontainer. Using VSCode, the dev containers helper connect my "Windows" ssh-agent to my devcontainer... which in itself is strange, as I would really like my remote linux to be the ssh-agent, as to not share my keys on my windows machine like I have to now. But that is another matter. And as indicated then using SSH_AUTH_SOCK env variable it breaks VSCode because then SSH_AUTH_SOCK becomes . and the docker-compose complains that
is not a valid volume format. It somehow look like I would need to start VSCode with SSH_AUTH_SOCK set to my linux SSH_AUTH_SOCK so that VSCode continue to work... which doesn't appear usable. |
I agree, using the ssh-agent seems preferable.
That should actually work. If
Docker Compose should do the variable replacement there. Maybe another indicator that |
SSH_AUTH_SOCK is set by my .bashrc but in my linux, it works nicely when I use it with ssh, but vscode still translate to . One interesting thing is that my ssh-agent in order to use a single socket start ssh-agent, create a symlink to the socket and then set SSH_AUTH_SOCK to the symlink.
So maybe that could be a reason for this issue. Another could be that .bashrc is only used for some interactive login and I may need to put it in a .profile or .bash_profile, I will try that to see if things change. But I can assure you that it currently prefer my Windows ssh-agent over my Linux one.
I wish this part was a little more verbose and somehow provide clues as to why my Linux ssh-agent was not found, maybe some kind of warning that the SSH_AUTH_SOCK is not set, the extension fallback to the native host ssh-agent ? With some URL pointing to how to properly set SSH_AUTH_SOCK in a way for Remote-SSH to detect it. Because the issue my SSH_AUTH_SOCK is set when I used ssh manually, it is also set when I used remote-ssh feature of VSCode, it is only apparently not set when I used the remote-devcontainer plugin feature. |
I have removed the symlink by using ssh-agent -a and no change.
still attach to my windows ssh-agent:
I also added the ssh-agent setup in my .bash_profile and .profile, no impact. |
I will also improve logging for this. For now we can use the trace logging output. |
In the area around ssh-agent, there apparently are no trace logs. |
That doesn't seem to be the full log. Check for Also check your local |
Is there a file I can retrieve? Right now then I do rebuild the log is within a terminal window and history doesn't go back to the beginning. I have put the full log in here. I found this snippet to be relevant:
Yet, whenever I log SSH (or with Remote SSH) on that machine SSH_AUTH_SOCK is set. Likely this has something to do with interactive login mode vs something else. That is an aspect of Linux that I am less familiar with.
|
I found on stack overlow a command syntax to use non-interactive login:
and when I use that I see no value. Will try to find out how to make that work then will retry with vscode. Yet, I am not clear why Remote-SSH would work, but not Devcontainer. |
You can find log files from previous sessions with |
Would it be possible to add a cli arg to make this more easily possible? I am confused how to do this. |
@TheButlah The ssh-agent is only forwarded when using the Dev Containers extension for VS Code. The Dev Containers CLI does not do that yet. Labelling as feature request. |
One wishes I have is that once devcontainer/cli does it, that vscode stop doing it on its own and relies on the devcontainer/cli tool to do it instead. The idea is that there is a single mechanism to understand/document/debug. It also seems like there is a similar system related to GPG, likely both would need to be moved from vscode to devcontainer/cli. |
BTW, to solve this, I had to both mount the agent socket into the container, set the permission of the socket to allow the user to access it, and set On mac, the socket path was the magic path of I still advocate that this functionality be implemented directly in the devcontainers cli, as figuring out how to do all of that was a nightmare. |
@TheButlah I will see if I can repro your result, I am on Ubuntu and I have attempted many things, without success so far. Also there seem to be 2 modes of usage in devcontainer, either Dockefile, docker-compose. I am using docker-compose, which may be slightly different sometimes. I remember having tried to mount the socket in docker-compose and check permission, also move the ssh-agent socket location from ~/.ssh/ which was not accessible to /tmp/, and then also passing an SSH_AUTH_SOCK value that made sense within the container, but where I had success with normal docker container, it didn't work, from memory, using devcontainer. |
JFYI by mounting
Is unfortunately non-portable to other OS like Windows. Native support from I would also like to flag that vscode is additionally do some more magic that involved even |
Based on what I'm gathering (and for my several years of trying to do this lazily across docker and k8s) this will require a wrapper so you can mux PTY/std fds and agent sock to target container over stdin/stdout. Which I'm guessing is what the extension does when it runs, based on what I see in lsof. Some similar logic to adapt to whatever Windows needs. Frankly, the easiest solution right now is to run an sshd inside the container (that's super ugly, but will result in less complaints from my devs that writing my own minimally used thing) since it will handle all this stuff out of the box. It's a nontrivial effort because basically the same pty logic from docker's run/exec commands to setup the terminal and do the right thing over stdin/stdout to the daemon. Then, each channel (pty/ssh agent/gpg agent/x11 socket/...) needs its own flow control to avoid head-of-line blocking before demux. BTW, this technique is definitely required in k8s where you can't easily just reach in and mount stuff. Of course if Microsoft didn't hold the dev containers extension behind the proprietary firewall, this could probably be made to work a bit quicker with some copy+paest engineering. My use-case is simple: I want to develop in containers without vscode or similar tooling and simply hop in, vim it good, commit, and push all from within the container. I should be able to leave the containers running, drop my ssh session, hop back in, deal with it being run as another user (so realistically, the socket should be proxied inside the container) and generally be as clean every time i do a devcontainer exec. |
If the issue is socket permissions (e.g. host user is # usage:
# devcontainer up \
# --remote-env "SSH_AUTH_SOCK=/tmp/ssh-auth-sock" \
# --mount "type=bind,source=${SSH_AUTH_SOCK},target=/tmp/ssh-auth-sock" \
# ... etc.
# If SSH_AUTH_SOCK exists and isn't owned by the container user, use socat to proxy
# between a socket owned by the container user and the one mounted in from the host
if test -n "${SSH_AUTH_SOCK:-}" \
&& test "${SSH_AUTH_SOCK}" != ~/.ssh/socket \
&& test "$(stat -c "%u:%g" "${SSH_AUTH_SOCK}")" != "$(id -u):$(id -g)"; then
ssh_auth_sock=~/.ssh/socket;
# If the remapped ssh socket doesn't already exist
if ! test -f "${ssh_auth_sock}"; then
# Map the host's ssh-agent socket to one owned by the container user
sudo --background socat "UNIX-LISTEN:${ssh_auth_sock},fork,user=$(id -nu),group=$(id -ng),mode=777" "UNIX-CONNECT:${SSH_AUTH_SOCK}";
sleep 5;
fi
# test the remapped ssh-agent socket
SSH_AUTH_SOCK="${ssh_auth_sock}" ssh-add -L 1>&2;
# set SSH_AUTH_SOCK to the new remapped one
echo "SSH_AUTH_SOCK=${ssh_auth_sock}" >> ~/.bashrc;
export SSH_AUTH_SOCK="${ssh_auth_sock}";
unset ssh_auth_sock;
fi |
as this is normally done automatically via VSCode however this feature is still exclusive to MS remote extension and has not yet been upstream to the FOSS CLI - devcontainers/cli#441 (comment)
I have a devcontainer that I will be using in vscode and in CI.
In the CI we use devcontainer up/exec
in vscode, we see there is a dev container helper that sets up ssh-agent.
In the CI we setup ssh-agent and add the key, but I cannot find a way to have the same devcontainer works in both environment.
I run vscode on windows and remote container are on linux. I can mount my SSH_AUTH_SOCK to /tmp/ssh-agent.socket and then I can start ssh-agent -a /tmp/ssh-agent.socket, but ssh-add -L still report no identities and outside of the container ssh-add -L do report at least one key that I did add to the ssh-agent.
Would you have an example of how one can use devcontainer with docker-compose to access the local ssh-agent, in a compatible way that would also work within vscode itself?
(when I load the same devcontainer in vscode, the SSH_AUTH_SOCK gets transformed into a ".", yet my linux remove is using ssh-agent and has a proper SSH_AUTH_SOCK value). Somehow I think the Windows version is being used, for which no SSH_AUTH_SOCK exists, but I do have the ssh-agent running on Windows.
I would definitely prefer that the remote container uses the remote linux ssh-agent than my windows.
The text was updated successfully, but these errors were encountered: