1Password has an excellent solution for managing SSH keys securely using their 1Password SSH Agent. However I interact with a few devices that either require keyboard-interactive multi-factor authentication (MFA) or force the use of a password instead of accepting keys or certificates.
Thankfully, through the use of the
1Password CLI,
the SSH_ASKPASS
environment variable, and a little shell script, we can use
1Password to fill in these MFA tokens and passwords too.
The script, op_ssh_askpass further below, is expected to be used as follows:
# MFA example:
$ op_ssh_askpass 'op://Private/secsvr/one time password?attribute=otp' -- secsvr
# Password example:
$ op_ssh_askpass 'op://Private/legacy server/password' -- root@legacysvr
The way the script works is to detect if it is being invoked directly or by the SSH client.
If invoked directly, it sets up the necessary environment variables to tell SSH to invoke the same script whenever SSH is prompting for a password (or MFA token) and then invokes the SSH client with the provided arguments.
If invoked by SSH, the script simply reads the secret from 1Password, triggering a biometric input from me if needed, and outputs the secret to stdout, as SSH expects in this context, automating the credential input.
Here is the complete op_ssh_askpass script:
#!/bin/bash
main () {
if [ -n "$OP_SSH_ASKPASS_SECRETREF" ]; then
op read "${OP_SSH_ASKPASS_SECRETREF}"
return $?
fi
if [ -z "$1" ]; then
printf 'Usage: %s op://<vault>/<item>/<field> -- <ssh args...>\n' "$0"
return 1
fi
local _script_dir=$(cd "$(dirname "$0")" && pwd)
SSH_ASKPASS="${_script_dir}/$(basename "$0")"
SSH_ASKPASS_REQUIRE=force
OP_SSH_ASKPASS_SECRETREF="$1"
shift
export OP_SSH_ASKPASS_SECRETREF SSH_ASKPASS SSH_ASKPASS_REQUIRE
if [ "$1" = "--" ]; then
shift
fi
ssh "$@"
return $?
}
main "$@"
My primary desktop OS is Windows 11 with WSL2, there may be other solutions more appropriate to other environments.
Naturally, these commands can be aliased or wrapped in a function for convenience, and I have done in my own environment.
The script could also be extended to support additional features, such as handling a server that has both a password prompt and an MFA prompt, or fetching additional SSH args from other fields in a 1Password item.