Skip to main content

Official Python client for the Lanyard BYOK Vault.

Project description

Lanyard Python SDK (lanyard-py)

Lanyard is a local Bring Your Own Key (BYOK) manager that stores sensitive data (API Keys, Passwords, Cryptographic pairs) securely inside the native OS Keychain.

This SDK allows your Python applications to seamlessly request access to a user's Lanyard vault. It acts like a local OAuth flow: your app asks for a key, the Lanyard Desktop UI pops up to ask the user for consent, and the decrypted key is returned directly to your application's memory.

Features

  • Zero Dependencies: Built entirely on Python standard libraries (urllib, json).
  • Secure by Default: Keys are never saved to disk by your app. They remain in the OS secure enclave.
  • Context-Aware UI: Ask for specific types of data (e.g., only "Passwords") and provide custom prompt text.
  • Drop-in Integration: Implement secure key fetching in under 10 lines of code.

Installation

pip install lanyard

Quick Start: The "Link & Fetch" Flow

Integrating Lanyard into your app involves a two-step process:

  1. The Link Request (First Setup): Prompt the user to select a key from their vault.
  2. The Direct Fetch (Every subsequent boot): Use the saved UUID to quietly fetch the key.
from lanyard import LanyardClient
from lanyard.exceptions import LanyardNotRunningError, LanyardAccessDeniedError

# 1. Initialize the client with your application's name
client = LanyardClient(app_name="YourApp")

def first_time_setup():
    """Triggered when the user clicks 'Connect Lanyard' in your app."""
    try:
        # Prompts the Lanyard UI drop-down menu
        response = client.request_link(
            reason="Required: OpenAI API Key", 
            category="api_key"
        )
        
        # Save this UUID to your app's local settings/database
        lanyard_uuid = response["target_id"] 
        save_to_settings("openai_lanyard_id", lanyard_uuid)
        
        print("Successfully linked! Key data:", response["data"])

    except LanyardNotRunningError:
        print("Please download and open the Lanyard Desktop application.")
    except LanyardAccessDeniedError:
        print("User cancelled the request.")

def fetch_key():
    """Triggered when you need to fetch data from lanyard."""
    saved_uuid = load_from_settings("openai_lanyard_id")
    
    if saved_uuid:
        try:
            # Fetches the specific field. (If the user checked 'Always Allow' 
            # in the past, this returns instantly without a UI popup!)
            openai_key = client.get_field(saved_uuid, "Private/Secret Key")
            
            # Apply to your environment
            import openai
            openai.api_key = openai_key
            
        except LanyardAccessDeniedError:
            print("Access revoked by user.")

API Reference

LanyardClient(app_name: str, port: Optional[int] = None)

Initializes the SDK.

  • app_name: The name of your application. This is displayed prominently in the Lanyard Desktop UI to ensure the user knows who is requesting their data.
  • port: (Optional) Lanyard dynamically manages ports. If left as None, the SDK will automatically read the ~/.lanyard/port file to find the active server.

client.request_link(reason: str = None, category: str = None, timeout: int = 300) -> dict

Wakes up the Lanyard Desktop UI and presents the user with a dropdown menu to select a key.

  • reason: (Optional) Italicized subtext displayed in the UI to give the user context (e.g., "Requires an AWS root key").
  • category: (Optional) Filters the dropdown to only show specific data types. Valid options: "api_key", "password", "env", "crypto", "license", "recovery".
  • Returns: A dictionary containing the target_id (UUID) and the decrypted data dictionary.

client.get_secret(target_id: str, timeout: int = 300) -> dict

Requests a specific key by its UUID. If the user previously checked "Always Allow" for your app, this returns instantly. Otherwise, it prompts the UI for explicit approval.

  • Returns: A dictionary containing all fields inside the requested Lanyard item.

client.get_field(target_id: str, field_name: str, timeout: int = 300) -> str

A helper method that calls get_secret() and extracts a single string field.

  • field_name: The exact string name of the field you want (e.g., "Endpoint URL").

Error Handling

Lanyard provides explicit exceptions so your application can gracefully degrade if the user rejects a request or doesn't have Lanyard installed.

  • LanyardNotRunningError: Raised when the local Lanyard HTTP server cannot be reached.
  • LanyardAccessDeniedError: Raised when the user clicks "Deny", enters the wrong Master PIN, or cancels the request.
  • LanyardTimeoutError: Raised if the user ignores the prompt and the request times out (default 300s).
  • LanyardKeyNotFoundError: Raised if get_field requests a field name that doesn't exist in the returned payload.
  • LanyardError: Base exception for malformed requests or unexpected HTTP errors.

Security Model

Lanyard does not provide encrypted keys to your application. When an access request is approved, Lanyard decrypts the data using the user's Master PIN and passes the plaintext data to your application's memory via localhost IPC.

It is the responsibility of the integrating application to use this data securely in memory and never write it to disk outside of the OS Credentials Manager. You should only save the Lanyard UUID (target_id) to your configuration files.

Changelogs

0.1.2 - Updated README.md 0.1.2 - Added "recovery" as a valid category option. Used for storing recovery keys. 0.1.1 - Updated README.md

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

lanyard-0.1.2.tar.gz (5.7 kB view details)

Uploaded Source

Built Distribution

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

lanyard-0.1.2-py3-none-any.whl (6.4 kB view details)

Uploaded Python 3

File details

Details for the file lanyard-0.1.2.tar.gz.

File metadata

  • Download URL: lanyard-0.1.2.tar.gz
  • Upload date:
  • Size: 5.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for lanyard-0.1.2.tar.gz
Algorithm Hash digest
SHA256 ca3bda76f786b825816a69100773bc9c07d6c8bba779502f3cf1634198e251bb
MD5 3947ea9b6065fab2904d5a0569963467
BLAKE2b-256 526662c2b2bf82ba4e5e22b92b6d4d92d7cdb9958683338a07a5cb03e25e807f

See more details on using hashes here.

File details

Details for the file lanyard-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: lanyard-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 6.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for lanyard-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1184cdb53b1f911f0d6597a3ee40d2c745113e78740422c17c74fe094fa977d5
MD5 a960e053b0e8d3e99a70aeddefe63440
BLAKE2b-256 e208a119282b7501d8f0b6718beb940661c83865318b5db63f6e0a75aacd2482

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