InfraGuard

인스턴스 변수 ([env])

인스턴스별 env 변수를 Crypt 로 암호화 저장하고, Tools 스크립트의 {{PLACEHOLDER}} 매시업에 쓸 내장 토큰 사전을 함께 제공하는 [env] 모달.

개요 — 무엇을 하나

**인스턴스 변수([env])**는 Assets ▸ Instances 목록의 각 인스턴스 카드에 달린 env 아이콘 액션으로 열리는 모달입니다. 여기서 그 인스턴스 하나에만 속하는 변수(DB 접속 정보, 로그 경로, 임계값 등)를 정의합니다. 이 변수들은 두 가지 역할을 합니다.

  1. 비밀 금고(값 암호화) — 값은 항상 표준 암호화 방식으로 infr_instance_var.value_enc 에 암호화 저장됩니다. 평문은 DB 어디에도 남지 않습니다. is_secret=1 로 표시한 값은 목록에서 마스킹되고, 보려면 **열람(reveal)**을 눌러야 하며 열람은 감사 로그에 남습니다.
  2. 매시업 사전({{PLACEHOLDER}} 치환) — Inventory ▸ Tools 의 수집·설치 스크립트에는 {{DB_HOST}}, {{EVE_JSON_PATH}} 같은 토큰이 들어 있습니다. [env] 에 정의한 변수(그리고 인스턴스가 자동 제공하는 내장 토큰)가 이 토큰을 그 인스턴스의 실제 값으로 치환합니다. 하드코딩 크리덴셜을 없애기 위한 §보안 부채 규칙의 핵심 장치입니다.

또한 모달은 내장 토큰 사전(infr_token_catalog, 38종·8분류·다국어)을 함께 보여 줍니다. 각 토큰이 무엇인지·왜 필요한지·어떻게 채우는지를 세션 언어로 설명하므로, "이 스크립트가 요구하는 이 값을 어디서 얻나"를 헤매지 않게 합니다.

[env] 변수는 인스턴스별 사전입니다. 여러 인스턴스에서 공유해야 하는 비밀은 Inventory ▸ 키정보(vault)의 전역 키가 폴백으로 채웁니다(인스턴스 정의가 우선). 서버 튜닝 근거로 올려두는 nginx/my.cnf/sysctl 설정 스냅샷은 [env] 가 아니라 [param] — 인스턴스 파라미터를 씁니다.

언제 쓰나

화면 구성

모달은 3개 탭으로 구성됩니다.

탭 코드값 내용
현재 설정된 변수 vars 이 인스턴스에 저장된 변수 목록(테이블) + 아직 정의되지 않은 매핑 토큰의 빠른 입력 줄. 비밀은 마스킹·열람 버튼.
내장 토큰 tokens 카탈로그 사전. 상단 인스턴스 내장 토큰(값 자동) + 카테고리 서브탭(database·redis·path·network·security·binary·threshold·other). 각 토큰: 의미·용도·예시 + 사용중(Tools 에서 참조)·정의됨(이 인스턴스에 있음) 배지, [변수로 추가].
(동적) 새 변수 / 변수명 form add/edit 폼. [새 변수 추가](탭바 우측) 또는 행 편집·토큰 [변수로 추가]로 열립니다.

변수 테이블 컬럼

컬럼 설명
var_key 변수명(토큰명). 대문자·숫자·_, 첫 글자는 대문자여야 합니다.
value 비밀이 아니면 평문 표시(매시업에 그대로 쓰임), 비밀이면 •••••• 마스킹 + [열람].
is_secret 비밀 플래그. 켜면 목록에서 값을 숨기고 열람에 감사가 붙습니다.
note 자유 메모(최대 255자).

내장 토큰(자동 제공 · 7종)

인스턴스 필드에서 파생되어 정의 없이 항상 매시업에 쓸 수 있습니다(값이 있는 것만 노출, 비밀 아님).

토큰 원천 필드
HOSTNAME infr_instance.hostname
ALIAS infr_instance.alias (server_status 메트릭 매칭 키)
IP_PRIVATE infr_instance.ip_private
IP_PUBLIC infr_instance.ip_public
SSH_HOST infr_instance.ssh_host
SSH_PORT infr_instance.ssh_port
SSH_USER infr_instance.ssh_user

