@panguard-ai/manager 0.2.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/LICENSE +21 -0
- package/dist/agent-registry.d.ts +88 -0
- package/dist/agent-registry.d.ts.map +1 -0
- package/dist/agent-registry.js +202 -0
- package/dist/agent-registry.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/manager.d.ts +153 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/manager.js +303 -0
- package/dist/manager.js.map +1 -0
- package/dist/policy-engine.d.ts +94 -0
- package/dist/policy-engine.d.ts.map +1 -0
- package/dist/policy-engine.js +171 -0
- package/dist/policy-engine.js.map +1 -0
- package/dist/threat-aggregator.d.ts +89 -0
- package/dist/threat-aggregator.d.ts.map +1 -0
- package/dist/threat-aggregator.js +344 -0
- package/dist/threat-aggregator.js.map +1 -0
- package/dist/types.d.ts +141 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +17 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +46 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +87 -0
- package/dist/utils.js.map +1 -0
- package/package.json +29 -0
package/dist/manager.js
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manager - Central orchestrator for distributed Guard agent architecture
|
|
3
|
+
* Manager - 分散式 Guard 代理架構的中央協調器
|
|
4
|
+
*
|
|
5
|
+
* Coordinates multiple Guard agents across endpoints:
|
|
6
|
+
* - Agent registration and lifecycle management
|
|
7
|
+
* - Heartbeat monitoring with stale agent detection
|
|
8
|
+
* - Threat ingestion and cross-agent correlation
|
|
9
|
+
* - Centralized policy creation and distribution
|
|
10
|
+
*
|
|
11
|
+
* @module @panguard-ai/manager/manager
|
|
12
|
+
*/
|
|
13
|
+
import { createLogger } from '@panguard-ai/core';
|
|
14
|
+
import { AgentRegistry } from './agent-registry.js';
|
|
15
|
+
import { ThreatAggregator } from './threat-aggregator.js';
|
|
16
|
+
import { PolicyEngine } from './policy-engine.js';
|
|
17
|
+
const logger = createLogger('panguard-manager:core');
|
|
18
|
+
/**
|
|
19
|
+
* Manager is the main orchestrator for the distributed Guard architecture.
|
|
20
|
+
*
|
|
21
|
+
* It composes AgentRegistry, ThreatAggregator, and PolicyEngine to provide
|
|
22
|
+
* a unified API for managing the entire fleet of Guard agents.
|
|
23
|
+
*/
|
|
24
|
+
export class Manager {
|
|
25
|
+
config;
|
|
26
|
+
registry;
|
|
27
|
+
aggregator;
|
|
28
|
+
policyEngine;
|
|
29
|
+
running;
|
|
30
|
+
startTime;
|
|
31
|
+
staleCheckTimer;
|
|
32
|
+
purgeTimer;
|
|
33
|
+
// Policy broadcast queue / 策略廣播佇列
|
|
34
|
+
broadcastQueue;
|
|
35
|
+
constructor(config) {
|
|
36
|
+
this.config = config;
|
|
37
|
+
this.registry = new AgentRegistry(config.maxAgents);
|
|
38
|
+
this.aggregator = new ThreatAggregator(config.correlationWindowMs, config.threatRetentionMs);
|
|
39
|
+
this.policyEngine = new PolicyEngine();
|
|
40
|
+
this.running = false;
|
|
41
|
+
this.startTime = 0;
|
|
42
|
+
this.staleCheckTimer = null;
|
|
43
|
+
this.purgeTimer = null;
|
|
44
|
+
this.broadcastQueue = [];
|
|
45
|
+
logger.info(`Manager initialized (maxAgents: ${config.maxAgents}, ` +
|
|
46
|
+
`heartbeatTimeout: ${config.heartbeatTimeoutMs}ms) / ` +
|
|
47
|
+
`Manager 已初始化`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Start the Manager service.
|
|
51
|
+
* Begins periodic stale agent checking and threat purging.
|
|
52
|
+
*/
|
|
53
|
+
start() {
|
|
54
|
+
if (this.running) {
|
|
55
|
+
logger.warn('Manager already running / Manager 已在執行中');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this.running = true;
|
|
59
|
+
this.startTime = Date.now();
|
|
60
|
+
// Periodic stale agent check / 定期檢查過期代理
|
|
61
|
+
this.staleCheckTimer = setInterval(() => {
|
|
62
|
+
this.checkStaleAgents();
|
|
63
|
+
}, this.config.heartbeatIntervalMs);
|
|
64
|
+
// Periodic threat data purge / 定期清除威脅資料
|
|
65
|
+
const purgeIntervalMs = Math.min(this.config.threatRetentionMs / 4, 3_600_000 // max 1 hour
|
|
66
|
+
);
|
|
67
|
+
this.purgeTimer = setInterval(() => {
|
|
68
|
+
this.aggregator.purgeExpired();
|
|
69
|
+
}, purgeIntervalMs);
|
|
70
|
+
logger.info(`Manager started on port ${this.config.port} / ` +
|
|
71
|
+
`Manager 已啟動於埠 ${this.config.port}`);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Stop the Manager service.
|
|
75
|
+
* Clears all periodic timers.
|
|
76
|
+
*/
|
|
77
|
+
stop() {
|
|
78
|
+
if (!this.running)
|
|
79
|
+
return;
|
|
80
|
+
if (this.staleCheckTimer) {
|
|
81
|
+
clearInterval(this.staleCheckTimer);
|
|
82
|
+
this.staleCheckTimer = null;
|
|
83
|
+
}
|
|
84
|
+
if (this.purgeTimer) {
|
|
85
|
+
clearInterval(this.purgeTimer);
|
|
86
|
+
this.purgeTimer = null;
|
|
87
|
+
}
|
|
88
|
+
this.running = false;
|
|
89
|
+
logger.info(`Manager stopped (uptime: ${Date.now() - this.startTime}ms) / Manager 已停止`);
|
|
90
|
+
}
|
|
91
|
+
// ===== Agent Lifecycle / 代理生命週期 =====
|
|
92
|
+
/**
|
|
93
|
+
* Handle a new agent registration request.
|
|
94
|
+
*
|
|
95
|
+
* @param request - Registration data from the Guard agent
|
|
96
|
+
* @returns Immutable copy of the registration record
|
|
97
|
+
* @throws Error if max agents exceeded
|
|
98
|
+
*/
|
|
99
|
+
handleRegistration(request) {
|
|
100
|
+
const registration = this.registry.registerAgent(request);
|
|
101
|
+
logger.info(`Agent joined: ${registration.agentId} from ${registration.hostname} / ` +
|
|
102
|
+
`代理已加入: ${registration.agentId} 來自 ${registration.hostname}`);
|
|
103
|
+
return registration;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Handle a heartbeat from a Guard agent.
|
|
107
|
+
* Updates the agent's status and last-seen timestamp.
|
|
108
|
+
*
|
|
109
|
+
* @param heartbeat - Heartbeat data from the agent
|
|
110
|
+
* @returns Updated registration, or undefined if agent unknown
|
|
111
|
+
*/
|
|
112
|
+
handleHeartbeat(heartbeat) {
|
|
113
|
+
return this.registry.updateHeartbeat(heartbeat);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Handle a threat report from a Guard agent.
|
|
117
|
+
* Ingests threats into the aggregator and checks for cross-agent correlation.
|
|
118
|
+
*
|
|
119
|
+
* @param report - Threat report containing one or more events
|
|
120
|
+
* @returns Array of aggregated threats, with correlation data if detected
|
|
121
|
+
*/
|
|
122
|
+
handleThreatReport(report) {
|
|
123
|
+
const agent = this.registry.getAgent(report.agentId);
|
|
124
|
+
const hostname = agent?.hostname ?? 'unknown';
|
|
125
|
+
const aggregated = this.aggregator.ingestReport(report, hostname);
|
|
126
|
+
// Log correlation detections
|
|
127
|
+
const correlated = aggregated.filter((t) => t.correlatedWith.length > 0);
|
|
128
|
+
if (correlated.length > 0) {
|
|
129
|
+
logger.warn(`ALERT: ${correlated.length} cross-agent correlations detected from ${hostname} / ` +
|
|
130
|
+
`警報: 從 ${hostname} 偵測到 ${correlated.length} 個跨代理關聯`);
|
|
131
|
+
}
|
|
132
|
+
return aggregated;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Remove an agent from the fleet.
|
|
136
|
+
*
|
|
137
|
+
* @param agentId - The agent's unique identifier
|
|
138
|
+
* @returns true if the agent was found and removed
|
|
139
|
+
*/
|
|
140
|
+
handleDeregistration(agentId) {
|
|
141
|
+
return this.registry.deregisterAgent(agentId);
|
|
142
|
+
}
|
|
143
|
+
// ===== Policy Management / 策略管理 =====
|
|
144
|
+
/**
|
|
145
|
+
* Create and optionally broadcast a new security policy.
|
|
146
|
+
*
|
|
147
|
+
* @param rules - Policy rules to include
|
|
148
|
+
* @param broadcast - Whether to queue broadcast to all active agents
|
|
149
|
+
* @returns The created policy
|
|
150
|
+
*/
|
|
151
|
+
createPolicy(rules, broadcast = true) {
|
|
152
|
+
const activeAgentIds = this.registry
|
|
153
|
+
.getActiveAgents()
|
|
154
|
+
.map((a) => a.agentId);
|
|
155
|
+
const policy = this.policyEngine.createPolicy(rules, activeAgentIds);
|
|
156
|
+
if (broadcast) {
|
|
157
|
+
this.broadcastPolicy(policy);
|
|
158
|
+
}
|
|
159
|
+
return policy;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Queue a policy update for broadcast to all active agents.
|
|
163
|
+
*
|
|
164
|
+
* @param policy - The policy to broadcast
|
|
165
|
+
* @returns Broadcast result with target agent list
|
|
166
|
+
*/
|
|
167
|
+
broadcastPolicy(policy) {
|
|
168
|
+
const activeAgents = this.registry.getActiveAgents();
|
|
169
|
+
const targetIds = activeAgents.map((a) => a.agentId);
|
|
170
|
+
const result = {
|
|
171
|
+
policyId: policy.policyId,
|
|
172
|
+
targetAgents: [...targetIds],
|
|
173
|
+
queuedAt: new Date().toISOString(),
|
|
174
|
+
};
|
|
175
|
+
this.broadcastQueue.push(result);
|
|
176
|
+
logger.info(`Policy ${policy.policyId} queued for broadcast to ${targetIds.length} agents / ` +
|
|
177
|
+
`策略 ${policy.policyId} 已排入佇列廣播至 ${targetIds.length} 個代理`);
|
|
178
|
+
return {
|
|
179
|
+
...result,
|
|
180
|
+
targetAgents: [...result.targetAgents],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Get the active global policy.
|
|
185
|
+
*
|
|
186
|
+
* @returns Active policy or null
|
|
187
|
+
*/
|
|
188
|
+
getActivePolicy() {
|
|
189
|
+
return this.policyEngine.getActivePolicy();
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Get the policy applicable to a specific agent.
|
|
193
|
+
*
|
|
194
|
+
* @param agentId - The agent's unique identifier
|
|
195
|
+
* @returns Policy for the agent, or null
|
|
196
|
+
*/
|
|
197
|
+
getPolicyForAgent(agentId) {
|
|
198
|
+
return this.policyEngine.getPolicyForAgent(agentId);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get pending policy broadcast results.
|
|
202
|
+
*
|
|
203
|
+
* @returns Immutable array of broadcast results
|
|
204
|
+
*/
|
|
205
|
+
getPendingBroadcasts() {
|
|
206
|
+
return this.broadcastQueue.map((r) => ({
|
|
207
|
+
...r,
|
|
208
|
+
targetAgents: [...r.targetAgents],
|
|
209
|
+
}));
|
|
210
|
+
}
|
|
211
|
+
// ===== Monitoring / 監控 =====
|
|
212
|
+
/**
|
|
213
|
+
* Check for and handle stale agents.
|
|
214
|
+
* Called periodically by the stale check timer.
|
|
215
|
+
*/
|
|
216
|
+
checkStaleAgents() {
|
|
217
|
+
const stale = this.registry.getStaleAgents(this.config.heartbeatTimeoutMs);
|
|
218
|
+
if (stale.length > 0) {
|
|
219
|
+
logger.warn(`${stale.length} stale agent(s) detected / ` +
|
|
220
|
+
`偵測到 ${stale.length} 個過期代理`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// ===== Dashboard / 儀表板 =====
|
|
224
|
+
/**
|
|
225
|
+
* Generate a comprehensive overview for the management dashboard.
|
|
226
|
+
*
|
|
227
|
+
* @returns Immutable manager overview object
|
|
228
|
+
*/
|
|
229
|
+
getOverview() {
|
|
230
|
+
const allAgents = this.registry.getAllAgents();
|
|
231
|
+
const statusCounts = this.registry.getStatusCounts();
|
|
232
|
+
const threatSummary = this.aggregator.getSummary();
|
|
233
|
+
const policyVersion = this.policyEngine.getCurrentVersion();
|
|
234
|
+
const agentOverviews = allAgents.map((a) => {
|
|
235
|
+
const agentThreats = this.aggregator.getThreatsByAgent(a.agentId);
|
|
236
|
+
return {
|
|
237
|
+
agentId: a.agentId,
|
|
238
|
+
hostname: a.hostname,
|
|
239
|
+
status: a.status,
|
|
240
|
+
lastHeartbeat: a.lastHeartbeat,
|
|
241
|
+
threatCount: agentThreats.length,
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
return {
|
|
245
|
+
totalAgents: allAgents.length,
|
|
246
|
+
onlineAgents: statusCounts.online,
|
|
247
|
+
staleAgents: statusCounts.stale,
|
|
248
|
+
offlineAgents: statusCounts.offline,
|
|
249
|
+
agents: agentOverviews,
|
|
250
|
+
threatSummary,
|
|
251
|
+
activePolicyVersion: policyVersion,
|
|
252
|
+
uptimeMs: this.running ? Date.now() - this.startTime : 0,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Get threat summary from the aggregator.
|
|
257
|
+
*
|
|
258
|
+
* @returns Immutable threat summary
|
|
259
|
+
*/
|
|
260
|
+
getThreatSummary() {
|
|
261
|
+
return this.aggregator.getSummary();
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Get threats reported by a specific agent.
|
|
265
|
+
*
|
|
266
|
+
* @param agentId - The agent's unique identifier
|
|
267
|
+
* @returns Array of aggregated threats
|
|
268
|
+
*/
|
|
269
|
+
getThreatsByAgent(agentId) {
|
|
270
|
+
return this.aggregator.getThreatsByAgent(agentId);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Get recent threats across all agents.
|
|
274
|
+
*
|
|
275
|
+
* @param since - Date threshold
|
|
276
|
+
* @returns Array of aggregated threats
|
|
277
|
+
*/
|
|
278
|
+
getRecentThreats(since) {
|
|
279
|
+
return this.aggregator.getRecentThreats(since);
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Get a specific agent's registration.
|
|
283
|
+
*
|
|
284
|
+
* @param agentId - The agent's unique identifier
|
|
285
|
+
* @returns Agent registration or undefined
|
|
286
|
+
*/
|
|
287
|
+
getAgent(agentId) {
|
|
288
|
+
return this.registry.getAgent(agentId);
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Check if the manager is currently running.
|
|
292
|
+
*/
|
|
293
|
+
isRunning() {
|
|
294
|
+
return this.running;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Get the number of registered agents.
|
|
298
|
+
*/
|
|
299
|
+
getAgentCount() {
|
|
300
|
+
return this.registry.size;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PolicyEngine - Centralized security policy management
|
|
3
|
+
* PolicyEngine - 集中式安全策略管理
|
|
4
|
+
*
|
|
5
|
+
* Manages security policies that are distributed to Guard agents.
|
|
6
|
+
* Supports global policies and per-agent/group customization.
|
|
7
|
+
*
|
|
8
|
+
* @module @panguard-ai/manager/policy-engine
|
|
9
|
+
*/
|
|
10
|
+
import type { PolicyRule, PolicyUpdate } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Agent group assignment for policy targeting.
|
|
13
|
+
*/
|
|
14
|
+
interface AgentGroup {
|
|
15
|
+
readonly groupId: string;
|
|
16
|
+
readonly name: string;
|
|
17
|
+
readonly agentIds: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Manages creation, versioning, and distribution of security policies.
|
|
21
|
+
* All returned data is immutable copies.
|
|
22
|
+
*/
|
|
23
|
+
export declare class PolicyEngine {
|
|
24
|
+
private activePolicy;
|
|
25
|
+
private readonly policyHistory;
|
|
26
|
+
private readonly agentGroups;
|
|
27
|
+
private readonly agentOverrides;
|
|
28
|
+
constructor();
|
|
29
|
+
/**
|
|
30
|
+
* Create a new global policy from a set of rules.
|
|
31
|
+
* Increments the version number from the previous active policy.
|
|
32
|
+
*
|
|
33
|
+
* @param rules - Array of policy rules to include
|
|
34
|
+
* @param targetAgentIds - Agent IDs this policy applies to (empty = all)
|
|
35
|
+
* @returns Immutable copy of the new policy
|
|
36
|
+
*/
|
|
37
|
+
createPolicy(rules: readonly PolicyRule[], targetAgentIds?: readonly string[]): PolicyUpdate;
|
|
38
|
+
/**
|
|
39
|
+
* Get the current active global policy.
|
|
40
|
+
*
|
|
41
|
+
* @returns Immutable copy of the active policy, or null if none set
|
|
42
|
+
*/
|
|
43
|
+
getActivePolicy(): PolicyUpdate | null;
|
|
44
|
+
/**
|
|
45
|
+
* Get the policy applicable to a specific agent.
|
|
46
|
+
* Returns agent-specific override if one exists, otherwise the global policy.
|
|
47
|
+
*
|
|
48
|
+
* @param agentId - The agent's unique identifier
|
|
49
|
+
* @returns Immutable copy of the applicable policy, or null
|
|
50
|
+
*/
|
|
51
|
+
getPolicyForAgent(agentId: string): PolicyUpdate | null;
|
|
52
|
+
/**
|
|
53
|
+
* Set a policy override for a specific agent.
|
|
54
|
+
* The agent will receive this policy instead of the global one.
|
|
55
|
+
*
|
|
56
|
+
* @param agentId - The agent's unique identifier
|
|
57
|
+
* @param rules - Array of policy rules for this agent
|
|
58
|
+
* @returns Immutable copy of the agent-specific policy
|
|
59
|
+
*/
|
|
60
|
+
setAgentOverride(agentId: string, rules: readonly PolicyRule[]): PolicyUpdate;
|
|
61
|
+
/**
|
|
62
|
+
* Remove a policy override for an agent, reverting to global policy.
|
|
63
|
+
*
|
|
64
|
+
* @param agentId - The agent's unique identifier
|
|
65
|
+
* @returns true if an override was removed
|
|
66
|
+
*/
|
|
67
|
+
removeAgentOverride(agentId: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Create a named agent group for policy targeting.
|
|
70
|
+
*
|
|
71
|
+
* @param groupId - Unique group identifier
|
|
72
|
+
* @param name - Human-readable group name
|
|
73
|
+
* @param agentIds - Agent IDs in this group
|
|
74
|
+
*/
|
|
75
|
+
createAgentGroup(groupId: string, name: string, agentIds: readonly string[]): AgentGroup;
|
|
76
|
+
/**
|
|
77
|
+
* Get the policy version history.
|
|
78
|
+
*
|
|
79
|
+
* @returns Array of immutable historical policy copies
|
|
80
|
+
*/
|
|
81
|
+
getPolicyHistory(): readonly PolicyUpdate[];
|
|
82
|
+
/**
|
|
83
|
+
* Get the current policy version number.
|
|
84
|
+
*
|
|
85
|
+
* @returns Current version, or 0 if no policy exists
|
|
86
|
+
*/
|
|
87
|
+
getCurrentVersion(): number;
|
|
88
|
+
/**
|
|
89
|
+
* Create a deep immutable copy of a PolicyUpdate.
|
|
90
|
+
*/
|
|
91
|
+
private copyPolicy;
|
|
92
|
+
}
|
|
93
|
+
export {};
|
|
94
|
+
//# sourceMappingURL=policy-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-engine.d.ts","sourceRoot":"","sources":["../src/policy-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAI3D;;GAEG;AACH,UAAU,UAAU;IAClB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC;AAED;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,YAAY,CAAsB;IAC1C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAiB;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA0B;IACtD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA4B;;IAS3D;;;;;;;OAOG;IACH,YAAY,CACV,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,cAAc,GAAE,SAAS,MAAM,EAAO,GACrC,YAAY;IA8Bf;;;;OAIG;IACH,eAAe,IAAI,YAAY,GAAG,IAAI;IAKtC;;;;;;OAMG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAYvD;;;;;;;OAOG;IACH,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,SAAS,UAAU,EAAE,GAC3B,YAAY;IAsBf;;;;;OAKG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAU7C;;;;;;OAMG;IACH,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,UAAU;IAgBb;;;;OAIG;IACH,gBAAgB,IAAI,SAAS,YAAY,EAAE;IAI3C;;;;OAIG;IACH,iBAAiB,IAAI,MAAM;IAI3B;;OAEG;IACH,OAAO,CAAC,UAAU;CAUnB"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PolicyEngine - Centralized security policy management
|
|
3
|
+
* PolicyEngine - 集中式安全策略管理
|
|
4
|
+
*
|
|
5
|
+
* Manages security policies that are distributed to Guard agents.
|
|
6
|
+
* Supports global policies and per-agent/group customization.
|
|
7
|
+
*
|
|
8
|
+
* @module @panguard-ai/manager/policy-engine
|
|
9
|
+
*/
|
|
10
|
+
import { createLogger } from '@panguard-ai/core';
|
|
11
|
+
import { generatePolicyId } from './utils.js';
|
|
12
|
+
const logger = createLogger('panguard-manager:policy');
|
|
13
|
+
/**
|
|
14
|
+
* Manages creation, versioning, and distribution of security policies.
|
|
15
|
+
* All returned data is immutable copies.
|
|
16
|
+
*/
|
|
17
|
+
export class PolicyEngine {
|
|
18
|
+
activePolicy;
|
|
19
|
+
policyHistory;
|
|
20
|
+
agentGroups;
|
|
21
|
+
agentOverrides;
|
|
22
|
+
constructor() {
|
|
23
|
+
this.activePolicy = null;
|
|
24
|
+
this.policyHistory = [];
|
|
25
|
+
this.agentGroups = new Map();
|
|
26
|
+
this.agentOverrides = new Map();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Create a new global policy from a set of rules.
|
|
30
|
+
* Increments the version number from the previous active policy.
|
|
31
|
+
*
|
|
32
|
+
* @param rules - Array of policy rules to include
|
|
33
|
+
* @param targetAgentIds - Agent IDs this policy applies to (empty = all)
|
|
34
|
+
* @returns Immutable copy of the new policy
|
|
35
|
+
*/
|
|
36
|
+
createPolicy(rules, targetAgentIds = []) {
|
|
37
|
+
const previousVersion = this.activePolicy?.version ?? 0;
|
|
38
|
+
const policy = {
|
|
39
|
+
policyId: generatePolicyId(),
|
|
40
|
+
version: previousVersion + 1,
|
|
41
|
+
rules: rules.map((r) => ({
|
|
42
|
+
...r,
|
|
43
|
+
condition: { ...r.condition },
|
|
44
|
+
})),
|
|
45
|
+
updatedAt: new Date().toISOString(),
|
|
46
|
+
appliedTo: [...targetAgentIds],
|
|
47
|
+
};
|
|
48
|
+
// Archive the previous policy / 歸檔先前的策略
|
|
49
|
+
if (this.activePolicy) {
|
|
50
|
+
this.policyHistory.push(this.activePolicy);
|
|
51
|
+
}
|
|
52
|
+
this.activePolicy = policy;
|
|
53
|
+
logger.info(`Policy created: ${policy.policyId} v${policy.version} ` +
|
|
54
|
+
`(${rules.length} rules, targets: ${targetAgentIds.length || 'all'}) / ` +
|
|
55
|
+
`策略已建立: ${policy.policyId} v${policy.version}`);
|
|
56
|
+
return this.copyPolicy(policy);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get the current active global policy.
|
|
60
|
+
*
|
|
61
|
+
* @returns Immutable copy of the active policy, or null if none set
|
|
62
|
+
*/
|
|
63
|
+
getActivePolicy() {
|
|
64
|
+
if (!this.activePolicy)
|
|
65
|
+
return null;
|
|
66
|
+
return this.copyPolicy(this.activePolicy);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get the policy applicable to a specific agent.
|
|
70
|
+
* Returns agent-specific override if one exists, otherwise the global policy.
|
|
71
|
+
*
|
|
72
|
+
* @param agentId - The agent's unique identifier
|
|
73
|
+
* @returns Immutable copy of the applicable policy, or null
|
|
74
|
+
*/
|
|
75
|
+
getPolicyForAgent(agentId) {
|
|
76
|
+
// Check for agent-specific override first
|
|
77
|
+
const override = this.agentOverrides.get(agentId);
|
|
78
|
+
if (override) {
|
|
79
|
+
return this.copyPolicy(override);
|
|
80
|
+
}
|
|
81
|
+
// Fall back to global policy / 回退至全域策略
|
|
82
|
+
if (!this.activePolicy)
|
|
83
|
+
return null;
|
|
84
|
+
return this.copyPolicy(this.activePolicy);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Set a policy override for a specific agent.
|
|
88
|
+
* The agent will receive this policy instead of the global one.
|
|
89
|
+
*
|
|
90
|
+
* @param agentId - The agent's unique identifier
|
|
91
|
+
* @param rules - Array of policy rules for this agent
|
|
92
|
+
* @returns Immutable copy of the agent-specific policy
|
|
93
|
+
*/
|
|
94
|
+
setAgentOverride(agentId, rules) {
|
|
95
|
+
const policy = {
|
|
96
|
+
policyId: generatePolicyId(),
|
|
97
|
+
version: 1,
|
|
98
|
+
rules: rules.map((r) => ({
|
|
99
|
+
...r,
|
|
100
|
+
condition: { ...r.condition },
|
|
101
|
+
})),
|
|
102
|
+
updatedAt: new Date().toISOString(),
|
|
103
|
+
appliedTo: [agentId],
|
|
104
|
+
};
|
|
105
|
+
this.agentOverrides.set(agentId, policy);
|
|
106
|
+
logger.info(`Agent override set: ${agentId} -> ${policy.policyId} / ` +
|
|
107
|
+
`代理覆寫策略已設定: ${agentId}`);
|
|
108
|
+
return this.copyPolicy(policy);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Remove a policy override for an agent, reverting to global policy.
|
|
112
|
+
*
|
|
113
|
+
* @param agentId - The agent's unique identifier
|
|
114
|
+
* @returns true if an override was removed
|
|
115
|
+
*/
|
|
116
|
+
removeAgentOverride(agentId) {
|
|
117
|
+
const removed = this.agentOverrides.delete(agentId);
|
|
118
|
+
if (removed) {
|
|
119
|
+
logger.info(`Agent override removed: ${agentId} / 代理覆寫策略已移除: ${agentId}`);
|
|
120
|
+
}
|
|
121
|
+
return removed;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create a named agent group for policy targeting.
|
|
125
|
+
*
|
|
126
|
+
* @param groupId - Unique group identifier
|
|
127
|
+
* @param name - Human-readable group name
|
|
128
|
+
* @param agentIds - Agent IDs in this group
|
|
129
|
+
*/
|
|
130
|
+
createAgentGroup(groupId, name, agentIds) {
|
|
131
|
+
const group = {
|
|
132
|
+
groupId,
|
|
133
|
+
name,
|
|
134
|
+
agentIds: [...agentIds],
|
|
135
|
+
};
|
|
136
|
+
this.agentGroups.set(groupId, group);
|
|
137
|
+
logger.info(`Agent group created: ${groupId} (${name}, ${agentIds.length} agents) / ` +
|
|
138
|
+
`代理群組已建立: ${groupId}`);
|
|
139
|
+
return { ...group, agentIds: [...group.agentIds] };
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Get the policy version history.
|
|
143
|
+
*
|
|
144
|
+
* @returns Array of immutable historical policy copies
|
|
145
|
+
*/
|
|
146
|
+
getPolicyHistory() {
|
|
147
|
+
return this.policyHistory.map((p) => this.copyPolicy(p));
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get the current policy version number.
|
|
151
|
+
*
|
|
152
|
+
* @returns Current version, or 0 if no policy exists
|
|
153
|
+
*/
|
|
154
|
+
getCurrentVersion() {
|
|
155
|
+
return this.activePolicy?.version ?? 0;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Create a deep immutable copy of a PolicyUpdate.
|
|
159
|
+
*/
|
|
160
|
+
copyPolicy(policy) {
|
|
161
|
+
return {
|
|
162
|
+
...policy,
|
|
163
|
+
rules: policy.rules.map((r) => ({
|
|
164
|
+
...r,
|
|
165
|
+
condition: { ...r.condition },
|
|
166
|
+
})),
|
|
167
|
+
appliedTo: [...policy.appliedTo],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=policy-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy-engine.js","sourceRoot":"","sources":["../src/policy-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ThreatAggregator - Collects and correlates threats from multiple Guard agents
|
|
3
|
+
* ThreatAggregator - 從多個 Guard 代理收集並關聯威脅
|
|
4
|
+
*
|
|
5
|
+
* Performs cross-agent correlation to detect coordinated attacks:
|
|
6
|
+
* - Same source IP appearing across different agents
|
|
7
|
+
* - Same malware hash detected on different endpoints
|
|
8
|
+
* - Same MITRE ATT&CK technique from same source
|
|
9
|
+
*
|
|
10
|
+
* @module @panguard-ai/manager/threat-aggregator
|
|
11
|
+
*/
|
|
12
|
+
import type { ThreatReport, AggregatedThreat, CorrelationMatch, ThreatSummary } from './types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Aggregates threats from multiple agents and performs cross-agent correlation.
|
|
15
|
+
*
|
|
16
|
+
* Uses secondary indexes (IP index, hash index) for O(1) correlation lookups
|
|
17
|
+
* instead of O(n^2) pairwise comparison.
|
|
18
|
+
*/
|
|
19
|
+
export declare class ThreatAggregator {
|
|
20
|
+
private readonly threats;
|
|
21
|
+
private readonly correlations;
|
|
22
|
+
private readonly ipIndex;
|
|
23
|
+
private readonly hashIndex;
|
|
24
|
+
private readonly categoryIndex;
|
|
25
|
+
private readonly correlationWindowMs;
|
|
26
|
+
private readonly retentionMs;
|
|
27
|
+
constructor(correlationWindowMs: number, retentionMs: number);
|
|
28
|
+
/**
|
|
29
|
+
* Ingest a threat report from a Guard agent.
|
|
30
|
+
* Each threat event is stored as an AggregatedThreat and indexed
|
|
31
|
+
* for correlation. Cross-agent matches are detected during ingestion.
|
|
32
|
+
*
|
|
33
|
+
* @param report - The threat report containing one or more events
|
|
34
|
+
* @param hostname - The hostname of the reporting agent
|
|
35
|
+
* @returns Array of newly created AggregatedThreats
|
|
36
|
+
*/
|
|
37
|
+
ingestReport(report: ThreatReport, hostname: string): readonly AggregatedThreat[];
|
|
38
|
+
/**
|
|
39
|
+
* Index a threat for correlation lookups.
|
|
40
|
+
*/
|
|
41
|
+
private indexThreat;
|
|
42
|
+
/**
|
|
43
|
+
* Find existing threats that correlate with a new threat.
|
|
44
|
+
* Only matches threats from DIFFERENT agents within the correlation window.
|
|
45
|
+
*/
|
|
46
|
+
private findCorrelations;
|
|
47
|
+
/**
|
|
48
|
+
* Get all threats received since a given timestamp.
|
|
49
|
+
*
|
|
50
|
+
* @param since - Date threshold for filtering
|
|
51
|
+
* @returns Array of immutable AggregatedThreat copies
|
|
52
|
+
*/
|
|
53
|
+
getRecentThreats(since: Date): readonly AggregatedThreat[];
|
|
54
|
+
/**
|
|
55
|
+
* Get all threats reported by a specific agent.
|
|
56
|
+
*
|
|
57
|
+
* @param agentId - The agent's unique identifier
|
|
58
|
+
* @returns Array of immutable AggregatedThreat copies
|
|
59
|
+
*/
|
|
60
|
+
getThreatsByAgent(agentId: string): readonly AggregatedThreat[];
|
|
61
|
+
/**
|
|
62
|
+
* Get all correlation matches.
|
|
63
|
+
*
|
|
64
|
+
* @returns Immutable array of correlation match records
|
|
65
|
+
*/
|
|
66
|
+
getCorrelations(): readonly CorrelationMatch[];
|
|
67
|
+
/**
|
|
68
|
+
* Generate a summary of the current threat landscape.
|
|
69
|
+
*
|
|
70
|
+
* @returns Immutable threat summary object
|
|
71
|
+
*/
|
|
72
|
+
getSummary(): ThreatSummary;
|
|
73
|
+
/**
|
|
74
|
+
* Purge threats older than the retention period.
|
|
75
|
+
* Also cleans up corresponding index entries.
|
|
76
|
+
*
|
|
77
|
+
* @returns Number of threats purged
|
|
78
|
+
*/
|
|
79
|
+
purgeExpired(): number;
|
|
80
|
+
/**
|
|
81
|
+
* Rebuild all secondary indexes from the current threat data.
|
|
82
|
+
*/
|
|
83
|
+
private rebuildIndexes;
|
|
84
|
+
/**
|
|
85
|
+
* Get the total number of tracked threats.
|
|
86
|
+
*/
|
|
87
|
+
get size(): number;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=threat-aggregator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"threat-aggregator.d.ts","sourceRoot":"","sources":["../src/threat-aggregator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EACV,YAAY,EAEZ,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACd,MAAM,YAAY,CAAC;AAYpB;;;;;GAKG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgC;IACxD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAGlD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4B;IACpD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4B;IACtD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4B;IAG1D,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,mBAAmB,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAU5D;;;;;;;;OAQG;IACH,YAAY,CACV,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,MAAM,GACf,SAAS,gBAAgB,EAAE;IAuE9B;;OAEG;IACH,OAAO,CAAC,WAAW;IA0BnB;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IA0FxB;;;;;OAKG;IACH,gBAAgB,CAAC,KAAK,EAAE,IAAI,GAAG,SAAS,gBAAgB,EAAE;IAU1D;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,gBAAgB,EAAE;IAS/D;;;;OAIG;IACH,eAAe,IAAI,SAAS,gBAAgB,EAAE;IAI9C;;;;OAIG;IACH,UAAU,IAAI,aAAa;IAyC3B;;;;;OAKG;IACH,YAAY,IAAI,MAAM;IA6BtB;;OAEG;IACH,OAAO,CAAC,cAAc;IActB;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|