Envilder Python SDK
Securely load environment variables from AWS SSM Parameter Store or Azure Key Vault directly into your Python application. Zero vendor lock-in: secrets stay in your cloud.
Part of the Envilder project.
Prerequisites
- Python 3.10+
- AWS provider: AWS credentials configured (CLI, environment variables, or IAM role)
- Azure provider: Azure credentials via
az login, managed identity, or environment variables
Install
uv add envilder
# or
pip install envilder
Quick Start
One-liner
from envilder import Envilder
# Resolve secrets and inject into os.environ
Envilder.load('envilder.json')
import os
print(os.environ['DB_PASSWORD'])
Resolve without injecting
from envilder import Envilder
secrets = Envilder.resolve_file('envilder.json')
print(secrets['DB_PASSWORD'])
Fluent builder (with overrides)
Override the map file's $config at runtime: useful for switching providers,
profiles, or vault URLs per environment:
from envilder import Envilder, SecretProviderType
# Override provider + vault URL
secrets = (
Envilder.from_map_file('envilder.json')
.with_provider(SecretProviderType.AZURE)
.with_vault_url('https://my-vault.vault.azure.net')
.resolve()
)
# Override AWS profile and inject
(
Envilder.from_map_file('envilder.json')
.with_profile('staging')
.inject()
)
Environment-based loading
Route secret loading based on your current environment. Each environment
maps to its own secrets file (or None to skip loading):
from envilder import Envilder
import os
env = os.getenv('APP_ENV', 'development')
# Resolve + inject into os.environ
Envilder.load(env, {
'production': 'prod-secrets.json',
'development': 'dev-secrets.json',
'test': None, # no secrets loaded
})
Resolve without injecting:
secrets = Envilder.resolve_file(env, {
'production': 'prod-secrets.json',
'development': 'dev-secrets.json',
'test': None,
})
Behaviour:
- If the environment maps to a file path, secrets are loaded from that file.
- If the environment maps to
Noneor is not in the mapping, an empty dict is returned silently: no errors, no output. - The environment name is stripped of leading/trailing whitespace before lookup.
- Empty or whitespace-only environment names raise
ValueError.
Secret validation
Opt-in validation ensures all resolved secrets have non-empty values:
from envilder import Envilder, validate_secrets
secrets = Envilder.resolve_file('envilder.json')
validate_secrets(secrets) # raises SecretValidationError if any value is empty
validate_secrets() checks that:
- The dictionary is not empty (raises
SecretValidationErrorwith emptymissing_keys) - Every value is non-None and non-whitespace (raises
SecretValidationErrorlisting the failing keys) - Passes silently when all values are present
from envilder import SecretValidationError, validate_secrets
try:
validate_secrets(secrets)
except SecretValidationError as e:
print(f"Missing: {', '.join(e.missing_keys)}")
Advanced usage
Implement the ISecretProvider protocol to plug in a custom backend
(e.g., HashiCorp Vault, GCP Secret Manager):
from envilder import EnvilderClient, ISecretProvider, MapFileParser
class MyCustomProvider(ISecretProvider):
def get_secret(self, name: str) -> str | None:
# fetch from your custom backend
...
with open('envilder.json', encoding='utf-8') as file:
map_file = MapFileParser().parse(file.read())
provider = MyCustomProvider()
secrets = EnvilderClient(provider).resolve_secrets(map_file)
EnvilderClient.inject_into_environment(secrets)
API Reference
Static facade (Envilder)
| Method | Description |
|---|---|
load(path) |
Resolve secrets and inject into os.environ |
resolve_file(path) |
Resolve secrets, return as dict |
load(env, mapping) |
Environment-based resolve + inject |
resolve_file(env, mapping) |
Environment-based resolve |
from_map_file(path) |
Returns fluent builder for configuration |
Fluent builder (via from_map_file())
| Method | Description |
|---|---|
with_provider(type) |
Override secret provider (AWS/Azure) |
with_profile(name) |
Override AWS named profile |
with_vault_url(url) |
Override Azure Key Vault URL |
resolve() |
Resolve secrets, return as dict |
inject() |
Resolve + inject into os.environ |
Validation
| Function | Description |
|---|---|
validate_secrets(dict) |
Raises SecretValidationError if any value is empty or dict is empty |
Map File Format
{
"$schema": "https://envilder.com/schema/map-file.v1.json",
"$config": {
"provider": "aws",
"profile": "my-profile"
},
"DB_PASSWORD": "/app/prod/db-password",
"API_KEY": "/app/prod/api-key"
}
Supported providers: aws (default), azure.
For Azure, add vaultUrl:
{
"$schema": "https://envilder.com/schema/map-file.v1.json",
"$config": {
"provider": "azure",
"vaultUrl": "https://my-vault.vault.azure.net"
},
"DB_PASSWORD": "db-password",
"API_KEY": "api-key"
}
Links
License
MIT
Development
Setup
# From the repo root
make install-sdk-python
Quality checks
make check-sdk-python # black + isort + mypy (no changes)
make format-sdk-python # auto-format
Running tests
Unit tests run without any external dependencies:
cd tests/sdks/python
python -m pytest -v -m "not acceptance"
Acceptance tests require Docker and a LocalStack auth token:
export LOCALSTACK_AUTH_TOKEN=<your-token>
cd tests/sdks/python
python -m pytest -v -m acceptance
All tests:
make test-sdk-python
Metadata
Release files for envilder 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| envilder-0.5.1.tar.gz | 77.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| envilder-0.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 95.5 kB
Release files / envilder-0.5.1.tar.gz
| Download URL | envilder-0.5.1.tar.gz |
|---|---|
| Size | 77.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ab607ff37df7ce968f2d0a35fdbe1cebfd7ac0c55c34547468527e04b2851492
|
|
BLAKE2b-256 checksum How to use checksums |
c3c622a2a6ff8540ce87e870647c212d2b52eb889acfc4a649c55a96b7a232be
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency logRelease files / envilder-0.5.1-py3-none-any.whl
| Download URL | envilder-0.5.1-py3-none-any.whl |
|---|---|
| Size | 18.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5b46addd867542f85f29a2f3d89ba2923d76f80fc404df6ad44cbf10a614b585
|
|
BLAKE2b-256 checksum How to use checksums |
799bc7e70841062a28d3ffda9c1271c0dab8d67261dda148b4bb1863554000a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency log