@panguard-ai/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/adapter-registry.d.ts +150 -0
- package/dist/adapters/adapter-registry.d.ts.map +1 -0
- package/dist/adapters/adapter-registry.js +271 -0
- package/dist/adapters/adapter-registry.js.map +1 -0
- package/dist/adapters/base-adapter.d.ts +101 -0
- package/dist/adapters/base-adapter.d.ts.map +1 -0
- package/dist/adapters/base-adapter.js +160 -0
- package/dist/adapters/base-adapter.js.map +1 -0
- package/dist/adapters/defender-adapter.d.ts +90 -0
- package/dist/adapters/defender-adapter.d.ts.map +1 -0
- package/dist/adapters/defender-adapter.js +227 -0
- package/dist/adapters/defender-adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +22 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +23 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/syslog-adapter.d.ts +207 -0
- package/dist/adapters/syslog-adapter.d.ts.map +1 -0
- package/dist/adapters/syslog-adapter.js +432 -0
- package/dist/adapters/syslog-adapter.js.map +1 -0
- package/dist/adapters/types.d.ts +135 -0
- package/dist/adapters/types.d.ts.map +1 -0
- package/dist/adapters/types.js +13 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/adapters/wazuh-adapter.d.ts +120 -0
- package/dist/adapters/wazuh-adapter.d.ts.map +1 -0
- package/dist/adapters/wazuh-adapter.js +266 -0
- package/dist/adapters/wazuh-adapter.js.map +1 -0
- package/dist/ai/claude-provider.d.ts +66 -0
- package/dist/ai/claude-provider.d.ts.map +1 -0
- package/dist/ai/claude-provider.js +166 -0
- package/dist/ai/claude-provider.js.map +1 -0
- package/dist/ai/funnel-router.d.ts +75 -0
- package/dist/ai/funnel-router.d.ts.map +1 -0
- package/dist/ai/funnel-router.js +173 -0
- package/dist/ai/funnel-router.js.map +1 -0
- package/dist/ai/index.d.ts +77 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +95 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/ollama-provider.d.ts +73 -0
- package/dist/ai/ollama-provider.d.ts.map +1 -0
- package/dist/ai/ollama-provider.js +200 -0
- package/dist/ai/ollama-provider.js.map +1 -0
- package/dist/ai/openai-provider.d.ts +70 -0
- package/dist/ai/openai-provider.d.ts.map +1 -0
- package/dist/ai/openai-provider.js +175 -0
- package/dist/ai/openai-provider.js.map +1 -0
- package/dist/ai/prompts/event-classifier.d.ts +25 -0
- package/dist/ai/prompts/event-classifier.d.ts.map +1 -0
- package/dist/ai/prompts/event-classifier.js +94 -0
- package/dist/ai/prompts/event-classifier.js.map +1 -0
- package/dist/ai/prompts/index.d.ts +13 -0
- package/dist/ai/prompts/index.d.ts.map +1 -0
- package/dist/ai/prompts/index.js +13 -0
- package/dist/ai/prompts/index.js.map +1 -0
- package/dist/ai/prompts/report-generator.d.ts +25 -0
- package/dist/ai/prompts/report-generator.d.ts.map +1 -0
- package/dist/ai/prompts/report-generator.js +131 -0
- package/dist/ai/prompts/report-generator.js.map +1 -0
- package/dist/ai/prompts/threat-analyzer.d.ts +26 -0
- package/dist/ai/prompts/threat-analyzer.d.ts.map +1 -0
- package/dist/ai/prompts/threat-analyzer.js +75 -0
- package/dist/ai/prompts/threat-analyzer.js.map +1 -0
- package/dist/ai/provider-base.d.ts +100 -0
- package/dist/ai/provider-base.d.ts.map +1 -0
- package/dist/ai/provider-base.js +166 -0
- package/dist/ai/provider-base.js.map +1 -0
- package/dist/ai/response-parser.d.ts +36 -0
- package/dist/ai/response-parser.d.ts.map +1 -0
- package/dist/ai/response-parser.js +195 -0
- package/dist/ai/response-parser.js.map +1 -0
- package/dist/ai/token-tracker.d.ts +72 -0
- package/dist/ai/token-tracker.d.ts.map +1 -0
- package/dist/ai/token-tracker.js +145 -0
- package/dist/ai/token-tracker.js.map +1 -0
- package/dist/ai/types.d.ts +138 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +12 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/cli/index.d.ts +146 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +515 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/prompts.d.ts +58 -0
- package/dist/cli/prompts.d.ts.map +1 -0
- package/dist/cli/prompts.js +327 -0
- package/dist/cli/prompts.js.map +1 -0
- package/dist/cli/wizard.d.ts +58 -0
- package/dist/cli/wizard.d.ts.map +1 -0
- package/dist/cli/wizard.js +200 -0
- package/dist/cli/wizard.js.map +1 -0
- package/dist/discovery/firewall-checker.d.ts +28 -0
- package/dist/discovery/firewall-checker.d.ts.map +1 -0
- package/dist/discovery/firewall-checker.js +379 -0
- package/dist/discovery/firewall-checker.js.map +1 -0
- package/dist/discovery/index.d.ts +23 -0
- package/dist/discovery/index.d.ts.map +1 -0
- package/dist/discovery/index.js +29 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/network-scanner.d.ts +60 -0
- package/dist/discovery/network-scanner.d.ts.map +1 -0
- package/dist/discovery/network-scanner.js +640 -0
- package/dist/discovery/network-scanner.js.map +1 -0
- package/dist/discovery/os-detector.d.ts +24 -0
- package/dist/discovery/os-detector.d.ts.map +1 -0
- package/dist/discovery/os-detector.js +253 -0
- package/dist/discovery/os-detector.js.map +1 -0
- package/dist/discovery/osquery-provider.d.ts +127 -0
- package/dist/discovery/osquery-provider.d.ts.map +1 -0
- package/dist/discovery/osquery-provider.js +214 -0
- package/dist/discovery/osquery-provider.js.map +1 -0
- package/dist/discovery/risk-scorer.d.ts +66 -0
- package/dist/discovery/risk-scorer.d.ts.map +1 -0
- package/dist/discovery/risk-scorer.js +294 -0
- package/dist/discovery/risk-scorer.js.map +1 -0
- package/dist/discovery/security-tools.d.ts +31 -0
- package/dist/discovery/security-tools.d.ts.map +1 -0
- package/dist/discovery/security-tools.js +346 -0
- package/dist/discovery/security-tools.js.map +1 -0
- package/dist/discovery/service-detector.d.ts +28 -0
- package/dist/discovery/service-detector.d.ts.map +1 -0
- package/dist/discovery/service-detector.js +300 -0
- package/dist/discovery/service-detector.js.map +1 -0
- package/dist/discovery/types.d.ts +502 -0
- package/dist/discovery/types.d.ts.map +1 -0
- package/dist/discovery/types.js +12 -0
- package/dist/discovery/types.js.map +1 -0
- package/dist/discovery/user-auditor.d.ts +28 -0
- package/dist/discovery/user-auditor.d.ts.map +1 -0
- package/dist/discovery/user-auditor.js +385 -0
- package/dist/discovery/user-auditor.js.map +1 -0
- package/dist/i18n/config.d.ts +45 -0
- package/dist/i18n/config.d.ts.map +1 -0
- package/dist/i18n/config.js +135 -0
- package/dist/i18n/config.js.map +1 -0
- package/dist/i18n/index.d.ts +8 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/index.js +8 -0
- package/dist/i18n/index.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/monitor/event-normalizer.d.ts +102 -0
- package/dist/monitor/event-normalizer.d.ts.map +1 -0
- package/dist/monitor/event-normalizer.js +195 -0
- package/dist/monitor/event-normalizer.js.map +1 -0
- package/dist/monitor/file-monitor.d.ts +90 -0
- package/dist/monitor/file-monitor.d.ts.map +1 -0
- package/dist/monitor/file-monitor.js +222 -0
- package/dist/monitor/file-monitor.js.map +1 -0
- package/dist/monitor/index.d.ts +147 -0
- package/dist/monitor/index.d.ts.map +1 -0
- package/dist/monitor/index.js +293 -0
- package/dist/monitor/index.js.map +1 -0
- package/dist/monitor/log-monitor.d.ts +102 -0
- package/dist/monitor/log-monitor.d.ts.map +1 -0
- package/dist/monitor/log-monitor.js +245 -0
- package/dist/monitor/log-monitor.js.map +1 -0
- package/dist/monitor/network-monitor.d.ts +103 -0
- package/dist/monitor/network-monitor.d.ts.map +1 -0
- package/dist/monitor/network-monitor.js +336 -0
- package/dist/monitor/network-monitor.js.map +1 -0
- package/dist/monitor/process-monitor.d.ts +108 -0
- package/dist/monitor/process-monitor.d.ts.map +1 -0
- package/dist/monitor/process-monitor.js +245 -0
- package/dist/monitor/process-monitor.js.map +1 -0
- package/dist/monitor/threat-intel-feeds.d.ts +141 -0
- package/dist/monitor/threat-intel-feeds.d.ts.map +1 -0
- package/dist/monitor/threat-intel-feeds.js +430 -0
- package/dist/monitor/threat-intel-feeds.js.map +1 -0
- package/dist/monitor/threat-intel.d.ts +83 -0
- package/dist/monitor/threat-intel.d.ts.map +1 -0
- package/dist/monitor/threat-intel.js +215 -0
- package/dist/monitor/threat-intel.js.map +1 -0
- package/dist/monitor/types.d.ts +65 -0
- package/dist/monitor/types.d.ts.map +1 -0
- package/dist/monitor/types.js +20 -0
- package/dist/monitor/types.js.map +1 -0
- package/dist/rules/index.d.ts +115 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +244 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/rule-loader.d.ts +54 -0
- package/dist/rules/rule-loader.d.ts.map +1 -0
- package/dist/rules/rule-loader.js +167 -0
- package/dist/rules/rule-loader.js.map +1 -0
- package/dist/rules/sigma-matcher.d.ts +40 -0
- package/dist/rules/sigma-matcher.d.ts.map +1 -0
- package/dist/rules/sigma-matcher.js +447 -0
- package/dist/rules/sigma-matcher.js.map +1 -0
- package/dist/rules/sigma-parser.d.ts +36 -0
- package/dist/rules/sigma-parser.d.ts.map +1 -0
- package/dist/rules/sigma-parser.js +180 -0
- package/dist/rules/sigma-parser.js.map +1 -0
- package/dist/rules/types.d.ts +112 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/types.js +11 -0
- package/dist/rules/types.js.map +1 -0
- package/dist/rules/yara-scanner.d.ts +103 -0
- package/dist/rules/yara-scanner.d.ts.map +1 -0
- package/dist/rules/yara-scanner.js +421 -0
- package/dist/rules/yara-scanner.js.map +1 -0
- package/dist/scoring/achievements.d.ts +76 -0
- package/dist/scoring/achievements.d.ts.map +1 -0
- package/dist/scoring/achievements.js +211 -0
- package/dist/scoring/achievements.js.map +1 -0
- package/dist/scoring/index.d.ts +3 -0
- package/dist/scoring/index.d.ts.map +1 -0
- package/dist/scoring/index.js +3 -0
- package/dist/scoring/index.js.map +1 -0
- package/dist/scoring/security-score.d.ts +60 -0
- package/dist/scoring/security-score.d.ts.map +1 -0
- package/dist/scoring/security-score.js +211 -0
- package/dist/scoring/security-score.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +38 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +71 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/validation.d.ts +35 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +56 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +60 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Panguard AI - Core Package
|
|
3
|
+
* Panguard 安全平台 - 核心套件
|
|
4
|
+
*
|
|
5
|
+
* Core shared modules for the Panguard AI platform.
|
|
6
|
+
* Provides types, i18n, utilities, discovery, monitoring, rules, AI, and adapters.
|
|
7
|
+
* 核心共用模組,提供類型、國際化、工具函式、偵察、監控、規則、AI 和對接器。
|
|
8
|
+
*
|
|
9
|
+
* @module @panguard-ai/core
|
|
10
|
+
*/
|
|
11
|
+
// i18n / 國際化
|
|
12
|
+
export { initI18n, getI18n, changeLanguage, t, resetI18n } from './i18n/index.js';
|
|
13
|
+
// Utils / 工具函式
|
|
14
|
+
export { createLogger, setLogLevel, validateInput, sanitizeString, validateFilePath, } from './utils/index.js';
|
|
15
|
+
// Discovery engine / 偵察引擎
|
|
16
|
+
export { DISCOVERY_VERSION, detectOS, getNetworkInterfaces, scanOpenPorts, getActiveConnections, getGateway, getDnsServers, getDnsServersAsync, detectServices, detectSecurityTools, checkFirewall, auditUsers, calculateRiskScore, getRiskLevel, OsqueryProvider, createOsqueryProvider, } from './discovery/index.js';
|
|
17
|
+
// Rules engine / 規則引擎
|
|
18
|
+
export { RULES_VERSION, RuleEngine, parseSigmaYaml, parseSigmaFile, matchEvent, matchEventAgainstRules, loadRulesFromDirectory, watchRulesDirectory, YaraScanner, } from './rules/index.js';
|
|
19
|
+
// Monitor engine / 監控引擎
|
|
20
|
+
export { MONITOR_VERSION, MonitorEngine, LogMonitor, NetworkMonitor, ProcessMonitor, FileMonitor, checkThreatIntel, isPrivateIP, addThreatIntelEntry, getThreatIntelEntries, setFeedManager, getFeedManager, normalizeLogEvent, normalizeNetworkEvent, normalizeProcessEvent, normalizeFileEvent, DEFAULT_MONITOR_CONFIG, ThreatIntelFeedManager, } from './monitor/index.js';
|
|
21
|
+
// Scoring / 安全分數
|
|
22
|
+
export { calculateSecurityScore, scoreToGrade, scoreToColor, generateScoreSummary, AchievementTracker, ACHIEVEMENTS, } from './scoring/index.js';
|
|
23
|
+
// AI / LLM interface / AI/LLM 介面
|
|
24
|
+
export { AI_VERSION, createLLM } from './ai/index.js';
|
|
25
|
+
// Adapters / 對接器
|
|
26
|
+
export { ADAPTERS_VERSION, BaseAdapter, mapSeverity, mapEventSource, DefenderAdapter, WazuhAdapter, SyslogAdapter, parseSyslogMessage, AdapterRegistry, } from './adapters/index.js';
|
|
27
|
+
// CLI utilities / CLI 工具
|
|
28
|
+
export { c, colorSeverity, colorScore, colorGrade, Spinner, spinner, ProgressBar, progressBar, table, box, banner, header, symbols, divider, scoreDisplay, statusPanel, stripAnsi, formatDuration, timeAgo, visLen, promptSelect, promptText, promptConfirm, WizardEngine, } from './cli/index.js';
|
|
29
|
+
/** Core package version / 核心套件版本 */
|
|
30
|
+
export const CORE_VERSION = '0.1.0';
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAYH,aAAa;AACb,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAElF,eAAe;AACf,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,cAAc,EACd,gBAAgB,GACjB,MAAM,kBAAkB,CAAC;AAG1B,0BAA0B;AAC1B,OAAO,EACL,iBAAiB,EACjB,QAAQ,EACR,oBAAoB,EACpB,aAAa,EACb,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,eAAe,EACf,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAsB9B,sBAAsB;AACtB,OAAO,EACL,aAAa,EACb,UAAU,EACV,cAAc,EACd,cAAc,EACd,UAAU,EACV,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAW1B,wBAAwB;AACxB,OAAO,EACL,eAAe,EACf,aAAa,EACb,UAAU,EACV,cAAc,EACd,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,mBAAmB,EACnB,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,oBAAoB,CAAC;AAa5B,iBAAiB;AACjB,OAAO,EACL,sBAAsB,EACtB,YAAY,EACZ,YAAY,EACZ,oBAAoB,EACpB,kBAAkB,EAClB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAU5B,iCAAiC;AACjC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAStD,iBAAiB;AACjB,OAAO,EACL,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,cAAc,EACd,eAAe,EACf,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,eAAe,GAChB,MAAM,qBAAqB,CAAC;AAQ7B,yBAAyB;AACzB,OAAO,EACL,CAAC,EACD,aAAa,EACb,UAAU,EACV,UAAU,EACV,OAAO,EACP,OAAO,EACP,WAAW,EACX,WAAW,EACX,KAAK,EACL,GAAG,EACH,MAAM,EACN,MAAM,EACN,OAAO,EACP,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,EACd,OAAO,EACP,MAAM,EACN,YAAY,EACZ,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,gBAAgB,CAAC;AAcxB,oCAAoC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event normalizer - converts raw events to SecurityEvent format
|
|
3
|
+
* 事件正規化器 - 將原始事件轉換為 SecurityEvent 格式
|
|
4
|
+
*
|
|
5
|
+
* @module @panguard-ai/core/monitor/event-normalizer
|
|
6
|
+
*/
|
|
7
|
+
import type { SecurityEvent } from '../types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Raw log event input
|
|
10
|
+
* 原始日誌事件輸入
|
|
11
|
+
*/
|
|
12
|
+
interface RawLogEvent {
|
|
13
|
+
/** Log message / 日誌訊息 */
|
|
14
|
+
message: string;
|
|
15
|
+
/** Log source identifier / 日誌來源識別碼 */
|
|
16
|
+
source: string;
|
|
17
|
+
/** Event timestamp / 事件時間戳 */
|
|
18
|
+
timestamp?: Date;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Raw network connection input
|
|
22
|
+
* 原始網路連線輸入
|
|
23
|
+
*/
|
|
24
|
+
interface RawNetworkConnection {
|
|
25
|
+
/** Local IP address / 本地 IP 位址 */
|
|
26
|
+
localAddr: string;
|
|
27
|
+
/** Local port / 本地埠號 */
|
|
28
|
+
localPort: number;
|
|
29
|
+
/** Remote IP address / 遠端 IP 位址 */
|
|
30
|
+
remoteAddr: string;
|
|
31
|
+
/** Remote port / 遠端埠號 */
|
|
32
|
+
remotePort: number;
|
|
33
|
+
/** Connection state / 連線狀態 */
|
|
34
|
+
state: string;
|
|
35
|
+
/** Associated process name / 關聯程序名稱 */
|
|
36
|
+
process?: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Raw process input
|
|
40
|
+
* 原始程序輸入
|
|
41
|
+
*/
|
|
42
|
+
interface RawProcess {
|
|
43
|
+
/** Process ID / 程序 ID */
|
|
44
|
+
pid: number;
|
|
45
|
+
/** Process name / 程序名稱 */
|
|
46
|
+
name: string;
|
|
47
|
+
/** Executable path / 可執行檔路徑 */
|
|
48
|
+
path?: string;
|
|
49
|
+
/** User running the process / 執行程序的使用者 */
|
|
50
|
+
user?: string;
|
|
51
|
+
/** Full command line / 完整命令列 */
|
|
52
|
+
command?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Raw file event input
|
|
56
|
+
* 原始檔案事件輸入
|
|
57
|
+
*/
|
|
58
|
+
interface RawFileEvent {
|
|
59
|
+
/** File path / 檔案路徑 */
|
|
60
|
+
path: string;
|
|
61
|
+
/** Action performed / 執行的動作 */
|
|
62
|
+
action: 'modified' | 'created' | 'deleted';
|
|
63
|
+
/** Previous hash / 先前的雜湊 */
|
|
64
|
+
oldHash?: string;
|
|
65
|
+
/** New hash / 新的雜湊 */
|
|
66
|
+
newHash?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Normalize a raw log event into a SecurityEvent
|
|
70
|
+
* 將原始日誌事件正規化為 SecurityEvent
|
|
71
|
+
*
|
|
72
|
+
* @param raw - Raw log event / 原始日誌事件
|
|
73
|
+
* @returns Normalized SecurityEvent / 正規化的 SecurityEvent
|
|
74
|
+
*/
|
|
75
|
+
export declare function normalizeLogEvent(raw: RawLogEvent): SecurityEvent;
|
|
76
|
+
/**
|
|
77
|
+
* Normalize a network connection into a SecurityEvent
|
|
78
|
+
* 將網路連線正規化為 SecurityEvent
|
|
79
|
+
*
|
|
80
|
+
* @param connection - Raw network connection / 原始網路連線
|
|
81
|
+
* @returns Normalized SecurityEvent / 正規化的 SecurityEvent
|
|
82
|
+
*/
|
|
83
|
+
export declare function normalizeNetworkEvent(connection: RawNetworkConnection): SecurityEvent;
|
|
84
|
+
/**
|
|
85
|
+
* Normalize a process event into a SecurityEvent
|
|
86
|
+
* 將程序事件正規化為 SecurityEvent
|
|
87
|
+
*
|
|
88
|
+
* @param process - Raw process info / 原始程序資訊
|
|
89
|
+
* @param action - Process action / 程序動作
|
|
90
|
+
* @returns Normalized SecurityEvent / 正規化的 SecurityEvent
|
|
91
|
+
*/
|
|
92
|
+
export declare function normalizeProcessEvent(process: RawProcess, action: 'started' | 'stopped'): SecurityEvent;
|
|
93
|
+
/**
|
|
94
|
+
* Normalize a file event into a SecurityEvent
|
|
95
|
+
* 將檔案事件正規化為 SecurityEvent
|
|
96
|
+
*
|
|
97
|
+
* @param file - Raw file event / 原始檔案事件
|
|
98
|
+
* @returns Normalized SecurityEvent / 正規化的 SecurityEvent
|
|
99
|
+
*/
|
|
100
|
+
export declare function normalizeFileEvent(file: RawFileEvent): SecurityEvent;
|
|
101
|
+
export {};
|
|
102
|
+
//# sourceMappingURL=event-normalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-normalizer.d.ts","sourceRoot":"","sources":["../../src/monitor/event-normalizer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAyB,MAAM,aAAa,CAAC;AAExE;;;GAGG;AACH,UAAU,WAAW;IACnB,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED;;;GAGG;AACH,UAAU,oBAAoB;IAC5B,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,yBAAyB;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,UAAU,UAAU;IAClB,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,UAAU,YAAY;IACpB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,MAAM,EAAE,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA8ED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,WAAW,GAAG,aAAa,CAcjE;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,oBAAoB,GAAG,aAAa,CAqBrF;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,SAAS,GAAG,SAAS,GAC5B,aAAa,CAqBf;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,CAiCpE"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event normalizer - converts raw events to SecurityEvent format
|
|
3
|
+
* 事件正規化器 - 將原始事件轉換為 SecurityEvent 格式
|
|
4
|
+
*
|
|
5
|
+
* @module @panguard-ai/core/monitor/event-normalizer
|
|
6
|
+
*/
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
import { hostname, platform } from 'node:os';
|
|
9
|
+
/** Current hostname cached / 快取的目前主機名稱 */
|
|
10
|
+
const currentHost = hostname();
|
|
11
|
+
/**
|
|
12
|
+
* Determine the EventSource based on the current platform
|
|
13
|
+
* 根據目前平台決定 EventSource
|
|
14
|
+
*
|
|
15
|
+
* @returns EventSource for the current OS / 目前作業系統的 EventSource
|
|
16
|
+
*/
|
|
17
|
+
function getPlatformLogSource() {
|
|
18
|
+
const os = platform();
|
|
19
|
+
if (os === 'win32')
|
|
20
|
+
return 'windows_event';
|
|
21
|
+
return 'syslog';
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse severity from log message content by matching keywords
|
|
25
|
+
* 通過匹配關鍵字從日誌訊息內容解析嚴重等級
|
|
26
|
+
*
|
|
27
|
+
* @param message - Log message to parse / 要解析的日誌訊息
|
|
28
|
+
* @returns Severity level / 嚴重等級
|
|
29
|
+
*/
|
|
30
|
+
function parseSeverityFromMessage(message) {
|
|
31
|
+
const lower = message.toLowerCase();
|
|
32
|
+
if (lower.includes('critical') || lower.includes('emergency') || lower.includes('fatal')) {
|
|
33
|
+
return 'critical';
|
|
34
|
+
}
|
|
35
|
+
if (lower.includes('error') || lower.includes('fail') || lower.includes('denied')) {
|
|
36
|
+
return 'high';
|
|
37
|
+
}
|
|
38
|
+
if (lower.includes('warn') || lower.includes('warning') || lower.includes('suspicious')) {
|
|
39
|
+
return 'medium';
|
|
40
|
+
}
|
|
41
|
+
if (lower.includes('notice') || lower.includes('auth')) {
|
|
42
|
+
return 'low';
|
|
43
|
+
}
|
|
44
|
+
return 'info';
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Extract a basic MITRE ATT&CK category from message patterns
|
|
48
|
+
* 從訊息模式中擷取基本的 MITRE ATT&CK 分類
|
|
49
|
+
*
|
|
50
|
+
* @param message - Log message / 日誌訊息
|
|
51
|
+
* @returns Category string / 分類字串
|
|
52
|
+
*/
|
|
53
|
+
function extractCategoryFromMessage(message) {
|
|
54
|
+
const lower = message.toLowerCase();
|
|
55
|
+
if (lower.includes('login') ||
|
|
56
|
+
lower.includes('auth') ||
|
|
57
|
+
lower.includes('ssh') ||
|
|
58
|
+
lower.includes('logon')) {
|
|
59
|
+
return 'Initial Access';
|
|
60
|
+
}
|
|
61
|
+
if (lower.includes('sudo') || lower.includes('privilege') || lower.includes('elevation')) {
|
|
62
|
+
return 'Privilege Escalation';
|
|
63
|
+
}
|
|
64
|
+
if (lower.includes('firewall') || lower.includes('iptables') || lower.includes('blocked')) {
|
|
65
|
+
return 'Defense Evasion';
|
|
66
|
+
}
|
|
67
|
+
if (lower.includes('cron') || lower.includes('scheduled') || lower.includes('persistence')) {
|
|
68
|
+
return 'Persistence';
|
|
69
|
+
}
|
|
70
|
+
if (lower.includes('download') || lower.includes('curl') || lower.includes('wget')) {
|
|
71
|
+
return 'Command and Control';
|
|
72
|
+
}
|
|
73
|
+
if (lower.includes('exec') || lower.includes('spawn') || lower.includes('script')) {
|
|
74
|
+
return 'Execution';
|
|
75
|
+
}
|
|
76
|
+
return 'General';
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Normalize a raw log event into a SecurityEvent
|
|
80
|
+
* 將原始日誌事件正規化為 SecurityEvent
|
|
81
|
+
*
|
|
82
|
+
* @param raw - Raw log event / 原始日誌事件
|
|
83
|
+
* @returns Normalized SecurityEvent / 正規化的 SecurityEvent
|
|
84
|
+
*/
|
|
85
|
+
export function normalizeLogEvent(raw) {
|
|
86
|
+
return {
|
|
87
|
+
id: randomUUID(),
|
|
88
|
+
timestamp: raw.timestamp ?? new Date(),
|
|
89
|
+
source: getPlatformLogSource(),
|
|
90
|
+
severity: parseSeverityFromMessage(raw.message),
|
|
91
|
+
category: extractCategoryFromMessage(raw.message),
|
|
92
|
+
description: raw.message,
|
|
93
|
+
raw,
|
|
94
|
+
host: currentHost,
|
|
95
|
+
metadata: {
|
|
96
|
+
logSource: raw.source,
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Normalize a network connection into a SecurityEvent
|
|
102
|
+
* 將網路連線正規化為 SecurityEvent
|
|
103
|
+
*
|
|
104
|
+
* @param connection - Raw network connection / 原始網路連線
|
|
105
|
+
* @returns Normalized SecurityEvent / 正規化的 SecurityEvent
|
|
106
|
+
*/
|
|
107
|
+
export function normalizeNetworkEvent(connection) {
|
|
108
|
+
const description = `Network connection: ${connection.localAddr}:${connection.localPort} -> ${connection.remoteAddr}:${connection.remotePort} [${connection.state}]${connection.process ? ` (${connection.process})` : ''}`;
|
|
109
|
+
return {
|
|
110
|
+
id: randomUUID(),
|
|
111
|
+
timestamp: new Date(),
|
|
112
|
+
source: 'network',
|
|
113
|
+
severity: 'info',
|
|
114
|
+
category: 'Network Activity',
|
|
115
|
+
description,
|
|
116
|
+
raw: connection,
|
|
117
|
+
host: currentHost,
|
|
118
|
+
metadata: {
|
|
119
|
+
localAddr: connection.localAddr,
|
|
120
|
+
localPort: connection.localPort,
|
|
121
|
+
remoteAddr: connection.remoteAddr,
|
|
122
|
+
remotePort: connection.remotePort,
|
|
123
|
+
state: connection.state,
|
|
124
|
+
process: connection.process,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Normalize a process event into a SecurityEvent
|
|
130
|
+
* 將程序事件正規化為 SecurityEvent
|
|
131
|
+
*
|
|
132
|
+
* @param process - Raw process info / 原始程序資訊
|
|
133
|
+
* @param action - Process action / 程序動作
|
|
134
|
+
* @returns Normalized SecurityEvent / 正規化的 SecurityEvent
|
|
135
|
+
*/
|
|
136
|
+
export function normalizeProcessEvent(process, action) {
|
|
137
|
+
const description = `Process ${action}: ${process.name} (PID: ${process.pid})${process.user ? ` by ${process.user}` : ''}`;
|
|
138
|
+
return {
|
|
139
|
+
id: randomUUID(),
|
|
140
|
+
timestamp: new Date(),
|
|
141
|
+
source: 'process',
|
|
142
|
+
severity: 'info',
|
|
143
|
+
category: action === 'started' ? 'Execution' : 'General',
|
|
144
|
+
description,
|
|
145
|
+
raw: { ...process, action },
|
|
146
|
+
host: currentHost,
|
|
147
|
+
metadata: {
|
|
148
|
+
pid: process.pid,
|
|
149
|
+
processName: process.name,
|
|
150
|
+
action,
|
|
151
|
+
path: process.path,
|
|
152
|
+
user: process.user,
|
|
153
|
+
command: process.command,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Normalize a file event into a SecurityEvent
|
|
159
|
+
* 將檔案事件正規化為 SecurityEvent
|
|
160
|
+
*
|
|
161
|
+
* @param file - Raw file event / 原始檔案事件
|
|
162
|
+
* @returns Normalized SecurityEvent / 正規化的 SecurityEvent
|
|
163
|
+
*/
|
|
164
|
+
export function normalizeFileEvent(file) {
|
|
165
|
+
const actionLabels = {
|
|
166
|
+
modified: 'modified',
|
|
167
|
+
created: 'created',
|
|
168
|
+
deleted: 'deleted',
|
|
169
|
+
};
|
|
170
|
+
const description = `File ${actionLabels[file.action]}: ${file.path}`;
|
|
171
|
+
let severity = 'info';
|
|
172
|
+
if (file.action === 'modified' && file.oldHash && file.newHash && file.oldHash !== file.newHash) {
|
|
173
|
+
severity = 'medium';
|
|
174
|
+
}
|
|
175
|
+
if (file.action === 'deleted') {
|
|
176
|
+
severity = 'low';
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
id: randomUUID(),
|
|
180
|
+
timestamp: new Date(),
|
|
181
|
+
source: 'file',
|
|
182
|
+
severity,
|
|
183
|
+
category: 'Defense Evasion',
|
|
184
|
+
description,
|
|
185
|
+
raw: file,
|
|
186
|
+
host: currentHost,
|
|
187
|
+
metadata: {
|
|
188
|
+
filePath: file.path,
|
|
189
|
+
action: file.action,
|
|
190
|
+
oldHash: file.oldHash,
|
|
191
|
+
newHash: file.newHash,
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=event-normalizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-normalizer.js","sourceRoot":"","sources":["../../src/monitor/event-normalizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File integrity monitoring via hash comparison
|
|
3
|
+
* 透過雜湊比對進行檔案完整性監控
|
|
4
|
+
*
|
|
5
|
+
* Periodically computes SHA-256 hashes of watched files and detects
|
|
6
|
+
* creation, modification, and deletion events.
|
|
7
|
+
* 定期計算受監控檔案的 SHA-256 雜湊值,並偵測建立、修改和刪除事件。
|
|
8
|
+
*
|
|
9
|
+
* @module @panguard-ai/core/monitor/file-monitor
|
|
10
|
+
*/
|
|
11
|
+
import { EventEmitter } from 'node:events';
|
|
12
|
+
import type { FileHashRecord } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* FileMonitor - monitors file integrity by comparing SHA-256 hashes
|
|
15
|
+
* FileMonitor - 透過比較 SHA-256 雜湊值監控檔案完整性
|
|
16
|
+
*
|
|
17
|
+
* Events emitted:
|
|
18
|
+
* - 'file_changed': SecurityEvent - when a file hash changes / 當檔案雜湊值改變時
|
|
19
|
+
* - 'file_created': SecurityEvent - when a new file is detected / 當偵測到新檔案時
|
|
20
|
+
* - 'file_deleted': SecurityEvent - when a watched file is removed / 當受監控檔案被移除時
|
|
21
|
+
* - 'error': Error - when file checking encounters an error / 當檔案檢查遇到錯誤時
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const monitor = new FileMonitor(['/etc/passwd', '/etc/shadow'], 60000);
|
|
26
|
+
* monitor.on('file_changed', (event) => console.log('Changed:', event));
|
|
27
|
+
* monitor.start();
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class FileMonitor extends EventEmitter {
|
|
31
|
+
/** Whether the monitor is currently running / 監控器是否正在執行 */
|
|
32
|
+
private running;
|
|
33
|
+
/** Polling timer / 輪詢計時器 */
|
|
34
|
+
private timer?;
|
|
35
|
+
/** Stored file hash records / 儲存的檔案雜湊記錄 */
|
|
36
|
+
private fileHashes;
|
|
37
|
+
/** Paths to watch / 要監控的路徑 */
|
|
38
|
+
private watchPaths;
|
|
39
|
+
/** Polling interval in milliseconds / 輪詢間隔(毫秒) */
|
|
40
|
+
private pollInterval;
|
|
41
|
+
/**
|
|
42
|
+
* Create a new FileMonitor instance
|
|
43
|
+
* 建立新的 FileMonitor 實例
|
|
44
|
+
*
|
|
45
|
+
* @param watchPaths - Array of file paths to monitor / 要監控的檔案路徑陣列
|
|
46
|
+
* @param pollInterval - Polling interval in ms (default 60000) / 輪詢間隔毫秒數(預設 60000)
|
|
47
|
+
*/
|
|
48
|
+
constructor(watchPaths: string[], pollInterval?: number);
|
|
49
|
+
/**
|
|
50
|
+
* Start monitoring file integrity
|
|
51
|
+
* 開始監控檔案完整性
|
|
52
|
+
*/
|
|
53
|
+
start(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Stop monitoring and clean up
|
|
56
|
+
* 停止監控並清理
|
|
57
|
+
*/
|
|
58
|
+
stop(): void;
|
|
59
|
+
/**
|
|
60
|
+
* Check if the monitor is currently running
|
|
61
|
+
* 檢查監控器是否正在執行
|
|
62
|
+
*
|
|
63
|
+
* @returns True if running / 如果正在執行則為 true
|
|
64
|
+
*/
|
|
65
|
+
isRunning(): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Compute the SHA-256 hash of a file
|
|
68
|
+
* 計算檔案的 SHA-256 雜湊值
|
|
69
|
+
*
|
|
70
|
+
* @param filePath - Path to the file / 檔案路徑
|
|
71
|
+
* @returns Hex-encoded SHA-256 hash / 十六進位編碼的 SHA-256 雜湊值
|
|
72
|
+
*/
|
|
73
|
+
computeHash(filePath: string): Promise<string>;
|
|
74
|
+
/**
|
|
75
|
+
* Get the current file hash records
|
|
76
|
+
* 取得目前的檔案雜湊記錄
|
|
77
|
+
*
|
|
78
|
+
* @returns Map of file path to hash record / 檔案路徑到雜湊記錄的映射
|
|
79
|
+
*/
|
|
80
|
+
getFileHashes(): ReadonlyMap<string, FileHashRecord>;
|
|
81
|
+
/**
|
|
82
|
+
* Check all watched files for changes
|
|
83
|
+
* 檢查所有受監控檔案的變更
|
|
84
|
+
*
|
|
85
|
+
* Compares current hashes with stored hashes and emits appropriate events.
|
|
86
|
+
* 比較目前雜湊值與儲存的雜湊值,並發出適當的事件。
|
|
87
|
+
*/
|
|
88
|
+
private checkFiles;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=file-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-monitor.d.ts","sourceRoot":"","sources":["../../src/monitor/file-monitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAM3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAY,SAAQ,YAAY;IAC3C,2DAA2D;IAC3D,OAAO,CAAC,OAAO,CAAS;IACxB,4BAA4B;IAC5B,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,2CAA2C;IAC3C,OAAO,CAAC,UAAU,CAA0C;IAC5D,8BAA8B;IAC9B,OAAO,CAAC,UAAU,CAAW;IAC7B,kDAAkD;IAClD,OAAO,CAAC,YAAY,CAAS;IAE7B;;;;;;OAMG;gBACS,UAAU,EAAE,MAAM,EAAE,EAAE,YAAY,SAAQ;IAMtD;;;OAGG;IACH,KAAK,IAAI,IAAI;IAmBb;;;OAGG;IACH,IAAI,IAAI,IAAI;IAeZ;;;;;OAKG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;;;OAMG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKpD;;;;;OAKG;IACH,aAAa,IAAI,WAAW,CAAC,MAAM,EAAE,cAAc,CAAC;IAIpD;;;;;;OAMG;YACW,UAAU;CA2GzB"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File integrity monitoring via hash comparison
|
|
3
|
+
* 透過雜湊比對進行檔案完整性監控
|
|
4
|
+
*
|
|
5
|
+
* Periodically computes SHA-256 hashes of watched files and detects
|
|
6
|
+
* creation, modification, and deletion events.
|
|
7
|
+
* 定期計算受監控檔案的 SHA-256 雜湊值,並偵測建立、修改和刪除事件。
|
|
8
|
+
*
|
|
9
|
+
* @module @panguard-ai/core/monitor/file-monitor
|
|
10
|
+
*/
|
|
11
|
+
import { EventEmitter } from 'node:events';
|
|
12
|
+
import { createHash } from 'node:crypto';
|
|
13
|
+
import { readFile, stat } from 'node:fs/promises';
|
|
14
|
+
import { createLogger } from '../utils/index.js';
|
|
15
|
+
import { normalizeFileEvent } from './event-normalizer.js';
|
|
16
|
+
const logger = createLogger('file-monitor');
|
|
17
|
+
/**
|
|
18
|
+
* FileMonitor - monitors file integrity by comparing SHA-256 hashes
|
|
19
|
+
* FileMonitor - 透過比較 SHA-256 雜湊值監控檔案完整性
|
|
20
|
+
*
|
|
21
|
+
* Events emitted:
|
|
22
|
+
* - 'file_changed': SecurityEvent - when a file hash changes / 當檔案雜湊值改變時
|
|
23
|
+
* - 'file_created': SecurityEvent - when a new file is detected / 當偵測到新檔案時
|
|
24
|
+
* - 'file_deleted': SecurityEvent - when a watched file is removed / 當受監控檔案被移除時
|
|
25
|
+
* - 'error': Error - when file checking encounters an error / 當檔案檢查遇到錯誤時
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* const monitor = new FileMonitor(['/etc/passwd', '/etc/shadow'], 60000);
|
|
30
|
+
* monitor.on('file_changed', (event) => console.log('Changed:', event));
|
|
31
|
+
* monitor.start();
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export class FileMonitor extends EventEmitter {
|
|
35
|
+
/** Whether the monitor is currently running / 監控器是否正在執行 */
|
|
36
|
+
running = false;
|
|
37
|
+
/** Polling timer / 輪詢計時器 */
|
|
38
|
+
timer;
|
|
39
|
+
/** Stored file hash records / 儲存的檔案雜湊記錄 */
|
|
40
|
+
fileHashes = new Map();
|
|
41
|
+
/** Paths to watch / 要監控的路徑 */
|
|
42
|
+
watchPaths;
|
|
43
|
+
/** Polling interval in milliseconds / 輪詢間隔(毫秒) */
|
|
44
|
+
pollInterval;
|
|
45
|
+
/**
|
|
46
|
+
* Create a new FileMonitor instance
|
|
47
|
+
* 建立新的 FileMonitor 實例
|
|
48
|
+
*
|
|
49
|
+
* @param watchPaths - Array of file paths to monitor / 要監控的檔案路徑陣列
|
|
50
|
+
* @param pollInterval - Polling interval in ms (default 60000) / 輪詢間隔毫秒數(預設 60000)
|
|
51
|
+
*/
|
|
52
|
+
constructor(watchPaths, pollInterval = 60000) {
|
|
53
|
+
super();
|
|
54
|
+
this.watchPaths = watchPaths;
|
|
55
|
+
this.pollInterval = pollInterval;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Start monitoring file integrity
|
|
59
|
+
* 開始監控檔案完整性
|
|
60
|
+
*/
|
|
61
|
+
start() {
|
|
62
|
+
if (this.running) {
|
|
63
|
+
logger.warn('FileMonitor is already running');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
this.running = true;
|
|
67
|
+
logger.info(`FileMonitor started (watching ${this.watchPaths.length} paths, poll interval: ${this.pollInterval}ms)`);
|
|
68
|
+
// Run an initial check immediately / 立即執行首次檢查
|
|
69
|
+
void this.checkFiles();
|
|
70
|
+
this.timer = setInterval(() => {
|
|
71
|
+
void this.checkFiles();
|
|
72
|
+
}, this.pollInterval);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Stop monitoring and clean up
|
|
76
|
+
* 停止監控並清理
|
|
77
|
+
*/
|
|
78
|
+
stop() {
|
|
79
|
+
if (!this.running) {
|
|
80
|
+
logger.warn('FileMonitor is not running');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (this.timer) {
|
|
84
|
+
clearInterval(this.timer);
|
|
85
|
+
this.timer = undefined;
|
|
86
|
+
}
|
|
87
|
+
this.running = false;
|
|
88
|
+
logger.info('FileMonitor stopped');
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Check if the monitor is currently running
|
|
92
|
+
* 檢查監控器是否正在執行
|
|
93
|
+
*
|
|
94
|
+
* @returns True if running / 如果正在執行則為 true
|
|
95
|
+
*/
|
|
96
|
+
isRunning() {
|
|
97
|
+
return this.running;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Compute the SHA-256 hash of a file
|
|
101
|
+
* 計算檔案的 SHA-256 雜湊值
|
|
102
|
+
*
|
|
103
|
+
* @param filePath - Path to the file / 檔案路徑
|
|
104
|
+
* @returns Hex-encoded SHA-256 hash / 十六進位編碼的 SHA-256 雜湊值
|
|
105
|
+
*/
|
|
106
|
+
async computeHash(filePath) {
|
|
107
|
+
const content = await readFile(filePath);
|
|
108
|
+
return createHash('sha256').update(content).digest('hex');
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get the current file hash records
|
|
112
|
+
* 取得目前的檔案雜湊記錄
|
|
113
|
+
*
|
|
114
|
+
* @returns Map of file path to hash record / 檔案路徑到雜湊記錄的映射
|
|
115
|
+
*/
|
|
116
|
+
getFileHashes() {
|
|
117
|
+
return this.fileHashes;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Check all watched files for changes
|
|
121
|
+
* 檢查所有受監控檔案的變更
|
|
122
|
+
*
|
|
123
|
+
* Compares current hashes with stored hashes and emits appropriate events.
|
|
124
|
+
* 比較目前雜湊值與儲存的雜湊值,並發出適當的事件。
|
|
125
|
+
*/
|
|
126
|
+
async checkFiles() {
|
|
127
|
+
const currentPaths = new Set();
|
|
128
|
+
for (const filePath of this.watchPaths) {
|
|
129
|
+
currentPaths.add(filePath);
|
|
130
|
+
try {
|
|
131
|
+
const fileStat = await stat(filePath);
|
|
132
|
+
const currentHash = await this.computeHash(filePath);
|
|
133
|
+
const now = new Date().toISOString();
|
|
134
|
+
const existingRecord = this.fileHashes.get(filePath);
|
|
135
|
+
if (!existingRecord) {
|
|
136
|
+
// New file detected (first check or newly created)
|
|
137
|
+
// 偵測到新檔案(首次檢查或新建立)
|
|
138
|
+
this.fileHashes.set(filePath, {
|
|
139
|
+
path: filePath,
|
|
140
|
+
hash: currentHash,
|
|
141
|
+
lastChecked: now,
|
|
142
|
+
size: fileStat.size,
|
|
143
|
+
});
|
|
144
|
+
// Only emit file_created if this is not the first run
|
|
145
|
+
// 僅在非首次執行時發出 file_created 事件
|
|
146
|
+
if (this.fileHashes.size >
|
|
147
|
+
this.watchPaths.length - (this.watchPaths.length - currentPaths.size)) {
|
|
148
|
+
// We check if we have seen at least one full cycle
|
|
149
|
+
// The first poll populates the baseline, subsequent polls detect changes
|
|
150
|
+
}
|
|
151
|
+
// Emit file_created for files discovered after initial baseline
|
|
152
|
+
// 為在初始基線之後發現的檔案發出 file_created
|
|
153
|
+
// On first run, we just store the baseline without emitting
|
|
154
|
+
// 首次執行時,我們只儲存基線而不發出事件
|
|
155
|
+
}
|
|
156
|
+
else if (existingRecord.hash !== currentHash) {
|
|
157
|
+
// File has been modified / 檔案已被修改
|
|
158
|
+
const oldHash = existingRecord.hash;
|
|
159
|
+
this.fileHashes.set(filePath, {
|
|
160
|
+
path: filePath,
|
|
161
|
+
hash: currentHash,
|
|
162
|
+
lastChecked: now,
|
|
163
|
+
size: fileStat.size,
|
|
164
|
+
});
|
|
165
|
+
const event = normalizeFileEvent({
|
|
166
|
+
path: filePath,
|
|
167
|
+
action: 'modified',
|
|
168
|
+
oldHash,
|
|
169
|
+
newHash: currentHash,
|
|
170
|
+
});
|
|
171
|
+
this.emit('file_changed', event);
|
|
172
|
+
logger.info(`File modified: ${filePath}`, {
|
|
173
|
+
oldHash: oldHash.substring(0, 12),
|
|
174
|
+
newHash: currentHash.substring(0, 12),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// File unchanged, update last checked time
|
|
179
|
+
// 檔案未變更,更新最後檢查時間
|
|
180
|
+
existingRecord.lastChecked = now;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
const error = err;
|
|
185
|
+
if (error.code === 'ENOENT') {
|
|
186
|
+
// File does not exist / 檔案不存在
|
|
187
|
+
const existingRecord = this.fileHashes.get(filePath);
|
|
188
|
+
if (existingRecord) {
|
|
189
|
+
// File was previously tracked but now deleted
|
|
190
|
+
// 檔案先前被追蹤但現在已被刪除
|
|
191
|
+
this.fileHashes.delete(filePath);
|
|
192
|
+
const event = normalizeFileEvent({
|
|
193
|
+
path: filePath,
|
|
194
|
+
action: 'deleted',
|
|
195
|
+
oldHash: existingRecord.hash,
|
|
196
|
+
});
|
|
197
|
+
this.emit('file_deleted', event);
|
|
198
|
+
logger.info(`File deleted: ${filePath}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
logger.error(`Failed to check file: ${filePath}`, { error: String(err) });
|
|
203
|
+
this.emit('error', err instanceof Error ? err : new Error(String(err)));
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Check for files that were being tracked but are no longer in watchPaths
|
|
208
|
+
// 檢查先前被追蹤但不再在 watchPaths 中的檔案
|
|
209
|
+
for (const [trackedPath, record] of this.fileHashes) {
|
|
210
|
+
if (!currentPaths.has(trackedPath)) {
|
|
211
|
+
this.fileHashes.delete(trackedPath);
|
|
212
|
+
const event = normalizeFileEvent({
|
|
213
|
+
path: trackedPath,
|
|
214
|
+
action: 'deleted',
|
|
215
|
+
oldHash: record.hash,
|
|
216
|
+
});
|
|
217
|
+
this.emit('file_deleted', event);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
//# sourceMappingURL=file-monitor.js.map
|