security: rotate bootstrap and clean workspace

This commit is contained in:
2026-03-13 12:14:37 +03:00
parent 03a90f58bd
commit feb07bf366
10 changed files with 219 additions and 21 deletions

View File

@@ -8,8 +8,10 @@
# @INVARIANT: Safe to run multiple times (idempotent).
# [SECTION: IMPORTS]
import os
import sys
from pathlib import Path
from cryptography.fernet import Fernet
# Add src to path
sys.path.append(str(Path(__file__).parent.parent.parent))
@@ -19,6 +21,41 @@ from src.core.logger import logger, belief_scope
from src.scripts.seed_permissions import seed_permissions
# [/SECTION]
ENV_FILE_PATH = Path(__file__).resolve().parents[2] / ".env"
# [DEF:ensure_encryption_key:Function]
# @PURPOSE: Ensure backend runtime has a persistent Fernet encryption key during first-time installation.
# @PRE: Backend root is writable or ENCRYPTION_KEY is already provided via environment.
# @POST: ENCRYPTION_KEY exists in process environment or backend/.env.
def ensure_encryption_key(env_file_path: Path = ENV_FILE_PATH) -> str:
existing_key = os.getenv("ENCRYPTION_KEY", "").strip()
if existing_key:
Fernet(existing_key.encode())
logger.info("ENCRYPTION_KEY already provided via environment; skipping generation.")
return existing_key
if env_file_path.exists():
for raw_line in env_file_path.read_text(encoding="utf-8").splitlines():
if raw_line.startswith("ENCRYPTION_KEY="):
persisted_key = raw_line.partition("=")[2].strip()
if persisted_key:
Fernet(persisted_key.encode())
os.environ["ENCRYPTION_KEY"] = persisted_key
logger.info(f"Loaded existing ENCRYPTION_KEY from {env_file_path}.")
return persisted_key
generated_key = Fernet.generate_key().decode()
with env_file_path.open("a", encoding="utf-8") as env_file:
if env_file.tell() > 0:
env_file.write("\n")
env_file.write(f"ENCRYPTION_KEY={generated_key}\n")
os.environ["ENCRYPTION_KEY"] = generated_key
logger.info(f"Generated ENCRYPTION_KEY and persisted it to {env_file_path}.")
return generated_key
# [/DEF:ensure_encryption_key:Function]
# [DEF:run_init:Function]
# @PURPOSE: Main entry point for the initialization script.
# @POST: auth.db is initialized with the correct schema and seeded permissions.
@@ -26,6 +63,7 @@ def run_init():
with belief_scope("init_auth_db"):
logger.info("Initializing authentication database...")
try:
ensure_encryption_key()
init_db()
logger.info("Authentication database initialized successfully.")
@@ -40,4 +78,4 @@ def run_init():
if __name__ == "__main__":
run_init()
# [/DEF:backend.src.scripts.init_auth_db:Module]
# [/DEF:backend.src.scripts.init_auth_db:Module]