Fix: Secret Key

Use a random-generated secret key stored in either the environment
variables or in a file in the app directory instead of hard-coding.
This commit is contained in:
Candifloss 2025-04-03 10:49:17 +05:30
parent deeaf9e645
commit 55dd86c27c
4 changed files with 59 additions and 3 deletions

1
.gitignore vendored
View File

@ -162,3 +162,4 @@ cython_debug/
inventory_export.csv
config.py
.flask_secret_key

5
app.py
View File

@ -1,6 +1,7 @@
# Validate configuration before starting the app
from functions.validate_config import validate_config
from config import item_attributes, sql_conf, app_secret_key
from functions.secret_key import get_secret_key
from config import item_attributes, sql_conf
config_status = validate_config(item_attributes)
if config_status != "Ok":
@ -22,7 +23,7 @@ from routes.upload import upload_bp
from routes.confirm_save import confirm_save_bp
app = Flask(__name__)
app.secret_key = app_secret_key # Required for flashing messages and session
app.secret_key = get_secret_key() # Required for flashing messages and session
app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql://{sql_conf.SQL_USER}:{sql_conf.SQL_PASSWORD}@{sql_conf.SQL_HOST}/{sql_conf.SQL_DB}'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)

View File

@ -1,6 +1,5 @@
from definitions.attributes import *
app_secret_key = "test_phase_secret_key"
# MySQL information
class sql_conf:

55
functions/secret_key.py Normal file
View File

@ -0,0 +1,55 @@
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()}")