@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
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform OS detection
|
|
3
|
+
* 跨平台作業系統偵測
|
|
4
|
+
*
|
|
5
|
+
* Detects operating system information including distribution, version,
|
|
6
|
+
* architecture, kernel, and patch level across macOS, Linux, and Windows.
|
|
7
|
+
* 偵測作業系統資訊,包括跨 macOS、Linux 和 Windows 的發行版、版本、架構、核心和修補等級。
|
|
8
|
+
*
|
|
9
|
+
* @module @panguard-ai/core/discovery/os-detector
|
|
10
|
+
*/
|
|
11
|
+
import type { OSInfo } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Detect comprehensive operating system information
|
|
14
|
+
* 偵測完整的作業系統資訊
|
|
15
|
+
*
|
|
16
|
+
* Uses platform-specific commands to gather detailed OS information.
|
|
17
|
+
* Falls back to Node.js os module data when commands fail.
|
|
18
|
+
* 使用平台特定命令收集詳細的作業系統資訊。
|
|
19
|
+
* 當命令失敗時,回退到 Node.js os 模組資料。
|
|
20
|
+
*
|
|
21
|
+
* @returns Complete OS information / 完整的作業系統資訊
|
|
22
|
+
*/
|
|
23
|
+
export declare function detectOS(): Promise<OSInfo>;
|
|
24
|
+
//# sourceMappingURL=os-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"os-detector.d.ts","sourceRoot":"","sources":["../../src/discovery/os-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAqLzC;;;;;;;;;;GAUG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC,CA6DhD"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform OS detection
|
|
3
|
+
* 跨平台作業系統偵測
|
|
4
|
+
*
|
|
5
|
+
* Detects operating system information including distribution, version,
|
|
6
|
+
* architecture, kernel, and patch level across macOS, Linux, and Windows.
|
|
7
|
+
* 偵測作業系統資訊,包括跨 macOS、Linux 和 Windows 的發行版、版本、架構、核心和修補等級。
|
|
8
|
+
*
|
|
9
|
+
* @module @panguard-ai/core/discovery/os-detector
|
|
10
|
+
*/
|
|
11
|
+
import { execFile } from 'child_process';
|
|
12
|
+
import { promisify } from 'util';
|
|
13
|
+
import { platform as osPlatform, arch as osArch, hostname as osHostname, uptime as osUptime, release as osRelease, type as osType, } from 'os';
|
|
14
|
+
import { readFile } from 'fs/promises';
|
|
15
|
+
import { createLogger } from '../utils/logger.js';
|
|
16
|
+
const execFileAsync = promisify(execFile);
|
|
17
|
+
const logger = createLogger('discovery:os');
|
|
18
|
+
/**
|
|
19
|
+
* Safely execute a command and return stdout, or empty string on failure
|
|
20
|
+
* 安全地執行命令並回傳 stdout,失敗時回傳空字串
|
|
21
|
+
*
|
|
22
|
+
* @param cmd - Command to execute / 要執行的命令
|
|
23
|
+
* @param args - Command arguments / 命令參數
|
|
24
|
+
* @returns stdout output trimmed / 修剪後的 stdout 輸出
|
|
25
|
+
*/
|
|
26
|
+
async function safeExec(cmd, args) {
|
|
27
|
+
try {
|
|
28
|
+
const { stdout } = await execFileAsync(cmd, args, { timeout: 10_000 });
|
|
29
|
+
return stdout.trim();
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
logger.debug(`Command failed: ${cmd} ${args.join(' ')}`, {
|
|
33
|
+
error: err instanceof Error ? err.message : String(err),
|
|
34
|
+
});
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Detect macOS-specific OS information
|
|
40
|
+
* 偵測 macOS 特定的作業系統資訊
|
|
41
|
+
*
|
|
42
|
+
* @returns Partial OSInfo with macOS-specific fields / 包含 macOS 特定欄位的部分 OSInfo
|
|
43
|
+
*/
|
|
44
|
+
async function detectMacOS() {
|
|
45
|
+
const result = { distro: 'macOS' };
|
|
46
|
+
try {
|
|
47
|
+
const productName = await safeExec('sw_vers', ['-productName']);
|
|
48
|
+
const productVersion = await safeExec('sw_vers', ['-productVersion']);
|
|
49
|
+
if (productName) {
|
|
50
|
+
result.distro = productName;
|
|
51
|
+
}
|
|
52
|
+
if (productVersion) {
|
|
53
|
+
result.version = productVersion;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
logger.warn('Failed to detect macOS version via sw_vers', {
|
|
58
|
+
error: err instanceof Error ? err.message : String(err),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Detect patch level via softwareupdate
|
|
62
|
+
// 透過 softwareupdate 偵測修補等級
|
|
63
|
+
try {
|
|
64
|
+
const updateOutput = await safeExec('softwareupdate', ['-l']);
|
|
65
|
+
if (updateOutput.includes('No new software available')) {
|
|
66
|
+
result.patchLevel = 'up-to-date';
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const lines = updateOutput.split('\n').filter((l) => l.includes('*'));
|
|
70
|
+
result.patchLevel = lines.length > 0 ? `${lines.length} updates available` : 'unknown';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
result.patchLevel = 'unknown';
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Detect Linux-specific OS information
|
|
80
|
+
* 偵測 Linux 特定的作業系統資訊
|
|
81
|
+
*
|
|
82
|
+
* @returns Partial OSInfo with Linux-specific fields / 包含 Linux 特定欄位的部分 OSInfo
|
|
83
|
+
*/
|
|
84
|
+
async function detectLinux() {
|
|
85
|
+
const result = { distro: 'Linux' };
|
|
86
|
+
// Try lsb_release first
|
|
87
|
+
// 優先嘗試 lsb_release
|
|
88
|
+
try {
|
|
89
|
+
const lsbOutput = await safeExec('lsb_release', ['-a']);
|
|
90
|
+
if (lsbOutput) {
|
|
91
|
+
const descMatch = lsbOutput.match(/Description:\s*(.+)/);
|
|
92
|
+
const releaseMatch = lsbOutput.match(/Release:\s*(.+)/);
|
|
93
|
+
if (descMatch?.[1]) {
|
|
94
|
+
result.distro = descMatch[1].trim();
|
|
95
|
+
}
|
|
96
|
+
if (releaseMatch?.[1]) {
|
|
97
|
+
result.version = releaseMatch[1].trim();
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// lsb_release not available, try /etc/os-release
|
|
104
|
+
// lsb_release 不可用,嘗試 /etc/os-release
|
|
105
|
+
}
|
|
106
|
+
// Fallback: read /etc/os-release
|
|
107
|
+
// 備用:讀取 /etc/os-release
|
|
108
|
+
try {
|
|
109
|
+
const osReleaseContent = await readFile('/etc/os-release', 'utf-8');
|
|
110
|
+
const nameMatch = osReleaseContent.match(/^PRETTY_NAME="?(.+?)"?\s*$/m);
|
|
111
|
+
const versionMatch = osReleaseContent.match(/^VERSION_ID="?(.+?)"?\s*$/m);
|
|
112
|
+
if (nameMatch?.[1]) {
|
|
113
|
+
result.distro = nameMatch[1];
|
|
114
|
+
}
|
|
115
|
+
if (versionMatch?.[1]) {
|
|
116
|
+
result.version = versionMatch[1];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
logger.warn('Failed to read /etc/os-release');
|
|
121
|
+
}
|
|
122
|
+
// Detect patch level
|
|
123
|
+
// 偵測修補等級
|
|
124
|
+
try {
|
|
125
|
+
const kernelVersion = await safeExec('uname', ['-r']);
|
|
126
|
+
result.patchLevel = kernelVersion || 'unknown';
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
result.patchLevel = 'unknown';
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Detect Windows-specific OS information
|
|
135
|
+
* 偵測 Windows 特定的作業系統資訊
|
|
136
|
+
*
|
|
137
|
+
* @returns Partial OSInfo with Windows-specific fields / 包含 Windows 特定欄位的部分 OSInfo
|
|
138
|
+
*/
|
|
139
|
+
async function detectWindows() {
|
|
140
|
+
const result = {
|
|
141
|
+
distro: 'Windows',
|
|
142
|
+
version: osRelease(),
|
|
143
|
+
};
|
|
144
|
+
try {
|
|
145
|
+
const wmicOutput = await safeExec('wmic', ['os', 'get', 'Caption,Version', '/format:csv']);
|
|
146
|
+
if (wmicOutput) {
|
|
147
|
+
const lines = wmicOutput.split('\n').filter((l) => l.trim().length > 0);
|
|
148
|
+
// CSV format: Node,Caption,Version
|
|
149
|
+
// CSV 格式:Node,Caption,Version
|
|
150
|
+
const lastLine = lines[lines.length - 1];
|
|
151
|
+
if (lastLine) {
|
|
152
|
+
const parts = lastLine.split(',');
|
|
153
|
+
const caption = parts[1];
|
|
154
|
+
const ver = parts[2];
|
|
155
|
+
if (caption && ver) {
|
|
156
|
+
result.distro = caption.trim();
|
|
157
|
+
result.version = ver.trim();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
logger.warn('Failed to detect Windows version via wmic');
|
|
164
|
+
}
|
|
165
|
+
// Detect patch level via systeminfo
|
|
166
|
+
// 透過 systeminfo 偵測修補等級
|
|
167
|
+
try {
|
|
168
|
+
const sysinfoOutput = await safeExec('wmic', ['qfe', 'get', 'HotFixID', '/format:csv']);
|
|
169
|
+
if (sysinfoOutput) {
|
|
170
|
+
const hotfixes = sysinfoOutput
|
|
171
|
+
.split('\n')
|
|
172
|
+
.filter((l) => l.trim().length > 0 && !l.includes('HotFixID'))
|
|
173
|
+
.map((l) => l.split(',').pop()?.trim())
|
|
174
|
+
.filter((h) => Boolean(h));
|
|
175
|
+
const latest = hotfixes[hotfixes.length - 1];
|
|
176
|
+
result.patchLevel =
|
|
177
|
+
hotfixes.length > 0
|
|
178
|
+
? `${hotfixes.length} hotfixes installed (latest: ${latest ?? 'unknown'})`
|
|
179
|
+
: 'unknown';
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
result.patchLevel = 'unknown';
|
|
184
|
+
}
|
|
185
|
+
return result;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Detect comprehensive operating system information
|
|
189
|
+
* 偵測完整的作業系統資訊
|
|
190
|
+
*
|
|
191
|
+
* Uses platform-specific commands to gather detailed OS information.
|
|
192
|
+
* Falls back to Node.js os module data when commands fail.
|
|
193
|
+
* 使用平台特定命令收集詳細的作業系統資訊。
|
|
194
|
+
* 當命令失敗時,回退到 Node.js os 模組資料。
|
|
195
|
+
*
|
|
196
|
+
* @returns Complete OS information / 完整的作業系統資訊
|
|
197
|
+
*/
|
|
198
|
+
export async function detectOS() {
|
|
199
|
+
const currentPlatform = osPlatform();
|
|
200
|
+
logger.info(`Detecting OS on platform: ${currentPlatform}`);
|
|
201
|
+
// Build base info from Node.js os module
|
|
202
|
+
// 從 Node.js os 模組建立基本資訊
|
|
203
|
+
const baseInfo = {
|
|
204
|
+
platform: currentPlatform,
|
|
205
|
+
distro: osType(),
|
|
206
|
+
version: osRelease(),
|
|
207
|
+
arch: osArch(),
|
|
208
|
+
kernel: osRelease(),
|
|
209
|
+
hostname: osHostname(),
|
|
210
|
+
uptime: osUptime(),
|
|
211
|
+
patchLevel: 'unknown',
|
|
212
|
+
};
|
|
213
|
+
try {
|
|
214
|
+
let platformSpecific = {};
|
|
215
|
+
switch (currentPlatform) {
|
|
216
|
+
case 'darwin':
|
|
217
|
+
platformSpecific = await detectMacOS();
|
|
218
|
+
break;
|
|
219
|
+
case 'linux':
|
|
220
|
+
platformSpecific = await detectLinux();
|
|
221
|
+
break;
|
|
222
|
+
case 'win32':
|
|
223
|
+
platformSpecific = await detectWindows();
|
|
224
|
+
break;
|
|
225
|
+
default:
|
|
226
|
+
logger.warn(`Unsupported platform: ${currentPlatform}, using defaults`);
|
|
227
|
+
}
|
|
228
|
+
// Get kernel version on UNIX-like systems
|
|
229
|
+
// 在類 UNIX 系統上取得核心版本
|
|
230
|
+
if (currentPlatform === 'darwin' || currentPlatform === 'linux') {
|
|
231
|
+
const kernelVersion = await safeExec('uname', ['-r']);
|
|
232
|
+
if (kernelVersion) {
|
|
233
|
+
baseInfo.kernel = kernelVersion;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const result = {
|
|
237
|
+
...baseInfo,
|
|
238
|
+
...platformSpecific,
|
|
239
|
+
};
|
|
240
|
+
logger.info(`OS detected: ${result.distro} ${result.version}`, {
|
|
241
|
+
platform: result.platform,
|
|
242
|
+
arch: result.arch,
|
|
243
|
+
});
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
catch (err) {
|
|
247
|
+
logger.error('OS detection failed, returning base info', {
|
|
248
|
+
error: err instanceof Error ? err.message : String(err),
|
|
249
|
+
});
|
|
250
|
+
return baseInfo;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
//# sourceMappingURL=os-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"os-detector.js","sourceRoot":"","sources":["../../src/discovery/os-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* osquery Integration Provider - SQL-based system state queries
|
|
3
|
+
* osquery 整合提供者 - 基於 SQL 的系統狀態查詢
|
|
4
|
+
*
|
|
5
|
+
* Provides system discovery via osquery when available, with graceful
|
|
6
|
+
* fallback to the existing shell-based discovery methods.
|
|
7
|
+
* 當 osquery 可用時提供系統偵察,否則優雅降級到現有的 shell 指令方式。
|
|
8
|
+
*
|
|
9
|
+
* @module @panguard-ai/core/discovery/osquery-provider
|
|
10
|
+
*/
|
|
11
|
+
import type { PortInfo, UserInfo } from './types.js';
|
|
12
|
+
/** osquery process entry */
|
|
13
|
+
export interface OsqueryProcess {
|
|
14
|
+
pid: number;
|
|
15
|
+
name: string;
|
|
16
|
+
path: string;
|
|
17
|
+
cmdline: string;
|
|
18
|
+
uid: number;
|
|
19
|
+
state: string;
|
|
20
|
+
}
|
|
21
|
+
/** osquery listening port entry */
|
|
22
|
+
export interface OsqueryListeningPort {
|
|
23
|
+
pid: number;
|
|
24
|
+
port: number;
|
|
25
|
+
protocol: string;
|
|
26
|
+
address: string;
|
|
27
|
+
processName: string;
|
|
28
|
+
}
|
|
29
|
+
/** osquery logged-in user entry */
|
|
30
|
+
export interface OsqueryLoggedInUser {
|
|
31
|
+
user: string;
|
|
32
|
+
host: string;
|
|
33
|
+
time: number;
|
|
34
|
+
tty: string;
|
|
35
|
+
type: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* osquery Provider - queries system state via SQL
|
|
39
|
+
* osquery 提供者 - 透過 SQL 查詢系統狀態
|
|
40
|
+
*/
|
|
41
|
+
export declare class OsqueryProvider {
|
|
42
|
+
private osqueryPath;
|
|
43
|
+
private available;
|
|
44
|
+
constructor(osqueryPath?: string);
|
|
45
|
+
/**
|
|
46
|
+
* Check if osquery is installed and accessible
|
|
47
|
+
* 檢查 osquery 是否已安裝且可存取
|
|
48
|
+
*/
|
|
49
|
+
isAvailable(): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* Execute a SQL query via osqueryi
|
|
52
|
+
* 透過 osqueryi 執行 SQL 查詢
|
|
53
|
+
*/
|
|
54
|
+
query<T>(sql: string): Promise<T[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Get running processes via osquery
|
|
57
|
+
* 透過 osquery 取得執行中的程序
|
|
58
|
+
*/
|
|
59
|
+
getProcesses(): Promise<OsqueryProcess[]>;
|
|
60
|
+
/**
|
|
61
|
+
* Get listening ports via osquery
|
|
62
|
+
* 透過 osquery 取得監聽 port
|
|
63
|
+
*/
|
|
64
|
+
getListeningPorts(): Promise<OsqueryListeningPort[]>;
|
|
65
|
+
/**
|
|
66
|
+
* Convert osquery ports to PortInfo format (matching existing discovery types)
|
|
67
|
+
* 將 osquery port 轉換為 PortInfo 格式
|
|
68
|
+
*/
|
|
69
|
+
getPortsAsPortInfo(): Promise<PortInfo[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Get user list via osquery
|
|
72
|
+
* 透過 osquery 取得用戶列表
|
|
73
|
+
*/
|
|
74
|
+
getUsers(): Promise<UserInfo[]>;
|
|
75
|
+
/**
|
|
76
|
+
* Get currently logged-in users via osquery
|
|
77
|
+
* 透過 osquery 取得目前登入的用戶
|
|
78
|
+
*/
|
|
79
|
+
getLoggedInUsers(): Promise<OsqueryLoggedInUser[]>;
|
|
80
|
+
/**
|
|
81
|
+
* Get system info via osquery
|
|
82
|
+
* 透過 osquery 取得系統資訊
|
|
83
|
+
*/
|
|
84
|
+
getSystemInfo(): Promise<Record<string, string>>;
|
|
85
|
+
/**
|
|
86
|
+
* Get OS version via osquery
|
|
87
|
+
* 透過 osquery 取得作業系統版本
|
|
88
|
+
*/
|
|
89
|
+
getOSVersion(): Promise<Record<string, string>>;
|
|
90
|
+
/**
|
|
91
|
+
* Check for kernel modules (Linux) or kexts (macOS)
|
|
92
|
+
* 檢查核心模組
|
|
93
|
+
*/
|
|
94
|
+
getKernelModules(): Promise<Array<{
|
|
95
|
+
name: string;
|
|
96
|
+
size: string;
|
|
97
|
+
status: string;
|
|
98
|
+
}>>;
|
|
99
|
+
/**
|
|
100
|
+
* Get network interfaces via osquery
|
|
101
|
+
* 透過 osquery 取得網路介面
|
|
102
|
+
*/
|
|
103
|
+
getInterfaces(): Promise<Array<{
|
|
104
|
+
interface: string;
|
|
105
|
+
address: string;
|
|
106
|
+
mask: string;
|
|
107
|
+
type: string;
|
|
108
|
+
}>>;
|
|
109
|
+
/**
|
|
110
|
+
* Run a custom security audit query
|
|
111
|
+
* 執行自訂安全稽核查詢
|
|
112
|
+
*/
|
|
113
|
+
securityAudit(): Promise<{
|
|
114
|
+
suidBinaries: number;
|
|
115
|
+
listeningPorts: number;
|
|
116
|
+
loggedInUsers: number;
|
|
117
|
+
totalProcesses: number;
|
|
118
|
+
}>;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Create an OsqueryProvider with availability check
|
|
122
|
+
* 建立帶可用性檢查的 OsqueryProvider
|
|
123
|
+
*
|
|
124
|
+
* Returns the provider if osquery is available, null otherwise.
|
|
125
|
+
*/
|
|
126
|
+
export declare function createOsqueryProvider(osqueryPath?: string): Promise<OsqueryProvider | null>;
|
|
127
|
+
//# sourceMappingURL=osquery-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"osquery-provider.d.ts","sourceRoot":"","sources":["../../src/discovery/osquery-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAKrD,4BAA4B;AAC5B,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mCAAmC;AACnC,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,mCAAmC;AACnC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAwB;gBAE7B,WAAW,GAAE,MAAmB;IAI5C;;;OAGG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAmBrC;;;OAGG;IACG,KAAK,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAgBzC;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAoB/C;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAsB1D;;;OAGG;IACG,kBAAkB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAY/C;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAsBrC;;;OAGG;IACG,gBAAgB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAkBxD;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAQtD;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAOrD;;;OAGG;IACG,gBAAgB,IAAI,OAAO,CAAC,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAcxF;;;OAGG;IACG,aAAa,IAAI,OAAO,CAC5B,KAAK,CAAC;QACJ,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CACH;IAeD;;;OAGG;IACG,aAAa,IAAI,OAAO,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CAcH;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAIjG"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* osquery Integration Provider - SQL-based system state queries
|
|
3
|
+
* osquery 整合提供者 - 基於 SQL 的系統狀態查詢
|
|
4
|
+
*
|
|
5
|
+
* Provides system discovery via osquery when available, with graceful
|
|
6
|
+
* fallback to the existing shell-based discovery methods.
|
|
7
|
+
* 當 osquery 可用時提供系統偵察,否則優雅降級到現有的 shell 指令方式。
|
|
8
|
+
*
|
|
9
|
+
* @module @panguard-ai/core/discovery/osquery-provider
|
|
10
|
+
*/
|
|
11
|
+
import { execFile } from 'node:child_process';
|
|
12
|
+
import { promisify } from 'node:util';
|
|
13
|
+
import { createLogger } from '../utils/logger.js';
|
|
14
|
+
const execFileAsync = promisify(execFile);
|
|
15
|
+
const logger = createLogger('osquery');
|
|
16
|
+
/**
|
|
17
|
+
* osquery Provider - queries system state via SQL
|
|
18
|
+
* osquery 提供者 - 透過 SQL 查詢系統狀態
|
|
19
|
+
*/
|
|
20
|
+
export class OsqueryProvider {
|
|
21
|
+
osqueryPath;
|
|
22
|
+
available = null;
|
|
23
|
+
constructor(osqueryPath = 'osqueryi') {
|
|
24
|
+
this.osqueryPath = osqueryPath;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Check if osquery is installed and accessible
|
|
28
|
+
* 檢查 osquery 是否已安裝且可存取
|
|
29
|
+
*/
|
|
30
|
+
async isAvailable() {
|
|
31
|
+
if (this.available !== null)
|
|
32
|
+
return this.available;
|
|
33
|
+
try {
|
|
34
|
+
const { stdout } = await execFileAsync(this.osqueryPath, ['--version'], {
|
|
35
|
+
timeout: 5000,
|
|
36
|
+
});
|
|
37
|
+
this.available = stdout.includes('osquery');
|
|
38
|
+
if (this.available) {
|
|
39
|
+
logger.info(`osquery available: ${stdout.trim()}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
this.available = false;
|
|
44
|
+
logger.info('osquery not available, using fallback discovery');
|
|
45
|
+
}
|
|
46
|
+
return this.available;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Execute a SQL query via osqueryi
|
|
50
|
+
* 透過 osqueryi 執行 SQL 查詢
|
|
51
|
+
*/
|
|
52
|
+
async query(sql) {
|
|
53
|
+
if (!(await this.isAvailable())) {
|
|
54
|
+
throw new Error('osquery is not available');
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
const { stdout } = await execFileAsync(this.osqueryPath, ['--json', sql], { timeout: 30000 });
|
|
58
|
+
return JSON.parse(stdout);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
62
|
+
logger.error(`osquery query failed: ${msg}`, { sql });
|
|
63
|
+
throw new Error(`osquery query failed: ${msg}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get running processes via osquery
|
|
68
|
+
* 透過 osquery 取得執行中的程序
|
|
69
|
+
*/
|
|
70
|
+
async getProcesses() {
|
|
71
|
+
const rows = await this.query('SELECT pid, name, path, cmdline, uid, state FROM processes');
|
|
72
|
+
return rows.map((row) => ({
|
|
73
|
+
pid: parseInt(row.pid, 10),
|
|
74
|
+
name: row.name,
|
|
75
|
+
path: row.path,
|
|
76
|
+
cmdline: row.cmdline,
|
|
77
|
+
uid: parseInt(row.uid, 10),
|
|
78
|
+
state: row.state,
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get listening ports via osquery
|
|
83
|
+
* 透過 osquery 取得監聽 port
|
|
84
|
+
*/
|
|
85
|
+
async getListeningPorts() {
|
|
86
|
+
const rows = await this.query('SELECT lp.pid, lp.port, lp.protocol, lp.address, p.name ' +
|
|
87
|
+
'FROM listening_ports lp LEFT JOIN processes p ON lp.pid = p.pid ' +
|
|
88
|
+
'WHERE lp.port > 0');
|
|
89
|
+
return rows.map((row) => ({
|
|
90
|
+
pid: parseInt(row.pid, 10),
|
|
91
|
+
port: parseInt(row.port, 10),
|
|
92
|
+
protocol: row.protocol === '6' ? 'tcp' : row.protocol === '17' ? 'udp' : row.protocol,
|
|
93
|
+
address: row.address,
|
|
94
|
+
processName: row.name ?? 'unknown',
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Convert osquery ports to PortInfo format (matching existing discovery types)
|
|
99
|
+
* 將 osquery port 轉換為 PortInfo 格式
|
|
100
|
+
*/
|
|
101
|
+
async getPortsAsPortInfo() {
|
|
102
|
+
const ports = await this.getListeningPorts();
|
|
103
|
+
return ports.map((p) => ({
|
|
104
|
+
port: p.port,
|
|
105
|
+
protocol: p.protocol,
|
|
106
|
+
state: 'LISTEN',
|
|
107
|
+
service: p.processName,
|
|
108
|
+
process: p.processName,
|
|
109
|
+
pid: p.pid,
|
|
110
|
+
}));
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Get user list via osquery
|
|
114
|
+
* 透過 osquery 取得用戶列表
|
|
115
|
+
*/
|
|
116
|
+
async getUsers() {
|
|
117
|
+
const rows = await this.query('SELECT uid, gid, username, description, shell, directory FROM users');
|
|
118
|
+
return rows.map((row) => ({
|
|
119
|
+
username: row.username,
|
|
120
|
+
uid: row.uid,
|
|
121
|
+
gid: row.gid,
|
|
122
|
+
home: row.directory,
|
|
123
|
+
shell: row.shell,
|
|
124
|
+
groups: [],
|
|
125
|
+
isAdmin: parseInt(row.uid, 10) === 0,
|
|
126
|
+
lastLogin: undefined,
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get currently logged-in users via osquery
|
|
131
|
+
* 透過 osquery 取得目前登入的用戶
|
|
132
|
+
*/
|
|
133
|
+
async getLoggedInUsers() {
|
|
134
|
+
const rows = await this.query('SELECT user, host, time, tty, type FROM logged_in_users');
|
|
135
|
+
return rows.map((row) => ({
|
|
136
|
+
user: row.user,
|
|
137
|
+
host: row.host,
|
|
138
|
+
time: parseInt(row.time, 10),
|
|
139
|
+
tty: row.tty,
|
|
140
|
+
type: row.type,
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get system info via osquery
|
|
145
|
+
* 透過 osquery 取得系統資訊
|
|
146
|
+
*/
|
|
147
|
+
async getSystemInfo() {
|
|
148
|
+
const rows = await this.query('SELECT hostname, computer_name, cpu_brand, cpu_type, ' +
|
|
149
|
+
'physical_memory, hardware_vendor, hardware_model FROM system_info');
|
|
150
|
+
return rows[0] ?? {};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get OS version via osquery
|
|
154
|
+
* 透過 osquery 取得作業系統版本
|
|
155
|
+
*/
|
|
156
|
+
async getOSVersion() {
|
|
157
|
+
const rows = await this.query('SELECT name, version, major, minor, patch, build, platform FROM os_version');
|
|
158
|
+
return rows[0] ?? {};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check for kernel modules (Linux) or kexts (macOS)
|
|
162
|
+
* 檢查核心模組
|
|
163
|
+
*/
|
|
164
|
+
async getKernelModules() {
|
|
165
|
+
try {
|
|
166
|
+
const rows = await this.query('SELECT name, size, status FROM kernel_modules');
|
|
167
|
+
return rows;
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
// Not all platforms support this table
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get network interfaces via osquery
|
|
176
|
+
* 透過 osquery 取得網路介面
|
|
177
|
+
*/
|
|
178
|
+
async getInterfaces() {
|
|
179
|
+
const rows = await this.query('SELECT ia.interface, ia.address, ia.mask, id.type ' +
|
|
180
|
+
'FROM interface_addresses ia ' +
|
|
181
|
+
'JOIN interface_details id ON ia.interface = id.interface ' +
|
|
182
|
+
'WHERE ia.address != "" AND ia.address != "::1" AND ia.address != "127.0.0.1"');
|
|
183
|
+
return rows;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Run a custom security audit query
|
|
187
|
+
* 執行自訂安全稽核查詢
|
|
188
|
+
*/
|
|
189
|
+
async securityAudit() {
|
|
190
|
+
const [ports, users, processes] = await Promise.all([
|
|
191
|
+
this.getListeningPorts().catch(() => []),
|
|
192
|
+
this.getLoggedInUsers().catch(() => []),
|
|
193
|
+
this.getProcesses().catch(() => []),
|
|
194
|
+
]);
|
|
195
|
+
return {
|
|
196
|
+
suidBinaries: 0, // Would need platform-specific query
|
|
197
|
+
listeningPorts: ports.length,
|
|
198
|
+
loggedInUsers: users.length,
|
|
199
|
+
totalProcesses: processes.length,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Create an OsqueryProvider with availability check
|
|
205
|
+
* 建立帶可用性檢查的 OsqueryProvider
|
|
206
|
+
*
|
|
207
|
+
* Returns the provider if osquery is available, null otherwise.
|
|
208
|
+
*/
|
|
209
|
+
export async function createOsqueryProvider(osqueryPath) {
|
|
210
|
+
const provider = new OsqueryProvider(osqueryPath);
|
|
211
|
+
const available = await provider.isAvailable();
|
|
212
|
+
return available ? provider : null;
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=osquery-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"osquery-provider.js","sourceRoot":"","sources":["../../src/discovery/osquery-provider.ts"],"names":[],"mappings":"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"}
|