diff --git a/web/settings.py b/web/settings.py index 4ddcae8bb..c5a797113 100644 --- a/web/settings.py +++ b/web/settings.py @@ -47,10 +47,19 @@ # Helpful notice for ops without breaking startup print("Sentry DSN not configured; error events will not be sent.") -SECRET_KEY = env.str("SECRET_KEY", default="django-insecure-5kyff0s@l_##j3jawec5@b%!^^e(j7v)ouj4b7q6kru#o#a)o3") -# Debug settings +# Debug settings - must be defined before SECRET_KEY validation ENVIRONMENT = env.str("ENVIRONMENT", default="development") +# Read and validate SECRET_KEY with proper whitespace handling +raw_secret_key = env.str("SECRET_KEY", default="") +SECRET_KEY = raw_secret_key.strip() if raw_secret_key else "" + +if ENVIRONMENT == "production" and not SECRET_KEY: + raise ValueError("SECRET_KEY environment variable must be set in production") + +if not SECRET_KEY: + SECRET_KEY = "django-insecure-5kyff0s@l_##j3jawec5@b%!^^e(j7v)ouj4b7q6kru#o#a)o3" + # Default DEBUG to False for security DEBUG = False diff --git a/web/views.py b/web/views.py index b4d485749..b30839cf9 100644 --- a/web/views.py +++ b/web/views.py @@ -1115,7 +1115,37 @@ def run_cmd(cmd): break # Always attempt a reload so code changes take effect (application systemd unit) - subprocess.run(["/bin/systemctl", "restart", "education-website"], capture_output=True) + # Only attempt systemctl restart on Linux systems where it's available + import platform + import shutil + + if platform.system() == "Linux": + trusted_systemctl_paths = ("/bin/systemctl", "/usr/bin/systemctl") + systemctl_path = next( + (p for p in trusted_systemctl_paths if os.path.isfile(p) and os.access(p, os.X_OK)), + None, + ) + if not systemctl_path: + log_lines.append("Service restart failed: systemctl not found in trusted paths") + ok = False + else: + try: + proc = subprocess.run( + [systemctl_path, "restart", "education-website"], + capture_output=True, + check=False, + timeout=30, + text=True, + ) + log_lines.append(f"systemctl restart rc={proc.returncode}") + if proc.returncode != 0: + log_lines.append(f"Service restart failed: {proc.stderr[:200] if proc.stderr else 'non-zero exit'}") + ok = False + except (OSError, subprocess.TimeoutExpired) as e: + log_lines.append(f"Service restart failed: {e}") + ok = False + else: + log_lines.append("Skipped service restart (not on Linux system)") # Slack summary (truncate to avoid long messages) slack_msg = (