Log into one password cli within python script run time

Doc5506
Doc5506
Community Member

Hello,

I have a python script where I would like to be prompted to log into one password and then have the rest of the script retrieve various login information that I have stored.

The script looks something like this:

`import os

os.system("eval $(op signin my_account)")
os.system("op get totp [item]")
more op get instructions`

--> results in a not logged in error

I have also tried:

`session_token = subprocess.check_output("op signin [my_account] --raw", shell=True, text=True)
two_factor = os.system("op get totp [my item] --session session_token")
print(two_factor)`

--> results in an invalid session key error

I know I am having a session error. The os.system command creates its own terminal session which is then closed after the command, which also logs me back out of onepassword.

Can you please give me any suggestions for how to log into one password within the runtime of my python script?

Thank you!

(I am on macOS Mojave, Python 3.8, op 0.9.3)


1Password Version: op 0.9.3
Extension Version: N/A
OS Version: OSX 10.14.6
Sync Type: N/A

Comments

  • SvenS1P
    edited April 2020

    Hey @Doc5506,

    It's good to hear that you're trying out our CLI tool! I haven't used Python in a while, so you'll have to bear with me if I make any Python mistakes here :sweat:

    The second example you provided looks like the correct approach to me. You'll need to make a few changes to get it to work though:

    • session_token should be moved outside of the string, using something like .format()
    • os.system() returns the status code rather than the output (this is the case on my Linux machine at least), so two_factor won't contain your one-time password. You can store the output of the op command using subprocess.check_output() again.

    So with those changes, you'll get something like this:

    session_token = subprocess.check_output("op signin [sign-in address] --raw", shell=True, text=True)
    two_factor = subprocess.check_output("op get totp [my item] --session {}".format(session_token), shell=True, text=True)
    print(two_factor)
    

    Let me know if that works for you, but if not I'll be happy to continue digging :smile:

    Edit: I said to use --output=raw instead of --raw and --session=[session token] instead of --session [session token] in a previous version of my post. That was for an older version of op, so I've edited this out of my post now. I also was using a slightly older version of python where text=True wasn't supported, but I've re-checked the docs and this is correct so I've modified my code to reflect this too.

  • Doc5506
    Doc5506
    Community Member
    edited April 2020

    Thank you for your reply! Unfortunately, I am still getting an error.

    import subprocess
    command1 = "op signin [my_account] --raw"
    session_token = subprocess.check_output(command1, shell=True, text=True).strip()
    
    print(f"session_token: {session_token}")
    
    two_factor = subprocess.check_output(f"op get totp secure.paycor.com --session={session_token}")
    print(two_factor)
    

    The first subprocess call returns a session token. I added the strip() when I realized that the session token had a newline character at the end (which strip() removes).

    Unfortunately, I think that the second subprocess call spawns a new subprocess in which the session token generated in the first subprocess is not longer valid and it errors out there.

    Thanks again for being willing to help me with this.

  • Ah, sorry that didn't fix it @Doc5506! The session token remains valid for 30 minutes, even if a new shell session is started.

    Do you get the same error as before? I tried out your code and I get this error:

    FileNotFoundError: [Errno 2] No such file or directory: 'op get totp Test --session [session key]'
    

    If you're getting a similar thing to me rather than the original one, then adding the shell=True option to your second subprocess.check_output() call should fix it. So something like this:

    import subprocess
    command1 = "op signin [my_account] --raw"
    session_token = subprocess.check_output(command1, shell=True, text=True).strip()
    
    print(f"session_token: {session_token}")
    
    two_factor = subprocess.check_output(f"op get totp secure.paycor.com --session {session_token}", shell=True, text=True).strip()
    print(two_factor)
    

    I also added text=True to return a string and .strip() at the end to remove the new line as you did in the first call. Also note that you can use --session with or without the =, it works with either one. When I was testing it out at first, I had an old version of op installed somewhere that was overriding the newest version — I've fixed it now! :+1:

  • Doc5506
    Doc5506
    Community Member

    That fixed it! Thank you so much for your help!!!

  • You're very welcome @Doc5506! Just as a small side-note, if you want to avoid using shell=True, and there may be good reasons to do so depending on what your code will be doing, you can run op instead by using a list of arguments:

    import subprocess
    command1 = ["op", "signin", "[my account]", "--raw"]
    session_token = subprocess.check_output(command1, text=True).strip()
    
    print(f"session_token: {session_token}")
    
    two_factor = subprocess.check_output(["op", "get", "totp", "secure.paycor.com", "--session", session_token], text=True).strip()
    print(two_factor)
    

    Note that I haven't used quotes around session_token when I use it in the second op command.

    Give us a shout if there's anything else we can help with! :smile:

  • Doc5506
    Doc5506
    Community Member

    Super helpful! Thanks for taking the extra time!!

  • No problem @Doc5506! :chuffed::+1:

    Stay safe,
    Matthew

This discussion has been closed.