diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index fddb57f7..b68c6c8e 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -13,13 +13,13 @@ on: jobs: - integration-test-trusted: + test-trusted: # actions that are trusted by default must only be opened from within the repo, and skipped for forks because they'll fail there if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v3 @@ -35,7 +35,15 @@ jobs: pip install pytest-asyncio && pip install pydantic && python -m pytest src/onepassword/test_client.py - + - name: Example Test + if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9' + env: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.EXAMPLE_TESTS_OP_SERVICE_ACCOUNT_TOKEN }} + OP_VAULT_ID: ${{ secrets.EXAMPLE_TESTS_OP_VAULT_ID }} + run: | + pip install cryptography && + pip install . && + python example/example.py lint: name: Lint runs-on: ubuntu-latest @@ -84,7 +92,7 @@ jobs: uses: actions/setup-python@v4 with: python-version: '3.x' - + - name: Integration Test env: OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TEST_SERVICE_ACCOUNT_TOKEN }} @@ -94,8 +102,14 @@ jobs: pip install pydantic && python -m pytest src/onepassword/test_client.py - - run: | - echo "Integration tests completed successfully!" + - name: Example Test + if: matrix.os == 'ubuntu-latest' + env: + OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TEST_SERVICE_ACCOUNT_TOKEN }} + OP_VAULT_ID: ${{ secrets.TEST_SERVICE_ACCOUNT_VAULT_ID }} + run: | + pip install . && + python example/example.py # Update check run called "integration-fork" on the forked PR - uses: actions/github-script@v6 @@ -105,7 +119,7 @@ jobs: job: ${{ github.job }} ref: ${{ github.event.client_payload.pull_request.head.sha }} # Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run - conclusion: ${{ job.status }} + conclusion: ${{ job.status }} with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/example/README.md b/example/README.md new file mode 100644 index 00000000..218399ea --- /dev/null +++ b/example/README.md @@ -0,0 +1,48 @@ +# Examples +This folder contains a code snippet demonstrating how to use the 1Password Python SDK for performing various operations on 1Password vaults and items. Specifically, the example showcases how to: + +- Authenticate with the 1Password API using a service account token. +- List available vaults and items within those vaults. +- Retrieve a specific secret and resolve a one-time password (TOTP). +- Create a new item in a vault with multiple fields and tags. +- Update an existing item by modifying its fields and adding a new website. +- Generate different types of passwords (PIN, memorable, and random). +- Share an item with valid recipients and create a shareable link. +- Archive or delete items from the vault. +- Create and manage SSH key items. +- Create and manage document items, including replacing and reading documents. +- Create and manage file field items by attaching and deleting files. + +## Prerequisites + +1. Clone the repository and follow the steps to [get started](https://github.com/1Password/onepassword-sdk-python/blob/main/README.md). +2. Ensure that you have a valid service account token by exporting it as an environment variable: + ```bash + export OP_SERVICE_ACCOUNT_TOKEN="" + ``` +3. Export the vault UUID you wish to interact with as an environment variable: + ```bash + export OP_VAULT_ID="" + ``` + +## How to Run + +To run the example file, navigate to project root directory and run: +```bash +python example/example.py +``` + +## Terminal Output + +When running the example, the terminal will display: + +- A list of vaults and items. +- Retrieved secrets and TOTP codes. +- Details of newly created and updated items. +- Generated passwords (PIN, memorable, random). +- A shareable link for shared items. +- SSH key attributes like public key and fingerprint. +- Document content after replacing the file. +- A list of file field items and file deletions. + +These outputs show the results of vault and item operations, password generation, item sharing, and management of SSH and document items. diff --git a/example/example.py b/example/example.py index 0796bc07..02996cd2 100644 --- a/example/example.py +++ b/example/example.py @@ -44,18 +44,16 @@ async def main(): print(error) # [developer-docs.sdk.python.validate-secret-reference]-end - # [developer-docs.sdk.python.resolve-secret]-start - # 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") - print(value) - # [developer-docs.sdk.python.resolve-secret]-end + vault_id= os.getenv("OP_VAULT_ID") + if vault_id is None: + raise Exception("OP_VAULT_ID environment variable is not set") # [developer-docs.sdk.python.create-item]-start # Create an Item and add it to your vault. to_create = ItemCreateParams( title="MyName", category=ItemCategory.LOGIN, - vault_id="7turaasywpymt3jecxoxk5roli", + vault_id=vault_id, fields=[ ItemField( id="username", @@ -95,6 +93,12 @@ async def main(): print(dict(created_item)) + # [developer-docs.sdk.python.resolve-secret]-start + # Retrieves a secret from 1Password. Takes a secret reference as input and returns the secret to which it points. + value = await client.secrets.resolve(f"op://{created_item.vault_id}/{created_item.id}/username") + print(value) + # [developer-docs.sdk.python.resolve-secret]-end + # [developer-docs.sdk.python.resolve-totp-code]-start # Retrieves a secret from 1Password. Takes a secret reference as input and returns the secret to which it points. code = await client.secrets.resolve( @@ -173,11 +177,11 @@ async def main(): await share_item(client, created_item.vault_id, updated_item.id) - await create_ssh_key_item(client) + await create_ssh_key_item(client, vault_id) - await create_and_replace_document_item(client) + await create_and_replace_document_item(client, vault_id) - await create_attach_and_delete_file_field_item(client) + await create_attach_and_delete_file_field_item(client, vault_id) # [developer-docs.sdk.python.delete-item]-start # Delete a item from your vault. @@ -230,7 +234,7 @@ async def share_item(client: Client, vault_id: str, item_id: str): # [developer-docs.sdk.python.item-share-create-share]-end -async def create_ssh_key_item(client: Client): +async def create_ssh_key_item(client: Client, vault_id: str): # [developer-docs.sdk.python.create-sshkey-item]-start # Generate a 2048-bit RSA private key private_key = rsa.generate_private_key( @@ -249,7 +253,7 @@ async def create_ssh_key_item(client: Client): to_create = ItemCreateParams( title="SSH Key Item Created With Python SDK", category=ItemCategory.SSHKEY, - vault_id="7turaasywpymt3jecxoxk5roli", + vault_id=vault_id, fields=[ ItemField( id="private_key", @@ -273,13 +277,13 @@ async def create_ssh_key_item(client: Client): await client.items.delete(created_item.vault_id, created_item.id) -async def create_and_replace_document_item(client: Client): +async def create_and_replace_document_item(client: Client, vault_id: str): # [developer-docs.sdk.python.create-document-item]-start # Create a Document Item to_create = ItemCreateParams( title="Document Item Created with Python SDK", category=ItemCategory.DOCUMENT, - vault_id="7turaasywpymt3jecxoxk5roli", + vault_id=vault_id, sections=[ ItemSection(id="", title=""), ], @@ -312,13 +316,13 @@ async def create_and_replace_document_item(client: Client): await client.items.delete(replaced_item.vault_id, replaced_item.id) -async def create_attach_and_delete_file_field_item(client: Client): +async def create_attach_and_delete_file_field_item(client: Client, vault_id: str): # [developer-docs.sdk.python.create-item-with-file-field]-start # Create a File Field Item to_create = ItemCreateParams( title="FileField Item created with Python SDK", category=ItemCategory.LOGIN, - vault_id="7turaasywpymt3jecxoxk5roli", + vault_id=vault_id, fields=[ ItemField( id="username",