feat: /api/admin/* 내부망 게이트 + 부트스트랩 엔드포인트 #50
No reviewers
Labels
No labels
api
bug
chore
collector
decision-needed
docs
enhancement
feature
feedback-loop
frontend
infra
skill
test
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
xhh/financial-data-platform!50
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/admin-private-origin-bootstrap"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
관리 엔드포인트를 공개 인터넷에서 원천 차단하고, CLI 없이 Tailscale 브라우저에서 첫 write 키를 발급할 수 있게 한다. v0.3.0 배포 직전 마지막 조각.
서버
require_private_origin의존성: XFF 첫 IP 가_TRUSTED_NETWORKS(RFC1918 + Tailscale CGNAT + loopback + link-local) 면 통과, 공개 IP 면 403admin.router재구성: prefix dep = private_origin, 일반 엔드포인트는 추가로require_scope("write"),POST /bootstrap만 scope 면제/bootstrap: 활성 write 키가 0개일 때만 write 스코프 포함 키 발급is_private는 TEST-NET 까지 True 처리하는 함정이 있어 명시적 allowlistUI
7_API_Keys.py— 401 대응 안내. 하단 '신규 발급' 폼이 scope=write 로 제출 시 일반 POST 가 401 이면 같은 payload 로/bootstrap자동 폴백. 발급된 원문 키를 사이드바에 즉시 주입.회귀 테스트
tests/api/test_private_origin.py20 신규 케이스 (IP 판정 파라미터 11, 게이트 4, bootstrap 5). 85 → 105 tests.문서
Test plan
https://stock-admin.xhhan.com접속 → API Keys 페이지 → 부트스트랩 발급 동작 확인curl -X POST https://stock.xhhan.com/api/admin/keys/bootstrap ...403 확인공개 인터넷에서 관리 엔드포인트 원천 차단. CLI 를 거치지 않고 Tailscale 브라우저에서 바로 첫 write 키를 발급받을 수 있게 한다. 서버 ---- - `api/auth.py::require_private_origin` — XFF 첫 IP 가 사설/CGNAT/loopback allowlist 안이거나 XFF 없음이면 통과, 공개 IP 면 403. stdlib `is_private` 는 TEST-NET (203.0.113.0/24) 까지 True 로 치는 이슈가 있어 명시적 `_TRUSTED_NETWORKS` 리스트 사용. - `api/routers/admin.py` 재구성: - 라우터 prefix dep: `[Depends(require_private_origin)]` (공통) - 일반 엔드포인트: 추가로 `Depends(require_scope("write"))` - `POST /bootstrap`: scope 면제. 활성 write 키가 0개일 때만 발급 허용. write 스코프 포함 필수 (읽기 전용 키 부트스트랩 금지). 중복 이름 409. UI -- - `frontend/streamlit/pages/7_API_Keys.py` — 401 대응 분기 추가: 사이드바 키 미입력/활성 키 0개 상황에서 부트스트랩 폼을 노출. 발급 성공 시 원문 키를 `st.session_state["api_key"]` 에 즉시 주입해 같은 세션에서 바로 admin 조작 가능. 회귀 테스트 ---------- - `tests/api/test_private_origin.py` 신규 20건: - `_is_private_ip` 파라미터화 11건 (RFC1918, CGNAT, loopback, 공개 IP, TEST-NET, 잘못된 문자열) - 공개 XFF 403 / 사설 XFF 는 스코프 체커로 진행 - 부트스트랩: 빈 DB 성공 / read-only 422 / 중복 401 / 공개 XFF 403 / 전 키 폐기 후 재bootstrap 가능 85 → 105 tests pass (+20). CLAUDE.md 에 "관리 엔드포인트 보호 — private origin 게이트" 섹션 추가. v0.3.0 배포 직전 마지막 조각. CLI 부트스트랩 단계 완전 제거. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>