Python script for retrieving un, pw and/or totp from op cli

Doc5506
Doc5506
Community Member
edited April 2020 in CLI

Made this script for myself. I am doing some browser automation to retrieve my account information and statements periodically using python3 and selenium. I did not want to embed my log in credentials in my script and therefore created this script. The script prompts me to log into one password, but then retrieves my website login credentials by interfacing with the op cli. The script can be run independently as its own mini cli or embedded into other python scripts directly or as a module.

I am still learning to program so would welcome any feedback if deficiencies are found, but generally just wanted to share. Thanks to @Matthew_1P who helped me out when I was stuck.

#!/usr/bin/env python3

import subprocess
import sys
import json


def get_un_and_pw(op_item, session_token):
    """
    1. run shell command to get json data from op cli
    2. convert json to python dictionary
    3. dict['details']['fields'] has a list of dictionaries with un and pw
    4. extract username(un) and password(pw)

dict['details']['fields']

    [{'designation': 'password', 'name': 'password', 'type': 'P', 'value': 'this_is_a_fake_password'},  {'designation': 'username', 'name': 'username', 'type': 'T', 'value': 'fake_username'}]
    """
    # get json data of op_item
    shell_command = ["op", "get", "item", op_item, "--session", session_token]
    json_data = subprocess.check_output(shell_command)

    # convert json_data into python dict
    op_dict = json.loads(json_data)

    # extract un and pw
    for dict_item in op_dict["details"]["fields"]:  # looping over list of dictionaries
        try:
            if dict_item["designation"] == "password":
                pw = dict_item["value"]
        except KeyError:
            pass
        try:
            if dict_item["designation"] == "username":
                un = dict_item["value"]
        except KeyError:
            pass
    return un, pw


def get_pw_only(op_item, session_token):
    shell_command = ["op", "get", "item", op_item, "--session", session_token]
    json_data = subprocess.check_output(shell_command)
    op_dict = json.loads(json_data)
    for dict_item in op_dict["details"]["fields"]:  # looping over list of dictionaries
        try:
            if dict_item["designation"] == "password":
                pw = dict_item["value"]
        except KeyError:
            pass
    return pw


def get_totp(op_item, session_token):
    """
    Return time based one time password (totp) for op item
    """
    try:
        shell_command = ["op", "get", "totp", op_item, "--session", session_token]
        return subprocess.check_output(shell_command, text=True).strip()
    except Exception:
        return None


def main(op_item, session_token=None):
    """
    Input: name of one password item (op_item)
    Output: return username, password, TOTP.  TOTP will return None if absent
    """
    un, pw = get_un_and_pw(op_item, session_token)
    totp = get_totp(op_item, session_token)
    return un, pw, totp


if __name__ == "__main__":
    # code below if used as a command line program

    # log into op and get session token
    # can also use this as a module and embed next two lines of code in other programs making a call to this one to get session_token
    session_token_command = ["op", "signin", "your_account_name", "--raw"]
    session_token = subprocess.check_output(session_token_command, text=True).strip()

    # get credentials
    un, pw, totp = main(sys.argv[1], session_token)

    # display retrieved credentials
    print(f"Login item: {sys.argv[1]}")
    print(f"Username: {un}")
    print(f"Password: {pw}")
    print(f"TOTP: {totp}")

1Password Version: Not Provided
Extension Version: Not Provided
OS Version: Not Provided
Sync Type: Not Provided

Comments

  • SvenS1P
    edited April 2020

    Hey @Doc5506, glad I could help you out! That sounds like a great use-case of the CLI tool. Is it bank/financial statements that you're downloading? If so, I hadn't thought of doing that before — I may have to give Selenium or something similar a try, it would be excellent if I could automate more of my finances. :chuffed::+1:

  • Doc5506
    Doc5506
    Community Member

    Yes @Matthew_1P . I have 3 op cli + python + selenium use cases so far:

    1. Log into financial websites and download statements
    2. Log into my payroll company website (I own a small business) --> download employee pay stubs -->automatically email to each employee
    3. Download billpay statements (or scan and OCR paper statements) from vendors --> parse amount due for each payee with regex--> temporarily store multiple (payee, amount) entries in csv file --> log into bank website and automatically enter all csv values into online bill pay to pay automatically.

    I have been meaning to automate this stuff for a while, but the extended time off due to the coronavirus has given me the time to figure out the areas where I was getting stuck. ...just trying to be as productive as I can with the downtime! Hopefully, we can develop treatments or a vaccine as soon as possible so we can all get back to a "new normal".

    Also @Matthew_1P : If you want to learn selenium for python the best tutorial I have been able to find is a Udemy course called "Elegant Browser Automation" by Brandon Blair. It is not free but you can usually buy it for $10-15 during one of Udemy's frequent sales. (I have no financial interest)

    Thanks again for your help! Hopefully my post will help some other python user wanting some starter code to combine python and the op cli tool!

  • felix_1p
    felix_1p
    1Password Alumni

    I think I have to look into automating getting bank statements with selenium as well :smile: That's a neat idea!

    Thank you for posting the script. Not only will it be useful for others, but it also helps us to see how people are using the command line tool and what we can do to make it easier to use.

This discussion has been closed.