Skip to content
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

In order to use an SSH DOCKER_HOST on OS X and Linux, you must configure an ssh-agent. #1459

Closed
maxsatula opened this issue Dec 3, 2019 · 39 comments · Fixed by #1914
Closed

Comments

@maxsatula
Copy link

newEnv.SSH_AUTH_SOCK = await getSshAuthSock();

await ext.ui.showWarningMessage('In order to use an SSH DOCKER_HOST on OS X and Linux, you must configure an ssh-agent.');

I doubt setting of SSH_AUTH_SOCK variable is necessary. I keep it undefined, but have IdentityAgent, IdentityFile, AddKeysToAgent in my .ssh/config. However the code referenced at the top makes my configuration unusable for this extension, while it perfectly works everywhere else outside vscode-docker.

Can this check be removed or replaced with something else? There are other options for SSH to avoid interactive password prompt, such as BatchMode or IdentitiesOnly.

Thank you!

@philliphoff
Copy link
Member

Some of the manipulation of environment variables related to SSH is due limitations in the way dockerode (used to connect to the Docker host) must be initialized. That said, there may be more that we could do to support a wider variety of SSH configurations.

@maxsatula
Copy link
Author

Yep, and dockerode does not seem to respect .ssh/config file at all, so the solution might not be that simple as I suggested earlier :(

@maxsatula
Copy link
Author

Nonetheless, I would appreciate a possibility to customize value of SSH_AUTH_SOCK.
I run agent as ssh-agent -a <my_fixed_path_to_UNIX_socket>, so the path is known and static.

@bwateratmsft
Copy link
Collaborator

bwateratmsft commented Dec 6, 2019

Dockerode indeed does not respect it, unfortunately; Dockerode is using the ssh2 node package which does not use .ssh/config. I would suggest filing this there because it would be a better solution for it to be implemented there (in ssh2).

@dbreshears dbreshears added this to the Future milestone Dec 6, 2019
@maxsatula
Copy link
Author

Nonetheless, I would appreciate a possibility to customize value of SSH_AUTH_SOCK.

Do you think it makes sense to implement this part here?

@lcxywfe
Copy link

lcxywfe commented Feb 23, 2020

Dockerode indeed does not respect it, unfortunately; Dockerode is using the ssh2 node package which does not use .ssh/config. I would suggest filing this there because it would be a better solution for it to be implemented there (in ssh2).

Sorry, so, does it support ssh with a jump host ?

@bwateratmsft
Copy link
Collaborator

@lcxywfe it may be possible to use a jump host but we have never tried it.

@lcxywfe
Copy link

lcxywfe commented Feb 24, 2020

@bwateratmsft I mean, could tell me how to modify the DOCKER_HOST (or another variable) to use a jump host.

@steverice
Copy link

steverice commented Apr 4, 2020

It seems like ssh2 already supports specifying an agent, there's just no way to specify ssh2 options in vscode-docker and have them provided to the ssh2 client.

docker-modem will pass the options it gets along to ssh2, and dockerode will pass along its options as well.

It seems like the missing link is just that vscode-docker doesn't provide any config when initializing Dockerode. If vscode-docker gave us a way to specify options for ssh2 that would be used here, we should be able to use ssh2 options like agent and agentForward.

(one way to specify those options might be to read them from .ssh/config, as ssh2 suggests)

@bwateratmsft
Copy link
Collaborator

bwateratmsft commented Apr 5, 2020

@steverice this is already possible, it's what the SSH_AUTH_SOCK environment variable is designed for. No need for config in-product to do the same thing (especially since it's a temporary socket on Mac and Linux that changes every reboot!)

@maxsatula
Copy link
Author

@bwateratmsft
Could you please point out how SSH_AUTH_SOCK variable should be initialized when vscode runs on Windows, and it's Linux counterpart starts automatically through Remote WSL plugin? I basically was unable to find a right spot to set it.

Secondly, it is not always true that socket changes at every reboot. If agent runs as ssh-agent -a <your_permanent_socket_path>, then one can rely on a permanent location. So it does make sense (at least for those people who run ssh agent like that) to have a persistent configuration of what SSH_AUTH_SOCK is.

@bwateratmsft
Copy link
Collaborator

On Windows, you need to set up OpenSSH (more info here). On Windows with OpenSSH as the SSH agent, it's always \\.\pipe\openssh-ssh-agent. You can use Pageant instead of OpenSSH, in which case you must set SSH_AUTH_SOCK to pageant.

Because the path is always predictable on Windows, if SSH_AUTH_SOCK is unset, we assume it is \\.\pipe\openssh-ssh-agent. That code is here.

