valt0
Python client for Valt0. It fetches secrets from a local Valt0 vault at runtime, so you don't
have to keep them in .env files, config files, or CI variables.
- License: Apache-2.0
- Requires: Python >= 3.9, and the
valt0service/CLI installed and running locally
Installation
pip install valt0-client
The package is installed as valt0-client and imported as valt0.
Usage
import valt0
vault = valt0.open_vault(id="your-vault-id", name="your-vault-name")
# The with block zeroes the underlying buffer as soon as you are finished
with vault.secret("DATABASE_PASSWORD") as secret:
# Preferred: the raw bytes, wiped on exit
pw = secret.bytes()
# Or, when a string is unavoidable
db.connect(password=secret.reveal())
Without a with block, call secret.destroy() yourself, ideally in a finally.
Secrets are redacted by default
A Secret won't leak its value into a log line, a traceback, an f-string, or a pickle. You only
get the plaintext when you ask for it explicitly:
print(secret) # [REDACTED]
print(repr(secret)) # Secret([REDACTED])
f"{secret}" # [REDACTED]
logging.info("connecting %s", secret) # connecting [REDACTED]
json.dumps({"pw": secret}, default=str) # {"pw": "[REDACTED]"}
pickle.dumps(secret) # TypeError: Secret objects cannot be pickled or copied
secret.reveal() # the actual value
Redaction covers str(), repr() and format(). Pickling and copying raise TypeError, so a
secret can't slip out through multiprocessing or a cache.
Errors
open_vault and Vault.secret raise two specific errors for the most common connection failures:
try:
vault = valt0.open_vault(id="your-vault-id", name="your-vault-name")
except valt0.CantConnectToServiceError:
... # socket or session file not found: is the valt0 service running?
except valt0.NoServiceResponseError:
... # the service did not answer within the transport timeout (1s)
except valt0.Valt0Error:
... # any other error, e.g. the vault could not be loaded
Threads and asyncio
The client is synchronous and thread-safe; every call uses its own connection. From async code, run it in a worker thread:
secret = await asyncio.to_thread(vault.secret, "DATABASE_PASSWORD")
API
open_vault(*, id: str, name: str) -> Vault
Opens the vault identified by id.
Raises an error if the service is unreachable or the vault cannot be loaded.
| Argument | Type | Description |
|---|---|---|
id |
str |
Vault identifier — the only value used to locate the vault |
name |
str |
Display label for messages; .valt0 is appended if missing |
Note:
namecan be anything. Valt0 does not check that it matches the vaultid— it is only used for messaging purposes, so pick whatever makes the vault easy to recognise.
Vault
| Member | Description |
|---|---|
id |
The vault's id |
name |
The vault's name |
secret(name) |
Secret: fetches one secret by name |
Secret
| Member | Description |
|---|---|
bytes() |
The raw bytes as a bytearray (the underlying buffer, not a copy). This is the preferred accessor. |
reveal() |
The value as a str. Strings are immutable and can't be wiped, so use sparingly. ValueError if not UTF-8 text. |
destroy() |
Zeroes the buffer. Buffers returned by bytes() are zeroed too, and later calls return empty values. |
with secret |
Calls destroy() when the block exits. |
Errors
| Error | Raised when |
|---|---|
Valt0Error |
Base class of every error the client raises |
CantConnectToServiceError |
The service socket or session file does not exist |
NoServiceResponseError |
The service did not respond before the deadline |
Platform support
Linux, macOS and Windows, including inside containers.
On Linux and macOS the client reaches the service through its unix socket, or over TCP to
host.docker.internal when VALT0_TRANSPORT_CHANNEL=tcp. On Windows it always uses TCP to
127.0.0.1 (CPython has no AF_UNIX support there), and VALT0_TRANSPORT_CHANNEL and
VALT0_SOCKET_PATH are ignored.
Development
python -m venv .venv && . .venv/bin/activate
pip install -e . pytest
pytest
The tests run against a strict fake of the Valt0 service (tests/fake_service.py).
tests/test_go_parity.py also runs the Go client through the same scenarios and checks that both
clients send the same requests and return the same results; it runs when go is installed and the
Go client is checked out at ../../golang/client (or $VALT0_GO_CLIENT_DIR). See
RELEASING.md for publishing.
Links
Maintained by BYTE 1620. Licensed under Apache-2.0.
Metadata
Release files for valt0-client 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| valt0_client-1.0.0.tar.gz | 34.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| valt0_client-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 54.3 kB
Release files / valt0_client-1.0.0.tar.gz
| Download URL | valt0_client-1.0.0.tar.gz |
|---|---|
| Size | 34.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c86eec4aa630aabd063dc5841e90e81813a0f98b8dd1756abff6f6d6d70854a9
|
|
BLAKE2b-256 checksum How to use checksums |
7f9781b17c98d476e090b30b2c1fda3b49beba4a0fa68f9cffee1e17c90f0595
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / valt0_client-1.0.0-py3-none-any.whl
| Download URL | valt0_client-1.0.0-py3-none-any.whl |
|---|---|
| Size | 20.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dfe251d3635ad4d96f7133ce5cbf63d0c8b14cb3699cb20098f90833889763e5
|
|
BLAKE2b-256 checksum How to use checksums |
5075f7ddce0e520378b3607cf12065f4b98e352753c2e3b4a357df96c1ef049d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|