Skip to main content

A Pydantic v2 settings extension for secure configuration management using HashiCorp Vault OpenSource (OSS) and Enterprise

Project description

license python version version

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 namespace
  • VAULT_KV_VERSION — KV engine version (1 or 2, default 2)
  • 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

pydantic2_settings_vault-2.0.0.tar.gz (245.4 kB view details)

Uploaded Source

Built Distribution

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

pydantic2_settings_vault-2.0.0-py3-none-any.whl (26.1 kB view details)

Uploaded Python 3

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

Hashes for pydantic2_settings_vault-2.0.0.tar.gz
Algorithm Hash digest
SHA256 2a99cd7d90377631f59d11dffd9569a7f74ea006c49e2b95c9cf1128a29afad5
MD5 235324051a5879239531cd87828e49b2
BLAKE2b-256 db406a9cd7510754d83939b1f96fa55a91ab376d0b79dcf79afcff3524dc0593

See more details on using hashes here.

File details

Details for the file pydantic2_settings_vault-2.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pydantic2_settings_vault-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 58d9a7b7c76e08225c9855490c1fda359ca6fc0377ad96a73f60809c93dc18fc
MD5 6df3f85b717ed525b867620548dcba74
BLAKE2b-256 bc693acf9c31616e877539c294ff2da71bcd46fc30fdd5d19f9e590d38d0e854

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