Skip to main content

A Python library for unified secrets management across HashiCorp Vault, system keyring, and .env files.

Project description

credential-bridge

A unified Python library for secrets management across HashiCorp Vault, the OS system keyring, and .env files.


Table of Contents


Features

  • Three backends: HashiCorp Vault (KV-v2), OS system keyring, and .env files
  • SecretsManager facade: switch backends without changing application code
  • Plugin architecture: register third-party backends with one call
  • Typed exceptions: granular hierarchy rooted at CredentialBridgeError
  • Typer + Rich CLI: cb, vault-cli, keyring-cli, env-cli, and run-wizard entry points
  • Cross-platform: works on Linux, macOS, and Windows

Installation

pip install credential-bridge

# With dev dependencies
pip install "credential-bridge[dev]"

Quick Start

Using SecretsManager

from credential_bridge import SecretsManager

# HashiCorp Vault (set VAULT_ADDR env var first)
sm = SecretsManager("vault", vault_token="s.xxx")
sm.add_secret("myapp/database", {"user": "admin", "pass": "s3cr3t"})
secret = sm.get_secret("myapp/database")

# System keyring
sm = SecretsManager("keyring", service_name="myapp")
sm.add_secret("api_key", {"api_key": "sk-abc123"})

# .env file
sm = SecretsManager("env", path=".env")
sm.add_secret("DATABASE", {"DB_HOST": "localhost", "DB_PORT": "5432"})

Using backends directly

from credential_bridge import VaultBackend, KeyringBackend, EnvFileBackend

# Vault with AppRole auth
vault = VaultBackend(
    vault_url="https://vault.example.com",
    vault_role_id="<role-id>",
    vault_secret_id="<secret-id>",
)
vault.add_secret("myapp/db", {"password": "hunter2"})

# Keyring
kr = KeyringBackend(service_name="myapp")
kr.add_secret("token", {"value": "sk-abc123"})

# .env file
env = EnvFileBackend(path=".env")
env.add_secret("DATABASE", {"DB_HOST": "localhost", "DB_PORT": "5432"})

CLI Usage

# Show all commands
cb --help

# Vault
cb vault add myapp/db --secret user=admin --secret pass=s3cr3t
cb vault get myapp/db
cb vault list
cb vault delete myapp/db

# Keyring
cb keyring add api_key --secret api_key=sk-abc123 --service-name myapp
cb keyring get api_key --service-name myapp
cb keyring delete api_key --service-name myapp

# .env file
cb env add DATABASE --secret DB_HOST=localhost --secret DB_PORT=5432
cb env get DB_HOST
cb env list
cb env delete DB_HOST

# Interactive wizard
cb wizard

Backends

Backend Best use case
Vault Production workloads requiring audit logs, dynamic secrets, fine-grained policies, and centralized governance
Keyring Developer machines and CI environments where OS-level credential storage is available
.env file Local development, Docker Compose setups, and twelve-factor apps that read config from the environment

Custom Backends

Implement BaseSecretBackend and register it with SecretsManager:

from credential_bridge import BaseSecretBackend, SecretsManager
from credential_bridge.manager import register_backend
from typing import Any, Dict, List

class RedisBackend(BaseSecretBackend):
    backend_name = "redis"  # required — omitting raises TypeError

    def add_secret(self, name: str, secret: Dict[str, Any]) -> None: ...
    def get_secret(self, name: str) -> Dict[str, Any]: ...
    def update_secret(self, name: str, secret: Dict[str, Any]) -> None: ...
    def delete_secret(self, name: str) -> None: ...
    def list_secrets(self, path: str = "") -> List[str]: ...

register_backend("redis", RedisBackend)

sm = SecretsManager("redis", host="localhost", port=6379)

Error Handling

All exceptions inherit from CredentialBridgeError:

CredentialBridgeError
├── BackendError
│   ├── VaultError
│   │   ├── VaultAuthError          — bad token / AppRole credentials
│   │   ├── VaultConnectionError    — unreachable server
│   │   └── VaultSecretNotFoundError — secret path does not exist
│   ├── KeyringError
│   └── EnvFileError
│       ├── EnvFileNotFoundError    — key not found
│       └── EnvFileKeyExistsError   — add_secret called on existing key
├── BackendNotRegisteredError
└── ConfigurationError
from credential_bridge import (
    SecretsManager,
    VaultAuthError,
    VaultConnectionError,
    VaultSecretNotFoundError,
    CredentialBridgeError,
)

sm = SecretsManager("vault", vault_token="s.xxx")

try:
    secret = sm.get_secret("myapp/database")
except VaultSecretNotFoundError:
    print("Secret path does not exist")
except VaultAuthError:
    print("Authentication failed — check your token or AppRole credentials")
except VaultConnectionError:
    print("Could not reach Vault — check VAULT_ADDR")
except CredentialBridgeError as exc:
    print(f"Unexpected error: {exc}")

Environment Variables

Variable Description
VAULT_ADDR Vault server URL (e.g. https://vault.example.com)
VAULT_TOKEN Token for Token auth method
VAULT_ROLE_ID Role ID for AppRole auth method
VAULT_SECRET_ID Secret ID for AppRole auth method

Resolution order for VaultBackend: constructor argument → environment variable → ~/.vault_config.json.


Development

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run unit tests
pytest tests/unit/

# Run integration tests (requires external services)
pytest tests/integration/ -m integration

# Lint
ruff check src/

# Type check
mypy src/

# Serve docs locally
mkdocs serve

Contributing

All contributions are welcome! Fork the repo, make your changes, and open a pull request. You can also open an issue with the label enhancement.

View all contributors


License

MIT — see LICENSE.txt for details.

(back to top)

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

credential_bridge-0.1.1.tar.gz (1.0 MB view details)

Uploaded Source

Built Distribution

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

credential_bridge-0.1.1-py3-none-any.whl (29.1 kB view details)

Uploaded Python 3

File details

Details for the file credential_bridge-0.1.1.tar.gz.

File metadata

  • Download URL: credential_bridge-0.1.1.tar.gz
  • Upload date:
  • Size: 1.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.15

File hashes

Hashes for credential_bridge-0.1.1.tar.gz
Algorithm Hash digest
SHA256 df3de41fa18f9eb8e0df0927e53c305e6422a880c83ece3349073f600b18b5ec
MD5 a28fa4d366595ab67a98ce98f7db549f
BLAKE2b-256 828adcc5997b553d8fd3cf0eca0c42374d758b3c0af9eabd99e14c18e00e38bf

See more details on using hashes here.

File details

Details for the file credential_bridge-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for credential_bridge-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 0519375259075bb07dfdde0b6c87ff45ab3c2a774e55ee569b6a6cdfcb3d8489
MD5 b6b8160064c0d9d9fc47a58d554a9fab
BLAKE2b-256 bdab9d0b5ace4aa84177a595f4abd22b6a30d1b937653776a1ad77f187838667

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