Skip to main content

Python SDK for ZN-Vault secrets management

Project description

ZN-Vault Python SDK

PyPI version Python 3.9+

A Python client library for ZN-Vault secrets management system.

PyPI: https://pypi.org/project/znvault/

Installation

pip install znvault

Or with a specific version:

pip install znvault==1.0.0

Or install from source:

git clone https://github.com/zincware/zn-vault-sdk-python.git
cd zn-vault-sdk-python
pip install -e .

Quick Start

from znvault import ZnVaultClient, SecretType, CreateSecretRequest

# Create client with API key
client = ZnVaultClient.create(
    "https://vault.example.com:8443",
    api_key="znv_xxxx"
)

# Or use the builder pattern
client = (
    ZnVaultClient.builder()
    .base_url("https://vault.example.com:8443")
    .api_key("znv_xxxx")
    .timeout(60)
    .trust_self_signed(True)  # For development
    .build()
)

# Check health
health = client.health.check()
print(f"Status: {health.status}")

# Login with username/password
auth = client.auth.login("username", "password")
print(f"Logged in: {auth.access_token[:30]}...")

Authentication

Username/Password

# Login
result = client.auth.login("alice", "password123", totp_code="123456")

# Refresh token
new_tokens = client.auth.refresh()

# Get current user
user = client.auth.me()
print(f"Username: {user.username}")

# Logout
client.auth.logout()

API Keys

# Create API key
key = client.auth.create_api_key("my-service", expires_in="90d")
print(f"Key: {key.key}")  # Only shown once

# List API keys
keys = client.auth.list_api_keys()

# Revoke API key
client.auth.revoke_api_key(key.id)

Secrets Management

Create Secrets

from znvault import CreateSecretRequest, SecretType

# Create a credential secret
request = CreateSecretRequest(
    alias="api/production/db-creds",
    tenant="acme",
    type=SecretType.CREDENTIAL,
    data={"username": "dbuser", "password": "secret123"},
    tags=["production", "database"]
)
secret = client.secrets.create(request)
print(f"Created: {secret.id}")

Retrieve Secrets

# Get metadata by ID
secret = client.secrets.get("secret-id")

# Get by tenant and alias
secret = client.secrets.get_by_alias("acme", "api/production/db-creds")

# Decrypt secret value
data = client.secrets.decrypt("secret-id")
password = data.data["password"]

Update and Delete

from znvault import UpdateSecretRequest

# Update secret (creates new version)
update = UpdateSecretRequest(
    data={"username": "newuser", "password": "newpass"}
)
secret = client.secrets.update("secret-id", update)
print(f"New version: {secret.version}")

# Delete secret
client.secrets.delete("secret-id")

List and Filter

from znvault import SecretFilter, SecretType

# List with filters
filter = SecretFilter(
    tenant="acme",
    env="production",
    type=SecretType.CREDENTIAL,
    limit=100
)
secrets = client.secrets.list(filter)

Pattern Matching & Search

Use wildcard patterns with * to query secrets by path:

from znvault import SecretFilter

# Find all secrets under a path
web_secrets = client.secrets.list(SecretFilter(alias_pattern="web/*"))

# Find secrets containing "/env/" anywhere in the path
env_secrets = client.secrets.list(SecretFilter(alias_pattern="*/env/*"))

# SQL-like pattern matching
db_secrets = client.secrets.list(SecretFilter(alias_pattern="*/env/secret_*"))

# Match multiple path segments
# Matches: db-mysql/production, db-postgres/prod-us, etc.
prod_db = client.secrets.list(SecretFilter(alias_pattern="db-*/prod*"))

# Combine pattern with type filter
credentials = client.secrets.list(SecretFilter(
    alias_pattern="*/production/*",
    type=SecretType.CREDENTIAL
))

# Search for expiring certificates matching a pattern
from datetime import datetime, timedelta