사용법

변수 추가 (정식 폼)

  1. 현재 설정된 변수 탭 우측 [새 변수 추가] → 폼 탭으로 이동.

  2. 변수명을 입력합니다. 저장 시 자동으로 대문자화되며, 서버 검증 규칙은 다음과 같습니다.

    var_key  : 필수, 최대 60자, 정규식 ^[A-Z][A-Z0-9_]*$   (대문자 시작, 대문자·숫자·밑줄만)
    value    : 선택, 최대 4000자
    is_secret: 불리언
    note     : 선택, 최대 255자
    
  3. 값을 입력하고, 크리덴셜/토큰이면 비밀 체크를 켭니다.

  4. 저장 → 값은 암호화되어 암호화되어 value_enc 에 저장됩니다.

편집 시 값 칸을 비워 두면 기존 값이 유지됩니다(vault keep-hint 패턴). 비밀번호를 바꾸지 않고 메모만 고칠 때 유용합니다. 값을 명시적으로 지우려면(=null) 새 값 없이 저장합니다.

빠른 입력 (토큰 프리필)

Tools 스크립트가 요구하지만 아직 정의되지 않은 토큰은 현재 설정된 변수 탭에 카테고리별 빠른 입력 줄로 뜹니다. 값만 입력하고 저장하면 var_key=토큰명, id=0 으로 upsert 됩니다. 토큰명에 PASS|SECRET|TOKEN|KEY|CRED 가 들어가면 자동으로 비밀로 저장됩니다.

비밀 열람 (감사)

목록에서 비밀 값 옆 눈(eye) 아이콘 → 서버가 복호화해 반환. 이 동작은 감사 로그에 남습니다.

GET /asset/instances/vars/{id}/reveal?instance_id={iid}
→ [audit] instance_var.reveal { instance_id, key, by }

매시업에서의 쓰임

Tools 코드 모달에서 이 인스턴스를 매시업 소스로 고르면, 비밀이 아닌 변수와 내장 토큰이 {{TOKEN}} 자리에 자동 치환됩니다. 비밀 변수는 목록 API가 값을 내려 주지 않으므로(마스킹), 매시업에는 열람을 통해서만 반영됩니다. 자세한 흐름은 Inventory(주머니)와 인스턴스 목록·액션 참고.

데이터 소스

테이블

테이블 용도 비고
infr_instance_var 인스턴스별 변수(값=Crypt) UNIQUE(instance_id, var_key), 마이그레이션 000642
infr_token_catalog 내장 토큰 다국어 사전(38종) label/description = JSON {ko,en,…}, 마이그레이션 000650
infr_instance 내장 토큰 원천(hostname·alias·ip·ssh) 조인 소스
infr_snippet (kind=tool) 실제 사용 토큰 교차(사용중 배지) extractPlaceholders() 로 body 파싱

infr_instance_var 스키마

id           bigint PK
instance_id  bigint            -- → infr_instance.id
var_key      varchar(60)       -- 토큰명 {{VAR_KEY}}
value_enc    text NULL         -- 암호화 저장 (평문 금지)
is_secret    tinyint(1)        -- 목록 마스킹 + reveal 감사
note         varchar(255) NULL
created_by / updated_by  int NULL
timestamps
UNIQUE(instance_id, var_key), KEY(instance_id)

토큰 카탈로그 분류 (38종)

분류 개수 예시 토큰
builtin 7 HOSTNAME · ALIAS · IP_PRIVATE · IP_PUBLIC · SSH_HOST · SSH_PORT · SSH_USER
database 5 DB_HOST · DB_USER · DB_PASS(비밀) · DB_NAME · CNF_PATH
redis 3 REDIS_HOST · REDIS_PORT · REDIS_PASS(비밀)
path 7 EVE_JSON_PATH · NGINX_LOG_PATH · AGG_CONFIG_PATH · LOG_PATH · BACKUP_TARGET · BACKUP_PREV · BACKUP_SRC
network 8 SERVER_NAME · SERVER_INDEX · PUBLIC_IPS · INTERNAL_CIDR_PREFIX · OFFICE_IP · HOME_NET_PREFIX · TRIGGER_URL · ALIAS_MAP
security 2 TLX_TOKEN(비밀) · IPSET_NAME
binary 4 CONNTRACK_BIN · IPTABLES_BIN · CHAIN_IN · CHAIN_OUT
threshold 2 ANOMALY_THRESHOLD · MIN_HITS