For those that use the ssh-agent -a option--it's not any more difficult to use. You still do eval $(ssh-agent ...), which starts the agent and sets the environment variables. Also, on at least Ubuntu, it wasn't necessary to do anything with ssh-agent, because it's done automatically, including setting SSH_AUTH_SOCK. All that was needed was a one-time ssh-add <keyfile>.

In any case, I'd like to point out that using an ssh:// DOCKER_HOST or docker.host, while possible, is not the preferred way of using the extension with SSH. Using the Remote - SSH extension with the Docker extension in "workspace" mode and installed in the remote session is going to offer a better experience with less setup overhead. More info here.

@maxsatula
Copy link
Author

maxsatula commented Apr 6, 2020

You described the cases when vscode is used

  1. On Windows, no WSL
  2. On Linux natively

I was talking about WSL - Remote configuration, more info here and especially here,
where Windows part is just used for rendering, and WSL part does all the work. vscode runs some sort of server on WSL in background and talks to it, and I am not sure I can set any environment variables upon vscode server startup (not the Windows part which would be easy as you described, but it does just rendering). Neither it is a standalone Linux execution, which otherwise would also be easy to setup as you described.

Good point regarding Remote - SSH extension though

@bwateratmsft
Copy link
Collaborator

Just to make sure I understand your scenario correctly, are you using Remote - WSL to connect to WSL, but the Docker daemon is running somewhere else and you need to use SSH to get to it? Or is Docker also running in WSL?

@maxsatula
Copy link
Author

maxsatula commented Apr 6, 2020

Correct, docker is running elsewhere.

P.S. (offtopic) Docker cannot run on WSL locally, unless it is "WSL 2" which is not publicly available yet.

@bwateratmsft
Copy link
Collaborator

Gotcha. For WSL, at least the Ubuntu flavor, you can accomplish this by putting something like this into /home/username/.bashrc, probably toward the bottom:

if [ ! -e ~/mysock ]; then
  eval $(ssh-agent -s -a ~/mysock)
  ssh-add ~/id_rsa
else
  echo SSH agent already running
  export SSH_AUTH_SOCK=~/mysock
fi

What this does is, if the socket does not exist (first run of the session), it starts ssh-agent with the specified ~/mysock as the SSH_AUTH_SOCK and adds the keyfile; otherwise if it does exist it simply sets the variable.

That echo in the else block is optional but made it easier to tell what it was doing.

(P.S. I'm eagerly awaiting WSL2 myself. 😄 It's a huge improvement over the local VM that Windows does today, particularly in performance.)

@maxsatula
Copy link
Author

You gonna kill me now...
Sure, it occurred to me to set something in rc file, rather than opening an issue here, but it affects entire WSL environment, which is used for other stuff, thus is not considered a clean solution. Say, I have 4 agents for various cases (no kidding), and trying to avoid setting a "default" agent in .bashrc. Right now I went to the extension source code and hacked it by hardcoding my sock path in the javascript source, rather than messing with profile.

I am not sure if it worth to continue persuading that SSH_AUTH_SOCK option is needed or just give up and keep doing some workarounds.

@maxsatula
Copy link
Author

Also, I am not sure (hontstly, have not tested yet) whether VS Code Server runs any bash profile files upon startup. It is quite possible it may skip it overall

@bwateratmsft
Copy link
Collaborator

It did run .bashrc when I tried it, at least. I was able to get a Remote - WSL session with the Docker extension attached to an SSH Docker daemon, after killing the previously-started ssh-agent (from another terminal).

Still, I see your point about this not being clean, since it would affect the whole environment. I will keep this issue open for now. I imagine it's not a common case to mix three environments (the Windows host + WSL + remote SSH Docker daemon) but you aren't the first to try it, so we will keep it in mind. 😄

In the meantime, I did find this guide on how to make a script run specifically for the VSCode remote session, rather than for everything (i.e. in .bashrc), if that works it's probably better than .bashrc.

Strangely though, my experience of it running .bashrc when connecting contradicts this quote from that document:

When VS Code Remote is started in WSL, no shell startup scripts are run. This was done to avoid issues with startup scripts that are tuned for shells.

@maxsatula
Copy link
Author

~/.vscode-server/server-env-setup - that is probably the best solution, thank you for the link!

@lcxywfe
Copy link

lcxywfe commented Apr 9, 2020

@bwateratmsft Sorry, I am following the steps here, but when I wanted to "Open in Browser", I got "No valid ports were mapped from the container to the host." Do you know how to solve it?

