Skip to content

Latest commit

 

History

History
185 lines (144 loc) · 16.8 KB

File metadata and controls

185 lines (144 loc) · 16.8 KB

API Contract

IoT, 백엔드, 프론트가 같은 API·통신 인터페이스를 기준으로 개발하기 위한 문서입니다. 스키마가 바뀔 때는 database.md함께 수정한 뒤 PR을 올립니다.

이 문서는 통신 계약(MQTT · 인증 · REST)만 다룹니다. DB 테이블(§1–§12)은 database.md — 아래 본문은 §13부터입니다.

담당 · 역할

팀 분담 전체: CONTRIBUTING.md

영역 주 담당 협업
§13 MQTT devices/register 윤아령 (IoT) 강유진 (Mosquitto·인증서), 최지현 (mTLS)
§14 JWT · /auth/* 박소정 (Backend) 박대호 (프론트 로그인)
§15 REST (기기·CVE·설정·대시보드) 박소정 (Backend) 박대호 (프론트 연동)
§15 스캔 (/scans, /network-scans) 박소정 (Backend) 최지현 (Trivy·네트워크 스캔)
§15 AI 분석 (/cves/{id}/analysis) 박소정 (Backend API) 박대호 (ML·LLM 모델·UI 스펙)
SBOM ingest · S3 upload 박소정 (Backend) 윤아령 (Collector)
WireGuard /devices/{id}/vpn/join 박소정 (Backend) 윤아령 (Collector), 강유진 (EC2·SG)
섹션 내용 주 담당
§13 MQTT 기기 등록 윤아령
§14 인증 (JWT) 박소정
§15 REST API 엔드포인트 박소정
§16 변경 이력

상세 OpenAPI는 추후 shared/openapi.yaml 로 이전할 수 있습니다.
DB 테이블 정의: database.md · 아키텍처·연결 정보: architecture.md · 배포: deployment.md
인프라 (현재 운영): EC2 18.183.189.134 · DB project5 · API http://18.183.189.134:8000 · MQTT mqtts://18.183.189.134:8883 (TLS 1.3 mTLS) · topic devices/register


13. MQTT 기기 등록 (Collector → Mosquitto → Backend)

담당: 윤아령 (IoT) · 협업: 강유진 (브로커·인증서), 최지현 (mTLS)

기기가 브로커에 접속해 등록 전용 토픽으로 JSON을 발행하면, FastAPI가 동일 토픽을 구독해 devices upsert 및 last_seen_at 갱신을 수행합니다.
SBOM은 MQTT가 아닌 HTTPS로 별도 전송합니다 (§6).

전송: TLS 1.3 mTLS, 포트 8883 (mqtts://)

항목
Broker URL mqtts://<EC2_HOST>:8883
TLS 최소 TLS 1.3
인증 mTLS — CA 서명 클라이언트 인증서 필수 (collector-client)
인증서 배포 Pi: ca.crt + collector-client.crt/key (CA private key는 Pi에 두지 않음)

인증서 생성: infra/scripts/generate_mqtt_certs.sh (MQTT_SERVER_IP에 EC2 IP 포함 권장)

13.1 Topic

Topic QoS 방향 설명
devices/register 1 Collector → Broker → Backend 기기 메타데이터 등록·heartbeat

13.2 페이로드

{
  "device_id": "550e8400-e29b-41d4-a716-446655440000",
  "customer_id": 1,
  "name": "doorlock-rpi-001",
  "ip_address": "192.168.0.10",
  "model": "Raspberry Pi 4",
  "kernel_version": "6.6.31-v8+",
  "arch": "aarch64",
  "os_info": "Debian GNU/Linux 12 (bookworm)"
}
필드 필수 설명
device_id 필수 UUID 권장. 문자열이어도 백엔드가 결정적 UUID5로 변환
customer_id 선택 고객사. 없으면 DEFAULT_DEVICE_CUSTOMER_ID(기본 1)부터 시작해 customers에 없는 번호를 +1씩 찾아 할당(기존 기기는 유지). legacy user_id도 동일 의미로 허용
name, ip_address, model, kernel_version, arch, os_info 선택 devices 테이블 메타데이터

created_at, updated_at, last_seen_at은 서버가 기록합니다.

13.3 처리 규칙

  1. Backend는 기동 시 devices/register 구독
  2. device_iddevices INSERT 또는 UPDATE (last_seen_at 갱신)

14. 인증 (관리자)

담당: 박소정 (Backend) · 협업: 박대호 (Frontend)

  • 방식: JWT (Bearer)
  • 로그인: POST /auth/loginOAuth2PasswordRequestForm (username=email, password), 응답 { access_token, token_type }
  • 회원가입: POST /auth/register{ email, password }
  • 내 정보: GET /auth/me (Bearer 필요)
  • 토큰 갱신 엔드포인트: (TBD) — 현재 만료(30분) 시 재로그인 필요

15. REST API (Backend)

담당: 박소정 (Backend) · 스캔 API 협업: 최지현 · AI 분석·프론트: 박대호

Base URL: 버전 프리픽스 없이 루트에 바로 노출 (http://<HOST>:8000/devices 등). 지금은 프로젝트 초기 단계라 /api/v1 같은 버전 프리픽스를 붙이지 않기로 했고, 필요해지면 라우터 prefix만 바꾸면 되므로 나중에 추가해도 무비용입니다.

2026-08-27부로 읽기(GET) 엔드포인트도 전부 관리자 JWT(Bearer)가 필요합니다 — 대시보드가 로그인 없이도 조회 가능해야 한다는 초기 방침을 프론트 로그인 플로우 완성 이후 재검토해 강화했습니다(§16, §TODO 참고). Collector가 호출하는 /ingest/sbom, /api/v1/sbom/upload/*는 JWT 대신 기기별 API 키(TOFU, 아래 참고)로 인증합니다. 생성/수정/삭제는 계속 관리자 JWT(Bearer)가 필요합니다. 상세 요청/응답 필드는 각 라우터의 Pydantic 스키마(backend/app/schemas/) 참고.

2026-08-28부로 기기(devices)를 다루는 모든 엔드포인트가 호출한 관리자 계정의 customer_id로 자동 범위 제한됩니다(계정별 기기 격리) — 로그인한 관리자와 다른 고객사 소속 기기는 존재해도 404로 응답합니다. 대상: GET/PATCH/DELETE /devices/{id}, /devices/{id}/cves*, /devices/{id}/risk-summary, /devices/{id}/scans*, /scans/{scan_id}, /devices/{id}/network-scans, /devices/{id}/report, /dashboard/*, /cves/{id}/devices, /cves/top. 관리자 계정에 customer_id가 없으면(NULL) 기기 목록·/cves/top은 빈 배열을 반환합니다. CVE 카탈로그 자체(/cves, /cves/{id})는 기기와 무관해 범위 제한 대상이 아닙니다.

메서드 경로 설명 인증
POST /auth/register 관리자 회원가입 -
POST /auth/login 로그인, JWT 발급 -
GET /auth/me 내 정보 조회 JWT
PATCH /auth/me 이메일 변경 JWT
POST /auth/me/password 비밀번호 변경 (current_password, new_password) JWT
GET /settings 내 설정 조회 — 저장된 값이 없으면 기본값(auto_scan=true, scan_interval=24, risk_threshold_*=9/7/4) 반환 JWT
PATCH /settings 설정 변경분만 저장 (첫 저장 시 행 생성) JWT
GET /scan-schedule 스캔 주기 조회 — 시스템 전체 공통(§2.1), 저장된 값 없으면 기본값(scan_interval=24) 반환 JWT
PUT /scan-schedule 스캔 주기 변경 (scan_interval은 24/168/720만 허용) — 저장 즉시 재스캔 스케줄러가 새 주기로 재계산 JWT
GET /devices 기기 목록/검색 (name, model, ip_address, package, cve, skip, limit) — 항상 호출자 소속 고객사 기기만 (자유 customer_id 쿼리 파라미터는 2026-08-28 제거) JWT
GET /devices/{device_id} 기기 상세 (패키지 수, 위험도 포함) JWT
POST /devices 기기 수동 등록 (Settings "기기 등록" 모달). customer_id 미지정 시 호출자 소속 고객사로 자동 지정 JWT
PATCH /devices/{device_id} 기기 정보 수정 JWT
DELETE /devices/{device_id} 기기 삭제 — 소프트 삭제(deleted_at만 설정). 스캔 이력(scan_history/devices_cves/packages/sbom)은 FK 보존을 위해 지우지 않으며, 목록/상세/스캔 관련 API와 자동 재스캔 대상에서 제외된다 JWT
GET /cves CVE 목록/검색 (q, severity) JWT
GET /cves/top 미해결 CVE 중 위험도 Top-N (대시보드 "긴급 CVE Top5") — 호출자 소속 고객사 기기 기준 JWT
GET /cves/{cve_id} CVE 상세 (CWE, 참고 링크 전체 목록 포함) JWT
GET /cves/{cve_id}/devices 이 CVE에 현재 걸려있는 기기 목록 (기기별 최신 탐지 1건만) JWT
GET /devices/{device_id}/cves 기기별 탐지된 CVE 이력 (status 필터). 같은 기기를 여러 번 스캔하면 같은 CVE가 스캔 횟수만큼 중복될 수 있음 (이력으로서는 정상) JWT
GET /devices/{device_id}/risk-summary 기기별 정제된 현재 위험 상태 — CVE별 최신 탐지 1건 + 심각도별 개수·최고 CVSS 점수 + 출처 컨테이너(source_container, 기기가 여러 컨테이너로 구성된 경우 어느 것 CVE인지). AI 위험도 융합(Trivy+네트워크 스캔)이나 프론트 상세페이지에 넘길 때는 /cves가 아니라 이 엔드포인트를 쓴다 JWT
GET /devices/{device_id}/cves/{cve_id}/analysis 기기 1대 x CVE 1건의 상세 진단 — CVE 기본정보+탐지정보+AI 분석(services/ai_analysis.py, 2-Stage 앙상블 모델 + Groq LLM 실연동, CVE별 분석 텍스트 DB 캐싱)을 합쳐서 반환. risk_score/patch_score는 0100 스케일(2026-09-03부로 변경 — 이전 mock은 010/CVSS 스케일이었음). Detail 페이지 전용 JWT
PATCH /devices/{device_id}/cves/{id} 기기-CVE 상태 변경 (해결 처리 등) JWT
GET /devices/{device_id}/report 기기 취약점 진단 결과 PDF 다운로드 (report_type=customer|audit, 기본값 customer). 활성 CVE 전체를 모아 심각도별 요약+CVE별 상세로 생성 JWT
GET /devices/{device_id}/scans 스캔 이력 목록 JWT
POST /devices/{device_id}/scans 스캔 요청 — scan_historystatus=pending으로 즉시 기록 후 응답, 실제 Syft/Trivy 실행은 백그라운드로 진행되어 완료되면 같은 행이 completed/failed로 갱신된다. sbom_id를 생략하면 기기의 최신 SBOM을 자동으로 찾아 스캔 JWT
GET /scans/{scan_id} 스캔 이력 상세 — 폴링해서 status 변화를 확인 JWT
GET /devices/{device_id}/network-scans 네트워크 스캔 결과 — RustScan(포트탐지)→Nmap(서비스식별)→Nuclei(취약점매칭) (severity 필터) JWT
POST /devices/{device_id}/network-scans 네트워크 스캔 요청 — scan_historyscan_type=network, status=pending으로 즉시 기록 후 응답, 실제 RustScan→Nmap→Nuclei 실행은 백그라운드로 진행되어 완료되면 같은 행이 completed/failed로 갱신된다 JWT
GET /dashboard/vulnerability-trend 대시보드 일자별 취약점 그래프 — 최근 N일(days, 기본 7) 탐지/해결 건수 JWT
GET /dashboard/vulnerability-by-device 대시보드 기기별 누적 취약점 그래프 — 미해결 취약점 많은 기기 상위 N개(limit, 기본 6) + 전체 미해결 합계(total_unresolved, 대시보드 "미해결 CVE 합계" 카드용) JWT
GET /dashboard/scan-status 대시보드 "최근 24시간 스캔 상태" 카드용 — 최근 24시간 내 가장 최근 스캔의 status(success/failed/running/none)와 scanned_at JWT
GET /notifications 내 알림 목록 (unread_only, limit 기본 20) — total/unread_count/items 반환 JWT
PATCH /notifications/{id}/read 알림 1건 읽음 처리 JWT
PATCH /notifications/read-all 내 안 읽은 알림 전체 읽음 처리 JWT
POST /ingest/sbom SBOM 업로드. device_id가 없으면 최소 정보로 선등록 후 저장. sbom_format=cyclonedx-json이면 components[]packages로 파싱, 그 외 포맷은 원본만 저장. source_container(optional) — 기기가 여러 컨테이너로 구성된 경우 이 SBOM의 출처. 스캔은 자동으로 트리거되지 않음 — 저장 후 별도로 POST /devices/{device_id}/scans 호출 필요 기기 API 키(아래 참고)

/ingest/sbom, /api/v1/sbom/upload/* 인증 — 기기별 API 키 (Trust-On-First-Use): Collector는 JWT를 쓸 수 없어서, 대신 요청 헤더 X-Device-Api-Key로 인증합니다(backend/app/services/device_registration.pyverify_or_bind_device_api_key). 헤더가 없으면 기존처럼 통과합니다(구버전 Collector와 하위 호환). 헤더가 있으면 그 기기(device_id)가 처음 보내는 값을 그대로 등록하고, 이후 요청부터는 그 값과 일치해야만 통과합니다 — 한 번 등록되면 그 키를 모르는 제3자는 같은 device_id로 가짜 SBOM을 올릴 수 없습니다. Collector가 실제로 키를 만들어서 보내야 보호가 시작됩니다 — 지금은 Collector 쪽에서 아직 X-Device-Api-Key를 안 보내므로, 기기별로 임의의 랜덤 문자열을 한 번 만들어 로컬에 저장하고 매 요청에 그대로 실어 보내는 부분이 남아있습니다 — 담당: 박소정 · 윤아령 · 최지현


16. 변경 이력

아래 이력의 § 번호는 작성 시점 기준입니다. 이 문서와 database.md가 하나의 파일이던 시절에 매겨진 것으로, §1§12는 현재 database.md의 테이블 섹션에 해당합니다.

날짜 작성자 내용
2026-05-27 박소정 초안 템플릿 생성
2026-06-24 박소정 ER 다이어그램 기반 DB 스키마 섹션 추가 (users~network_scans)
2026-06-26 박소정 최종 ERD 기준 스키마 수정 (scan_history, package_cves, notifications 추가)
2026-06-30 박소정 devices_cves에 scan_history_id 필드 추가
2026-07-11 박소정 customers 테이블 추가, devices.user_id → customer_id 변경, 각 테이블 역할 설명 추가
2026-07-11 윤아령 MQTT devices/register 기기 등록 계약 추가
2026-07-22 윤아령 MQTT 등록에서 SBOM 분리 — SBOM은 HTTPS(§6), MQTT는 기기 메타데이터만
2026-07-23 윤아령 MQTT TLS 1.3 mTLS, 포트 8883 (mqtts://) 전환
2026-08-02 박소정 REST API(§15) 추가 — auth/devices/cves/scan/ingest 라우터 구현, base URL 미버전화 결정
2026-08-06 최지현 §8 cves에 cwe_ids/references/last_modified_date, §10 devices_cves에 installed_path 추가. §15에 GET /devices/{id}/risk-summary, GET /cves/{id}/devices 추가. POST /devices/{id}/scans Trivy 백그라운드 실행
2026-08-19 박소정 §15에 GET /devices/{id}/report(취약점 PDF 리포트, customer/audit) 추가
2026-08-27 박소정 §15 GET 엔드포인트 전체 JWT 인증 필수화(무인증 방침 폐기, TODO 항목 해결). §2 설정 API(GET/PATCH /settings), 기기 상세 CVE 분석 API(GET /devices/{id}/cves/{cve_id}/analysis), 대시보드 그래프 API 2종, 프로필 수정/비밀번호 변경 API(PATCH·POST /auth/me*), 기기 검색 package/cve 필터 추가
2026-08-28 박소정 계정별 기기 격리(멀티테넌시) 추가 — §1 users에 customer_id 추가, §4 devices 설명 보강, §15 기기 관련 엔드포인트 전체를 호출자 customer_id로 스코핑(타 고객사 기기는 404). GET /devices 자유 customer_id 쿼리 파라미터 제거, POST /devices customer_id 자동 지정으로 변경
2026-08-29 박소정 §15 GET /dashboard/scan-status 신규 추가, GET /dashboard/vulnerability-by-device에 total_unresolved 필드 추가(대시보드 하드코딩 값 실데이터 연결). 기기 리포트 PDF 출력·삭제 버튼을 목록에서 상세페이지로 이동(팀 피드백 반영)
2026-09-02 박소정 §4 devices에 deleted_at 추가, §15 DELETE /devices/{id}를 소프트 삭제로 변경 — 스캔 이력이 있는 기기 삭제 시 발생하던 500 에러 수정
2026-09-01 최지현 네트워크 스캔(RustScan+Nmap+Nuclei) — §11 network_scans, §15 POST /devices/{id}/network-scans
2026-09-02 최지현 §2.1 scan_schedule, §15 GET/PUT /scan-schedule — Trivy·네트워크 재스캔 스케줄러 연동
2026-09-03 박소정 §8 cves AI 피처·LLM 필드, §15 CVE analysis 실연동(협업: 박대호 ML·LLM), notifications API
2026-09-04 최지현 §6 sbom source_container, Trivy 컨테이너별 재스캔

TODO

  • /ingest/sbom · /api/v1/sbom/upload/* 인증 — 백엔드는 기기별 API 키(TOFU, §15 참고)로 구현 완료
  • Collector가 기기별 API 키를 생성·저장하고 X-Device-Api-Key 헤더로 실제로 보내는 부분 — 박소정 · 윤아령 · 최지현