InfraGuard

인스턴스 버전 원장 [ver]

인스턴스별 소프트웨어 버전을 수동 입력 또는 프로브 JSON import 로 관리하고 current/outdated/eol/vuln 상태로 추적합니다.

개요 — 무엇을 하나

Assets ▸ Instances(/asset/instances) 카드의 [ver] 버튼은 그 OS 인스턴스에 설치된 소프트웨어의 **버전 원장(1:N)**을 관리하는 모달을 엽니다. PHP·Node·nginx·MySQL·Docker·Jenkins 같은 런타임·서비스·툴의 버전을 한 곳에 모아두고, 각 항목을 current(최신) / outdated(구버전) / eol(지원종료) / vuln(취약) / unknown(미상) 상태로 표시해 패치 우선순위를 판단합니다.

두 개의 테이블이 협업합니다.

테이블 역할
infr_software_catalog 버전 관리 대상 소프트웨어 마스터(49종 · 8개 분류). key → 표시명·분류·탐지 명령·아이콘 매핑. 앱이 소유(read/write).
infr_instance_software 인스턴스별 버전 원장(1:N). UNIQUE(instance_id, software_key) — 수동 저장·JSON import 모두 이 키로 upsert.

갱신 경로는 두 가지입니다.

  1. 수동 add/edit — 모달의 "버전관리" 탭에서 카탈로그 드롭다운으로 소프트웨어를 고르고 버전·상태·메모를 입력.
  2. JSON import — 대상 호스트에서 scripts/infr_version_probe.cjs(Inventory ▸ Tools 에 시드됨)를 로컬로 실행 → 출력 JSON 을 "JSON import" 탭에 붙여넣어 일괄 upsert.

버전 원장은 뒤이어 서비스 카탈로그의 **[Analysis & Build]**가 데몬성 소프트웨어(nginx·mysql·redis·docker …)를 infr_service로 자동 승격하는 원천이 됩니다. 프로브가 채우는 런타임 존재성 축(아래)이 그 라이브니스 기본값을 잡습니다.

언제 쓰나

화면 구성

[ver] 모달 (탭 토글)

탭 내용
버전관리 이 인스턴스의 원장 행 목록(분류별 정렬) + add/edit/delete 폼. 카탈로그 드롭다운(아이콘·표시명)
JSON import textarea + [가져오기] — 프로브/수동 JSON 붙여넣기 일괄 upsert

원장 행이 담는 값

infr_instance_software 한 행:

필드 의미
software_key 카탈로그 key(php·nginx …). 정규식 ^[a-z0-9_]+$, 최대 40자. 카탈로그 밖 커스텀 키도 허용(coverage-max)
name / category 표시명·분류(비우면 카탈로그에서 스냅샷)
version 탐지/입력된 버전 문자열(최대 60자)
raw 탐지 원문(명령 출력 한 줄, 최대 255자)
status current / outdated / eol / vuln / unknown — 수명·취약 축
source manual(수동) / script(프로브) / import(JSON)
detected_at 탐지·기록 시각
note 자유 메모

런타임 존재성 축 (마이그레이션 000718)

버전(수명)과 직교하는, 데몬성 소프트웨어의 "지금 살아 있나" 축. 프로브가 채웁니다.

필드 의미
is_daemon 데몬/서비스 성격 여부(true/false/null)
svc_registered systemd 등록됨(is-enabled = enabled/static/disabled …)
proc_up 프로세스 가동(is-active > pgrep > 기대 포트 리슨)
listen_ports 리슨 중인 기대 포트 CSV(예: 80,443)
unit systemd unit 명

행에는 이 축에서 파생된 presence 배지가 붙습니다: proc_up→running > svc_registered→registered > is_daemon=false 또는 version 존재→binary > 그 외 null.

사용법

1. 수동으로 버전 추가/수정

  1. Instances 카드에서 [ver] 클릭 → "버전관리" 탭.
  2. [추가] → 카탈로그 드롭다운에서 소프트웨어 선택(예: nginx).
  3. version(예: 1.24.0), status(예: current), 필요 시 note 입력.
  4. 저장 → POST /asset/instances/software/save. 같은 (instance_id, software_key)가 있으면 update, 없으면 create(source=manual).

