A Pydantic v2 settings extension for secure configuration management using HashiCorp Vault OpenSource (OSS) and Enterprise
Project description
pydantic2-settings-vault
Simple extension of pydantic_settings to collect secrets in HashiCorp Vault OpenSource (OSS) and Enterprise
pydantic2-settings-vault is a extension for Pydantic Settings that enables secure configuration management by integrating with HashiCorp Vault. This library supports both the open-source (OSS) and Enterprise versions of Vault, providing a seamless way to retrieve and manage secrets within your Pydantic-based applications. By leveraging Vault's robust security features, pydantic2-settings-vault allows developers to easily incorporate secure secret management practices into their Python projects, enhancing overall application security and simplifying the handling of sensitive configuration data.
Installation
pip
pip install pydantic2-settings-vault
poetry
poetry add pydantic2-settings-vault
uv
uv add pydantic2-settings-vault
Documentation
User documentation is published with MkDocs Material:
https://sylvainmouquet.github.io/pydantic2-settings-vault/
Build or preview locally:
just docs-serve # live reload at http://127.0.0.1:8000
just docs-build # static site in site/
| Guide | Description |
|---|---|
| Usage guide | Field annotations, end-to-end setup, environment variables, Vault policies |
| Authentication | All supported Vault auth methods |
| Advanced configuration | HTTP client tuning, secret cache, pre-startup validation |
| Vault KV & policies | KV v1/v2 paths, policy examples, field-mapping patterns |
| Development | Local development and testing |
Quick start
See the usage guide for the full guide. Minimal setup:
from pydantic import Field, SecretStr
from pydantic_settings import BaseSettings, PydanticBaseSettingsSource
from pydantic2_settings_vault import VaultConfigSettingsSource
class AppSettings(BaseSettings):
API_KEY: SecretStr = Field(
...,
json_schema_extra={
"vault_secret_path": "secret/myapp/config",
"vault_secret_key": "api_key",
},
)
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
env_settings,
dotenv_settings,
VaultConfigSettingsSource(settings_cls=settings_cls),
)
Set AppRole credentials and load settings:
export VAULT_URL="https://vault.example.com:8200"
export VAULT_ROLE_ID="<role-id>"
export VAULT_SECRET_ID="<secret-id>"
settings = AppSettings()
For KV v2 (default), use the logical path mount/secret-name in field metadata; the library adds the /data/ segment for HTTP reads.
Development
This project uses Just as its task runner. Install uv and just, then:
just install # install dependencies
just test # run tests
just coverage # run tests with 100% coverage enforcement
just lint # ruff check and format verification
just format # auto-fix lint issues and format code
just type-check # pyright static analysis
just check # lint, type-check, and test
just docs-serve # preview user documentation (MkDocs)
just docs-build # build user documentation
just build # build package (requires VERSION env var)
List all recipes:
just --list
See docs/development.md for the full task reference.
Authentication methods
Select the auth backend with VAULT_AUTH_METHOD (default: approle). Override the mount path with optional VAULT_AUTH_MOUNT. Per-method setup examples and policy guidance are in the authentication guide.
| Method | VAULT_AUTH_METHOD |
Required environment variables |
|---|---|---|
| AppRole (default) | approle |
VAULT_ROLE_ID, VAULT_SECRET_ID |
| Token | token |
VAULT_TOKEN |
| Kubernetes | kubernetes |
VAULT_K8S_ROLE, plus VAULT_K8S_JWT or service-account token file |
| AWS | aws |
VAULT_AWS_ROLE, plus signed STS request env vars or botocore credentials |
| GCP | gcp |
VAULT_GCP_ROLE, plus VAULT_GCP_JWT or GOOGLE_APPLICATION_CREDENTIALS |
| Azure | azure |
VAULT_AZURE_ROLE, plus VAULT_AZURE_JWT or Azure managed identity |
| JWT | jwt |
VAULT_JWT_ROLE, VAULT_JWT |
| OIDC | oidc |
VAULT_OIDC_ROLE, plus VAULT_OIDC_JWT or VAULT_OIDC_ID_TOKEN |
| Cert | cert |
VAULT_CLIENT_CERT, VAULT_CLIENT_KEY, optional VAULT_CERT_NAME |
| LDAP | ldap |
VAULT_LDAP_USERNAME, VAULT_LDAP_PASSWORD |
| OCI | oci |
VAULT_OCI_ROLE, plus signed request headers or oci SDK credentials |
| Userpass | userpass |
VAULT_USERPASS_USERNAME, VAULT_USERPASS_PASSWORD |
| GitHub | github |
VAULT_GITHUB_TOKEN |
| Okta | okta |
VAULT_OKTA_USERNAME, VAULT_OKTA_PASSWORD, optional VAULT_OKTA_TOTP |
| Kerberos | kerberos |
VAULT_KERBEROS_TOKEN (base64 SPNEGO token) |
| RADIUS | radius |
VAULT_RADIUS_USERNAME, VAULT_RADIUS_PASSWORD |
| Alicloud | alicloud |
VAULT_ALICLOUD_ROLE, plus pre-signed STS request env vars |
| CF | cf |
VAULT_CF_ROLE, plus instance cert/key or pre-signed login fields |
| PCF | pcf |
Same as CF (VAULT_CF_ROLE, instance cert/key or pre-signed fields) |
Common variables for every method:
VAULT_URL— Vault API address (default:http://127.0.0.1:8200)VAULT_NAMESPACE— optional Enterprise namespaceVAULT_KV_VERSION— KV engine version (1or2, default2)VAULT_AUTH_MOUNT— optional auth mount override (defaults match each method name above)
Token auth uses a pre-issued token directly; no login call is made.
Kubernetes auth reads the service-account JWT from VAULT_K8S_JWT or, by default, /var/run/secrets/kubernetes.io/serviceaccount/token.
AWS auth signs an STS GetCallerIdentity request with instance profile, environment keys, or web identity when botocore is installed (pip install pydantic2-settings-vault[aws]). You can also supply a pre-signed request via VAULT_AWS_IAM_REQUEST_URL, VAULT_AWS_IAM_REQUEST_BODY, and VAULT_AWS_IAM_REQUEST_HEADERS.
GCP auth obtains a service-account JWT from google-auth when installed (pip install pydantic2-settings-vault[gcp]), or from VAULT_GCP_JWT.
Azure auth obtains a managed-identity or service-principal token from azure-identity when installed (pip install pydantic2-settings-vault[azure]), or from VAULT_AZURE_JWT.
JWT auth sends a signed bearer token to the JWT auth mount (POST /v1/auth/jwt/login).
OIDC auth sends an OIDC ID token to the OIDC/JWT mount. Use VAULT_OIDC_JWT or VAULT_OIDC_ID_TOKEN. For Microsoft Entra ID distributed claims, set optional VAULT_OIDC_DISTRIBUTED_CLAIM_ACCESS_TOKEN.
Cert auth presents a TLS client certificate during login (POST /v1/auth/cert/login). Set VAULT_CLIENT_CERT and VAULT_CLIENT_KEY; optionally VAULT_CERT_NAME to target a specific certificate role.
LDAP auth binds with username and password (POST /v1/auth/ldap/login/<username>).
OCI auth signs a GET request to the OCI login endpoint. Provide pre-signed headers via VAULT_OCI_REQUEST_HEADERS, or install oci (pip install pydantic2-settings-vault[oci]) and use instance principal (VAULT_OCI_AUTH_TYPE=instance, default) or API key (VAULT_OCI_AUTH_TYPE=api_key with standard OCI config).
Userpass auth binds with username and password (POST /v1/auth/userpass/login/<username>).
GitHub auth sends a personal access token (POST /v1/auth/github/login).
Okta auth binds with username and password against Okta (POST /v1/auth/okta/login/<username>). Set optional VAULT_OKTA_TOTP and VAULT_OKTA_MFA_PROVIDER when MFA is required.
Kerberos auth sends a pre-generated SPNEGO token in the Authorization: Negotiate header (POST /v1/auth/kerberos/login). Set VAULT_KERBEROS_TOKEN to the base64 token value (without the Negotiate prefix).
RADIUS auth binds with username and password (POST /v1/auth/radius/login/<username>).
Alicloud auth verifies a signed STS GetCallerIdentity request. Provide VAULT_ALICLOUD_IDENTITY_REQUEST_URL and VAULT_ALICLOUD_IDENTITY_REQUEST_HEADERS (base64-encoded values from vault login -method=alicloud or your own signer).
CF auth signs the instance identity certificate with CF_INSTANCE_KEY (POST /v1/auth/cf/login). On a CF instance, set VAULT_CF_ROLE and rely on CF_INSTANCE_CERT / CF_INSTANCE_KEY, or provide VAULT_CF_SIGNING_TIME and VAULT_CF_SIGNATURE. Install cryptography (pip install pydantic2-settings-vault[cf]) to generate signatures locally.
PCF auth uses the same login payload as CF against the legacy pcf mount (POST /v1/auth/pcf/login).
Example token auth:
os.environ["VAULT_AUTH_METHOD"] = "token"
os.environ["VAULT_TOKEN"] = "<configure it>"
os.environ["VAULT_URL"] = "<configure it>"
Example Kubernetes auth:
os.environ["VAULT_AUTH_METHOD"] = "kubernetes"
os.environ["VAULT_K8S_ROLE"] = "<vault role>"
os.environ["VAULT_URL"] = "<configure it>"
# Optional: os.environ["VAULT_K8S_JWT"] = "<service account jwt>"
# Optional: os.environ["VAULT_AUTH_MOUNT"] = "kubernetes"
Advanced configuration
Vault client controls
Tune HTTP timeouts, retry behavior, and fetch concurrency via VaultClientConfig:
from pydantic2_settings_vault import VaultClientConfig, VaultConfigSettingsSource
client_config = VaultClientConfig(
request_timeout=30.0, # seconds per Vault HTTP request
max_concurrent_requests=5, # parallel secret fetches per settings load
retry_max_attempts=5, # retries on transient failures
retry_min_delay=0.1, # initial backoff (seconds)
retry_max_delay=2.0, # maximum backoff (seconds)
)
VaultConfigSettingsSource(
settings_cls=settings_cls,
client_config=client_config,
)
Recommended presets for common environments:
| Environment | Preset | Timeout | Concurrency | Retries | Backoff (min → max) |
|---|---|---|---|---|---|
| Local development | VaultClientConfig.for_local() |
60s | 3 | 3 | 0.2s → 1.0s |
| CI pipelines | VaultClientConfig.for_ci() |
15s | 5 | 2 | 0.05s → 0.2s |
| Production | VaultClientConfig.for_production() |
30s | 10 | 5 | 0.1s → 2.0s |
Use local presets when Vault runs in Docker or on a laptop (slower startup, fewer parallel calls). Use CI presets to fail fast when Vault is unavailable. Use production presets for resilient secret loading under higher load.
Secret cache
Vault path fetches are deduplicated within a single settings load. To avoid repeated Vault calls across multiple settings initializations, opt in to the in-memory cache (disabled by default):
from pydantic2_settings_vault import VaultConfigSettingsSource, VaultSecretCache
# Shared module-level cache with a 5-minute TTL
VaultConfigSettingsSource(
settings_cls=settings_cls,
cache_enabled=True,
cache_ttl_seconds=300,
)
# Or pass an explicit cache instance shared across sources
secret_cache = VaultSecretCache(ttl_seconds=300)
VaultConfigSettingsSource(settings_cls=settings_cls, secret_cache=secret_cache)
Cached values are still validated by Pydantic when settings are constructed.
Pre-startup validation
Validate Vault environment variables and field metadata before loading settings:
from pydantic2_settings_vault import validate_vault_configuration
result = validate_vault_configuration(AppSettings)
if not result.valid:
for issue in result.errors:
print(f"{issue.code}: {issue.message}")
# Or fail fast during application startup:
validate_vault_configuration(AppSettings).raise_if_invalid()
# Optionally verify Vault authentication without fetching secrets:
validate_vault_configuration(AppSettings, check_auth=True).raise_if_invalid()
How it works
sequenceDiagram
participant A as Your Application
participant B as BaseSettings
participant V as Vault
note over A,B: 1. Retrieve settings
A->>B: get_app_settings()
note over B: 2. Collect secrets paths
B->>B: foreach fields, get the secret path and keep unique value
note over B,V: 3. HTTPS Asynchronously fetch secrets by path from Vault
B->>V: get_secrets(secrets/data/<A>)
B->>V: get_secrets(secrets/data/<B>)
note over V,B: 4. Vault returns secrets
V->>B: return secrets for secrets/data/<A>
V->>B: return secrets for secrets/data/<B>
note over B: 5. Fill fields with secrets values
B->>B: SECRET_ONE => secrets/data/<A>[SECRET_ONE] <br> SECRET_TWO => secrets/data/<A>[SECRET_TWO] <br> SECRET_THREE => secrets/data/<B>[SECRET_THREE]
note over B,A: 6. Return settings
B->>A: settings with variables and secrets
License
Pydantic2-Settings-Vault is released under the MIT License. See the LICENSE file for more details.
Contact
For questions, suggestions, or issues related to Pydantic2-Settings-Vault, please open an issue on the GitHub repository.
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 pydantic2_settings_vault-2.0.0.tar.gz.
File metadata
- Download URL: pydantic2_settings_vault-2.0.0.tar.gz
- Upload date:
- Size: 245.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2a99cd7d90377631f59d11dffd9569a7f74ea006c49e2b95c9cf1128a29afad5
|
|
| MD5 |
235324051a5879239531cd87828e49b2
|
|
| BLAKE2b-256 |
db406a9cd7510754d83939b1f96fa55a91ab376d0b79dcf79afcff3524dc0593
|
File details
Details for the file pydantic2_settings_vault-2.0.0-py3-none-any.whl.
File metadata
- Download URL: pydantic2_settings_vault-2.0.0-py3-none-any.whl
- Upload date:
- Size: 26.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58d9a7b7c76e08225c9855490c1fda359ca6fc0377ad96a73f60809c93dc18fc
|
|
| MD5 |
6df3f85b717ed525b867620548dcba74
|
|
| BLAKE2b-256 |
bc693acf9c31616e877539c294ff2da71bcd46fc30fdd5d19f9e590d38d0e854
|