@panguard-ai/panguard-guard 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.
Files changed (130) hide show
  1. package/dist/agent/analyze-agent.d.ts +62 -0
  2. package/dist/agent/analyze-agent.d.ts.map +1 -0
  3. package/dist/agent/analyze-agent.js +327 -0
  4. package/dist/agent/analyze-agent.js.map +1 -0
  5. package/dist/agent/detect-agent.d.ts +59 -0
  6. package/dist/agent/detect-agent.d.ts.map +1 -0
  7. package/dist/agent/detect-agent.js +214 -0
  8. package/dist/agent/detect-agent.js.map +1 -0
  9. package/dist/agent/index.d.ts +15 -0
  10. package/dist/agent/index.d.ts.map +1 -0
  11. package/dist/agent/index.js +14 -0
  12. package/dist/agent/index.js.map +1 -0
  13. package/dist/agent/report-agent.d.ts +122 -0
  14. package/dist/agent/report-agent.d.ts.map +1 -0
  15. package/dist/agent/report-agent.js +468 -0
  16. package/dist/agent/report-agent.js.map +1 -0
  17. package/dist/agent/respond-agent.d.ts +113 -0
  18. package/dist/agent/respond-agent.d.ts.map +1 -0
  19. package/dist/agent/respond-agent.js +749 -0
  20. package/dist/agent/respond-agent.js.map +1 -0
  21. package/dist/agent-client/index.d.ts +81 -0
  22. package/dist/agent-client/index.d.ts.map +1 -0
  23. package/dist/agent-client/index.js +170 -0
  24. package/dist/agent-client/index.js.map +1 -0
  25. package/dist/cli/index.d.ts +17 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +295 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/config.d.ts +23 -0
  30. package/dist/config.d.ts.map +1 -0
  31. package/dist/config.js +108 -0
  32. package/dist/config.js.map +1 -0
  33. package/dist/daemon/index.d.ts +66 -0
  34. package/dist/daemon/index.d.ts.map +1 -0
  35. package/dist/daemon/index.js +284 -0
  36. package/dist/daemon/index.js.map +1 -0
  37. package/dist/dashboard/index.d.ts +78 -0
  38. package/dist/dashboard/index.d.ts.map +1 -0
  39. package/dist/dashboard/index.js +455 -0
  40. package/dist/dashboard/index.js.map +1 -0
  41. package/dist/guard-engine.d.ts +108 -0
  42. package/dist/guard-engine.d.ts.map +1 -0
  43. package/dist/guard-engine.js +740 -0
  44. package/dist/guard-engine.js.map +1 -0
  45. package/dist/index.d.ts +29 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +39 -0
  48. package/dist/index.js.map +1 -0
  49. package/dist/install/index.d.ts +23 -0
  50. package/dist/install/index.d.ts.map +1 -0
  51. package/dist/install/index.js +216 -0
  52. package/dist/install/index.js.map +1 -0
  53. package/dist/investigation/index.d.ts +80 -0
  54. package/dist/investigation/index.d.ts.map +1 -0
  55. package/dist/investigation/index.js +570 -0
  56. package/dist/investigation/index.js.map +1 -0
  57. package/dist/license/index.d.ts +46 -0
  58. package/dist/license/index.d.ts.map +1 -0
  59. package/dist/license/index.js +145 -0
  60. package/dist/license/index.js.map +1 -0
  61. package/dist/memory/baseline.d.ts +34 -0
  62. package/dist/memory/baseline.d.ts.map +1 -0
  63. package/dist/memory/baseline.js +224 -0
  64. package/dist/memory/baseline.js.map +1 -0
  65. package/dist/memory/index.d.ts +32 -0
  66. package/dist/memory/index.d.ts.map +1 -0
  67. package/dist/memory/index.js +58 -0
  68. package/dist/memory/index.js.map +1 -0
  69. package/dist/memory/learning.d.ts +35 -0
  70. package/dist/memory/learning.d.ts.map +1 -0
  71. package/dist/memory/learning.js +60 -0
  72. package/dist/memory/learning.js.map +1 -0
  73. package/dist/monitors/falco-monitor.d.ts +62 -0
  74. package/dist/monitors/falco-monitor.d.ts.map +1 -0
  75. package/dist/monitors/falco-monitor.js +226 -0
  76. package/dist/monitors/falco-monitor.js.map +1 -0
  77. package/dist/monitors/suricata-monitor.d.ts +80 -0
  78. package/dist/monitors/suricata-monitor.d.ts.map +1 -0
  79. package/dist/monitors/suricata-monitor.js +227 -0
  80. package/dist/monitors/suricata-monitor.js.map +1 -0
  81. package/dist/notify/email.d.ts +23 -0
  82. package/dist/notify/email.d.ts.map +1 -0
  83. package/dist/notify/email.js +124 -0
  84. package/dist/notify/email.js.map +1 -0
  85. package/dist/notify/index.d.ts +31 -0
  86. package/dist/notify/index.d.ts.map +1 -0
  87. package/dist/notify/index.js +70 -0
  88. package/dist/notify/index.js.map +1 -0
  89. package/dist/notify/line-notify.d.ts.map +1 -0
  90. package/dist/notify/slack.d.ts +21 -0
  91. package/dist/notify/slack.d.ts.map +1 -0
  92. package/dist/notify/slack.js +92 -0
  93. package/dist/notify/slack.js.map +1 -0
  94. package/dist/notify/telegram.d.ts +21 -0
  95. package/dist/notify/telegram.d.ts.map +1 -0
  96. package/dist/notify/telegram.js +89 -0
  97. package/dist/notify/telegram.js.map +1 -0
  98. package/dist/response/file-quarantine.d.ts +63 -0
  99. package/dist/response/file-quarantine.d.ts.map +1 -0
  100. package/dist/response/file-quarantine.js +137 -0
  101. package/dist/response/file-quarantine.js.map +1 -0
  102. package/dist/response/index.d.ts +4 -0
  103. package/dist/response/index.d.ts.map +1 -0
  104. package/dist/response/index.js +4 -0
  105. package/dist/response/index.js.map +1 -0
  106. package/dist/response/ip-blocker.d.ts +69 -0
  107. package/dist/response/ip-blocker.d.ts.map +1 -0
  108. package/dist/response/ip-blocker.js +191 -0
  109. package/dist/response/ip-blocker.js.map +1 -0
  110. package/dist/response/process-killer.d.ts +49 -0
  111. package/dist/response/process-killer.d.ts.map +1 -0
  112. package/dist/response/process-killer.js +230 -0
  113. package/dist/response/process-killer.js.map +1 -0
  114. package/dist/rules/builtin-rules.d.ts +12 -0
  115. package/dist/rules/builtin-rules.d.ts.map +1 -0
  116. package/dist/rules/builtin-rules.js +471 -0
  117. package/dist/rules/builtin-rules.js.map +1 -0
  118. package/dist/threat-cloud/client-id.d.ts +13 -0
  119. package/dist/threat-cloud/client-id.d.ts.map +1 -0
  120. package/dist/threat-cloud/client-id.js +38 -0
  121. package/dist/threat-cloud/client-id.js.map +1 -0
  122. package/dist/threat-cloud/index.d.ts +103 -0
  123. package/dist/threat-cloud/index.d.ts.map +1 -0
  124. package/dist/threat-cloud/index.js +386 -0
  125. package/dist/threat-cloud/index.js.map +1 -0
  126. package/dist/types.d.ts +336 -0
  127. package/dist/types.d.ts.map +1 -0
  128. package/dist/types.js +42 -0
  129. package/dist/types.js.map +1 -0
  130. package/package.json +35 -0