name·category를 비워두면 카탈로그의 표시명·분류가 자동으로 채워집니다. 버전만 입력하세요.

2. 프로브로 일괄 등록 (권장)

대상 호스트에서 프로브를 로컬로 실행합니다. 크리덴셜·루트 불필요이며 로컬 명령만 씁니다(외부 호출 없음).

# 전체 카탈로그 탐지 (JSON 한 줄)
node infr_version_probe.cjs

# 사람이 읽기 좋게 들여쓰기
node infr_version_probe.cjs --pretty

# 특정 소프트웨어만
node infr_version_probe.cjs php,nginx,node

SE 는 보통 SSH 로 감싸 원격 수집합니다(스크립트를 배치할 필요도 없음).

ssh user@203.0.113.10 'node -' < infr_version_probe.cjs
# 또는 배치 후
ssh user@203.0.113.10 node /opt/infr/infr_version_probe.cjs

출력 JSON 을 복사해 [ver] ▸ JSON import 탭에 붙여넣고 [가져오기] → POST /asset/instances/software/import → 일괄 upsert.

프로브 출력 형태:

{
  "tool": "infr_version_probe",
  "hostname": "glory",
  "detected_at": "2026-08-13T04:00:00.000Z",
  "items": [
    { "key": "nginx", "version": "1.24.0", "raw": "nginx version: nginx/1.24.0",
      "is_daemon": true, "svc_registered": true, "proc_up": true,
      "listen_ports": "80,443", "unit": "nginx" },
    { "key": "php", "version": "8.4.3", "raw": "8.4.3", "is_daemon": true,
      "svc_registered": true, "proc_up": true, "unit": "php8.4-fpm" },
    { "key": "openssl", "version": "3.0.13", "raw": "OpenSSL 3.0.13 30 Jan 2024", "is_daemon": false }
  ]
}

import 응답은 imported(반영 건수)와 unknown(카탈로그에 없는 key 목록)을 돌려줍니다. unknown 이어도 행은 등록됩니다 — 다만 표시명·분류가 비고, 카탈로그에 그 key 를 추가하면 다음부터 보강됩니다.

3. import 가 받는 JSON 형식 3종

파서는 유연합니다. 아래 셋 모두 수용합니다.

// (1) items 배열 (프로브 표준)
{ "items": [ { "key": "nginx", "version": "1.24.0", "status": "current" } ] }

// (2) versions 맵
{ "versions": { "nginx": "1.24.0", "php": "8.4.3" } }

// (3) 평면 맵
{ "nginx": "1.24.0", "php": { "version": "8.4.3", "status": "outdated" } }

예약 키(hostname·detected_at·versions·items·tool·generated_by·source)는 소프트웨어로 오인하지 않고 건너뜁니다. source는 최상위 generated_by/tool/source에 probe 또는 script가 들어 있으면 script, 아니면 import로 기록됩니다.

4. 삭제

행의 삭제 버튼 → POST /asset/instances/software/delete({id, instance_id}). 되돌릴 수 없습니다.

데이터 소스

카탈로그 — infr_software_catalog (49종 · 8분류)

InfrSoftwareCatalogSeeder가 멱등 시드(updateOrCreate by key)합니다. 이 시더가 key→탐지 명령 매핑의 단일 진실이며, scripts/infr_version_probe.cjs의 CATALOG가 이와 동기됩니다.

분류(category) 예시 key
runtime (10) php · node · python · java · go · ruby · perl · dotnet · rust · bun
web (7) nginx · apache · haproxy · caddy · traefik · tomcat · ftp
database (8) mysql · postgresql · redis · mongodb · memcached · elasticsearch · rabbitmq · kafka
ci_cd (1) jenkins
container (5) docker · containerd · kubelet · podman · helm
os_core (3) kernel · glibc · systemd
security (7) openssl · openssh · sudo · certbot · fail2ban · firewalld · wireguard
observability (8) node_exporter · grafana_agent · filebeat · rsync · restic · git · curl · bash

