Security¶
Secret management, authentication, and encryption for production applications.
Overview¶
The security module provides:
- Secret Management: Secure storage and retrieval from multiple backends
- Authentication: Token providers and rotation
- Encryption: Symmetric encryption and password hashing
- Best Practices: Production-ready security patterns
Secret Management¶
Why Secret Management?¶
Secrets (API keys, passwords, tokens) should never be: - Hardcoded in source code - Committed to version control - Logged in plain text - Shared between environments
Secret Backends¶
Environment Variables¶
Simple, works everywhere:
from dspu.security import SecretManager
# Load from environment
secrets = SecretManager.from_env()
api_key = await secrets.get("API_KEY")
Use Case: Development, simple deployments, containers
HashiCorp Vault¶
Enterprise secret management:
# Connect to Vault
secrets = SecretManager.from_vault(
url="https://vault.example.com",
token="s.abc123"
)
# Read secret
db_password = await secrets.get("database/password")
Use Case: Enterprise, multi-environment, secret rotation
AWS Secrets Manager¶
AWS-native secret storage:
# Connect to AWS Secrets Manager
secrets = SecretManager.from_aws(region="us-east-1")
# Read secret
api_key = await secrets.get("prod/api/key")
Use Case: AWS deployments, IAM integration
Auto-Detection¶
Automatically select backend:
Secret Operations¶
# Get secret
value = await secrets.get("key")
# Set secret (if backend supports)
await secrets.set("key", "value")
# List secrets
keys = await secrets.list_secrets("prefix/*")
Authentication¶
Authentication Providers¶
Static Token¶
Simple API key authentication:
from dspu.security import StaticTokenProvider
auth = StaticTokenProvider(token="sk_live_abc123")
token = await auth.get_token()
# Use in requests
headers = {"Authorization": f"Bearer {token}"}
JWT¶
JSON Web Tokens:
from dspu.security import JWTProvider
auth = JWTProvider(
secret_key="your-secret-key",
issuer="my-service",
expiry_seconds=3600 # 1 hour
)
# Generate token
token = await auth.get_token(
scopes=["read", "write"],
claims={"user_id": 123}
)
# Verify token
claims = auth.verify_token(token)
OAuth2¶
OAuth2 client credentials flow:
from dspu.security import OAuth2Provider
auth = OAuth2Provider(
client_id="client_id",
client_secret="client_secret",
token_url="https://auth.example.com/token"
)
token = await auth.get_token()
Token Rotation¶
Automatic token refresh:
from dspu.security import RotatingToken, TokenData
# Define refresh function
async def fetch_token() -> TokenData:
response = await auth_api.get_token()
return TokenData(
token=response["access_token"],
expires_at=parse_expiry(response["expires_in"])
)
# Create rotating token
async with RotatingToken(
fetch_fn=fetch_token,
refresh_before=300 # Refresh 5 minutes before expiry
) as rotating:
# Always get fresh token
headers = {"Authorization": f"Bearer {rotating.current}"}
await api_client.get("/data", headers=headers)
Benefits: - Automatic refresh before expiry - Thread-safe access - Callbacks for monitoring
Encryption¶
Fernet (Simple)¶
Symmetric encryption:
from dspu.security import Fernet
# Generate key
key = Fernet.generate_key()
cipher = Fernet(key)
# Encrypt
encrypted = cipher.encrypt(b"sensitive data")
# Decrypt
decrypted = cipher.decrypt(encrypted)
Use Case: Simple encryption, config files, database fields
AES-256-GCM (Advanced)¶
Authenticated encryption:
from dspu.security import AES
# Generate key
key = AES.generate_key()
cipher = AES(key)
# Encrypt
encrypted = cipher.encrypt(b"sensitive data")
# Decrypt (verifies authenticity)
decrypted = cipher.decrypt(encrypted)
Use Case: High-security requirements, authenticated data
Password Hashing¶
Never store plain text passwords:
from dspu.security import hash_password, verify_password
# Hash password before storing
hashed = hash_password("user_password")
user.password_hash = hashed
# Verify on login
if verify_password("user_password", user.password_hash):
# Login successful
...
Features: - PBKDF2 with SHA-256 - Automatic salt generation - Configurable iterations
Secure Tokens¶
Generate cryptographically secure tokens:
from dspu.security import generate_secure_token
# Generate random token
token = generate_secure_token(length=32) # 32 bytes = 64 hex chars
# Use for session IDs, API keys, etc.
Data Hashing¶
Integrity verification:
from dspu.security import hash_data
# Hash data
hash_value = hash_data(b"data", algorithm="sha256")
# Compare hashes (constant time)
from dspu.security import constant_time_compare
is_same = constant_time_compare(hash1, hash2)
Common Patterns¶
Pattern 1: Application Configuration¶
from dspu.security import SecretManager
from dspu.config import Config, FileSource, EnvSource
# Load base config from file
config = Config.load_from_file(AppConfig, "config.yaml")
# Load secrets separately
secrets = SecretManager.from_env()
config.database.password = await secrets.get("database/password")
config.api_key = await secrets.get("api/key")
Pattern 2: Service Authentication¶
from dspu.security import JWTProvider, RotatingToken
# Setup JWT provider
jwt_secret = await secrets.get("jwt/secret")
auth = JWTProvider(secret_key=jwt_secret, expiry_seconds=900)
# Create rotating token
async def fetch_token():
token = await auth.get_token(scopes=["api:read", "api:write"])
# Token expires in 900 seconds
expires_at = datetime.now() + timedelta(seconds=900)
return TokenData(token=token, expires_at=expires_at)
async with RotatingToken(fetch_fn=fetch_token) as rotating:
# Use rotating.current in all API calls
await api.call(token=rotating.current)
Pattern 3: Database Field Encryption¶
from dspu.security import Fernet
# Get encryption key from secrets
encryption_key = await secrets.get("encryption/key")
cipher = Fernet(encryption_key.encode())
# Encrypt before storing
class User:
def __init__(self, email: str, phone: str):
self.email_encrypted = cipher.encrypt(email.encode())
self.phone_encrypted = cipher.encrypt(phone.encode())
@property
def email(self) -> str:
return cipher.decrypt(self.email_encrypted).decode()
@property
def phone(self) -> str:
return cipher.decrypt(self.phone_encrypted).decode()
Pattern 4: API Key Generation¶
from dspu.security import generate_secure_token, hash_password
# Generate API key
api_key = f"sk_live_{generate_secure_token(32)}"
# Hash before storing (like passwords)
api_key_hash = hash_password(api_key)
store_in_database(user_id, api_key_hash)
# Verify on API request
if verify_password(provided_key, stored_hash):
# Valid API key
...
Best Practices¶
Secret Management¶
✅ DO: - Use Vault or cloud secret managers in production - Rotate secrets regularly - Use environment variables for simple deployments - Separate secrets by environment - Audit secret access
❌ DON'T: - Don't commit secrets to git - Don't log secrets - Don't hardcode secrets - Don't share secrets between environments - Don't use weak secrets
Authentication¶
✅ DO: - Use short-lived tokens (15-60 minutes) - Implement automatic token rotation - Store JWT secrets in secret manager - Use HTTPS for all token transmission - Validate tokens on every request
❌ DON'T: - Don't use weak signing keys - Don't skip token expiry checks - Don't store tokens in localStorage (XSS risk) - Don't share tokens between services - Don't log tokens
Encryption¶
✅ DO: - Use AES-256-GCM for authenticated encryption - Generate keys with cryptographically secure methods - Store keys separately from encrypted data - Implement key rotation - Use Fernet for simplicity
❌ DON'T: - Don't roll your own cryptography - Don't use weak algorithms (DES, RC4, MD5) - Don't hardcode encryption keys - Don't skip authentication (use GCM/HMAC) - Don't reuse keys across environments
Password Security¶
✅ DO: - Always hash passwords before storing - Use PBKDF2/bcrypt/scrypt/Argon2 - Generate random salts per password - Use sufficient iterations (100,000+) - Enforce strong password requirements
❌ DON'T: - Don't store plain text passwords - Don't use simple hashing (MD5, SHA1) - Don't use same salt for all passwords - Don't skip salts - Don't allow weak passwords
Security Checklist¶
Development¶
- No secrets in source code
- No secrets in version control
- .gitignore configured for secrets
- Local secrets in environment/files
- Secrets documented
Production¶
- Secrets in secret manager (Vault/AWS)
- TLS/HTTPS everywhere
- Token rotation implemented
- Encryption keys rotated
- Audit logging enabled
- Secrets access restricted (IAM/RBAC)
- Regular security reviews
Code¶
- Input validation
- Output encoding
- SQL injection prevention
- XSS prevention
- CSRF protection
- Rate limiting
- Authentication on all endpoints
- Authorization checks
Installation¶
Includes:
- cryptography - Encryption
- pyjwt - JWT tokens
- hvac - Vault integration