I would like to mount the ssh-agent socket from the LXD host to the LXD container. It’s basically the equivalent of doing docker run --volume $SSH_AUTH_SOCK:/ssh-agent in Docker.
From this Topic 2579 I have learned that there is a proxy device now.
Based on this, I have tried the following but did not manage to get it work.
c1:~# ssh-add -L
Error connecting to agent: No such file or directory
Printed proxy.ssh-agent.log
$ cat /var/snap/lxd/common/lxd/logs/c1/proxy.ssh-agent.log
Created anonymous pair {5,6} of unix sockets
Added listener socket file descriptor 5 to epoll instance
Starting unix ↔ unix proxy
Error: Failed to connect to target: dial unix /run/user/1000/keyring/ssh: connect: no such file or directory
Failed to prepare new listener instance: dial unix /run/user/1000/keyring/ssh: connect: no such file or directoryStarting unix ↔ unix proxy
BTW, the users on the host as well as in the container have the UId 1000. The ssh-agent socket file does exist on the LXD host and has following permission.
This is running on my laptop and the /run/user/1000/keyring/ssh path is valid and it works fine when I run ssh-add -L on my laptop. Furthermore, I can use this path to mount it to a Docker container and ssh-add -L works as expected from within the Docker container.
> # => Back to the laptop and attach the device
$ lxc config device add c1 ssh-agent proxy \
connect=unix:/tmp/ssh-sx30Ld1L68wV/agent.26453 \
listen=unix:/tmp/ssh-sx30Ld1L68wV/agent.26453 \
bind=container \
uid=1000 \
gid=1000 \
mode=0660 \
security.uid=65534 \
security.gid=1000
> # Get the log
$ sudo cat /var/snap/lxd/common/lxd/logs/c1/proxy.ssh-agent.log
Created anonymous pair {5,6} of unix sockets
Added listener socket file descriptor 5 to epoll instance
# => So far it seems to work as there are no errors
> # => Back to the container c1
c1 $ ssh-add -L
error fetching identities: communication with agent failed
> # Get the log a second time
$ sudo cat /var/snap/lxd/common/lxd/logs/c1/proxy.ssh-agent.log
Created anonymous pair {5,6} of unix sockets
Added listener socket file descriptor 5 to epoll instance
Starting unix <-> unix proxy
Error: Failed to connect to target: dial unix /tmp/ssh-sx30Ld1L68wV/agent.26453: connect: no such file or directory
Failed to prepare new listener instance: dial unix /tmp/ssh-sx30Ld1L68wV/agent.26453: connect: no such file or directory
I have verified that the /tmp/ssh-sx30Ld1L68wV/agent.26453 file exists on both the host and the container and has the correct owner and file permissions. Both users have the UId of 1000 as well as the GId of 1000.
Okay, so the important message is this one in the proxy.ssh-agent.log log files.
connect: no such file or directory means that in the context of LXD, there is no ‘/run/user/1000/keyring/ssh’ file.
To verify, I used ssh-agent with the -a parameter (specify yourself the socket location), and tried
eval `ssh-agent -a /home/myusername/agent`
Then, I followed the rest of the steps and it worked.
Now, the issue is, what’s wrong with /tmp/ and /run/?
It is likely that the snap package confinement does not allow access to forkproxy to arbitrary directories.
I am using LXD installed by Snap and have not tested it with LXD installed by the Apt package. It’s useful to know that it works when the socket lives in /home/<username>/ directory. Based on your feedback I got it to work too.
Below is the sequence of steps in case it helps someone else.
This is a workaround I can live with, at least when it comes to ssh-agent forwarding. However in other use cases, such as forwarding the /var/run/docker.sock or /run/docker.sock file, this will not be an option. Unless I start Docker on the LXD host and explicitly tell it to write the Docker socket file to somewhere at /home/<username>/.
This looks like a bug to me. What do you think? Would you like me to create an issue on Github?
The LXD snap uses strict confinement (see the output of snap info lxd which does not make reference to classic).
However, there is a special interface called lxd-support that was created specially for LXD so that it can do many stuff even with the strict confinement (see the output of snap interfaces lxd).
I am not very familiar with what you get with the lxd-support interface or whether it can be adapted to help here.
Therefore, file a bug report on github (and post the link here).
As a title, use something like Strict confinement in LXD snap does not allow to proxy some sockets.
There is a fix on this that is scheduled to appear in LXD 3.5,
From what it looks, the issue is with LXD only and does not require changes in the lxd-support interface of the snap packages.
Currently, the LXD snap package in the edge channel is still at commit git-7a22ab3 (see the output of snap info lxd). That commit is from two days ago (https://github.com/stgraber/lxd/commits/import) while the fix for this bug is from one day ago. Therefore, there is an extra day of way if you want to test/verify this fix by switching to the edge channel.
Thanks @stgraber and @simos for the great help and the swift fix.
With this fix in place, I could successfully make the proxy device work with ssh-agent, gpg-agent, docker and lxd.
Below are the socket locations on the host that worked.
ssh-agent:
/run/user/1000/keyring/ssh
gpg-agent:
/run/user/1000/gnupg/S.gpg-agent
lxd:
/var/snap/lxd/common/lxd/unix.socket
docker:
/run/docker.sock
However, if I use the /var/run/docker.sock path for Docker, it does not work and I get the below error in the log.
sudo cat /var/snap/lxd/common/lxd/logs/c1/proxy.docker.log
Error: Failed to connect to target: dial unix /var/lib/snapd/hostfs/var/run/docker.sock: connect: no such file or directory
Failed to prepare new listener instance: dial unix /var/lib/snapd/hostfs/var/run/docker.sock: connect: no such file or directoryError: Failed to connect to target: dial unix /var/lib/snapd/hostfs/var/run/docker.sock: connect: no such file or directory
Failed to prepare new listener instance: dial unix /var/lib/snapd/hostfs/var/run/docker.sock: connect: no such file or directory
Hmm, so I think that the fact that /var/run is a symlink to /run is effectively working around the code we have for snap path resolution. It may be something we can fix by forcing an earlier symlink resolution, but in general I’d recommend staying away from symlinks.