From 7ddc7653265cade6ab0de6ffc67d1e991257c0b4 Mon Sep 17 00:00:00 2001 From: king Date: Sun, 24 May 2026 13:25:06 +0900 Subject: [PATCH] =?UTF-8?q?feat(sso):=20SESSION=5FSECRET=5FKEY=20=EB=AF=B8?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=8B=9C=20fail-fast=20+=20ALLOWED=5FEMAI?= =?UTF-8?q?LS=20env=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SESSION_SECRET_KEY 가 .env 에 없으면 컨테이너 기동 단계에서 RuntimeError. 알려진 기본값(change-this-session-secret) 폴백 제거로 운영 .env 누락 시 양쪽 secret 불일치로 SSO 가 조용히 깨지는 사고 방지. - ALLOWED_EMAILS 를 환경변수(쉼표 구분)로 덮어쓸 수 있게 변경. env 미설정 시 기존 4명 기본 목록 유지 → 운영 호환. - .env.example 갱신: SESSION_SECRET_KEY 안내 강화, ALLOWED_EMAILS 항목 추가. --- .env.example | 6 +++++- app/main.py | 28 +++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index f2c28e5..d092a3e 100644 --- a/.env.example +++ b/.env.example @@ -1,11 +1,15 @@ GOOGLE_CLIENT_ID=your-google-oauth-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-google-oauth-client-secret -# OMS(orderlist) 와 SSO 하려면 양쪽 .env 에 동일한 값으로 설정 +# OMS(orderlist) 와 SSO 하려면 양쪽 .env 에 동일한 값으로 설정. +# 미설정 시 컨테이너 기동 실패(fail-fast). openssl rand -hex 32 로 생성 권장. SESSION_SECRET_KEY=replace-with-a-long-random-secret SESSION_COOKIE_NAME=session SESSION_COOKIE_SECURE=true # 세션 유효기간(초). OMS(orderlist) 와 동일하게 맞출 것. 28800=8h SESSION_MAX_AGE=28800 + +# 포털 접근 허용 이메일. 쉼표로 구분. 비워두면 코드의 기본 목록 사용. +ALLOWED_EMAILS=king@dbxcorp.co.kr,julie@dbxcorp.co.kr,ellen@dbxcorp.co.kr,bj@dbxcorp.co.kr PUBLIC_BASE_URL=https://dbx.no1king.freeddns.org CS_ORDER_URL=https://cs.example.com # 비워두면 같은 도메인의 /orderlist/ 경로(NPM 리버스 프록시)로 자동 연결됨 diff --git a/app/main.py b/app/main.py index 147c0fe..4535873 100644 --- a/app/main.py +++ b/app/main.py @@ -19,12 +19,15 @@ load_dotenv() BASE_DIR = Path(__file__).resolve().parent ALLOWED_DOMAIN = "dbxcorp.co.kr" -ALLOWED_EMAILS = { + +# ALLOWED_EMAILS 는 운영 시 .env 의 ALLOWED_EMAILS (쉼표 구분)로 덮어쓸 수 있다. +# env 가 비어 있으면 아래 기본 목록을 그대로 사용 — 기존 운영 호환. +DEFAULT_ALLOWED_EMAILS = ( "king@dbxcorp.co.kr", "julie@dbxcorp.co.kr", "ellen@dbxcorp.co.kr", "bj@dbxcorp.co.kr", -} +) def env(name: str, default: str = "") -> str: @@ -32,6 +35,25 @@ def env(name: str, default: str = "") -> str: return value if value else default +def _parse_email_list(raw: str) -> set[str]: + return {e.strip().lower() for e in raw.split(",") if e.strip()} + + +_env_emails = _parse_email_list(env("ALLOWED_EMAILS", "")) +ALLOWED_EMAILS: set[str] = _env_emails or _parse_email_list(",".join(DEFAULT_ALLOWED_EMAILS)) + + +def _require_session_secret() -> str: + secret = env("SESSION_SECRET_KEY", "") + if not secret: + raise RuntimeError( + "SESSION_SECRET_KEY 환경변수가 설정되지 않았습니다. " + "openssl rand -hex 32 로 새 값을 만들어 .env 에 넣고 컨테이너를 재기동하세요. " + "OMS(orderlist) 와 SSO 하려면 양쪽 .env 에 같은 값이어야 합니다." + ) + return secret + + def build_google_oauth() -> OAuth: oauth = OAuth() oauth.register( @@ -47,7 +69,7 @@ def build_google_oauth() -> OAuth: app = FastAPI(title="DBX 메인 페이지") app.add_middleware( SessionMiddleware, - secret_key=env("SESSION_SECRET_KEY", "change-this-session-secret"), + secret_key=_require_session_secret(), session_cookie=env("SESSION_COOKIE_NAME", SESSION_COOKIE_DEFAULT), https_only=env("SESSION_COOKIE_SECURE", "true").lower() == "true", same_site="lax",