config: allow SESSION_COOKIE_SECURE override and disable on test deploy

The HTTP-only test deployment binds gunicorn to 0.0.0.0:8000 with no TLS
terminator, so a hardcoded SESSION_COOKIE_SECURE=True breaks browser
login. Make it opt-out via env (default True outside TESTING) and set
SESSION_COOKIE_SECURE=false in the generated web.env so the test box
keeps working over HTTP.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mwiegand 2026-05-07 00:56:48 +02:00
parent f81e839ba2
commit 0210ecd301
No known key found for this signature in database
3 changed files with 18 additions and 1 deletions

View file

@ -130,6 +130,7 @@ if [ ! -f /etc/left4me/web.env ]; then
printf 'DATABASE_URL=sqlite:////var/lib/left4me/left4me.db\n' printf 'DATABASE_URL=sqlite:////var/lib/left4me/left4me.db\n'
printf 'SECRET_KEY=%s\n' "$secret_key" printf 'SECRET_KEY=%s\n' "$secret_key"
printf 'JOB_WORKER_THREADS=4\n' printf 'JOB_WORKER_THREADS=4\n'
printf 'SESSION_COOKIE_SECURE=false\n'
} > "$tmp_web_env" } > "$tmp_web_env"
$sudo_cmd install -m 0640 -o root -g left4me "$tmp_web_env" /etc/left4me/web.env $sudo_cmd install -m 0640 -o root -g left4me "$tmp_web_env" /etc/left4me/web.env
fi fi

View file

@ -38,6 +38,10 @@ def create_app(test_config: dict[str, object] | None = None) -> Flask:
if not app.config.get("TESTING") and (not secret_key or secret_key == "dev"): if not app.config.get("TESTING") and (not secret_key or secret_key == "dev"):
raise RuntimeError("SECRET_KEY must be set to a non-default value outside of testing") raise RuntimeError("SECRET_KEY must be set to a non-default value outside of testing")
secure_env = os.getenv("SESSION_COOKIE_SECURE")
if secure_env is not None:
app.config["SESSION_COOKIE_SECURE"] = secure_env.lower() not in {"0", "false", "no"}
else:
app.config["SESSION_COOKIE_SECURE"] = not app.config.get("TESTING", False) app.config["SESSION_COOKIE_SECURE"] = not app.config.get("TESTING", False)
with app.app_context(): with app.app_context():

View file

@ -53,6 +53,18 @@ def test_session_cookie_secure_in_production(tmp_path, monkeypatch) -> None:
assert app.config["SESSION_COOKIE_SECURE"] is True assert app.config["SESSION_COOKIE_SECURE"] is True
def test_session_cookie_secure_env_override(tmp_path, monkeypatch) -> None:
db_url = f"sqlite:///{tmp_path/'cookie-env.db'}"
monkeypatch.setenv("DATABASE_URL", db_url)
monkeypatch.setenv("SESSION_COOKIE_SECURE", "false")
monkeypatch.setattr("l4d2web.app.recover_stale_jobs", lambda: None)
monkeypatch.setattr("l4d2web.app.start_job_workers", lambda app: None)
app = create_app({"TESTING": False, "DATABASE_URL": db_url, "SECRET_KEY": "real"})
assert app.config["SESSION_COOKIE_SECURE"] is False
def test_session_cookie_secure_disabled_in_testing(tmp_path, monkeypatch) -> None: def test_session_cookie_secure_disabled_in_testing(tmp_path, monkeypatch) -> None:
db_url = f"sqlite:///{tmp_path/'cookie-test.db'}" db_url = f"sqlite:///{tmp_path/'cookie-test.db'}"
monkeypatch.setenv("DATABASE_URL", db_url) monkeypatch.setenv("DATABASE_URL", db_url)