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)

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.3.0.tar.gz (36.7 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.3.0-py3-none-any.whl (39.1 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: znvault-1.3.0.tar.gz
  • Upload date:
  • Size: 36.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for znvault-1.3.0.tar.gz
Algorithm Hash digest
SHA256 af3c64feb30bca588c0fb357151b6d9ad040b98f9ae8c051386f6765b1e50f6e
MD5 7fbc1b68c00e7bd3d82ac2f4400b8375
BLAKE2b-256 e2d07ac953ac1b686a9ff0e2d5d9fdb20bfdb0ee7927323acf75be9bb8a795a0

See more details on using hashes here.

File details

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

File metadata

  • Download URL: znvault-1.3.0-py3-none-any.whl
  • Upload date:
  • Size: 39.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for znvault-1.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 868f1406af2ce96a089da40c03d513b3f474e02cc0cfaa95000f3cfb49ac7fb5
MD5 7763ec279ad606fe6cd124f09818ee47
BLAKE2b-256 81b29e5002f713413959c41361cccdd36fc8a715c47af8b228a4c3e497644c5c

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