InfraGuard

인벤토리 (주머니)

장애·침해 상황에서 즉시 꺼내 쓰는 스크립트(Tools)·명령어(Snippets)·가이드 문서(Docs)·팀 공유 키(Keys)를 한 곳에 담아두고 검색·복사·결합하는 빠른 대처 리소스함입니다.

개요 — 무엇을 하나

**Inventory("주머니")**는 SE·시스템·보안 담당자가 장애나 침해 상황에서 지체 없이 대응하도록, 필요한 자료를 미리 담아 두는 단일 콘솔입니다. 네 가지 자료를 탭으로 나눠 관리합니다.

탭 무엇 저장 테이블 대표 용도
Tools(툴) 수집·설치·진단 스크립트 (CodeMirror 편집) infr_snippet (kind=tool) run_report·eve_ingest 같은 수집기, 프로브 스크립트
Snippets(스니펫) 짧은 CLI 명령/한 줄 조각 infr_snippet (kind=snippet) 자주 쓰는 journalctl·ss·iptables 한 줄
Docs(가이드 문서) 플레이북·기준·네트워크 맵·마크다운 infr_doc 비상 대응 절차, 컴플라이언스 룰, 아키텍처 다이어그램
Keys(키정보) 팀 공유 비밀번호·API 키·전역 변수 infr_vault_key DB 계정, API 키, 매시업 폴백 토큰

핵심 특징:

Inventory는 크리덴셜을 코드에 하드코딩하지 않기 위한 장치이기도 합니다. 스크립트 본문에는 {{DB_PASSWORD}} 같은 토큰만 두고, 실제 값은 Keys(키정보)·인스턴스 변수·수집기 설정에서 매시업 시점에만 주입합니다.


언제 쓰나


화면 구성

상단에 툴 · 스니펫 · 가이드 문서 · 키정보 4개 탭과 각 탭의 개수 배지가 있습니다. 탭 목록은 활성화 시 개별 엔드포인트로 지연 로드됩니다(초기 화면은 옵션·카운트·권한·AI 준비여부·인스턴스 목록만 부트스트랩).

공통 컨트롤:

Tools · Snippets 카드

Docs 카드

카테고리별로 편집기 유형이 달라집니다.

카테고리 편집기 저장 위치
playbook (운영·비상 대응) 케이스+대응 리스트 (증상/대응/심각도) payload JSON
compliance (보안 지침·기준) 규칙+근거+참조 리스트 payload JSON
network_map (아키텍처·네트워크) Konva 네트워크 맵(노드·연결선·그룹·PNG 저장) payload JSON
access (계정·권한) 마크다운 body_md
misc (그 외) 마크다운 body_md

문서 상태는 draft(초안) / published(게시)이며, AI 어시스트 버튼으로 주제를 입력해 초안을 생성할 수 있습니다.

Keys 카드


사용법

1. Tool/Snippet 추가·편집

  1. 툴 또는 스니펫 탭에서 **[추가]**를 누릅니다(쓰기 권한 level≥2 필요).
  2. 필수: 종류(kind), 분류(category), 언어(lang), 제목(1개 이상 언어), 본문.
    • 언어(lang) 값: bash · javascript(Node.js) · sql · php · ini · other.
    • 제목·설명·본문은 언어 토글로 언어별 입력이 가능하며, 비운 언어는 다른 언어로 폴백 표시됩니다.
  3. 본문에 크리덴셜·호스트 같은 가변값은 {{TOKEN}} 으로 둡니다. 저장하면 서버가 정규식 {{ ... }}으로 토큰을 추출해 placeholders 메타에 반영합니다.
  4. 저장 시 감사 로그(snippet.create / snippet.update)가 남습니다. **[복제]**는 (copy) 접미의 동일 사본을 만듭니다.

토큰 이름에 PASS·SECRET·TOKEN·KEY·CRED 문자열이 들어가면 비밀 토큰으로 자동 분류되어, 매시업 시 자동 주입 대상에서 빠지고 "수동으로 채우세요" 안내가 붙습니다.

2. {{PLACEHOLDER}} 매시업 (결합 복사)

Tools 코드 모달에서 대상 인스턴스를 고르면, 토큰이 다음 우선순위로 채워집니다.

  1. 인스턴스 내장 토큰 — HOSTNAME·IP_PRIVATE·IP_PUBLIC·SSH_HOST·SSH_USER 등(비밀 아님).
  2. 인스턴스 변수 — 해당 인스턴스의 [env] 비밀 아닌 변수(인스턴스 변수).
  3. 소스별 채우기 — 수집기 설정(collector)·규칙 임계(rules)·인스턴스(instance) 값.
  4. 전역 비밀 폴백 — 위에서 못 채운 토큰을 내부키(Keys) 의 전역 변수로 최후 주입.

내장 토큰·인스턴스 변수로 안 채워진 비밀 토큰은 GET /inventory/keys/vars(전역 내부키 → 비밀 맵)로 폴백 주입됩니다. 이 요청은 레벨≥1 + 매 요청 감사(key.vars) 로 처리됩니다(Option B — 의도된 예외).

# 예: 저장된 본문
mysqldump -h {{DB_HOST}} -u {{DB_USER}} -p{{DB_PASSWORD}} {{DB_NAME}} > /backup/dump.sql

# 인스턴스 "blue" 선택 후 결합 복사 →
# {{DB_HOST}}=10.0.0.12(인스턴스), {{DB_USER}}=app(env 변수),
# {{DB_PASSWORD}}=(내부키 전역 폴백·감사), {{DB_NAME}}=(수동 입력)

3. 가이드 문서 작성 + AI 어시스트

  1. 문서 탭에서 [문서 추가] → 카테고리를 선택하면 편집기 유형이 바뀝니다.
  2. network_map은 노드 추가·드래그·그룹핑·연결(기부자→채택자)·PNG 저장을 지원하는 Konva 캔버스입니다.
  3. [AI 어시스트] — 주제(예: "랜섬웨어 대응")를 입력하면 준비된 AI provider가 스키마에 맞는 초안(playbook은 case/answer, compliance는 rule/rationale, 나머지는 markdown)을 생성합니다.
    • AI 키가 없으면 Mock 초안이 생성됩니다(설정: AI 어댑터).

4. 키정보(Vault Key) 관리·열람

  1. [키 추가](level≥2) → 분류(db/api/ssh/service/other), 키 종류(외부/내부), 제목, 사용자/URL/메모, 비밀값을 입력.
    • 내부키는 토큰명(대문자, 정규식 ^[A-Z][A-Z0-9_]*$, 예 TLX_TOKEN)을 지정해야 매시업 폴백으로 쓰입니다. 외부키는 토큰이 강제로 비워집니다.
    • 편집 시 비밀값을 비워 두면 기존 값이 유지됩니다(신규는 필수).
  2. 목록·카드에는 비밀이 절대 실리지 않고 has_secret 여부만 표시됩니다.
  3. 보기(eye) 토글 → GET /inventory/keys/{id}/reveal 이 복호화 값을 반환하고 감사 로그(key.reveal) 를 남깁니다. 복사 후 다시 숨기면 화면에서 사라집니다.

키 열람과 전역 비밀 주입(key.vars)은 전부 감사됩니다(누가·언제·어떤 키/토큰). 감사 기록은 감사 로그에서 확인할 수 있습니다. 비밀은 로그·URL·클립보드 히스토리에 남지 않도록 주의하세요.


데이터 소스

테이블

테이블 내용 비고
infr_snippet Tools(kind=tool) + Snippets(kind=snippet) 제목·설명·본문 다국어 JSON, placeholders 메타
infr_doc 가이드 문서 payload(json) 또는 body_md(markdown)
infr_vault_key 팀 공유 키 secret_enc = 암호화 저장
infr_audit_log 저장·삭제·열람 감사 append-only

엔드포인트 (경로 접두 /asset/inventory)

메서드·경로 동작 권한
GET /inventory 셸 부트스트랩(옵션·카운트·권한·인스턴스·i18n) 로그인(level≥1)
GET /inventory/snippets/list 툴/스니펫 목록(검색·필터·정렬·페이지) 로그인
POST /inventory/snippets/save 저장(생성/수정) level≥2
POST /inventory/snippets/duplicate 복제 level≥2
POST /inventory/snippets/delete 삭제 level≥2
GET /inventory/docs/list 문서 목록 로그인
POST /inventory/docs/save 문서 저장 level≥2
POST /inventory/docs/delete 문서 삭제 level≥2
POST /inventory/docs/ai-assist AI 초안 생성 level≥2
GET /inventory/keys/list 키 목록(마스킹) 로그인
GET /inventory/keys/vars 전역 내부키 → 비밀 맵(매시업 폴백) level≥1 + 감사
GET /inventory/keys/{id}/reveal 비밀 복호화 열람 level≥1 + 감사
POST /inventory/keys/save 키 저장 level≥2
POST /inventory/keys/delete 키 삭제 level≥2

부트스트랩 페이로드 주요 필드

{
  "counts": { "tool": 12, "snippet": 30, "doc": 8, "key": 15 },
  "can_write": true,          // level >= 2
  "can_reveal": true,         // level >= 1
  "ai_ready": true,           // 준비된 실제 AI provider 존재
  "instances": [ { "id": 1, "name": "blue", "alias": "blue",
                   "ip_private": "10.0.0.12", "reachable": true } ],
  "lang": "ko"
}

권한

작업 필요 레벨 감사
Inventory 열람(모든 탭 목록·검색) 로그인(demo=1 이상) —
키 열람(reveal) · 전역 비밀 주입(vars) level≥1 ✅ key.reveal / key.vars
Tool/Snippet/Doc/Key 저장·삭제·복제 level≥2(staff) ✅ *.create/update/delete/duplicate
AI 어시스트 level≥2 —

문제해결 · FAQ

Q. {{TOKEN}} 이 안 채워집니다. 비밀 토큰(PASS/SECRET/TOKEN/KEY/CRED 포함)은 자동 주입 대상이 아닙니다. 인스턴스 변수([env])나 내부키(전역 변수)로 등록하거나 수동으로 입력하세요. 인스턴스가 매시업 소스에 없으면 저장된 인스턴스가 없거나 필드가 비어 있는지 확인합니다.

Q. 키 [보기]를 눌러도 값이 안 나옵니다. 복호화 실패(복호화에 실패했습니다.)는 대개 APP_KEY가 저장 이후 바뀐 경우입니다. Crypt는 APP_KEY로 복호화하므로, 키를 회전했다면 기존 비밀은 다시 저장해야 합니다.

Q. AI 어시스트가 "AI Mock"으로만 나옵니다. 준비된 실제 AI provider가 없어서(ai_ready=false) Mock 초안이 생성된 상태입니다. AI 어댑터에서 provider 키를 등록하세요.

Q. 저장이 422로 거부됩니다. 제목을 최소 한 언어로 입력했는지, 본문(정본=ko 우선)이 비어 있지 않은지 확인하세요(제목을 하나 이상의 언어로 입력하세요. / 본문을 입력하세요.).

Q. 내부키 토큰명을 저장할 수 없습니다. 토큰명은 대문자로 시작하고 대문자·숫자·밑줄만 허용됩니다(^[A-Z][A-Z0-9_]*$). 예: DB_PASSWORD, TLX_TOKEN. 외부키는 토큰명을 가질 수 없습니다.

Q. 비밀이 목록/카드에 노출되나요? 아니요. 목록 응답에는 has_secret(존재 여부)만 포함되고 실제 값은 reveal 엔드포인트로만 반환됩니다.


관련 항목

인벤토리 — 도구 · 스니펫 · 문서 · 키정보
인벤토리 — 도구 · 스니펫 · 문서 · 키정보