본문으로 건너뛰기

라이브 읽기 전용 데모

포털을 공개 라이브 데모로 운영할 수 있습니다. 누구나 시드된 데모 계정으로 로그인해 실제 프로젝트, 스캔, 취약점, 라이선스, SBOM, 보고서를 둘러볼 수 있지만, 모든 쓰기 작업은 비활성화되며 데이터셋은 매일 밤 깨끗한 상태로 초기화됩니다.

호스팅 데모 바로 써보기​

**trusca-demo.duckdns.org**에서 운영 중인 데모를 바로 이용할 수 있습니다.

  • 로그인: 시드된 데모 계정으로 접속합니다. 관리자 화면까지 둘러보려면 explore@demo.trustedoss.dev, 라이브 스캔을 돌리려면 dev@demo.trustedoss.dev, 팀별 관리자 시야가 필요하면 *-admin@demo.trustedoss.dev 계정을 씁니다. 비밀번호는 모두 DemoTest2026!이고, 로그인 화면에는 자격 증명을 한 번에 채우는 버튼이 있습니다. 회원가입은 제공하지 않습니다. 계정을 만드는 것도 쓰기 작업이라, 데모에서는 공용 계정을 대신 안내합니다.
  • 둘러보기: 실제 프로젝트, 컴포넌트, CVE, 라이선스, SBOM, 보고서를 볼 수 있습니다. 생성·수정·삭제는 모두 403으로 막힙니다. 읽기 전용이기 때문입니다.
  • SBOM 업로드: CycloneDX 파일(예: BomLens로 만든 SBOM)을 Demo Sandbox 프로젝트에 올리면 소스 없이도 TRUSCA가 라이선스와 CVE를 매칭해 보여줍니다. 여기서 10MB 이하 소스 스캔도 직접 돌릴 수 있습니다. Demo Sandbox는 explore@demo.trustedoss.dev나 dev@demo.trustedoss.dev로 로그인하면 보입니다.
  • 주의: 데이터셋은 샌드박스를 포함해 매일 밤 지워지고 다시 시드됩니다. 올린 내용은 임시로 남고 다른 방문자에게도 보이므로, 사내·기밀 SBOM은 올리지 마세요.

이 문서의 나머지는 같은 구성 요소로 직접 읽기 전용 데모를 세우는 방법을 설명합니다.

두 가지 독립적인 구성 요소로 이루어집니다.

  1. DEMO_READ_ONLY 읽기 전용 모드 (모든 배포).
  2. 일일 자동 리셋 (데모 호스트의 systemd 타이머가 리셋 스크립트를 백엔드 컨테이너 안에서 실행).

1. 읽기 전용 모드 (DEMO_READ_ONLY)​

백엔드 환경 변수를 설정합니다.

DEMO_READ_ONLY=true

(허용되는 truthy 값은 1, true, yes, on이며 대소문자를 구분하지 않습니다. 요청 시점에 읽으므로, 값을 바꿀 때 재빌드 없이 프로세스 재시작만 하면 됩니다.)

활성화되면 단일 미들웨어가 API 전체에 정책을 강제하므로, 개별 엔드포인트가 정책을 우회할 수 없습니다.

  • 읽기는 항상 통과: GET, HEAD, OPTIONS(마지막은 CORS preflight 유지용).
  • 쓰기는 기본 차단: 모든 POST, PUT, PATCH, DELETE(및 기타 메서드)는 **허용 목록(allow-list)**에 없으면 거부됩니다.
  • 허용 목록은 데모에 꼭 필요한 인증 흐름뿐입니다: POST /auth/login, POST /auth/refresh, POST /auth/logout. 그 외 회원가입, 비밀번호 재설정· 변경, 프로젝트 생성, 스캔 트리거, 승인, 설정, 웹훅, 파일 업로드는 모두 차단됩니다.

차단된 요청은 Content-Type: application/problem+json의 RFC 7807 403을 받습니다.

{
"type": "urn:trustedoss:problem:demo-read-only",
"title": "Read-only demo",
"status": 403,
"detail": "This is a read-only live demo. Creating, updating, or deleting data is disabled. …",
"instance": "/v1/projects",
"demo_read_only": true
}

관리자 화면​

공개된 데모 계정 중에는 Super admin이 있어 방문자가 관리자 화면을 열 수 있습니다. 그래서 이 화면들은 읽기도 좁혀 둡니다.

  • /v1/admin과 /v1/user-anonymisation 아래 요청은 보여 줘도 되는 화면의 GET만 통과합니다. 시스템 상태와 피드 패널(Trivy DB, KEV, 지원 종료, 악성 패키지), 디스크 사용량, 스캔 큐, 팀, 조직, 사용자, 감사 로그가 여기에 해당합니다.
  • 그 밖의 요청은 같은 403 문제 유형에 "demo_admin_hidden": true를 붙여 거부합니다. 백업, 사용자·감사 로그 CSV 내보내기, 레지스트리·티켓 자격 증명, API 키 해시 마이그레이션, 익명화 대기열이 여기에 속합니다. 새 관리자 엔드포인트는 목록에 추가하기 전까지 거부됩니다.
  • 사용자 화면과 감사 로그 화면에는 demo-org 조직만 나옵니다. 이 조직의 팀에 멤버십이 있는 사용자, 그리고 그런 사용자가 행위자이거나 이 조직의 팀에 속한 감사 항목입니다. 호스트 운영자 계정처럼 데모 밖의 계정은 보이지 않고, 그런 계정이 데모 팀에 남긴 감사 항목에는 행위자가 표시되지 않습니다.
  • 팀, 조직, 스캔 큐, 그룹 디렉터리, 프로젝트, 대시보드도 demo-org 조직으로 한정됩니다. 이 조직 밖의 팀이나 프로젝트는 조회할 수 없습니다.
  • 보고서와 SBOM을 내려받아도 보고서 다운로드 이력에 행이 추가되지 않습니다. 개인 데이터 내보내기(GET /v1/users/me/export)도 거부합니다. 데모 계정은 여러 방문자가 함께 쓰므로 다른 방문자의 로그인 기록까지 담기기 때문입니다.

