Skip to main content

A python API to query a 1Password account using the 'op' command-line tool

Project description

PYONEPASSWORD

Description

A Python API to sign into and query a 1Password account using the op command.

Requirements

  • Python >= 3.8
  • 1Password command-line tool >= 2.0.0
  • Internet connectivity to 1Password.com
    • The op command queries your online account, not your local vault

Note: This version of pyonepassword does not support deprecated op 1.x versions. Support for those versions is still available, albeit with minimal maintanence. See pyonepassword-legacy for more information.

Installation

python3 -m pip install pyonepassword

Overview

pyonepassword essentially has two parts:

  1. Convenience Python classes for the various objects that the op command returns
  2. A full-fledged API for querying a 1Password account

If you already have a workflow to drive the op command, handle authentication, and so forth, but would benefit from an API that can ingest op's JSON and give you Python objects, you're in luck, number one might be just what you need.

On the other hand, if you're using op manually (maybe along side jq), or in shell scripts (or maybe not at all), and you'd like a full-service Python API rather than console commands, number two does that.

We'll get into some examples below for both of these.

Example Usage

Object API

pyonepassword provides Python classes for many of the objects op returns, including:

  • Several "item" types (login, password, secure note, etc)
  • User
  • User List (e.g., from 'op user list')
  • Group
  • Group List
  • Vault
  • Vault List
  • Account
  • Account List

All of these classes provide assorted convenience properties. For example obj.created_at returns a proper Python datetime object.

All of the object types are fundamentally dictionaries, so their data can be accessed as such, and they can be serialized back to JSON.

Also, all classes can be instantiated from either directly from a JSON string, or from an unserialized object.

Take the following Login item as an example:

{
  "id": "4smjvvepfbg3hencrmo7cozphe",
  "title": "Example Login",
  "version": 2,
  "vault": {
    "id": "yhdg6ovhkjcfhn3u25cp2bnl6e"
  },
  "category": "LOGIN",
  "last_edited_by": "RAXCWKNRRNGL7I3KSZOH5ERLHI",
  "created_at": "2021-06-29T18:42:03Z",
  "updated_at": "2022-03-17T03:40:49Z",
  "sections": [
    {
      "id": "linked items",
      "label": "Related Items"
    }
  ],
  "fields": [
    {
      "id": "password",
      "type": "CONCEALED",
      "purpose": "PASSWORD",
      "label": "password",
      "value": "doth-parrot-hid-tussock-veldt",
      "password_details": {
        "strength": "FANTASTIC"
      }
    },
    {
      "id": "username",
      "type": "STRING",
      "purpose": "USERNAME",
      "label": "username",
      "value": "zcutlip"
    },
    {
      "id": "notesPlain",
      "type": "STRING",
      "purpose": "NOTES",
      "label": "notesPlain"
    }
  ],
  "urls": [
    {
      "href": "http://example2.website"
    },
    {
      "primary": true,
      "href": "https://example.website"
    }
  ]
}

In just a line of Python, you can create an OPLoginItem object:

from pyonepassword.api.object_types import OPLoginItem

login_item = OPLoginItem(login_item_json)


print(login_item.username)
print(login_item.password)
print(login_item.primary_url.href)

# login_item is also a dictionary:
print(login_item["username"] == login_item.username)

Example usage of the OP class

If you want to fully automate connecting to and querying a 1Password account, that's what the OP class is for. It handles authentication (except for initial sign-in). And provides methods that are congruent to many of the op CLI tool's subcommands, such as:

  • item_get()
  • item_list()
  • user_get()
  • user_list()...

... and so forth.

All of these methods return objects types as described above. Also, item_get() returns the appropriate object type for the item, such as OPLoginItem or OPSecureNoteItem, as long as pyonepassword has a class for the returned item type.

Note: In some cases the op command may return items that don't conform to the expected structure. When this happens, the item dictionary will fail to validate, an exception will be raised. There is API for relaxing item validation, globally, on a per-class basis, or a per-item basis. See ITEM_VALIDATION.md for more information.

Sign-in and item retrieval

Below is an example demonstrating:

  • Sign-in
  • Specifying a default vault for queries
  • Retrieving an item from 1Password by name or by UUID
  • Overriding the default vault to retrieve a subsequent item from 1Password
import getpass

from pyonepassword import OP
from pyonepassword.api.exceptions import (
    OPSigninException,
    OPItemGetException,
    OPNotFoundException,
    OPConfigNotFoundException
)



# See examples/example-sign-in.py for more sign-in examples
def do_signin():
    # Let's check If biometric is enabled
    # If so, no need to provide a password
    if OP.uses_biometric():
        try:
            # no need to provide any authentication parameters if biometric is enabled
            op = OP()
        except OPAuthenticationException:
            print("Uh oh! Sign-in failed")
            exit(-1)
    else:
        # prompt user for a password (or get it some other way)
        my_password = getpass.getpass(prompt="1Password master password:\n")
        # You may optionally provide an account shorthand if you used a custom one during initial sign-in
        # shorthand = "arbitrary_account_shorthand"
        # return OP(account_shorthand=shorthand, password=my_password)
        # Or we'll try to look up account shorthand from your latest sign-in in op's config file
        op = OP(password=my_password)
    return op


