Settings management using Pydantic with support for multiple configuration sources including environment variables, configuration files, CLI arguments, and cloud secret management services
—
Integration with major cloud providers' secret management services including AWS Secrets Manager, Azure Key Vault, and Google Secret Manager. These sources enable secure configuration management in cloud environments with automatic credential handling and secret retrieval.
Load settings from AWS Secrets Manager with support for automatic credential detection and JSON secret parsing.
class AWSSecretsManagerSettingsSource(EnvSettingsSource):
"""Source for AWS Secrets Manager."""
def __init__(
self,
settings_cls: type[BaseSettings],
aws_secret_name: str | None = None,
aws_secret_key: str | None = None,
aws_session_token: str | None = None,
aws_access_key_id: str | None = None,
aws_secret_access_key: str | None = None,
aws_region_name: str | None = None,
case_sensitive: bool | None = None,
env_prefix: str | None = None,
env_nested_delimiter: str | None = None,
env_nested_max_split: int | None = None,
env_ignore_empty: bool | None = None,
env_parse_none_str: str | None = None,
env_parse_enums: bool | None = None,
):
"""
Initialize AWS Secrets Manager settings source.
Parameters:
- settings_cls: The settings class
- aws_secret_name: Name of the secret in AWS Secrets Manager
- aws_secret_key: Specific key within the secret (for JSON secrets)
- aws_session_token: AWS session token for authentication
- aws_access_key_id: AWS access key ID
- aws_secret_access_key: AWS secret access key
- aws_region_name: AWS region name
- case_sensitive: Whether secret keys are case-sensitive
- env_prefix: Prefix for secret keys
- env_nested_delimiter: Delimiter for nested secret values
- env_nested_max_split: Maximum splits for nested values
- env_ignore_empty: Whether to ignore empty secret values
- env_parse_none_str: String value to parse as None
- env_parse_enums: Whether to parse enum field names to values
"""Load settings from Azure Key Vault with support for managed identity authentication and secret versioning.
class AzureKeyVaultSettingsSource(EnvSettingsSource):
"""Source for Azure Key Vault."""
def __init__(
self,
settings_cls: type[BaseSettings],
azure_key_vault_url: str | None = None,
azure_client_id: str | None = None,
azure_client_secret: str | None = None,
azure_tenant_id: str | None = None,
case_sensitive: bool | None = None,
env_prefix: str | None = None,
env_nested_delimiter: str | None = None,
env_nested_max_split: int | None = None,
env_ignore_empty: bool | None = None,
env_parse_none_str: str | None = None,
env_parse_enums: bool | None = None,
):
"""
Initialize Azure Key Vault settings source.
Parameters:
- settings_cls: The settings class
- azure_key_vault_url: URL of the Azure Key Vault
- azure_client_id: Azure client ID for service principal auth
- azure_client_secret: Azure client secret for service principal auth
- azure_tenant_id: Azure tenant ID
- case_sensitive: Whether secret names are case-sensitive
- env_prefix: Prefix for secret names
- env_nested_delimiter: Delimiter for nested secret values
- env_nested_max_split: Maximum splits for nested values
- env_ignore_empty: Whether to ignore empty secret values
- env_parse_none_str: String value to parse as None
- env_parse_enums: Whether to parse enum field names to values
"""
class AzureKeyVaultMapping(Mapping[str, Optional[str]]):
"""Mapping interface for Azure Key Vault secrets."""
def __init__(
self,
vault_url: str,
credential: Any,
case_sensitive: bool = False,
env_prefix: str = "",
): ...Load settings from Google Secret Manager with support for service account authentication and project-based secret access.
class GoogleSecretManagerSettingsSource(EnvSettingsSource):
"""Source for Google Secret Manager."""
def __init__(
self,
settings_cls: type[BaseSettings],
gcp_project_id: str | None = None,
gcp_secret_name: str | None = None,
gcp_secret_version: str | None = None,
case_sensitive: bool | None = None,
env_prefix: str | None = None,
env_nested_delimiter: str | None = None,
env_nested_max_split: int | None = None,
env_ignore_empty: bool | None = None,
env_parse_none_str: str | None = None,
env_parse_enums: bool | None = None,
):
"""
Initialize Google Secret Manager settings source.
Parameters:
- settings_cls: The settings class
- gcp_project_id: Google Cloud project ID
- gcp_secret_name: Name of the secret in Secret Manager
- gcp_secret_version: Version of the secret (defaults to 'latest')
- case_sensitive: Whether secret names are case-sensitive
- env_prefix: Prefix for secret names
- env_nested_delimiter: Delimiter for nested secret values
- env_nested_max_split: Maximum splits for nested values
- env_ignore_empty: Whether to ignore empty secret values
- env_parse_none_str: String value to parse as None
- env_parse_enums: Whether to parse enum field names to values
"""
class GoogleSecretManagerMapping(Mapping[str, Optional[str]]):
"""Mapping interface for Google Secret Manager secrets."""
def __init__(
self,
project_id: str,
secret_name: str | None = None,
secret_version: str = "latest",
case_sensitive: bool = False,
env_prefix: str = "",
): ...from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic_settings import AWSSecretsManagerSettingsSource
class AppSettings(BaseSettings):
database_url: str
api_key: str
debug: bool = False
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
AWSSecretsManagerSettingsSource(
settings_cls,
aws_secret_name="myapp/production/config",
aws_region_name="us-east-1"
),
env_settings,
dotenv_settings,
file_secret_settings,
)
# Requires boto3 and AWS credentials configured
# Secret in AWS: {"database_url": "postgresql://...", "api_key": "secret123"}
settings = AppSettings()class DatabaseSettings(BaseSettings):
host: str
port: int
username: str
password: str
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
AWSSecretsManagerSettingsSource(
settings_cls,
aws_secret_name="myapp/database",
aws_secret_key="production", # Load from "production" key in JSON
aws_region_name="us-west-2"
),
env_settings,
)
# AWS Secret structure:
# {
# "production": {
# "host": "prod-db.company.com",
# "port": 5432,
# "username": "app_user",
# "password": "secure_password"
# },
# "staging": { ... }
# }
settings = DatabaseSettings()class AppSettings(BaseSettings):
api_token: str
service_url: str
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
AWSSecretsManagerSettingsSource(
settings_cls,
aws_secret_name="myapp/api-config",
aws_access_key_id="AKIA...",
aws_secret_access_key="...",
aws_region_name="eu-west-1"
),
env_settings,
)
settings = AppSettings()from pydantic_settings import AzureKeyVaultSettingsSource
class AppSettings(BaseSettings):
database_password: str
api_key: str
encryption_key: str
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
AzureKeyVaultSettingsSource(
settings_cls,
azure_key_vault_url="https://myapp-vault.vault.azure.net/",
azure_tenant_id="12345678-1234-1234-1234-123456789012"
),
env_settings,
)
# Requires azure-keyvault-secrets and azure-identity packages
# Uses DefaultAzureCredential for authentication (managed identity, etc.)
settings = AppSettings()class ProductionSettings(BaseSettings):
db_connection_string: str
jwt_secret: str
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
AzureKeyVaultSettingsSource(
settings_cls,
azure_key_vault_url="https://prod-vault.vault.azure.net/",
azure_client_id="app-service-principal-id",
azure_client_secret="service-principal-secret",
azure_tenant_id="company-tenant-id"
),
env_settings,
)
settings = ProductionSettings()from pydantic_settings import GoogleSecretManagerSettingsSource
class AppSettings(BaseSettings):
database_url: str
api_key: str
encryption_key: str
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
GoogleSecretManagerSettingsSource(
settings_cls,
gcp_project_id="my-gcp-project",
gcp_secret_name="myapp-config"
),
env_settings,
)
# Requires google-cloud-secret-manager package
# Uses Application Default Credentials or service account
settings = AppSettings()class AppSettings(BaseSettings):
api_key: str
database_password: str
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
GoogleSecretManagerSettingsSource(
settings_cls,
gcp_project_id="production-project",
gcp_secret_name="app-secrets",
gcp_secret_version="3" # Use specific version instead of 'latest'
),
env_settings,
)
settings = AppSettings()class MultiCloudSettings(BaseSettings):
# Different secrets from different providers
aws_api_key: str # From AWS Secrets Manager
azure_db_password: str # From Azure Key Vault
gcp_service_token: str # From Google Secret Manager
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
# AWS for API keys
AWSSecretsManagerSettingsSource(
settings_cls,
aws_secret_name="myapp/aws-config",
aws_region_name="us-east-1",
env_prefix="aws_"
),
# Azure for database secrets
AzureKeyVaultSettingsSource(
settings_cls,
azure_key_vault_url="https://db-vault.vault.azure.net/",
env_prefix="azure_"
),
# GCP for service tokens
GoogleSecretManagerSettingsSource(
settings_cls,
gcp_project_id="services-project",
gcp_secret_name="service-tokens",
env_prefix="gcp_"
),
env_settings,
)
settings = MultiCloudSettings()class FlexibleSettings(BaseSettings):
database_url: str
api_key: str
debug: bool = False
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
# Environment variables take precedence over cloud secrets
return (
init_settings,
env_settings, # Highest priority
AWSSecretsManagerSettingsSource(
settings_cls,
aws_secret_name="myapp/config",
aws_region_name="us-east-1"
),
dotenv_settings,
file_secret_settings,
)
# Can override cloud secrets with environment variables
# export DATABASE_URL="postgresql://localhost/dev" # Overrides AWS secret
settings = FlexibleSettings()from pydantic_settings import SettingsError
class RobustSettings(BaseSettings):
api_key: str
database_url: str
@classmethod
def settings_customise_sources(
cls,
settings_cls,
init_settings,
env_settings,
dotenv_settings,
file_secret_settings,
):
return (
init_settings,
env_settings,
# Fallback to local secrets if cloud fails
file_secret_settings,
dotenv_settings,
)
# Handle cloud provider authentication/access issues
try:
settings = RobustSettings()
except SettingsError as e:
print(f"Failed to load settings: {e}")
# Fallback to environment variables or local files
import os
os.environ['API_KEY'] = 'fallback-key'
settings = RobustSettings()Install with Tessl CLI
npx tessl i tessl/pypi-pydantic-settings