Securely load and manage encrypted environment variables
Project description
Encrypted Environment Loader
A secure Python package for managing encrypted environment variables. Load sensitive configuration from encrypted .env files using Fernet encryption.
Features
- Secure encryption using Fernet (AES 128 in CBC mode with HMAC-SHA256)
- Profile support for multiple environments (dev, prod, test, etc.)
- CLI tools for file management and subprocess execution
- Python API with context managers and decorators
- Shell integration for fish, bash, and zsh
- Safe editing with backup and validation
- CI/CD friendly with quiet modes and secret masking
- Modern Python with type hints and proper packaging
Installation
pip install encrypted-env-loader
Quick Start
1. Initialize a new encrypted environment file
# Generate new encrypted file with random key
encrypted-env init
# Output: Encryption key: gAAAAABh...
# Output: Set your encryption key: export ENCRYPTED_ENV_KEY='gAAAAABh...'
# Set the key in your shell
export ENCRYPTED_ENV_KEY='gAAAAABh...'
2. Edit your environment variables
# Opens decrypted content in $EDITOR, re-encrypts on save
encrypted-env edit
3. Run commands with encrypted environment
# Run any command with encrypted env loaded
encrypted-env run -- python app.py
encrypted-env run -- ./deploy.sh
Security Features
CI/CD Safe Operations
All commands support --quiet mode for CI environments and have secure defaults:
# Generate keys silently (CI-safe)
KEY=$(encrypted-env generate-key --quiet)
# Show variable names only (never exposes values)
encrypted-env show --names-only
# Validate files without output (exit codes only)
encrypted-env validate --quiet
Secret Masking
By default, commands mask sensitive values:
# Safe - shows masked values
encrypted-env show
# Output: DATABASE_URL=***
# API_KEY=***
# Requires explicit flag to show values
encrypted-env show --show-values # WARNING: exposes secrets
Examples and Testing
Run the comprehensive demo to see all features:
# Interactive demo with full output
./examples/demo.sh
# CI-friendly mode (no secrets exposed)
./examples/demo.sh --ci
# View usage examples
./examples/basic_usage.sh
CLI Reference
Core Operations
run - Execute commands with encrypted environment
encrypted-env run [--file FILE] [--profile PROFILE] -- <command>
# Examples
encrypted-env run -- python app.py
encrypted-env run --profile prod -- ./deploy.sh
encrypted-env run --file .env.custom.encrypted -- npm start
load - Generate shell commands to load environment
encrypted-env load [--file FILE] [--profile PROFILE] [--shell SHELL] [--quiet]
# Usage in fish shell
eval (encrypted-env load)
eval (encrypted-env load --profile dev)
# Usage in bash/zsh
eval $(encrypted-env load)
eval $(encrypted-env load --profile prod)
clear - Generate shell commands to clear environment
encrypted-env clear [--file FILE] [--profile PROFILE] [--shell SHELL] [--quiet]
# Usage
eval (encrypted-env clear) # fish
eval $(encrypted-env clear) # bash/zsh
File Management
init - Create new encrypted environment file
encrypted-env init [--file FILE] [--profile PROFILE] [--key-file KEYFILE] [--quiet]
# Examples
encrypted-env init # creates .env.encrypted
encrypted-env init --profile dev # creates .env.dev.encrypted
encrypted-env init --key-file .env.key # saves key to file
encrypted-env init --quiet # CI-friendly (key only)
encrypt - Encrypt existing .env file
encrypted-env encrypt <source> [--output OUTPUT] [--profile PROFILE] [--quiet]
# Examples
encrypted-env encrypt .env # creates .env.encrypted
encrypted-env encrypt .env.dev --profile dev # creates .env.dev.encrypted
encrypted-env encrypt .env --output custom.encrypted
decrypt - Decrypt to filesystem
encrypted-env decrypt [--file FILE] [--output OUTPUT] [--profile PROFILE] [--quiet]
# Examples
encrypted-env decrypt # decrypts to .env
encrypted-env decrypt --profile dev # decrypts .env.dev.encrypted to .env
encrypted-env decrypt --output .env.backup # custom output file
edit - Safely edit encrypted files
encrypted-env edit [--file FILE] [--profile PROFILE] [--quiet]
# Opens in $EDITOR (vi by default)
# Creates backup before editing
# Validates .env format before re-encrypting
encrypted-env edit --profile prod
Key Management
generate-key - Generate new encryption key
encrypted-env generate-key [--quiet]
# Interactive mode
encrypted-env generate-key
# Output: Generated key: gAAAAABh...
# CI mode
encrypted-env generate-key --quiet
# Output: gAAAAABh...
rekey - Change encryption key
encrypted-env rekey [--file FILE] [--profile PROFILE] [--old-key-env VAR] [--new-key-env VAR] [--quiet]
# Examples
ENCRYPTED_ENV_KEY="old_key" NEW_KEY="new_key" encrypted-env rekey --new-key-env NEW_KEY
encrypted-env rekey --quiet # generates new random key silently
Utilities
status - Show file information and variables
encrypted-env status [--file FILE] [--profile PROFILE]
# Example output:
# File: .env.encrypted
# Exists: True
# Size: 1024 bytes
# Key source: $ENCRYPTED_ENV_KEY
# Status: Valid (contains 5 variables)
# Variables:
# - DATABASE_URL
# - SECRET_KEY
validate - Check if file can be decrypted
encrypted-env validate [--file FILE] [--profile PROFILE] [--quiet]
# Exit code 0 if valid, 1 if invalid
show - Display variables (with security options)
encrypted-env show [--file FILE] [--profile PROFILE] [--names-only] [--show-values]
# Safe default (masks values)
encrypted-env show
# Output: DATABASE_URL=***
# CI-safe (names only)
encrypted-env show --names-only
# Output: DATABASE_URL
# API_KEY
# Explicit flag required to show values
encrypted-env show --show-values # WARNING: exposes secrets
Python API
Basic Usage
from encrypted_env_loader import load_encrypted_env
# Load with default settings (.env.encrypted, ENCRYPTED_ENV_KEY)
env_vars = load_encrypted_env()
# Load with specific parameters
env_vars = load_encrypted_env(
key="base64-encoded-key",
file_path=".env.prod.encrypted",
profile="prod",
change_os_env=True # Updates os.environ
)
Context Manager
from encrypted_env_loader import encrypted_env_context
import os
with encrypted_env_context(profile="dev"):
# Environment variables loaded here
database_url = os.getenv("DATABASE_URL")
secret_key = os.getenv("SECRET_KEY")
# Environment automatically restored when exiting context
Decorator
from encrypted_env_loader import with_encrypted_env
import os
@with_encrypted_env(profile="prod")
def deploy_application():
# Function runs with encrypted env loaded
api_key = os.getenv("API_KEY")
database_url = os.getenv("DATABASE_URL")
# Environment restored after function returns
deploy_application()
Utility Functions
from encrypted_env_loader import (
generate_key,
encrypt_env_file,
decrypt_env_file,
validate_encrypted_file
)
# Generate encryption key
key = generate_key()
# Encrypt a file
encrypt_env_file(".env", ".env.encrypted", key)
# Decrypt and get variables
env_vars = decrypt_env_file(".env.encrypted", key=key)
# Validate file
is_valid = validate_encrypted_file(".env.encrypted", key=key)
Profiles
Profiles allow managing multiple environment configurations:
# Profile-based file naming
.env.encrypted # default profile
.env.dev.encrypted # dev profile
.env.prod.encrypted # prod profile
.env.test.encrypted # test profile
# Usage
encrypted-env init --profile dev
encrypted-env run --profile prod -- python app.py
encrypted-env edit --profile test
Shell Integration
Fish Shell
# Load environment
eval (encrypted-env load --profile dev)
# Clear environment
eval (encrypted-env clear --profile dev)
# One-liner with auto-clear
encrypted-env run --profile dev -- python app.py
Bash/Zsh
# Load environment
eval $(encrypted-env load --profile dev)
# Clear environment
eval $(encrypted-env clear --profile dev)
# Use in loops (eval once, use many times)
eval $(encrypted-env load)
for i in {1..100}; do
curl -H "Authorization: $SECRET_TOKEN" api.example.com/data/$i
done
eval $(encrypted-env clear)
CI/CD Integration
GitHub Actions Example
- name: Setup encrypted environment
run: |
# Generate or retrieve key securely
echo "${{ secrets.ENCRYPTED_ENV_KEY }}" > .env.key
export ENCRYPTED_ENV_KEY=$(cat .env.key)
# Validate encrypted file
encrypted-env validate --quiet
# Run tests with encrypted environment
encrypted-env run -- pytest
Security Best Practices
# Never expose secrets in CI logs
encrypted-env show --names-only # ✅ Safe
encrypted-env validate --quiet # ✅ Safe
encrypted-env generate-key --quiet # ✅ Safe
# Avoid these in CI
encrypted-env show --show-values # ❌ Exposes secrets
encrypted-env status # ❌ May expose info
Security Considerations
- Key Storage: Never commit encryption keys to version control
- Key Rotation: Regularly rotate encryption keys using
rekeycommand - File Permissions: Ensure encrypted files have appropriate permissions
- Backup Strategy: Keep secure backups of both encrypted files and keys
- Environment Isolation: Use profiles to separate dev/staging/prod secrets
- CI/CD Safety: Use
--quietand--names-onlyflags in automated environments
Error Handling
The package provides specific exception types:
from encrypted_env_loader import EncryptedEnvError, DecryptionError, KeyError
try:
load_encrypted_env()
except KeyError:
print("Encryption key missing or invalid")
except DecryptionError:
print("File cannot be decrypted - wrong key or corrupted data")
except EncryptedEnvError:
print("General error with encrypted environment operations")
Development
Setup
git clone https://github.com/igutekunst/encrypted-env-loader
cd encrypted-env-loader
pip install -e ".[dev]"
Testing
# Run unit tests
pytest
# Run full demo/integration tests
./examples/demo.sh
# Run CI-safe tests
./examples/demo.sh --ci
# Test coverage
pytest --cov=encrypted_env_loader
Code Quality
black src tests
isort src tests
flake8 src tests
mypy src
License
MIT License - see LICENSE file.
Contributing
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
Changelog
0.1.0
- Initial release
- Basic encryption/decryption functionality
- CLI with all core commands
- Python API with context managers and decorators
- Profile support
- Shell integration
- CI/CD safety features with quiet modes and secret masking
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 encrypted_env_loader-0.2.0.tar.gz.
File metadata
- Download URL: encrypted_env_loader-0.2.0.tar.gz
- Upload date:
- Size: 18.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54d1a8fe5b23c47966d31991027beb1ebd4daabd43104977510493a0d9722f9d
|
|
| MD5 |
58aacc05b75613815b45f007aa85f27b
|
|
| BLAKE2b-256 |
05b501975714c39ee4eda95e0a72182a3ff60e5fab7212739c6a2a8ea52b9048
|
File details
Details for the file encrypted_env_loader-0.2.0-py3-none-any.whl.
File metadata
- Download URL: encrypted_env_loader-0.2.0-py3-none-any.whl
- Upload date:
- Size: 14.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.11.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d76c4d2a5920f8d4c8fe6ed33db46ddd3d05a2d38f8290d4f0782fec91a71021
|
|
| MD5 |
e29c323a85dbe42239c7f6db3e553da7
|
|
| BLAKE2b-256 |
42f501d7a10c476de0a48419c5c6c9aba1c49590ccff3b3ee3d7928da7eec9e2
|