def main():
  	op = do_signin()
    item_password = op.item_get_password("Example Login")

    # We can also look up the item by its UUID
    # as well as retrieve from an alternate vault
    item_password = op.item_get_password(
      "ykhsbhhv2vf6hn2u4qwblfrmg4", vault="Private")

Document retrieval

Below is an example demonstrating:

  • Retrieving a document and its file name from 1Password, based on item name
  • Retrieving a document & file name from 1Password, based on UUID
op = do_signin()
# File name and document title in 1Password are often different.
# so we get back the file name, and the bytes object representing the document
file_name, document_bytes = op.document_get("Example Login - 1Password Logo")

# we can also look up the document by UUID
file_name, document_bytes = op.document_get(
    "bmxpvuthureo7e52uqmvqcr4dy")
open(file_name, "wb").write(document_bytes)

Signing out of 1Password

Below is an example demonstrating:

  • Signing in, then signing out of 1Password
  • Signing out and also forgetting a 1Password account

Note: Currently pyonepassword's sign-out & forget support requires a signed-in session. It is not yet possible to forget an arbitrary account.

def main():
	  op = do_signin()

    # do signout
    op.signout()

    try:
		    print(op.item_get_password("Example Login"))
     except OPItemGetException:
      	# lookup fails since we signed out
        pass

    # now let's sign in again, then signout with forget=True
    op = do_signin()
    op.signout(forget=True)

    try:
        do_signin()
    except OPSigninException:
				# Sign-in fails since we erased the initial sign-in with forget=True
				pass

Getting Details for a User

op = OP(password=my_password)

# User's name:
user: OPUser = op.user_get("Firstname Lastname")

# or the user's UUID
user: OPUser = op.user_get(user_uuid)

Getting Details for a Group

op = OP(password=my_password)

# Group name:
group: OPGroup = op.group_get("Team Members")

# or the group's UUID
group: OPGroup = op.group_get("yhdg6ovhkjcfhn3u25cp2bnl6e")

Getting Details for a Vault

op = OP(password=my_password)

# Group name:
vault: OPVault = op.vault_get("Test Data")

# or the group's UUID
vault: OPVault = op.vault_get("yhdg6ovhkjcfhn3u25cp2bnl6e")

Extending Item Types

If any of the item types (login, password, etc.) are missing or don't provide sufficient properties or methods, it's very easy to add new ones or extend existing ones.

Here's an example extending OPLoginItem.

from pyonepassword import OP
from pyonepassword.api.decorators import op_register_item_type
from pyonepassword.api.object_types import OPLoginItem

@op_register_item_type
class OPEnhancedLoginItem(OPLoginItem):

    @property
    def custom_property(self):
      return self["custom_field"]


op = OP()
enhanced_login = op.item_get("Example Login", vault="Test Data")

print(enhanced_login.custom_property)

Item Deletion

from pyonepassword import OP  # noqa: E402
from pyonepassword.api.exceptions import OPItemDeleteException  # noqa: E402


def main():
    op: OP()
    try:
        # op.item_delete() can take any identifier accepted by the 'op' command:
        # Usage:  op item delete [{ <itemName> | <itemID> | <shareLink> | - }] [flags]
        deleted_uuid = op.item_delete("Example Login")  # noqa: F841
        # if desired inspect resulting UUID to ensure it's what was
        # Expected
    except OPItemDeleteException as ope:
        # 'op' command can fail for a few reaons, including
        # - item not found
        # - duplicate item names
        # Inspect the error message from the command
        print(ope.err_output)

Item Creation

For details on creating new items in a 1Password vault, see ITEM_CREATION.md

More Examples

Lots more examples are available in the examples directory

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyonepassword-3.12.1.tar.gz (81.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyonepassword-3.12.1-py3-none-any.whl (98.8 kB view details)

Uploaded Python 3

File details

Details for the file pyonepassword-3.12.1.tar.gz.

File metadata

  • Download URL: pyonepassword-3.12.1.tar.gz
  • Upload date:
  • Size: 81.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for pyonepassword-3.12.1.tar.gz
Algorithm Hash digest
SHA256 9d6e98129c2910aaafbfecfcb0245f8a88c39172c8dee37c11cf1e49907faba7
MD5 cf8812b9ccf353961466c0a3dcba2230
BLAKE2b-256 683401ac42a86d501f3cf45118034cac15b841c0b01ea7ac5c0b81a9771c2ca3

See more details on using hashes here.

File details

Details for the file pyonepassword-3.12.1-py3-none-any.whl.

File metadata

  • Download URL: pyonepassword-3.12.1-py3-none-any.whl
  • Upload date:
  • Size: 98.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.4

File hashes

Hashes for pyonepassword-3.12.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3cef4a976de6a66fb907b3ea7d27890ae22297e856b191aa846389376f688673
MD5 50a5762deae3afa7846b7c95c29e63f4
BLAKE2b-256 3c399fd4f3c8400b60f9336ce68f61afdf6613aa998089eb40e350ad582413c6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page