Here’s a guide to forwarding GPG over SSH.
This is helpful to not only assist with remote GPG operations, but will also work to
forward SSH credentials which were loaded via gpg-agent
.
Prerequisites
With modern versions of GPG (eg GnuPG 2.1), the gpg-agent
will automatically create sockets in $HOME/.gnupg
:
$ ls -l $HOME/.gnupg/S.gpg-agent*
srwx------ 1 jburke staff 0 Dec 17 10:22 /Users/jburke/.gnupg/S.gpg-agent=
srwx------ 1 jburke staff 0 Dec 17 10:22 /Users/jburke/.gnupg/S.gpg-agent.browser=
srwx------ 1 jburke staff 0 Dec 17 10:22 /Users/jburke/.gnupg/S.gpg-agent.extra=
srwx------ 1 jburke staff 0 Dec 17 10:22 /Users/jburke/.gnupg/S.gpg-agent.ssh=
Access to these sockets provides access to the gpg-agent
. If you’ve unlocked your PGP key or SSH key,
they will be accessible via the sockets.
The S.gpg-agent.extra
socket is a bit special in that it provides access to the PGP key, but restricts
which commands can be used. See the documentation for
--extra-socket
for more information.
To enable the extra-socket
, add something like the following to your .gnupg/gpg.conf
:
extra-socket /Users/jburke/.gnupg/S.gpg-agent.extra
Setup SSH config
Now we’ll configure SSH to forward the (restricted) PGP key socket and SSH agent forwarding:
Add to .ssh/config
:
Host remote.com
RemoteForward /home/jburke/.gnupg/S.gpg-agent /Users/jburke/.gnupg/S.gpg-agent.extra
RemoteForward /home/jburke/.gnupg/S.gpg-agent.ssh /Users/jburke/.gnupg/S.gpg-agent.ssh
Note that the format of RemoteForward
is RemoteForward <remote target> <local target>
.
On the remote host, test that it’s working by gpg2 --card-status
.
If only forwarding the “extra” socket, you’ll receive these errors:
$ gpg2 --card-status
gpg: error getting version from 'scdaemon': Forbidden
gpg: selecting openpgp failed: Forbidden
gpg: OpenPGP card not available: Forbidden
Those errors about “Forbidden” are expected since we’re only forwarding the
S.gpg-agent.extra
socket which has reduced privileges.
Debugging
If the desintation host already has gpg-agent
running, it may have setup its own sockets. The quickest way to
reset the world is:
On remote host, make sure to killall gpg-agent
.
Also: rm ~/.gnupg/S.*
.
Then ssh to remote. Verify with gpg2 --card-status
.
Needing to reset the remote environment by killing the gpg-agent
and manually
removing the sockets is not a satisfying workflow. Will need to figure out a method to
automate.
References
Excellent writeup from GnuPG here. Discusses alternatives if using an older version of GPG.