11#! /usr/bin/env bash
22# ============================================================================
3- # MORI SOC — 엔드포인트 온보딩 번들 (Zabbix Agent 2 + Trivy)
3+ # MORI SOC — 엔드포인트 온보딩 번들 (Zabbix Agent 2 + Fleet 에이전트 + Trivy)
44#
55# 대상 Linux 서버 1대를 MORI 관측 대상으로 만드는 원커맨드 스크립트.
66# 1) Zabbix Agent 2 설치 + MORI Zabbix Server 로 Active 연결 설정
7- # 2) Trivy 설치 + 파일시스템 취약점 스캔 → JSON 리포트
7+ # 2) Fleet 에이전트(fleetd/osquery) 설치 + Fleet 서버로 등록
8+ # 3) Trivy 설치 + 파일시스템 취약점 스캔 → JSON 리포트 (+ MORI 자동 배송)
89#
910# 사용 (대상 서버, root/sudo):
1011# sudo -E MORI_ZABBIX_SERVER=mori.example.com MORI_HOSTNAME=my-web-01 \
12+ # MORI_FLEET_URL=https://fleet.example.com:1337 MORI_FLEET_SECRET=<enroll-secret> \
1113# bash mori-endpoint-onboard.sh
1214#
1315# curl 로 바로 (다운로드→확인→실행 권장):
1820# -h, --help 도움말
1921# --check 사전 점검만(설치 안 함): OS/패키지매니저, root, Zabbix 연결
2022# --skip-zabbix Zabbix Agent 건너뛰기 (env: MORI_SKIP_ZABBIX=1)
23+ # --skip-fleet Fleet 에이전트 건너뛰기 (env: MORI_SKIP_FLEET=1)
2124# --skip-trivy Trivy 건너뛰기 (env: MORI_SKIP_TRIVY=1)
2225#
2326# env:
24- # MORI_ZABBIX_SERVER (필수 ) MORI Zabbix Server 호스트/IP (Agent 접속, :10051)
27+ # MORI_ZABBIX_SERVER (Zabbix용 ) MORI Zabbix Server 호스트/IP (Agent 접속, :10051)
2528# MORI_HOSTNAME (권장) 이 서버의 Zabbix Host name (기본: `hostname`)
2629# MORI_ZABBIX_PORT (선택) Zabbix Server 포트 (기본 10051)
30+ # MORI_FLEET_URL (Fleet용) Fleet 서버 URL (예: https://fleet.example.com:1337)
31+ # MORI_FLEET_SECRET (Fleet용) Fleet enroll secret
2732# MORI_TRIVY_OUTDIR (선택) Trivy JSON 출력 폴더 (기본: ./reports/trivy)
28- # MORI_INGEST_URL (선택) 설정 시 Trivy 리포트를 MORI 로 HTTP push
29- # (예: http://mori.example.com:18000). POST /ingest/trivy
33+ # MORI_INGEST_URL (선택) 설정 시 Trivy 리포트를 MORI 로 HTTP push (POST /ingest/trivy)
3034# MORI_INGEST_TOKEN (선택) 인제스트 토큰(서버의 MORI_INGEST_TOKEN 과 동일)
3135# ============================================================================
3236set -euo pipefail
@@ -35,16 +39,20 @@ ZBX_SERVER="${MORI_ZABBIX_SERVER:-}"
3539ZBX_PORT=" ${MORI_ZABBIX_PORT:- 10051} "
3640HOSTNAME_VAL=" ${MORI_HOSTNAME:- $(hostname)} "
3741TRIVY_OUTDIR=" ${MORI_TRIVY_OUTDIR:- ./ reports/ trivy} "
42+ FLEET_URL=" ${MORI_FLEET_URL:- } "
43+ FLEET_SECRET=" ${MORI_FLEET_SECRET:- } "
3844SKIP_ZABBIX=" ${MORI_SKIP_ZABBIX:- 0} "
45+ SKIP_FLEET=" ${MORI_SKIP_FLEET:- 0} "
3946SKIP_TRIVY=" ${MORI_SKIP_TRIVY:- 0} "
4047CHECK_ONLY=0
4148
4249# ── 인자 파싱 ────────────────────────────────────────────────────────────────
4350while [ $# -gt 0 ]; do
4451 case " $1 " in
45- -h|--help) sed -n ' 3,30p ' " $0 " | sed ' s/^# \{0,1\}//' ; exit 0 ;;
52+ -h|--help) sed -n ' 3,33p ' " $0 " | sed ' s/^# \{0,1\}//' ; exit 0 ;;
4653 --check) CHECK_ONLY=1 ;;
4754 --skip-zabbix) SKIP_ZABBIX=1 ;;
55+ --skip-fleet) SKIP_FLEET=1 ;;
4856 --skip-trivy) SKIP_TRIVY=1 ;;
4957 * ) echo " 알 수 없는 옵션: $1 (--help 참고)" ; exit 2 ;;
5058 esac
@@ -68,8 +76,9 @@ elif command -v brew >/dev/null 2>&1; then PKG="brew"
6876fi
6977
7078echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
71- echo " 🚀 MORI Endpoint Onboard"
72- echo " host=${HOSTNAME_VAL} pkg=${PKG:- unknown} zabbix=${ZBX_SERVER:- <unset>} :${ZBX_PORT} "
79+ echo " 🚀 MORI Endpoint Onboard (Zabbix Agent + Fleet + Trivy)"
80+ echo " host=${HOSTNAME_VAL} pkg=${PKG:- unknown} "
81+ echo " zabbix=${ZBX_SERVER:- <skip>} :${ZBX_PORT} fleet=${FLEET_URL:- <skip>} "
7382echo " ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
7483
7584# ── 사전 점검 ────────────────────────────────────────────────────────────────
@@ -142,7 +151,55 @@ if [ "$SKIP_ZABBIX" != "1" ]; then
142151 fi
143152fi
144153
145- # ── 2) Trivy ────────────────────────────────────────────────────────────────
154+ # ── 2) Fleet 에이전트 (fleetd/osquery) ──────────────────────────────────────
155+ install_fleetctl () {
156+ command -v fleetctl > /dev/null 2>&1 && return 0
157+ if command -v npm > /dev/null 2>&1 ; then
158+ $SUDO npm install -g fleetctl > /dev/null 2>&1 && command -v fleetctl > /dev/null 2>&1 && return 0
159+ fi
160+ # 폴백: GitHub 최신 릴리스에서 fleetctl(linux) 바이너리 다운로드
161+ local url
162+ url=$( curl -fsSL https://api.github.com/repos/fleetdm/fleet/releases/latest 2> /dev/null \
163+ | grep -oE ' https://[^"]*fleetctl_[^"]*_linux\.tar\.gz' | head -1)
164+ [ -n " $url " ] || return 1
165+ curl -fsSL " $url " -o /tmp/fleetctl.tar.gz 2> /dev/null && tar -xzf /tmp/fleetctl.tar.gz -C /tmp 2> /dev/null \
166+ && $SUDO install -m 0755 " $( find /tmp -name fleetctl -type f 2> /dev/null | head -1) " /usr/local/bin/fleetctl 2> /dev/null \
167+ && command -v fleetctl > /dev/null 2>&1
168+ }
169+
170+ if [ " $SKIP_FLEET " != " 1" ]; then
171+ if command -v orbit > /dev/null 2>&1 || systemctl is-active --quiet orbit 2> /dev/null; then
172+ ok " Fleet 에이전트(orbit) 이미 설치됨"
173+ elif [ -z " $FLEET_URL " ] || [ -z " $FLEET_SECRET " ]; then
174+ warn " MORI_FLEET_URL / MORI_FLEET_SECRET 미지정 — Fleet 에이전트 스킵 (Fleet UI→Add hosts 참고)"
175+ else
176+ log " Fleet 에이전트(fleetd) 설치..."
177+ if install_fleetctl; then
178+ case " $PKG " in apt) FTYPE=deb ;; dnf|yum) FTYPE=rpm ;; brew) FTYPE=pkg ;; * ) FTYPE=deb ;; esac
179+ log " fleetctl package 생성 (type=$FTYPE )..."
180+ ( cd /tmp && fleetctl package --type=" $FTYPE " --fleet-url=" $FLEET_URL " --enroll-secret=" $FLEET_SECRET " > /dev/null 2>&1 ) || warn " fleetctl package 생성 실패(인터넷/버전 확인)"
181+ PKGFILE=$( ls -t /tmp/fleet-osquery* ." $FTYPE " 2> /dev/null | head -1)
182+ if [ -n " ${PKGFILE:- } " ]; then
183+ case " $PKG " in
184+ apt) $SUDO dpkg -i " $PKGFILE " 2> /dev/null || $SUDO apt-get -f install -y ;;
185+ dnf|yum) $SUDO " $PKG " install -y " $PKGFILE " ;;
186+ * ) $SUDO installer -pkg " $PKGFILE " -target / 2> /dev/null || warn " 패키지 설치 수동 필요: $PKGFILE " ;;
187+ esac
188+ if systemctl is-active --quiet orbit 2> /dev/null; then
189+ ok " Fleet 에이전트(orbit) 실행 중 → $FLEET_URL "
190+ else
191+ warn " orbit 서비스 확인 필요 — 'systemctl status orbit'"
192+ fi
193+ else
194+ warn " 설치 패키지 생성 실패 — Fleet UI→Add hosts 의 명령을 사용하거나 수동 설치"
195+ fi
196+ else
197+ warn " fleetctl 설치 실패 — 'npm i -g fleetctl' 또는 fleetctl 바이너리 수동 설치 필요"
198+ fi
199+ fi
200+ fi
201+
202+ # ── 3) Trivy ────────────────────────────────────────────────────────────────
146203OUT=" "
147204if [ " $SKIP_TRIVY " != " 1" ]; then
148205 if command -v trivy > /dev/null 2>&1 ; then
@@ -197,6 +254,9 @@ echo " - Templates: 'MORI Linux Security Baseline' 연결"
197254echo " (생성: ./scripts/mori-zabbix-template.sh 또는 YAML import:"
198255echo " config/zabbix/templates/mori_linux_security_baseline.yaml)"
199256echo " 2) 임계 초과 → problem → mori-worker 30초 폴링 → MORI 🚨 Alert Triage"
257+ if [ " $SKIP_FLEET " != " 1" ] && [ -n " $FLEET_URL " ]; then
258+ echo " 2b) Fleet UI(:1337) → Hosts 에 '${HOSTNAME_VAL} ' online 확인 → 자산 식별/osquery"
259+ fi
200260if [ -n " $OUT " ]; then
201261echo " 3) Trivy 리포트 → MORI:"
202262echo " - MORI 호스트에서 실행: 이미 ${TRIVY_OUTDIR} 에 있음 (MORI_TRIVY_REPORT_GLOB=reports/trivy/*.json)"
0 commit comments