expiring_certs = client.secrets.list(SecretFilter(
    alias_pattern="*/ssl/*",
    sub_type="certificate",
    expiring_before=datetime.now() + timedelta(days=30)
))

Pattern Examples:

Pattern Matches
web/* web/api, web/frontend/config
*/env/* app/env/vars, service/env/config
db-*/prod* db-mysql/production, db-postgres/prod-us
*secret* my-secret, api/secret/key, secret-config
*/production/db-* app/production/db-main, api/production/db-replica

File Upload/Download

# Upload a file as a secret
secret = client.secrets.upload_file(
    alias="ssl/production/cert",
    tenant="acme",
    file_path="/path/to/cert.pem",
    tags=["certificate", "ssl"]
)

# Download a file secret
client.secrets.download_file("secret-id", "/path/to/output.pem")

Keypair Generation and Public Key Publishing

from znvault import GenerateKeypairRequest

# Generate an Ed25519 keypair
keypair = client.secrets.generate_keypair(
    GenerateKeypairRequest(
        algorithm="Ed25519",
        alias="ssh/production/deploy-key",
        tenant="acme",
        comment="Production deployment key",
        tags=["ssh", "deployment"]
    )
)

# Access private and public keys
print(f"Private key ID: {keypair.private_key.id}")
print(f"Public key ID: {keypair.public_key.id}")
print(f"Fingerprint: {keypair.public_key.fingerprint}")
print(f"OpenSSH format: {keypair.public_key.public_key_openssh}")

# Generate RSA keypair with custom key size
rsa_keypair = client.secrets.generate_keypair(
    GenerateKeypairRequest(
        algorithm="RSA",
        alias="ssh/production/rsa-key",
        tenant="acme",
        rsa_bits=4096,
        publish_public_key=True  # Automatically publish the public key
    )
)

# Generate ECDSA keypair
ecdsa_keypair = client.secrets.generate_keypair(
    GenerateKeypairRequest(
        algorithm="ECDSA",
        alias="ssh/production/ecdsa-key",
        tenant="acme",
        ecdsa_curve="P-384"
    )
)

# Publish a public key (make it publicly accessible)
result = client.secrets.publish(keypair.public_key.id)
print(f"Public URL: {result.public_url}")
print(f"Fingerprint: {result.fingerprint}")

# Get a published public key (no authentication required)
public_key = client.secrets.get_public_key("acme", "ssh/production/deploy-key")
print(f"Algorithm: {public_key.algorithm}")
print(f"Public key (PEM): {public_key.public_key_pem}")

# List all published public keys for a tenant (no authentication required)
public_keys = client.secrets.list_public_keys("acme")
for key in public_keys:
    print(f"{key.alias}: {key.fingerprint}")

# Unpublish a public key (make it private again)
client.secrets.unpublish(keypair.public_key.id)

KMS Operations

Key Management

from znvault import CreateKeyRequest, KeySpec, KeyUsage

# Create a KMS key
request = CreateKeyRequest(
    alias="alias/my-encryption-key",
    tenant="acme",
    description="Production encryption key",
    key_spec=KeySpec.AES_256,
    usage=KeyUsage.ENCRYPT_DECRYPT,
    rotation_enabled=True,
    rotation_days=90
)
key = client.kms.create_key(request)
print(f"Key ID: {key.key_id}")

# List keys
keys = client.kms.list_keys()

Encrypt/Decrypt

import base64

# Encrypt data
plaintext = b"sensitive data"
result = client.kms.encrypt("key-id", plaintext)
print(f"Ciphertext: {result.ciphertext}")

# Decrypt data
decrypted = client.kms.decrypt_bytes("key-id", result.ciphertext)
print(f"Decrypted: {decrypted.decode()}")

Data Keys

# Generate data key for envelope encryption
data_key = client.kms.generate_data_key("key-id")
# Use data_key.plaintext to encrypt locally
# Store data_key.ciphertext with the encrypted data

