Use a random-generated secret key stored in either the environment variables or in a file in the app directory instead of hard-coding.
55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
import os
|
|
import sys
|
|
from typing import Optional
|
|
import secrets
|
|
from warnings import warn
|
|
|
|
def get_secret_key() -> str:
|
|
"""
|
|
Secure secret key loader with fail-safes for different environments.
|
|
Priority:
|
|
1. Explicit environment variable (FLASK_SECRET_KEY)
|
|
2. Secret file (./.flask_secret_key)
|
|
3. Generated temporary key (development only)
|
|
|
|
Returns:
|
|
str: The secret key
|
|
|
|
Raises:
|
|
RuntimeError: In production if no key is configured
|
|
"""
|
|
# 1. Check environment variable first
|
|
if 'FLASK_SECRET_KEY' in os.environ:
|
|
if len(os.environ['FLASK_SECRET_KEY']) < 32:
|
|
warn('Weak secret key (min 32 chars recommended)')
|
|
return os.environ['FLASK_SECRET_KEY']
|
|
|
|
# 2. Check for secret file (Docker/K8s compatible)
|
|
secret_file = '.flask_secret_key'
|
|
if os.path.exists(secret_file):
|
|
with open(secret_file) as f:
|
|
key = f.read().strip()
|
|
if len(key) >= 32:
|
|
return key
|
|
warn(f'Weak key in {secret_file} (min 32 chars)')
|
|
|
|
# 3. Development fallback
|
|
if os.getenv('FLASK_ENV') == 'development':
|
|
key = secrets.token_hex(32)
|
|
warn(f'Using temporary development key: {key[:8]}...')
|
|
return key
|
|
|
|
# 4. Production failure
|
|
raise RuntimeError(
|
|
"No valid secret key configured.\n"
|
|
"Set FLASK_SECRET_KEY environment variable or "
|
|
f"create {secret_file} with 32+ random characters."
|
|
)
|
|
|
|
def generate_key() -> str:
|
|
"""Generate a strong secret key for configuration"""
|
|
return secrets.token_urlsafe(64) # URL-safe for easier handling
|
|
|
|
if __name__ == '__main__':
|
|
# CLI for key generation
|
|
print(f"New secret key: {generate_key()}") |