security: rotate bootstrap and clean workspace
This commit is contained in:
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user