op signin
Work?(filed in terminal
/ 1pass
)
If you try to sign into your 1password.com
teams account with their op
command-line utility, you may find it a little reluctant to oblige:
→ op signin
[ERROR] 2022/04/09 15:01:52 Output of 'op signin' is meant to be
executed by your terminal. Please run 'eval $(op signin)'. You can
use the '-f' flag to override this warning.
While you can use -f
(as the error hints), you may wonder how it is that op signin
knows that you haven't run it in an evaluating subshell. If I had to hazard a guess, it's looking at something like isatty(3)
, a POSIX-mandated function that checks if a given file descriptor is a terminal (or teletype) devices. If you you call isatty(0)
, you can tell if the input channel (stdin
) is attached to an interactive terminal.
In bash, you can use the test -t
(or [ -t
) predicate to determine if a file descriptor (by number) is hooked up to a tty device:
#!/bin/sh
if test -t 0; then
echo "Hello, Interactive User!"
else
echo "Hello, Batch User!"
fi
0
is the numeric index of the first open file descriptor for a process; by POSIX semantics, the first three of these are (in order): standard input, standard output, and standard error.
This test -t
approach is easily fooled however; consider these two shell sessions:
$ ./is-a-tty
Hello, Interactive User!
$ echo 'something' | ./is-a-tty
Hello, Batch User!
In the second invocation, echoing something into the process causes that process' standard input to be reopened to the output of the echo
command (its standard output). At that point, it ceases to be a terminal device and we follow the else branch.
With this knowledge, we can now workaround op signin
's little trick:
$ op signin | cat
export OP_SESSION_ABCDEFGHIJKLMNOPQRSTUVWXYZ="... secret redacted ..."
# This command is meant to be used with your shell's eval function.
# Run 'eval $(op signin account)' to sign in to your 1Password account.
# Use the --raw flag to only output the session token.
(The cat
UNIX utility, when called with no arguments, prints its standard input to its standard output. It's a bit of an I/O no-op. Crucially, it robs op signin
of its tty output device, sidestepping the issue we first ran into)