@@ -0,0 +1,386 @@
1
+ /**
2
+ * Collective Threat Intelligence (Threat Cloud)
3
+ * 集體威脅智慧(威脅雲)
4
+ *
5
+ * Provides anonymized threat data upload and community rule distribution.
6
+ * Supports HTTP cloud backend with local file fallback for offline mode.
7
+ * 提供匿名化威脅數據上傳和社群規則分發。
8
+ * 支援 HTTP 雲端後端和離線模式的本地檔案備援。
9
+ *
10
+ * @module @panguard-ai/panguard-guard/threat-cloud
11
+ */
12
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
13
+ import { join, dirname } from 'node:path';
14
+ import { request } from 'node:https';
15
+ import { createLogger } from '@panguard-ai/core';
16
+ import { getAnonymousClientId } from './client-id.js';
17
+ const logger = createLogger('panguard-guard:threat-cloud');
18
+ /** Local cache file name / 本地快取檔名 */
19
+ const CACHE_FILE = 'threat-cloud-cache.json';
20
+ /** Local upload queue file name / 本地上傳佇列檔名 */
21
+ const QUEUE_FILE = 'threat-cloud-queue.json';
22
+ /**
23
+ * Threat Cloud Client for collective intelligence sharing
24
+ * 集體情報分享的威脅雲客戶端
25
+ */
26
+ export class ThreatCloudClient {
27
+ endpoint;
28
+ dataDir;
29
+ clientId;
30
+ status = 'disconnected';
31
+ cache;
32
+ uploadQueue = [];
33
+ uploadBuffer = [];
34
+ flushTimer = null;
35
+ /** Max events before immediate flush */
36
+ static BATCH_SIZE = 50;
37
+ /** Max buffer size to prevent memory growth */
38
+ static MAX_BUFFER = 1000;
39
+ /** Periodic flush interval (ms) */
40
+ static FLUSH_INTERVAL = 60_000;
41
+ /**
42
+ * @param endpoint - Cloud API endpoint URL (undefined = offline mode) / 雲端 API 端點 URL
43
+ * @param dataDir - Local data directory for cache/queue / 本地資料目錄
44
+ */
45
+ constructor(endpoint, dataDir) {
46
+ this.endpoint = endpoint;
47
+ this.dataDir = dataDir;
48
+ this.clientId = getAnonymousClientId();
49
+ // Load local cache and upload queue / 載入本地快取和上傳佇列
50
+ this.cache = this.loadCache();
51
+ this.uploadQueue = this.loadQueue();
52
+ if (!endpoint) {
53
+ this.status = 'offline';
54
+ logger.info('Threat Cloud in offline mode (no endpoint configured) / 威脅雲離線模式');
55
+ }
56
+ else {
57
+ // Start periodic flush timer
58
+ this.flushTimer = setInterval(() => {
59
+ void this.flushBuffer();
60
+ }, ThreatCloudClient.FLUSH_INTERVAL);
61
+ }
62
+ }
63
+ /**
64
+ * Get current connection status / 取得當前連線狀態
65
+ */
66
+ getStatus() {
67
+ return this.status;
68
+ }
69
+ /**
70
+ * Upload anonymized threat data to the cloud.
71
+ * Data is buffered and sent in batches of up to 50 events.
72
+ * 上傳匿名化威脅數據至雲端。數據會緩衝並批次上傳(最多 50 筆)。
73
+ *
74
+ * @param data - Anonymized threat data / 匿名化威脅數據
75
+ */
76
+ async upload(data) {
77
+ if (this.status === 'offline' || !this.endpoint) {
78
+ this.uploadQueue.push(data);
79
+ this.saveQueue();
80
+ return false;
81
+ }
82
+ this.uploadBuffer.push(data);
83
+ // Cap buffer to prevent memory growth
84
+ if (this.uploadBuffer.length > ThreatCloudClient.MAX_BUFFER) {
85
+ this.uploadBuffer = this.uploadBuffer.slice(-ThreatCloudClient.MAX_BUFFER);
86
+ }
87
+ // Flush immediately if batch size reached
88
+ if (this.uploadBuffer.length >= ThreatCloudClient.BATCH_SIZE) {
89
+ return this.flushBuffer();
90
+ }
91
+ return true;
92
+ }
93
+ /**
94
+ * Flush the upload buffer (batch POST to cloud).
95
+ * 清空上傳緩衝區(批次 POST 至雲端)。
96
+ */
97
+ async flushBuffer() {
98
+ if (this.uploadBuffer.length === 0)
99
+ return true;
100
+ if (!this.endpoint)
101
+ return false;
102
+ const batch = [...this.uploadBuffer];
103
+ this.uploadBuffer = [];
104
+ try {
105
+ await this.httpPost(`${this.endpoint}/api/threats`, { events: batch });
106
+ this.cache.stats.totalUploaded += batch.length;
107
+ this.saveCache();
108
+ this.status = 'connected';
109
+ logger.info(`Batch uploaded ${batch.length} events / 批次上傳 ${batch.length} 筆事件`);
110
+ return true;
111
+ }
112
+ catch (err) {
113
+ const msg = err instanceof Error ? err.message : String(err);
114
+ logger.error(`Batch upload failed: ${msg}, re-buffering / 批次上傳失敗: ${msg},重新緩衝`);
115
+ // Put batch back at front of buffer
116
+ this.uploadBuffer.unshift(...batch);
117
+ // Enforce max buffer limit
118
+ if (this.uploadBuffer.length > ThreatCloudClient.MAX_BUFFER) {
119
+ this.uploadBuffer = this.uploadBuffer.slice(-ThreatCloudClient.MAX_BUFFER);
120
+ }
121
+ this.status = 'disconnected';
122
+ return false;
123
+ }
124
+ }
125
+ /**
126
+ * Stop the flush timer (call on shutdown).
127
+ * 停止定期清空計時器。
128
+ */
129
+ stopFlushTimer() {
130
+ if (this.flushTimer) {
131
+ clearInterval(this.flushTimer);
132
+ this.flushTimer = null;
133
+ }
134
+ }
135
+ /**
136
+ * Fetch latest community rules from the cloud
137
+ * 從雲端取得最新社群規則
138
+ *
139
+ * @returns Array of rule updates / 規則更新陣列
140
+ */
141
+ async fetchRules() {
142
+ if (this.status === 'offline' || !this.endpoint) {
143
+ logger.info('Returning cached rules (offline mode) / 回傳快取規則(離線模式)');
144
+ return this.cache.rules;
145
+ }
146
+ try {
147
+ const lastSync = this.cache.lastSync;
148
+ const url = `${this.endpoint}/api/rules?since=${encodeURIComponent(lastSync)}`;
149
+ const response = await this.httpGet(url);
150
+ const rules = JSON.parse(response);
151
+ // Merge new rules into cache / 將新規則合併到快取
152
+ for (const rule of rules) {
153
+ const existing = this.cache.rules.findIndex((r) => r.ruleId === rule.ruleId);
154
+ if (existing !== -1) {
155
+ this.cache.rules[existing] = rule;
156
+ }
157
+ else {
158
+ this.cache.rules.push(rule);
159
+ }
160
+ }
161
+ this.cache.lastSync = new Date().toISOString();
162
+ this.cache.stats.totalRulesReceived += rules.length;
163
+ this.saveCache();
164
+ this.status = 'connected';
165
+ logger.info(`Fetched ${rules.length} rules from cloud / 從雲端取得 ${rules.length} 條規則`);
166
+ return this.cache.rules;
167
+ }
168
+ catch (err) {
169
+ const msg = err instanceof Error ? err.message : String(err);
170
+ logger.error(`Fetch rules failed: ${msg}, using cache / 取得規則失敗: ${msg},使用快取`);
171
+ this.status = 'disconnected';
172
+ return this.cache.rules;
173
+ }
174
+ }
175
+ /**
176
+ * Flush the upload queue (sync pending data to cloud)
177
+ * 清空上傳佇列(將待上傳數據同步至雲端)
178
+ *
179
+ * @returns Number of items successfully uploaded / 成功上傳的項目數
180
+ */
181
+ async flushQueue() {
182
+ // Also flush any buffered events first
183
+ this.stopFlushTimer();
184
+ await this.flushBuffer();
185
+ if (this.uploadQueue.length === 0)
186
+ return 0;
187
+ if (this.status === 'offline' || !this.endpoint)
188
+ return 0;
189
+ let uploaded = 0;
190
+ const remaining = [];
191
+ for (const data of this.uploadQueue) {
192
+ try {
193
+ await this.httpPost(`${this.endpoint}/api/threats`, data);
194
+ uploaded++;
195
+ this.cache.stats.totalUploaded++;
196
+ }
197
+ catch {
198
+ remaining.push(data);
199
+ }
200
+ }
201
+ this.uploadQueue = remaining;
202
+ this.saveQueue();
203
+ this.saveCache();
204
+ logger.info(`Queue flush: ${uploaded} uploaded, ${remaining.length} remaining / ` +
205
+ `佇列清空: ${uploaded} 已上傳, ${remaining.length} 剩餘`);
206
+ return uploaded;
207
+ }
208
+ /**
209
+ * Fetch IP blocklist from the cloud (plain text, one IP per line).
210
+ * 從雲端取得 IP 封鎖清單(純文字,每行一個 IP)。
211
+ *
212
+ * @returns Array of blocked IPs / 封鎖 IP 陣列
213
+ */
214
+ async fetchBlocklist() {
215
+ if (this.status === 'offline' || !this.endpoint) {
216
+ return [];
217
+ }
218
+ try {
219
+ const url = `${this.endpoint}/api/feeds/ip-blocklist`;
220
+ const response = await this.httpGet(url);
221
+ const ips = response
222
+ .split('\n')
223
+ .map((line) => line.trim())
224
+ .filter((line) => line.length > 0 && !line.startsWith('#'));
225
+ this.status = 'connected';
226
+ logger.info(`Fetched ${ips.length} IPs from blocklist / 從封鎖清單取得 ${ips.length} 個 IP`);
227
+ return ips;
228
+ }
229
+ catch (err) {
230
+ const msg = err instanceof Error ? err.message : String(err);
231
+ logger.error(`Fetch blocklist failed: ${msg} / 取得封鎖清單失敗: ${msg}`);
232
+ this.status = 'disconnected';
233
+ return [];
234
+ }
235
+ }
236
+ /**
237
+ * Get cached rules without network call / 取得快取規則(不進行網路呼叫)
238
+ */
239
+ getCachedRules() {
240
+ return [...this.cache.rules];
241
+ }
242
+ /**
243
+ * Get queue size / 取得佇列大小
244
+ */
245
+ getQueueSize() {
246
+ return this.uploadQueue.length;
247
+ }
248
+ /**
249
+ * Get statistics / 取得統計
250
+ */
251
+ getStats() {
252
+ return {
253
+ ...this.cache.stats,
254
+ queueSize: this.uploadQueue.length,
255
+ };
256
+ }
257
+ // ---------------------------------------------------------------------------
258
+ // HTTP helpers / HTTP 輔助函數
259
+ // ---------------------------------------------------------------------------
260
+ httpPost(url, body) {
261
+ return new Promise((resolve, reject) => {
262
+ const payload = JSON.stringify(body);
263
+ const parsed = new URL(url);
264
+ const req = request({
265
+ hostname: parsed.hostname,
266
+ port: parsed.port || 443,
267
+ path: parsed.pathname + parsed.search,
268
+ method: 'POST',
269
+ headers: {
270
+ 'Content-Type': 'application/json',
271
+ 'Content-Length': Buffer.byteLength(payload),
272
+ 'X-Panguard-Client-Id': this.clientId,
273
+ },
274
+ timeout: 10000,
275
+ }, (res) => {
276
+ let data = '';
277
+ res.on('data', (chunk) => {
278
+ data += chunk.toString();
279
+ });
280
+ res.on('end', () => {
281
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
282
+ resolve(data);
283
+ }
284
+ else {
285
+ reject(new Error(`HTTP ${res.statusCode}: ${data}`));
286
+ }
287
+ });
288
+ });
289
+ req.on('error', reject);
290
+ req.on('timeout', () => {
291
+ req.destroy();
292
+ reject(new Error('Request timeout'));
293
+ });
294
+ req.write(payload);
295
+ req.end();
296
+ });
297
+ }
298
+ httpGet(url) {
299
+ return new Promise((resolve, reject) => {
300
+ const parsed = new URL(url);
301
+ const req = request({
302
+ hostname: parsed.hostname,
303
+ port: parsed.port || 443,
304
+ path: parsed.pathname + parsed.search,
305
+ method: 'GET',
306
+ headers: {
307
+ 'X-Panguard-Client-Id': this.clientId,
308
+ },
309
+ timeout: 10000,
310
+ }, (res) => {
311
+ let data = '';
312
+ res.on('data', (chunk) => {
313
+ data += chunk.toString();
314
+ });
315
+ res.on('end', () => {
316
+ if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) {
317
+ resolve(data);
318
+ }
319
+ else {
320
+ reject(new Error(`HTTP ${res.statusCode}: ${data}`));
321
+ }
322
+ });
323
+ });
324
+ req.on('error', reject);
325
+ req.on('timeout', () => {
326
+ req.destroy();
327
+ reject(new Error('Request timeout'));
328
+ });
329
+ req.end();
330
+ });
331
+ }
332
+ // ---------------------------------------------------------------------------
333
+ // Cache/queue persistence / 快取/佇列持久化
334
+ // ---------------------------------------------------------------------------
335
+ loadCache() {
336
+ const filePath = join(this.dataDir, CACHE_FILE);
337
+ try {
338
+ if (existsSync(filePath)) {
339
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
340
+ }
341
+ }
342
+ catch {
343
+ logger.warn('Failed to load threat cloud cache / 載入威脅雲快取失敗');
344
+ }
345
+ return {
346
+ rules: [],
347
+ lastSync: new Date(0).toISOString(),
348
+ stats: { totalUploaded: 0, totalRulesReceived: 0 },
349
+ };
350
+ }
351
+ saveCache() {
352
+ try {
353
+ const filePath = join(this.dataDir, CACHE_FILE);
354
+ mkdirSync(dirname(filePath), { recursive: true });
355
+ writeFileSync(filePath, JSON.stringify(this.cache, null, 2), 'utf-8');
356
+ }
357
+ catch (err) {
358
+ const msg = err instanceof Error ? err.message : String(err);
359
+ logger.error(`Failed to save cache: ${msg} / 儲存快取失敗: ${msg}`);
360
+ }
361
+ }
362
+ loadQueue() {
363
+ const filePath = join(this.dataDir, QUEUE_FILE);
364
+ try {
365
+ if (existsSync(filePath)) {
366
+ return JSON.parse(readFileSync(filePath, 'utf-8'));
367
+ }
368
+ }
369
+ catch {
370
+ logger.warn('Failed to load upload queue / 載入上傳佇列失敗');
371
+ }
372
+ return [];
373
+ }
374
+ saveQueue() {
375
+ try {
376
+ const filePath = join(this.dataDir, QUEUE_FILE);
377
+ mkdirSync(dirname(filePath), { recursive: true });
378
+ writeFileSync(filePath, JSON.stringify(this.uploadQueue, null, 2), 'utf-8');
379
+ }
380
+ catch (err) {
381
+ const msg = err instanceof Error ? err.message : String(err);
382
+ logger.error(`Failed to save queue: ${msg} / 儲存佇列失敗: ${msg}`);
383
+ }
384
+ }
385
+ }
386
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/threat-cloud/index.ts"],"names":[],"mappings":"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"}