Admin Operations

Tenants

from znvault import CreateTenantRequest

# Create tenant
request = CreateTenantRequest(name="newcorp", display_name="New Corp Inc")
tenant = client.tenants.create(request)

# List tenants
tenants = client.tenants.list()

Users

from znvault import CreateUserRequest

# Create user
request = CreateUserRequest(
    username="bob",
    password="secure123",
    email="bob@example.com",
    role="admin",
    tenant_id="acme"
)
user = client.users.create(request)

# List users
users = client.users.list(tenant_id="acme")

Roles

from znvault import CreateRoleRequest

# Create role
request = CreateRoleRequest(
    name="SecretReader",
    description="Can read secrets",
    permissions=["secret:read:*"]
)
role = client.roles.create(request)

# List roles
roles = client.roles.list(include_system=True)

Policies

from znvault import PolicyDocument, PolicyStatement, PolicyEffect

# Create ABAC policy
document = PolicyDocument(
    statements=[
        PolicyStatement(
            effect=PolicyEffect.ALLOW,
            actions=["secret:read:*"],
            resources=["secret:acme/*"]
        )
    ]
)

policy = client.policies.create(
    name="acme-secret-reader",
    document=document,
    tenant_id="acme"
)

Audit Logs

from znvault import AuditFilter
from datetime import datetime, timedelta

# List audit entries
filter = AuditFilter(
    action="secret:read",
    start_date=datetime.now() - timedelta(days=7),
    limit=100
)
entries = client.audit.list(filter)

# Verify audit chain integrity
result = client.audit.verify()
print(f"Chain valid: {result.valid}")

Error Handling

from znvault import (
    ZnVaultError,
    AuthenticationError,
    AuthorizationError,
    NotFoundError,
    ValidationError,
    RateLimitError,
)

try:
    secret = client.secrets.decrypt("invalid-id")
except NotFoundError as e:
    print(f"Secret not found: {e.resource_id}")
except AuthorizationError as e:
    print(f"Access denied: {e.message}")
except RateLimitError as e:
    print(f"Rate limited, retry after: {e.retry_after}s")
except ZnVaultError as e:
    print(f"Error [{e.status_code}]: {e.message}")

Development

Run Tests

# Install dev dependencies
pip install -e ".[dev]"

# Run unit tests
pytest tests/ -v

# Run with coverage
pytest tests/ --cov=znvault

# Run integration tests (requires running vault)
./test-integration.sh

Type Checking

mypy src/znvault

Linting

ruff check src/

License

Apache-2.0

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

znvault-1.7.0.tar.gz (44.4 kB view details)

Uploaded Source

Built Distribution

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

znvault-1.7.0-py3-none-any.whl (48.9 kB view details)

Uploaded Python 3

File details

Details for the file znvault-1.7.0.tar.gz.

File metadata

  • Download URL: znvault-1.7.0.tar.gz
  • Upload date:
  • Size: 44.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for znvault-1.7.0.tar.gz
Algorithm Hash digest
SHA256 7582f7c88771c8a3c277499c5b28f9e8e9e573b7bc95760eb4fc12f20a1c236f
MD5 1fbc5b4fbd522279286caddbc445e0b9
BLAKE2b-256 5722fdf3ab3f2bf2fc3b982fa480072bcf1ebd374ee1398ef2e3a12710243891

See more details on using hashes here.

File details

Details for the file znvault-1.7.0-py3-none-any.whl.

File metadata

  • Download URL: znvault-1.7.0-py3-none-any.whl
  • Upload date:
  • Size: 48.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for znvault-1.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c5a395c9ecb01704235a20937b286863c02e2c75ad55d990a198705b16d82b24
MD5 2d9ccbaec9fc32d213e8005a7eabffb1
BLAKE2b-256 86bae2edb3e9e3195b27281c6cb6f54bad6e53aef8a46dd5145705be0fb25e2d

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