I’ve been seeking for GPG solutions over server side VS client side for a while. It’s so hard to
leverage multiple gpg session at the same especially over ssh.
Fortunately, I realized there is a built-in feature call GPG forwarding that allows you to authorize
the server side request in the client side.
The idea is to forward your client sidse GPG socket to your server side, so that every time you
trigger a GPG authentication in server side, it can pop the GPG authentication GUI (pinentry
program) in your local machine.
Generate ssh config with gpg forwarding enabled using the following command. This will append a
config to your ~/.ssh/config.
generate-ssh-gpg-config kuro 10.0.0.3 ztlevi
You can either add StreamLocalBindUnlink yes to your /etc/ssh/sshd_config and restart your
sshd service. Or use ssh-with-gpg-socket-deleted kuro 10.0.0.3 ztlevi to kill remote gpg-agent
and then create a ssh session with local gpg forwarded.
function test-ssh-connection() { server=$1# server IP port=22 # port connect_timeout=5 # Connection timeout
timeout$connect_timeout bash -c "</dev/tcp/$server/$port" if [[ $? -eq 0 ]]; then echo"SSH Connection to $server over port $port is possible" return 0 else echo"SSH connection to $server over port $port is not possible" return 1 fi }
function generate-ssh-gpg-config() { # Test the ssh connection before you gneretae the ssh config that enables gpg forwarding # Args: # connection_name: e.g. kuro # hostname: e.g. 10.0.0.3 # user: e.g. ztlevi # # Usage: generate-ssh-gpg-config kuro 10.0.0.3 ztlevi echo"Generating ssh config that enables gpg forwarding...\n"
if [[ ${#@} -ne 3 ]]; then echo"generate-ssh-gpg-config has wrong input arguments! Your inputs: \`${@}\`" echo"Usage: generate-ssh-gpg-config kuro 10.0.0.3 ztlevi" fi
local connection_name=$1 local hostname=$2 local user=$3 test-ssh-connection $hostname || return 1 # Mapping the remote socket to local's extra socket local local_extra_socket=$(gpgconf --list-dir agent-extra-socket) local remote_socket=$(ssh "$user@$hostname""gpgconf --list-dir agent-socket")
function ssh-with-gpg-socket-deleted() { # You can either add `StreamLocalBindUnlink yes` to your /etc/ssh/sshd_config # Or, delete the remote gpg socket file before ssh. # Typically, kill gpg-agent will delete the socket files # # Args: # connection_name: e.g. kuro # hostname: e.g. 10.0.0.3 # user: e.g. ztlevi # # Usage: ssh-with-gpg-socket-deleted kuro 10.0.0.3 ztlevi
# Start gpg-agent locally if not running if ! pgrep -x "gpg-agent" >/dev/null; then gpg-agent --homedir $HOME/.gnupg --use-standard-socket --daemon fi
local connection_name=$1 local hostname=$2 local user=$3 ssh "${user}@${hostname}"'gpgconf --kill gpg-agent; rm -f $(gpgconf --list-dir agent-socket)' ssh "${connection_name}" }