@bwateratmsft
Copy link
Collaborator

Can you inspect the container and share the output?

@bwateratmsft
Copy link
Collaborator

Your container does not have any ports published. How did you start it? docker-compose up, docker run, a VSCode task, etc.?

@lcxywfe
Copy link

lcxywfe commented Apr 9, 2020

docker run

@bwateratmsft
Copy link
Collaborator

Can you share the full command line of your docker run command? Most likely you need to include the -P option, or otherwise manually specify port publishing with -p hostPort:containerPort.

@lcxywfe
Copy link

lcxywfe commented Apr 9, 2020

docker run -it --gpus all -v --privileged --cap-add=SYS_PTRACE --security-opt seccomp=unconfined xxx:xxx Let me try the -P

@lcxywfe
Copy link

lcxywfe commented Apr 9, 2020

I added -P, but it still told me No valid ports were mapped from the container to the host.

@lcxywfe
Copy link

lcxywfe commented Apr 9, 2020

-p works, but I misunderstood the Open in Browser, I just want to open a folder in the container. = =

@bwateratmsft
Copy link
Collaborator

Ah, gotcha. The Docker extension doesn't have a file browser for containers. The Remote - Containers can sorta do it, if you attach VSCode to the container, and do "Open Folder", you can see things.

Honestly the easiest way is to attach a shell to the container and use the command line to explore.

@lcxywfe
Copy link

lcxywfe commented Apr 9, 2020

Thanks, because my development environment is in a container : )

@bwateratmsft
Copy link
Collaborator

@steverice we've been looking at a way to do bring-your-own-Dockerode-settings to enable users to have complete control over what Dockerode does. I see that line you linked where the options are passed into ssh2, but it looks like based on this line, docker-modem does not pass all its input options into that function. So, in the current version of docker-modem, we still couldn't also fully control the options to ssh2. Additionally, since both docker-modem and ssh2 use the agent property but for different meanings, it could be difficult to control the SSH agent thing.

Is the need strong enough to make an issue/PR in docker-modem?

@steverice
Copy link

@bwateratmsft I'm not exactly sure 😁
What I'm trying to do is run a devcontainer using Docker on a remote host.

This seems to work okay after playing with some settings (and using docker context) except that the remote machine is lacking permissions to pull the docker images it needs from our internal ECR repo. I believe this works ordinarily from the CLI because of the following in my ~/.ssh/config (on macOS):

  ForwardAgent yes
  UseKeychain yes
  AddKeysToAgent yes

I came across this issue because it seems to deal with the docker-modem/dockerode settings issue… and I gathered from elsewhere that remote-container is using the code here in vscode-docker for communication. I'll try and hack an agentForward: true into the docker-modem code to see if it fixes my problem and report back.

(this is also why the line you linked wouldn't be an issue for me, as it only overrides the agent option)

@bwateratmsft
Copy link
Collaborator

It overrides the agent option but also it doesn't pass all of its options into ssh(); only the host/port/username/password/agent. So if you gave agentForward: true to Dockerode it still wouldn't be passed all the way to ssh2 :(

@karolz-ms
Copy link
Contributor

@steverice we've been looking at a way to do bring-your-own-Dockerode-settings to enable users to have complete control over what Dockerode does. I see that line you linked where the options are passed into ssh2, but it looks like based on this line, docker-modem does not pass all its input options into that function.

@bwateratmsft my understanding is Object.assign will only add to the target object, so whatever was passed in will be retained. Am I missing something?

@steverice
Copy link

@karolz-ms I think you're missing the same thing I did, which is that the options we care about are in the call to ssh() on that line and that line alone.
The Object.assign is being used for the http options which are used later.

I've opened apocas/docker-modem#118, let's see how that does.

@bwateratmsft
Copy link
Collaborator

bwateratmsft commented Apr 16, 2020

@bwateratmsft my understanding is Object.assign will only add to the target object, so whatever was passed in will be retained. Am I missing something?

That's correct, but the Object.assign is docker-modem setting its own options and overriding agent and protocol. It doesn't pass options into ssh(), so the settings from on high do not make it all the way to ssh2.

@karolz-ms
Copy link
Contributor

Roger, thanks guys

@bwateratmsft
Copy link
Collaborator

I've added a new setting, docker.dockerodeOptions, which will override everything else, and is passed unconditionally to the Dockerode constructor.

@bwateratmsft
Copy link
Collaborator

The fix is now available in version 1.2.0 of the Docker extension.

@vscodebot vscodebot bot locked and limited conversation to collaborators Jun 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants