Check if signed in with op
It would be handy if there was a way to check if a user was signed into an account without actually requiring them to sign in. op signin myproj
will always prompt for the password, even if there is an existing session in the shell.
1Password Version: Not Provided
Extension Version: Not Provided
OS Version: Not Provided
Sync Type: Not Provided
Comments
-
:+1:
My use case is that I'm making a script to generate some files that contain keys stored in 1Password. It would be great if I could check whether the use is already signed into our work subdomain before prompting them again.0 -
@danielcompton @CraigSiemens A fairly easy way would be to run
op get account
and check that the exit code is 0. We are considering adding something more specific for this use-case, though.0 -
How would I call the login from within a (Python) script and provide the password interactively?
signincheck = subprocess.Popen(['op', 'get', 'account', item_name], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if signincheck.returncode is None: signin = subprocess.Popen(['eval', '$(op', 'signin', '<subdomain>)]'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
0 -
@janedenone What does your script currently do? Since you are asking, I assume it does not work as you intend but it would knowing what currently happens.
0 -
@felix_1p There are two problems: signincheck.returncode always returns None (whether I am logged in or not), and the password dialog for the op signin action is never displayed. I also tried to provide the password via pexpect (unsuccessfully).
0 -
Thank you @janedenone ! I wouldn't be surprised if there is an issue related to how we write to and read from stdout/stdin. I will play around a bit with Python myself and report back with what I found out.
0 -
@janedenone I tested it myself and luckily it doesn't look like an issue with
op
itself. Here is what I came up with:import subprocess import os import sys ignore = open(os.devnull,"w") domain = '<domain>' envname = 'OP_SESSION_'+domain # Use existing environment variable if possible token = os.environ[envname] # Check if we are currently signed in signincheck = subprocess.call(['op', 'get', 'account', '--account='+domain], stdout=ignore, stderr=ignore) if signincheck == 1: signin = subprocess.Popen(['op', 'signin', domain, '--raw'], stdout=subprocess.PIPE) token = str(signin.communicate()[0], 'utf-8').strip() if signin.returncode != 0: print('unable to login') sys.exit(1) account = subprocess.Popen(['op', 'get', 'account', '--account='+domain], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env={envname: token}) print(account.communicate()[0])
signincheck.returncode always returns None
I believe that is because you didn't wait for the process to terminate (but I could be wrong). Adding
singincheck.wait()
or switching tosubprocess.call
as shown above works for me.the password dialog for the op signin action is never displayed
That's because you specified
stderr=subprocess.PIPE
. This causes Python to create a new file descriptor for stderr and makes it available viasignin.stderr
. If you want the process to use the same file/destination as the parent process, then just leave it unspecified.Now, as you can see, I'm not using
eval
in my example. By defaultop signin
returns something likeexport OP_SESSION_<domain>=....
which iseval
ed to set the environment variable. Setting the environment variable this way only affects other subprocesses of that process though. But that process terminates immediately after that.In order to make other processes started via
subprocess
"see" the environment variable, you have to explicitly set it. This is where--raw
comes in. It allows us to get the raw session token on stdout. We then store it in a variable and set the proper env variable in the next call.I also needed to specify
--account=....
explicitly otherwise the next command wouldn't consider the environment variable for whatever reason.The
ignore
file descriptor just redirects output I'm not interested in to/dev/null
. Alternatively just specifyingsubprocess.PIPE
would works as well, but I thought it would express the intent better.This is of course only one way to do it. I don't know how you plan to use
op
through Python, this is just what I came up with. There might also be better ways to call commands and use their output, my Python is a bit rusty.Please let me know if you have any questions about this!
0 -
Thanks, Felix (both for the code and the explanation). Unfortunately, I get an KeyError message regarding os.environ[envname], stating that there is no key OP_SESSION_. I tried specifying the subdomain via the domain variable both in caps and and in lower case letters.
0 -
That's one of the cases where my Python knowledge is rusty. You will have to check first whether the key exists (
if key in os.environ
maybe)? It worked for me because that environment variable existed.0