Files
portfolio-hub/docs/srs/Non-Functional/req-054_credential-management-security-write-only.md
T
genichinandClaude Opus 4.8 80d0511d7f docs(dcy-011): draft-req + confirm-req — REQ-052/053/054 Approved
Add three approved requirements documents for dcy-011:
- REQ-052: User-owned credential management API (Interface)
- REQ-053: Admin daemon CRUD API (Interface)
- REQ-054: Credential management security with write-only constraint (Non-Functional)

Update discovery document to reference generated requirements and update index with new REQ IDs and Change Log.

Scope: Self-service credential management + admin daemon CRUD + security-isolated API for portfolio-hub.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VHtM5Ws1HKCKQ4JGi6GRb5
2026-06-28 13:55:45 +09:00

92 lines
6.7 KiB
Markdown

# REQ-054: 인증정보 관리 보안 격리 — write-only·secret 미반환·로그 미노출
- Status: Approved
- Type: Non-Functional
- Priority: High
- Owner: Justin Ko
## Intent
- dcy-011 NFR-1(보안 최우선): 복호화된 `app_secret`/`app_key`(KIS API 비밀키 — 실계좌·실자금 직결)는 user-token/admin 어떤 관리 API 응답·로그에도 포함되어서는 안 된다.
- REQ-052(사용자 소유 스코프 인증정보 관리 API)와 REQ-053(admin 데몬 CRUD API)이 신설됨으로써 응답/로그 노출 표면이 확대된다. 이 표면에서 복호화 secret이 유출되지 않음을 독립적으로 측정·검증한다.
- `GET /v1/user_info`(service-token 전용, REQ-051/REQ-049)가 유일 decrypt-return 경로라는 불변 정책을 신규 관리 API 추가 이후에도 유지한다.
## Requirement
- 인증정보 관리 API(REQ-052: 소유 스코프 write/read/delete + 메타데이터, REQ-053: admin 데몬 CRUD) 응답 스키마에 `app_key` 및 `app_secret` 필드가 존재해서는 안 된다.
- 인증정보 관리 API 처리 중 생성되는 모든 로그(INFO, WARNING, ERROR 수준 포함)에 `app_secret` 또는 `app_key` 평문이 포함되어서는 안 된다. 로그에는 `broker` 이름, `daemon_id`, 오류 유형만 기록한다.
- 복호화된 `credential_payload`(`app_key`, `app_secret`)를 반환하는 유일 경로는 service-token 전용 `GET /v1/user_info`(REQ-051/REQ-049)이다. 이 REQ-052·REQ-053 신설로 인해 이 경로가 변경되어서는 안 된다.
- 인증정보 쓰기(등록/회전) 후 DB에 저장되는 값은 반드시 Fernet 암호화된 형태여야 한다. 평문 `app_secret`/`app_key`가 `broker_credentials` 테이블에 저장되어서는 안 된다.
## Acceptance Criteria
1. Given REQ-052 인증정보 write(등록/회전) 엔드포인트 응답 JSON, When 응답 필드를 열거, Then `app_key`, `app_secret` 키가 최상위 및 중첩 객체에 포함되지 않는다.
2. Given REQ-052 인증정보 메타데이터 GET 엔드포인트 응답 JSON, When 응답 필드를 열거, Then `app_key`, `app_secret` 키가 포함되지 않는다.
3. Given REQ-053 admin 데몬 생성·변경·(비)활성화 엔드포인트 응답 JSON, When 응답 필드를 열거, Then `app_key`, `app_secret`, `credential_payload` 키가 포함되지 않는다.
4. Given 인증정보 write/rotate 처리 중 caplog 수집, When 로그 출력을 확인, Then 실제 `app_key`/`app_secret` 값이 로그 메시지에 포함되지 않는다.
5. Given 인증정보 write 요청의 `app_key`/`app_secret` 값으로 DB row를 직접 조회, When `broker_credentials.credential_payload` 컬럼을 확인, Then 평문이 아닌 Fernet 암호화 토큰(`gAAAA...`) 형태로 저장되어 있다.
6. Given REQ-052 인증정보 write 후 service-token `GET /v1/user_info`(REQ-049)로 조회, When 호출, Then `broker.credential_payload.app_secret`이 올바르게 복호화되어 반환된다 — 관리 API 추가가 유일 decrypt 경로(REQ-051)를 파괴하지 않음 확인.
7. Given REQ-052·REQ-053 신규 엔드포인트가 추가된 후 기존 `GET /v1/user_info` 보안 격리 테스트(REQ-051 AC-1~8), When 회귀 실행, Then 전체 PASS — 신규 API 추가가 기존 service-token 전용 경로에 영향 없음 확인.
## Impacted Area
- Docs:
- `docs/interface-contract.md` — 인증정보 관리 API 보안 정책 섹션: 복호화 secret 미반환·로그 미노출·Fernet at-rest 불변·service-token 유일 decrypt 경로 명시.
- Modules:
- `app/schemas/` — REQ-052 응답 스키마(`CredentialMetaResponse`)에 `app_key`/`app_secret` 필드 부재 강제(Pydantic 모델 설계 단계 확인).
- `app/services/` — 인증정보 write 서비스에서 로그 호출 시 secret 평문 비포함 확인.
- `app/core/encryption.py` — Fernet 암호화 후 저장 경로(REQ-052 write) 재사용.
- Tests:
- caplog 기반 로그 secret 비노출 테스트(AC-4).
- 응답 스키마 secret 필드 부재 테스트(AC-1/2/3).
- DB 저장 암호화 확인 테스트(AC-5).
- REQ-051 회귀 테스트(AC-7): 신규 API 추가 후 기존 service-token gate 테스트 전부 PASS.
## Notes
- dcy-011 NFR-1(보안 — 최우선): REQ-052/REQ-053의 각 AC에 secret 부재 조건이 포함되어 있으나, 이 REQ-054는 신규 관리 API 전체를 아우르는 **독립 측정·검증 목적** Non-Functional REQ로 분리한다. REQ-051(서비스 토큰 전용 격리)과 나란히 추적한다.
- AC-7(REQ-051 회귀): REQ-052·REQ-053 구현 후 기존 service-token 보안 격리(REQ-051 AC-1~8)가 회귀 없이 통과함을 이 REQ의 검증 항목으로 포함한다.
- at-rest Fernet 암호화(AC-5): `CREDENTIAL_ENCRYPTION_KEY` 관리 정책은 REQ-051 Notes에 따라 이 REQ 범위 밖(환경변수 기반 유지).
- NFR-2(권한)·NFR-3(일관성)의 나머지는 REQ-052/REQ-053 AC에 흡수된다. NFR-1 보안만 별도 Non-Functional REQ로 승격한다.
- Source: dcy-011 NFR-1, R-1(복호화 secret 유출 리스크), S-2(복호화 secret 미포함 성공 기준).
## Change Log
### CHG-20260628-01
- Date: 2026-06-28
- Author: Justin Ko
#### Change Summary
- 신규 생성 (Proposed) — dcy-011 NFR-1 산출물.
#### Intent
- dcy-011 NFR-1(복호화 secret이 user-token/admin 응답·로그에 미포함, REQ-051 패턴)을 신규 관리 API(REQ-052·REQ-053) 표면 전체에 대한 독립 측정 가능 Non-Functional REQ로 정규화한다.
#### Acceptance Criteria Delta
- Added:
- AC-1 ~ AC-7 전체 (신규 초안)
- Updated: 없음
- Removed: 없음
#### Impacted Area Delta
- Docs:
- `docs/srs/Non-Functional/req-054_credential-management-security-write-only.md` 신규 생성
- `docs/interface-contract.md` 갱신 예고
- Modules:
- 응답 스키마(secret 필드 부재), 서비스 로그 확인
- Tests:
- caplog 로그 비노출(AC-4), 응답 schema secret 부재(AC-1~3), DB 암호화 확인(AC-5), REQ-051 회귀(AC-7) 신규
#### Delivery Trace Delta
- Batches: 미정 (suggest-batch-reqs 대기)
- Releases: 미정
#### Revalidation Impact
- Reverification Needed: no
- Existing Implementation Invalidated: no
- Status Recommendation: keep-current
- Follow-up Action: confirm-req 후 suggest-batch-reqs. REQ-052/REQ-053와 동일 batch 묶기 권고.
#### Validation Plan
- pytest caplog fixture로 AC-4(로그 비노출), 응답 JSON 필드 열거로 AC-1~3, DB row 직접 확인으로 AC-5, REQ-051 회귀 suite로 AC-7 검증.
### CHG-20260628-02
- Date: 2026-06-28
- Author: 팀장(Claude)
- confirm-req: `Proposed` → `Approved`. dcy-011 NFR-1 추적. 신규 관리 API(REQ-052/053) 응답·로그 secret 미포함(AC-1~4)·Fernet at-rest(AC-5)·service-token 유일 decrypt 불변(AC-6)·REQ-051 회귀(AC-7) testable. REQ-051과 나란히 독립 보안 REQ 승격 타당. blocker 없음.