Forward gpg-agent to container

Phil Pennock gnupg-users at spodhuis.org
Tue Jun 5 23:17:10 CEST 2018


On 2018-06-05 at 20:18 +0200, Peter Lebbing wrote:
> Have you tried by hand whether the concept of communicating over a
> socket to a container works at all? You could use socat to create a
> socket and communicate, one socat on your host system and one inside the
> container.
> 
> I have no experience with it, but it wouldn't surprise me at all if you
> can't cross the container boundary given how local UNIX stream sockets
> are. Then again, maybe I'm dead wrong.

Bind volume mounts work on sockets, you just bind-mount the socket into
the container.  This is how you can have a Docker client inside a Docker
container control the parent Docker setup.  The issue to beware of is
uids and the uid inside vs outside.

$ docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock alpine
/ # apk update && apk add --no-cache docker
[...]
/ # docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
86775493ab23        alpine              "/bin/sh"           50 seconds ago      Up 49 seconds                           boring_heyrovsky

That worked because "root inside container"; I've custom images which
are just careful with group permissions and can do the same thing when
non-root inside the container, which is "unprivileged but with access to
one socket".

It should be easy enough to manage the same thing with GnuPG assuming
that you're running Linux and so the Docker is local.  When Docker is
remote and you need to also get the socket available on that machine,
it's a little more involved.

For me, where I run macOS and use docker-machine, debugging this to
write this email was ... educational.

To forward:
 * Use `gpgconf --list-dir agent-ssh-socket` inside a container to see
   where the socket needs to end up for the build of GnuPG used by the
   OS userland inside that container.  This will vary by OS.  I'm using
   alpine below.
 * The biggest stumbling block is that OpenSSH daemon side doesn't
   unlink an existing socket by default, so you'll need to modify
   sshd_config inside the boot2docker environment first.
 * You'll need to be using a graphical pinentry program, for hopefully
   obvious reasons.  `brew install pinentry-mac`.


Prep:
$ docker-machine ssh default
$ vi /mnt/sda1/var/lib/boot2docker/ssh/sshd_config
	add: StreamLocalBindUnlink yes
$ kill -1 $(cat /var/run/sshd.pid )

Shell 1:
$ docker-machine ssh default -R /var/run/pdp.gnupg:$HOME/.gnupg/S.gpg-agent.extra
[ leave this window open, this is your login on the VM; when this
  closes, you stop forwarding GnuPG's socket ]

Shell 2:
$ docker run -it --rm -v /var/run/pdp.gnupg:/root/.gnupg/S.gpg-agent.ssh alpine
/ # chmod 0700 /root/.gnupg && chown root:root /root/.gnupg/S.gpg-agent
/ # apk update && apk add --no-cache gnupg

Shell 3:
$ docker ps
$ docker cp something-encrypted.asc thirsty_shaw:/tmp/foo.asc

Shell 2 (docker container):
/ # gpg --list-packets </tmp/foo.asc
/ # gpg --keyserver sks.spodhuis.org --recv-key 6DBEBBD40EA3493C
/ # gpg -d /tmp/foo.asc

The biggest frustration in all of this, leading to many red herring
investigations, was that OpenSSH defaults to not unlinking the socket,
and does so pretty silently, so you end up with a normally-stale socket
which can't be connected to, inside the VM but before Docker even comes
into play.  On the bright side, I now know how to install socat inside
boot2docker.

-Phil
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 996 bytes
Desc: Digital signature
URL: <https://lists.gnupg.org/pipermail/gnupg-users/attachments/20180605/e9183129/attachment.sig>


More information about the Gnupg-users mailing list