토큰 설명은 다국어입니다. App\Support\I18nJson::pick() 이 세션 언어 → en 폴백 → 임의 순으로 라벨/설명을 고릅니다. 그래서 언어를 바꾸면 같은 토큰의 해설이 그 언어로 나옵니다.

형식 주의 (따옴표·JSON)

토큰 삽입 형식
REDIS_PORT · SERVER_INDEX · MIN_HITS · ANOMALY_THRESHOLD 숫자 그대로 — 따옴표 없이 채운다
PUBLIC_IPS JSON 배열 리터럴 — ["203.0.113.10","203.0.113.11"]
ALIAS_MAP JSON 맵 리터럴 — {"DNS_SERVER":"demo"}
나머지 문자열 그대로 삽입(경로·호스트·계정 등)

권한

동작 엔드포인트 최소 레벨
목록 조회 GET /asset/instances/vars/list 조회(≥1, infr.auth)
토큰 사전 GET /asset/instances/vars/tokens 조회(≥1)
저장(생성/수정) POST /asset/instances/vars/save ≥2 (staff/admin)
삭제 POST /asset/instances/vars/delete ≥2
비밀 열람(reveal) GET /asset/instances/vars/{id}/reveal ≥1 + 감사 로그

레벨 체계는 demo=1 · staff=5 · admin=10 입니다(RBAC 레벨). 쓰기 게이트는 컨트롤러 canWrite()가 세션 infr_user_level >= 2 로 판정합니다. 열람은 낮은 레벨(≥1)도 가능하되 모든 열람이 [audit] instance_var.reveal 로 기록됩니다. 생성/수정/삭제도 각각 instance_var.create|update|delete 로 감사됩니다(감사 로그).

비밀 값(DB_PASS·REDIS_PASS·TLX_TOKEN 등)은 반드시 비밀 체크를 켜라. 켜지 않으면 목록 API가 평문을 그대로 내려 주어 매시업·화면에 노출됩니다. 비밀 변수는 열람을 통해서만 값이 반환되며 그때마다 감사가 남습니다.

문제해결 · FAQ

Q. 변수 저장이 422 로 거절됩니다. var_key 규칙 위반입니다. 대문자로 시작, 대문자·숫자·밑줄만, 최대 60자여야 합니다. 예: DB_HOST(O), db-host(X), 1PORT(X).

Q. 같은 이름으로 저장하니 중복 오류가 납니다. UNIQUE(instance_id, var_key) 제약입니다. 그 인스턴스에 이미 같은 키가 있습니다. 기존 항목을 편집하세요(키 변경 시 다른 기존 키와 충돌하면 거절됩니다).

Q. 편집에서 값 칸을 비웠더니 비밀번호가 그대로입니다. 의도된 동작입니다(keep-hint). 값 칸이 비면 기존 암호값을 유지합니다. 값을 실제로 바꾸려면 새 값을 입력하세요.

Q. 열람했더니 500 / "복호화 실패"가 뜹니다. value_enc 가 현재 APP_KEY 로 복호화되지 않습니다(키 교체 등). 값을 다시 저장하면 새 키로 재암호화됩니다.

Q. 매시업했는데 토큰이 빈 값으로 치환됩니다. (1) 그 토큰을 이 인스턴스에 아직 정의하지 않았거나, (2) 비밀로 저장되어 목록에 값이 안 실립니다. 내장 토큰 탭에서 정의됨 배지를 확인하고, 비밀이면 열람으로 채웁니다.

Q. 사용중 배지는 무슨 뜻인가? 활성 Tools 스크립트(infr_snippet.kind=tool)의 body 에서 그 {{토큰}}을 실제로 참조하고 있다는 뜻입니다(런타임 교차). 스크립트에 없는 토큰이라도 카탈로그 설명은 볼 수 있습니다.

관련 항목

카드의 [env] 버튼
카드의 [env] 버튼