pythoncommand-line-interface1password

Extracting credentials from 1Password using onepassword python library


I am using this python library ("OnePassword python client") in which to interact with my 1Password instance and extract API credentials from a vault named "Employee".

Python Function:

def authenticate(base_endpoint, api_key, api_secret):
    op = OnePassword()
    available_vaults = op.list_vaults()
    employee_vault = next((vault for vault in available_vaults if vault["name"] == "Employee"), None)
    if not employee_vault:
        print("No Employee vault found")
    items = op.list_items(vault=employee_vault["id"])
    addepar_item = next((item for item in items if item["title"] == "Addepar API"), None)
    if not addepar_item:
        print("Please check that Addepar API item exists in 1Password")
    item_details = op.get_item(uuid=addepar_item["id"], fields=["username", "credential"])
    if not item_details:
        print("Please check that Addepar API item credentials exists in 1Password")
    api_key = item_details["username"]
    api_secret = item_details["credential"]
    base_endpoint = "https://myfirm.addepar.com/api/v1/"

This function works flawlessly on a Mac, however, PC users are getting the following error:

PC User error:

C:\Users\User\PyCharmMiscProject\.venv\Scripts\python.exe C:\Users\User\PyCharmMiscProject\Main.py 

⚠ Please enter an Entity ID: 123

Traceback (most recent call last):

  File "C:\Users\User\PyCharmMiscProject\Main.py", line 180, in <module>

    entity_attributes = get_entity_attributes(entity_id)

  File "C:\Users\User\PyCharmMiscProject\Main.py", line 32, in get_entity_attributes

    base_endpoint, api_key, api_secret = authenticate(base_endpoint="", api_key="", api_secret="")

                                         ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  File "C:\Users\User\PyCharmMiscProject\Main.py", line 11, in authenticate

    op = OnePassword()

  File "C:\Users\User\PyCharmMiscProject\.venv\Lib\site-packages\onepassword.py", line 52, in __init__

    raise MissingCredentials()

onepassword.MissingCredentials
 
Process finished with exit code 1

My Thoughts: I was able to trace the error back to the onepassword library, specifically, the following file. I think this has something to do with bin_path, however, as Mac user, I am having challenges working out what is going on:

class OnePassword(object):

    def __init__(self, secret=None, token=None, shorthand=None, bin_path=""):
        self.op = os.path.join(bin_path, "op")
        if secret is not None:
            self.shorthand = str(uuid4())
            self.session_token = self.get_access_token(secret, shorthand=self.shorthand)
        elif token is not None and shorthand is not None:
            self.shorthand = shorthand
            self.session_token = token
        else:
            raise MissingCredentials()

I would appreciate any guidance on what might not be configured correctly that might be causing this issue.


Solution

  • The Wandera/1password-client [GIT] [PyPI] library simply does not support Windows.


    From the Operating systems part of the README (as of Jan 2025):

    The library is split into two parts: installation and client in which we are slowly updating to cover as many operating systems as possible the following table should ensure users understand what this library can and can't do at time of install.

    MacOS Linux
    Fully supported Y Y
    ...

    (Note: Redacted irrelevant rows from the table)

    Besides 'Add Windows functionality' still being the first item on the roadmap;

    There is still an open issue #10 talking about Windows support, but the last reply from 2023 only talks about the 'windows' branch which hasn't seen a commit in the last 2 years.


    As an alternative, looking at the official 1Password SDK page, there is an official Python SDK with support for MacOS, Linux and Windows.

    Example provided by 1Password/onepassword-sdk-python/

    import asyncio
    import os
    from onepassword.client import Client
    
    async def main():
        # Gets your service account token from the OP_SERVICE_ACCOUNT_TOKEN environment variable.
        token = os.getenv("OP_SERVICE_ACCOUNT_TOKEN")
    
        # Connects to 1Password. Fill in your own integration name and version.
        client = await Client.authenticate(auth=token, integration_name="My 1Password Integration", integration_version="v1.0.0")
    
        # Retrieves a secret from 1Password. Takes a secret reference as input and returns the secret to which it points.
        value = await client.secrets.resolve("op://vault/item/field")
        # use value here
    
    if __name__ == '__main__':
        asyncio.run(main())