우회 방지​

이 가드는 차단 목록이 아니라 허용 목록입니다. 나중에 추가되는 변이 엔드포인트는 별도 수정 없이 자동으로 차단됩니다. 허용 목록 비교 전에 경로를 정규화(역슬래시 변환, ./.. 세그먼트 해석, 끝 슬래시 제거)하므로 /v1/projects/../auth/login 같은 트래버설로 쓰기 경로를 허용 목록에 끼워 넣을 수 없습니다. HTTP 메서드는 대소문자 무관으로 비교하고 허용 목록은 (메서드, 경로) 쌍을 키로 쓰므로, 비정상 메서드가 허용된 경로에 편승할 수 없습니다.

프론트엔드 동작​

SPA는 공개 GET /health 응답({"status":"ok","demo_read_only":true})에서 플래그를 읽어,

  • 앱 상단에 슬림한 "읽기 전용 데모" 배너를 표시하고,
  • 쓰기 액션(예: "스캔", "프로젝트 등록" 버튼)을 비활성화하고 이유를 툴팁으로 안내합니다.

실제 경계는 미들웨어이며, UI 게이팅은 막다른 클릭을 줄이는 보조 수단입니다.

2. 일일 자동 리셋 (systemd 타이머)​

Hetzner 데모 호스트는 리셋을 systemd 타이머로 실행합니다. 유닛 파일은 deploy/hetzner/에 있습니다.

  • trustedoss-demo-reset.service: 리셋 스크립트를 실행 중인 백엔드 컨테이너 안에서 실행하는 oneshot 유닛입니다.

    ExecStart=/usr/local/bin/docker-compose -f docker-compose.yml \
    exec -T -e APP_ENV=demo backend python -m scripts.reset_demo

    컨테이너 안에서 실행하면 HTTP DEMO_READ_ONLY 가드를 우회합니다(스크립트가 Postgres에 직접 접근). 스크립트 자체의 APP_ENV 허용 목록이 안전 경계입니다.

  • trustedoss-demo-reset.timer: 서비스를 매일 03:17 UTC에 실행합니다 (OnCalendar=*-*-* 03:17:00 UTC, Persistent=true 이므로 호스트가 내려가 있어 놓친 리셋은 다음 부팅 때 한 번 실행됩니다).

리셋(apps/backend/scripts/reset_demo.py)은,

  • 데모 데이터셋만 삭제: demo-org 조직(FK cascade로 팀 → 프로젝트 → 스캔 → finding 제거)과 데모 사용자(demo-org 멤버십 기준: demo-org 에만 속한 사용자만 삭제; cascade로 멤버십·알림 제거). 전체 truncate가 아니므로 다른 조직에도 속한 다른 테넌트의 데이터는 절대 건드리지 않습니다.
  • 멱등한 seed_demo._seed로 재시드 하므로 데이터셋 형태가 일반 시드와 단일 소스로 일치합니다.
  • APP_ENV가 dev 또는 demo가 아니면 실행을 거부합니다(프로덕션 데이터베이스에는 절대 실행되지 않음).

호스트에서 타이머를 설치하고 활성화합니다.

sudo cp deploy/hetzner/trustedoss-demo-reset.service /etc/systemd/system/
sudo cp deploy/hetzner/trustedoss-demo-reset.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now trustedoss-demo-reset.timer
데모 비밀번호 고정

공개 데모 자격 증명이 매일 밤 바뀌지 않도록 호스트 .env의 호스트 .env에 DEMO_SUPER_ADMIN_PASSWORD를 설정하세요. 설정하지 않으면 무작위 비밀번호가 생기는 것이 아닙니다. 시드가 고정값으로 넘어가는데, 그 값은 이 저장소와 공개 데모를 설명하는 문서에 공개되어 있습니다. 그대로 두면 인스턴스의 모든 계정이 누구나 찾아볼 수 있는 비밀번호를 쓰게 됩니다. 직접 값을 정하고, 데모는 그 네트워크에 닿을 수 있는 사람 누구에게나 열려 있다고 보세요.

공개 데모가 어디서 운영되는지는 데모 SaaS 호스팅을 참고하세요.

수동 리셋

타이머를 기다리지 않고 즉시 리셋을 실행합니다.

sudo systemctl start trustedoss-demo-reset.service
# 또는 내부 명령을 직접 실행:
docker-compose -f docker-compose.yml exec -T -e APP_ENV=demo backend python -m scripts.reset_demo

로컬 읽기 전용 데모 (Docker Compose)​

읽기 전용 모드는 모든 배포에서 동작합니다. 로컬 읽기 전용 인스턴스는 .env에 DEMO_READ_ONLY=true를 추가하고 백엔드를 다시 만들면(docker-compose up -d backend) 됩니다. systemd 타이머는 데모 호스트용이며, 로컬에서는 깨끗한 데이터셋이 필요할 때마다 백엔드 컨테이너 안에서 리셋을 다시 실행하세요.

docker-compose -f docker-compose.dev.yml exec -e APP_ENV=demo backend \
python -m scripts.reset_demo