카탈로그 컬럼: key(unique) · name · category · detect_cmd(탐지 원라이너) · version_regex · icon(mdi) · vendor_url · seq · is_active.

ci_cd 분류는 마이그레이션 000721 이 enum 을 7→8값으로 확장해 추가했습니다(Jenkins 전용). enum 이라 신규 분류는 DDL ALTER 가 필요하지만, 이후 infr_instance_software.category는 varchar 라 코드만으로 확장됩니다.

Jenkins 특수 탐지 (X-Jenkins)

Jenkins 는 표준 --version 명령이 없는 자바 웹앱이라 프로브가 세 방법을 순차 시도합니다(전부 로컬·무인증).

  1. HTTP 헤더 — curl -sI http://127.0.0.1:{8080,8081,8443}/ 응답의 X-Jenkins: 헤더에서 버전 추출(가장 깔끔·빠름, 다른 서비스면 헤더가 없어 오탐 없음).
  2. WAR — java -jar /usr/share/java/jenkins.war --version(설치만 돼 있어도).
  3. 패키지 관리자 — rpm -q jenkins 또는 dpkg-query -W jenkins.

FTP 도 특수 처리합니다 — 실행 파일이 PATH 밖(/usr/sbin/vsftpd)일 수 있어 ps 로 실행 중인 데몬의 절대경로를 찾아 -v(pure-ftpd 는 -h)로 조회합니다.

버전 파싱 규칙

pickVersion()은 명령 출력의 첫 줄만 보지 않습니다.

원장 — infr_instance_software

instance_id로 infr_instance와 1:N. 조회는 인증된 사용자면 카탈로그 + 그 인스턴스의 원장 행을 함께 반환합니다.

권한

동작 엔드포인트 레벨 게이트
조회(카탈로그+원장) GET /asset/instances/software/list infr.auth(level ≥ 1, demo)
생성/수정 POST /asset/instances/software/save level ≥ 2 (staff/admin)
삭제 POST /asset/instances/software/delete level ≥ 2
JSON import POST /asset/instances/software/import level ≥ 2

문제해결 · FAQ

import 후 일부 항목이 표시명 없이 뜹니다

그 key가 infr_software_catalog에 없는 경우입니다. import 응답의 unknown[]에 나열됩니다. 카탈로그에 해당 key 를 추가(시더 또는 관리)하면 다음 import 부터 표시명·분류가 보강됩니다. 커스텀 소프트웨어라면 그대로 두어도 무방합니다.

"bad json" / "empty json" 오류

software_key 저장이 거부됩니다(422)

key 는 소문자·숫자·언더스코어만 허용(^[a-z0-9_]+$), 최대 40자입니다. 대문자·하이픈·공백을 쓰지 마세요(예: Node.js✗ → node✓). 또 편집으로 key 를 바꿨는데 그 key 가 같은 인스턴스에 이미 있으면 중복 오류가 납니다.

프로브에 특정 소프트웨어가 안 잡힙니다

프로브는 버전이 탐지된 항목만 출력합니다. 명령이 PATH 에 없거나(5초 타임아웃) 미설치면 조용히 건너뜁니다. 특정 key 만 강제로 보려면 node infr_version_probe.cjs <key>로 실행해 원문을 확인하세요.

MariaDB 버전이 클라이언트 버전으로 잡힙니다

프로브의 Distrib 우선 규칙이 이를 처리합니다. 여전히 이상하면 raw 값을 확인하고 수동으로 version을 교정하세요(source는 그대로 두면 됩니다).

버전은 있는데 서비스가 안 뜹니다

버전 원장은 소프트웨어 유무만 봅니다. 그것이 **서비스(데몬)**로 승격되려면 서비스 카탈로그에서 **[Analysis & Build]**를 실행해야 합니다. 그때 원장의 런타임 존재성 축(is_daemon·proc_up …)이 라이브니스 기본값이 됩니다. 프로브 JSON 을 나중에 넣었다면 [Analysis & Build]를 다시 돌리세요.

관련 항목

카드의 [ver] 버튼
카드의 [ver] 버튼