취약점 데이터 (Trivy DB)
v0.10.0부터 TRUSCA는 단일 임베디드 엔진 Trivy(Aqua Security)로 SBOM을 CVE에 대조합니다. 워커 이미지에 trivy 바이너리가 포함되어 있고, Trivy DB(NVD + OSV + GHSA + EPSS + KEV 통합 번들)는 첫 부팅 시 다운로드되어 주간 단위로 갱신됩니다. 본 페이지는 그 라이프사이클을 운영·감사하는 방법입니다.
배포를 운영하는 super_admin. docker-compose와 기본 셸 친숙도 가정. 설치본에서 마이그레이션 중이라면 v0.10.0 릴리스 노트의 DT 제거 절차를 먼저 확인하세요.
v0.10.0은 Dependency-Track(DT)과 /admin/dt 커넥터 페이지를 제거했습니다. Trivy DB가 같은 역할(SBOM ↔ CVE 매칭)을 4GB JVM + H2 DB 대신 ~500MB 풋프린트로 수행합니다. 결정 배경은 ADR-0001을 참조하세요.
라이프사이클 동작
워커 부팅 ──► trivy --download-db-only ──► /var/lib/trivy/db
│
↓
Celery beat (주간) ─► trivy --download-db-only (refresh)
│
↓
trivy sbom <sbom.json> ──► vulnerability_findings
구성 요소는 세 가지입니다.
- 부팅 시 다운로드. 워커는 Celery
worker_ready시그널 핸들러를 등록해 워커가 큐를 소비하기 시작하면 백그라운드 스레드에서trivy --download-db-only를 호출합니다. 첫 다운로드는 약 500MB로, 일반 네트워크에서 1~3분이 소요됩니다. 다운로드는 백그라운드로 진행되므로 Celery는 즉시 태스크를 받기 시작합니다 — 부트스트랩과 경합하는 스캔은 Trivy 자체 파일 락에 잠깐 블로킹(분 단위 아님)된 뒤 새 manifest를 읽습니다. 캐시 볼륨이 이미 채워진 워커 재시작에서는 다운로드가 no-op입니다(Trivy가 manifest를 stat해 0으로 종료). - 주간 갱신. Celery Beat 태스크(
trustedoss.trivy_db_refresh, 일요일 03:00 UTC)가 동일trivy --download-db-only를 실행합니다. Trivy의 manifest 계약은 부분 다운로드를 원자적으로 교체합니다 — 갱신 실패는 기존 DB를 그대로 둡니다. 취약점 재매칭 beat(trustedoss.vulnerability_rematch_enqueue, 6시간 주기)가 다음 tick에 새 어드바이저리를 픽업해 새 critical을 Slack / Teams 알림으로 노출합니다. - 스캔별 사용. 각 source-scan 파이프라인은
trivy sbom <cyclonedx.json>을 호출해 컴포넌트를 로컬 DB에 대조합니다. 스캔당 네트워크 왕복은 없습니다.
갱신 실패(타임아웃, 네트워크 미도달, 미러 인증 오류)는 /notifications에 설정된 Slack·Teams 채널로 TRIVY-DB-REFRESH-FAILED / TRIVY-DB-REFRESH-TIMEOUT 알림을 발사합니다 — 운영자는 웹훅 이벤트로 staleness를 인지하며 조용히 누락되지 않습니다.
업스트림 DB 재빌드 주기는 약 6시간입니다. 주간 갱신은 신선도와 egress 바이트를 트레이드오프합니다. 더 빠른 주기가 필요하면 TRIVY_DB_REFRESH_HOURS를 낮추고(admin 패널 + next_refresh_at에 노출되는 안내값) apps/backend/tasks/celery_app.py의 Beat 스케줄을 일간 cron으로 수정하세요.
환경 변수
| 키 | 기본값 | 설명 |
|---|---|---|
TRIVY_DB_REPOSITORY | ghcr.io/aquasecurity/trivy-db | DB를 받아오는 OCI 저장소. air-gapped 미러로 오버라이드. |
TRIVY_DB_REFRESH_HOURS | 168 (주간) | admin/health Trivy DB 패널에 next_refresh_at = last_update + 이 값으로 노출되는 안내 주기. 실제 beat 스케줄은 crontab(minute=0, hour=3, day_of_week='sun') — 더 빠른 주기는 apps/backend/tasks/celery_app.py에서 직접 수정. |
TRIVY_CACHE_DIR | /var/lib/trivy | DB가 풀리는 디렉터리. 두 compose 파일 모두 공유 trivy-cache named volume을 여기 마운트 — 워커(rw, 다운로드·갱신)와 backend(ro, 관리자 health/disk 패널). |
TRIVY_DB_BOOTSTRAP_ON_START | true | 워커의 worker_ready 핸들러가 부팅 시 trivy --download-db-only를 실행할지. 별도 프로세스가 캐시 볼륨에 DB를 미러링하는 air-gapped 클러스터에선 false로 설정 — 워커는 네트워크 pull을 시도하지 않음. |
TRIVY_DB_BOOTSTRAP_TIMEOUT_SECONDS | 900 | 부팅 시 다운로드 subprocess의 wall-clock 한도. 느린 회사 프록시에선 상향. 범위 [30, 3600]. |
TRIVY_DB_REFRESH_TIMEOUT_SECONDS | 900 | 주간 beat refresh subprocess의 wall-clock 한도. 범위 [30, 3600]. |
TRIVY_TIMEOUT_SECONDS | 300 | trivy sbom의 스캔별 타임아웃. 대규모 모놀리스에선 상향. |
모든 키는 apps/backend/core/config.py가 런타임에 읽으며, 워커·beat 컨테이너 재시작만으로 반영됩니다 — 리빌드 불필요.