/blog/

2024 0605 Use the 1Password SSH agent conditionally

I have been using the 1Password SSH Agent feature on my Mac, which is a pretty nice SSH agent implementation.

I use the IdentityAgent in ~/.ssh/config, which looks something like this:

Host *
    HashKnownHosts yes
    IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

This works great when I’m sitting at my Mac. When I invoke ssh for the first time in a while, it pops up a prompt to unlock 1Password with TouchID. A pretty good security/convenience tradeoff.

However, if I am ever somewhere else and want to SSH into my Mac from somewhere else, and then ssh back out, it causes a problem. It will still pop up a prompt on the Mac to unlock 1Password, with no way to authenticate unless I walk over to it.

The solution

To fix this, create a script ~/.ssh/test_ssh_tty.sh:

#!/bin/sh
set -eu
test -z "$SSH_TTY"

Make the script executable with chmod 700 ~/.ssh/test_ssh_tty.sh.

And modify ~/.ssh/config to look something like this:

Host *
    HashKnownHosts yes
    # If we are not logged in over SSH use the 1password agent.
    # The test script should just be 'set -e; test $SSH_TTY'
    # ... it would be nice to inline it here but I can't seem to make ssh_config syntax bend to my will
    Match exec ~/.ssh/test_ssh_tty.sh
        IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock"

The explanation

ssh supports Match statements, which let you apply some limited conditions:

Restricts the following declarations (up to the next Host or Match keyword) to be used only when the conditions following the Match keyword are satisfied.

Furthermore, ssh connects to a remote host, it sets the SSH_TTY environment variable. So by testing for the presence of that variable we can know whether the current session is an ssh session or a local one.

As I note in the comment in ~/.ssh/config, it would be nice if I could inline the test so I don’t need a separate script. I couldn’t get this to work with the Match rule’s quoting requirements, though. If you know how to do it, let me know.

Bonus recommendation 1: agent forwarding

This still presents a problem, though: I need to enter passwords for all ssh connections used without the 1Password Agent.

Instead, I use SSH agent forarding. This lets any agent running on my local system be used from the remote system. If I have an SSH agent running on whatever system I’m using to connect into the Mac can provide keys for connections out from the Mac as well.

A word of caution from the manual page:

Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the agent’s UNIX-domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent.

This is OK with me though, since the Mac is my personal system, and any attacker who was already on my primary system could do much worse.

Blink Shell is an excellent iOS terminal appliation and ssh client. It’s very thoughtfully designed, more than just a VT100 emulator and a soft keyboard. And relevant to this post, it supports agent forwarding, which is not universal among iOS ssh clients.

Responses

Webmentions

Hosted on remote sites, and collected here via Webmention.io (thanks!).

Comments

Comments are hosted on this site and powered by Remark42 (thanks!).