OpenBao/Vault secrets source for pydantic-settings with AppRole authentication
Project description
pydantic-settings-openbao
OpenBao/Vault secrets source for pydantic-settings with AppRole authentication, automatic token renewal, and graceful fallback to environment variables.
Features
- AppRole Authentication - Secure machine-to-machine authentication
- Automatic Token Renewal - TokenManager handles TTL-based token lifecycle
- Namespace Support - Multi-tenant isolation (team/project level)
- Two-Path Architecture - Separate
secretsandsupersecretspaths with deep merge - SecretStr Validation - Enforces
SecretStrfor supersecrets to prevent log exposure - Graceful Degradation - Falls back to
.envwhen OpenBao is unavailable - Type Safety - Full type annotations with
py.typedmarker (PEP 561)
Installation
pip install openbao-pydantic-settings-adapter
Note: The import name is openbao_settings:
from openbao_settings import OpenBaoSettingsSource
Quick Start
from pydantic import SecretStr
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
from openbao_settings import OpenBaoSettingsSource
class Settings(BaseSettings):
database_url: str
api_key: SecretStr # Fields from supersecrets MUST use SecretStr
@classmethod
def settings_customise_sources(
cls,
settings_cls: type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: PydanticBaseSettingsSource,
dotenv_settings: PydanticBaseSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
) -> tuple[PydanticBaseSettingsSource, ...]:
return (
init_settings,
OpenBaoSettingsSource(settings_cls), # OpenBao has priority
env_settings,
dotenv_settings,
)
settings = Settings()
Configuration
Configure via environment variables:
| Variable | Description | Required |
|---|---|---|
BAO_ADDR |
OpenBao server URL (e.g., http://localhost:8200) |
Yes |
BAO_SECRET_PATH |
Base path to secrets (e.g., myapp) |
Yes |
BAO_APPROLE_ROLE_ID |
AppRole Role ID | Yes |
BAO_APPROLE_SECRET_ID |
AppRole Secret ID | Yes |
BAO_NAMESPACE |
OpenBao namespace for multi-tenant isolation | No |
BAO_MOUNT_POINT |
KV engine mount point (default: kv) |
No |
BAO_TIMEOUT |
Connection timeout in seconds (default: 30) |
No |
BAO_TOKEN_RENEWAL_THRESHOLD |
When to renew token (default: 0.75 = at 75% of TTL) |
No |
For Docker/Kubernetes, you can use file-based credentials:
BAO_APPROLE_ROLE_ID_FILEBAO_APPROLE_SECRET_ID_FILEBAO_NAMESPACE_FILE
Secrets Architecture
The library reads from two paths and merges them:
kv/{BAO_SECRET_PATH}/secrets - Regular secrets (developers can view/edit)
kv/{BAO_SECRET_PATH}/supersecrets - Sensitive secrets (admin only)
Important: Fields loaded from supersecrets MUST use SecretStr type annotation. The library validates this at runtime and raises SecurityMisconfigurationError if violated.
# Wrong - will raise SecurityMisconfigurationError
class Settings(BaseSettings):
api_key: str # Loaded from supersecrets but not SecretStr!
# Correct
class Settings(BaseSettings):
api_key: SecretStr # Properly protected
Token Lifecycle
TokenManager automatically handles token renewal:
- Caches tokens per
(namespace, role_id)combination - Renews at 75% of TTL (configurable via
BAO_TOKEN_RENEWAL_THRESHOLD) - Thread-safe for multi-threaded applications
- Graceful degradation if OpenBao becomes unavailable
from openbao_settings import TokenManager
# Manual token invalidation (e.g., for credential rotation)
TokenManager().invalidate()
# Check token health
TokenManager().is_healthy(namespace="myapp", role_id="...")
Diagnostics
Track where settings were loaded from:
from openbao_settings import get_last_source_info
info = get_last_source_info()
print(info["source"]) # "openbao" or "env"
print(info["details"]) # Human-readable description
print(info["openbao_keys_loaded"]) # Number of keys from OpenBao
API Reference
Classes
OpenBaoSettingsSource- Main settings source for pydantic-settingsOpenBaoClient- Low-level HTTP client for OpenBao APITokenManager- Singleton for token lifecycle management
Exceptions
OpenBaoError- Base exception for all OpenBao errorsInvalidPathError- Path not found (HTTP 404)InvalidRequestError- Invalid request/credentials (HTTP 400)ForbiddenError- Access denied (HTTP 403)InvalidResponseError- Unexpected API response structureSecurityMisconfigurationError- SecretStr validation failed
Response Models
AppRoleLoginResponse- AppRole authentication responseKvV2ReadResponse- KV v2 read response
License
This project is licensed under the PolyForm Noncommercial License 1.0.0.
You may use this software for noncommercial purposes only.
See LICENSE for the full license text, or visit polyformproject.org.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file openbao_pydantic_settings_adapter-1.0.2.tar.gz.
File metadata
- Download URL: openbao_pydantic_settings_adapter-1.0.2.tar.gz
- Upload date:
- Size: 17.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa9975d52be873d0430696a49efdaed0dd4d4fe1503212a1aa48539a56bf977b
|
|
| MD5 |
96a75b053252febec663651c85914549
|
|
| BLAKE2b-256 |
007369b9ecde0c294e8c07a45f20d0ef2dc890f98ebfefe86a1d2f70667dab27
|
Provenance
The following attestation bundles were made for openbao_pydantic_settings_adapter-1.0.2.tar.gz:
Publisher:
publish.yml on itstandart/openbao-pydantic-settings-adapter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openbao_pydantic_settings_adapter-1.0.2.tar.gz -
Subject digest:
fa9975d52be873d0430696a49efdaed0dd4d4fe1503212a1aa48539a56bf977b - Sigstore transparency entry: 833742813
- Sigstore integration time:
-
Permalink:
itstandart/openbao-pydantic-settings-adapter@c2cfbd78efdbf59c8019efffd79dee9cb1adbf38 -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/itstandart
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c2cfbd78efdbf59c8019efffd79dee9cb1adbf38 -
Trigger Event:
push
-
Statement type:
File details
Details for the file openbao_pydantic_settings_adapter-1.0.2-py3-none-any.whl.
File metadata
- Download URL: openbao_pydantic_settings_adapter-1.0.2-py3-none-any.whl
- Upload date:
- Size: 19.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a63dbbdae15cf8456815c308929d56df05b5070d7e5c2029cd74dc95dff15357
|
|
| MD5 |
f5e5c680786c10a726478cf6a928690a
|
|
| BLAKE2b-256 |
06cd25ed05ba547ac67a4598f9c740a4ae87e2e50711a5deca97a29526b7ae55
|
Provenance
The following attestation bundles were made for openbao_pydantic_settings_adapter-1.0.2-py3-none-any.whl:
Publisher:
publish.yml on itstandart/openbao-pydantic-settings-adapter
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
openbao_pydantic_settings_adapter-1.0.2-py3-none-any.whl -
Subject digest:
a63dbbdae15cf8456815c308929d56df05b5070d7e5c2029cd74dc95dff15357 - Sigstore transparency entry: 833742814
- Sigstore integration time:
-
Permalink:
itstandart/openbao-pydantic-settings-adapter@c2cfbd78efdbf59c8019efffd79dee9cb1adbf38 -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/itstandart
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c2cfbd78efdbf59c8019efffd79dee9cb1adbf38 -
Trigger Event:
push
-
Statement type: