@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/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Panguard AI Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentRegistry - Manages connected Guard agent registrations
|
|
3
|
+
* AgentRegistry - 管理已連線的 Guard 代理登錄
|
|
4
|
+
*
|
|
5
|
+
* Maintains an internal Map of registered agents, supports heartbeat updates,
|
|
6
|
+
* and detects stale/offline agents. All returned data is immutable copies.
|
|
7
|
+
*
|
|
8
|
+
* @module @panguard-ai/manager/agent-registry
|
|
9
|
+
*/
|
|
10
|
+
import type { AgentRegistration, AgentRegistrationRequest, AgentHeartbeat, AgentStatus } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Registry that tracks all connected Guard agents.
|
|
13
|
+
* Uses immutable return patterns - internal state is never exposed directly.
|
|
14
|
+
*/
|
|
15
|
+
export declare class AgentRegistry {
|
|
16
|
+
private readonly agents;
|
|
17
|
+
private readonly maxAgents;
|
|
18
|
+
constructor(maxAgents: number);
|
|
19
|
+
/**
|
|
20
|
+
* Register a new Guard agent.
|
|
21
|
+
* Generates a unique agent ID and returns the registration record.
|
|
22
|
+
*
|
|
23
|
+
* @param request - Registration request from the agent
|
|
24
|
+
* @returns Immutable copy of the registration record
|
|
25
|
+
* @throws Error if maximum agent limit is reached
|
|
26
|
+
*/
|
|
27
|
+
registerAgent(request: AgentRegistrationRequest): AgentRegistration;
|
|
28
|
+
/**
|
|
29
|
+
* Remove an agent from the registry.
|
|
30
|
+
*
|
|
31
|
+
* @param agentId - The agent's unique identifier
|
|
32
|
+
* @returns true if the agent was found and removed
|
|
33
|
+
*/
|
|
34
|
+
deregisterAgent(agentId: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Update the heartbeat timestamp and metrics for an agent.
|
|
37
|
+
* Creates a new registration record with updated fields (immutable pattern).
|
|
38
|
+
*
|
|
39
|
+
* @param heartbeat - Heartbeat data from the agent
|
|
40
|
+
* @returns Updated registration or undefined if agent not found
|
|
41
|
+
*/
|
|
42
|
+
updateHeartbeat(heartbeat: AgentHeartbeat): AgentRegistration | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* Get a single agent's registration record.
|
|
45
|
+
*
|
|
46
|
+
* @param agentId - The agent's unique identifier
|
|
47
|
+
* @returns Immutable copy of the registration, or undefined
|
|
48
|
+
*/
|
|
49
|
+
getAgent(agentId: string): AgentRegistration | undefined;
|
|
50
|
+
/**
|
|
51
|
+
* Get all agents currently marked as online.
|
|
52
|
+
*
|
|
53
|
+
* @returns Array of immutable registration copies
|
|
54
|
+
*/
|
|
55
|
+
getActiveAgents(): readonly AgentRegistration[];
|
|
56
|
+
/**
|
|
57
|
+
* Get all registered agents regardless of status.
|
|
58
|
+
*
|
|
59
|
+
* @returns Array of immutable registration copies
|
|
60
|
+
*/
|
|
61
|
+
getAllAgents(): readonly AgentRegistration[];
|
|
62
|
+
/**
|
|
63
|
+
* Identify agents whose last heartbeat exceeds the timeout threshold.
|
|
64
|
+
* Marks them as 'stale' in the internal registry.
|
|
65
|
+
*
|
|
66
|
+
* @param timeoutMs - Maximum allowed milliseconds since last heartbeat
|
|
67
|
+
* @returns Array of agents that are now stale
|
|
68
|
+
*/
|
|
69
|
+
getStaleAgents(timeoutMs: number): readonly AgentRegistration[];
|
|
70
|
+
/**
|
|
71
|
+
* Mark an agent as offline.
|
|
72
|
+
*
|
|
73
|
+
* @param agentId - The agent's unique identifier
|
|
74
|
+
* @returns true if the agent was found and marked offline
|
|
75
|
+
*/
|
|
76
|
+
markOffline(agentId: string): boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Get the count of agents by status.
|
|
79
|
+
*
|
|
80
|
+
* @returns Object with counts for each status
|
|
81
|
+
*/
|
|
82
|
+
getStatusCounts(): Record<AgentStatus, number>;
|
|
83
|
+
/**
|
|
84
|
+
* Get the total number of registered agents.
|
|
85
|
+
*/
|
|
86
|
+
get size(): number;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=agent-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-registry.d.ts","sourceRoot":"","sources":["../src/agent-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EACV,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,EACd,WAAW,EACZ,MAAM,YAAY,CAAC;AAIpB;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiC;IACxD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,SAAS,EAAE,MAAM;IAK7B;;;;;;;OAOG;IACH,aAAa,CAAC,OAAO,EAAE,wBAAwB,GAAG,iBAAiB;IAmCnE;;;;;OAKG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAezC;;;;;;OAMG;IACH,eAAe,CAAC,SAAS,EAAE,cAAc,GAAG,iBAAiB,GAAG,SAAS;IAkBzE;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAMxD;;;;OAIG;IACH,eAAe,IAAI,SAAS,iBAAiB,EAAE;IAM/C;;;;OAIG;IACH,YAAY,IAAI,SAAS,iBAAiB,EAAE;IAO5C;;;;;;OAMG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,iBAAiB,EAAE;IA8B/D;;;;;OAKG;IACH,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAkBrC;;;;OAIG;IACH,eAAe,IAAI,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC;IAc9C;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentRegistry - Manages connected Guard agent registrations
|
|
3
|
+
* AgentRegistry - 管理已連線的 Guard 代理登錄
|
|
4
|
+
*
|
|
5
|
+
* Maintains an internal Map of registered agents, supports heartbeat updates,
|
|
6
|
+
* and detects stale/offline agents. All returned data is immutable copies.
|
|
7
|
+
*
|
|
8
|
+
* @module @panguard-ai/manager/agent-registry
|
|
9
|
+
*/
|
|
10
|
+
import { createLogger } from '@panguard-ai/core';
|
|
11
|
+
import { generateAgentId } from './utils.js';
|
|
12
|
+
const logger = createLogger('panguard-manager:registry');
|
|
13
|
+
/**
|
|
14
|
+
* Registry that tracks all connected Guard agents.
|
|
15
|
+
* Uses immutable return patterns - internal state is never exposed directly.
|
|
16
|
+
*/
|
|
17
|
+
export class AgentRegistry {
|
|
18
|
+
agents;
|
|
19
|
+
maxAgents;
|
|
20
|
+
constructor(maxAgents) {
|
|
21
|
+
this.agents = new Map();
|
|
22
|
+
this.maxAgents = maxAgents;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Register a new Guard agent.
|
|
26
|
+
* Generates a unique agent ID and returns the registration record.
|
|
27
|
+
*
|
|
28
|
+
* @param request - Registration request from the agent
|
|
29
|
+
* @returns Immutable copy of the registration record
|
|
30
|
+
* @throws Error if maximum agent limit is reached
|
|
31
|
+
*/
|
|
32
|
+
registerAgent(request) {
|
|
33
|
+
if (this.agents.size >= this.maxAgents) {
|
|
34
|
+
throw new Error(`Maximum agent limit reached (${this.maxAgents}). ` +
|
|
35
|
+
'Cannot register additional agents.');
|
|
36
|
+
}
|
|
37
|
+
const agentId = generateAgentId();
|
|
38
|
+
const now = new Date().toISOString();
|
|
39
|
+
const registration = {
|
|
40
|
+
agentId,
|
|
41
|
+
hostname: request.hostname,
|
|
42
|
+
platform: {
|
|
43
|
+
os: request.os,
|
|
44
|
+
arch: request.arch,
|
|
45
|
+
ip: request.ip,
|
|
46
|
+
},
|
|
47
|
+
version: request.version,
|
|
48
|
+
registeredAt: now,
|
|
49
|
+
lastHeartbeat: now,
|
|
50
|
+
status: 'online',
|
|
51
|
+
};
|
|
52
|
+
this.agents.set(agentId, registration);
|
|
53
|
+
logger.info(`Agent registered: ${agentId} (${request.hostname}, ${request.os}) / ` +
|
|
54
|
+
`代理已登錄: ${agentId} (${request.hostname}, ${request.os})`);
|
|
55
|
+
return { ...registration, platform: { ...registration.platform } };
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Remove an agent from the registry.
|
|
59
|
+
*
|
|
60
|
+
* @param agentId - The agent's unique identifier
|
|
61
|
+
* @returns true if the agent was found and removed
|
|
62
|
+
*/
|
|
63
|
+
deregisterAgent(agentId) {
|
|
64
|
+
const agent = this.agents.get(agentId);
|
|
65
|
+
if (!agent) {
|
|
66
|
+
logger.warn(`Deregister failed: agent ${agentId} not found`);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
this.agents.delete(agentId);
|
|
70
|
+
logger.info(`Agent deregistered: ${agentId} (${agent.hostname}) / ` +
|
|
71
|
+
`代理已登出: ${agentId} (${agent.hostname})`);
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Update the heartbeat timestamp and metrics for an agent.
|
|
76
|
+
* Creates a new registration record with updated fields (immutable pattern).
|
|
77
|
+
*
|
|
78
|
+
* @param heartbeat - Heartbeat data from the agent
|
|
79
|
+
* @returns Updated registration or undefined if agent not found
|
|
80
|
+
*/
|
|
81
|
+
updateHeartbeat(heartbeat) {
|
|
82
|
+
const existing = this.agents.get(heartbeat.agentId);
|
|
83
|
+
if (!existing) {
|
|
84
|
+
logger.warn(`Heartbeat from unknown agent: ${heartbeat.agentId}`);
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
const updated = {
|
|
88
|
+
...existing,
|
|
89
|
+
platform: { ...existing.platform },
|
|
90
|
+
lastHeartbeat: heartbeat.timestamp,
|
|
91
|
+
status: 'online',
|
|
92
|
+
};
|
|
93
|
+
this.agents.set(heartbeat.agentId, updated);
|
|
94
|
+
return { ...updated, platform: { ...updated.platform } };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get a single agent's registration record.
|
|
98
|
+
*
|
|
99
|
+
* @param agentId - The agent's unique identifier
|
|
100
|
+
* @returns Immutable copy of the registration, or undefined
|
|
101
|
+
*/
|
|
102
|
+
getAgent(agentId) {
|
|
103
|
+
const agent = this.agents.get(agentId);
|
|
104
|
+
if (!agent)
|
|
105
|
+
return undefined;
|
|
106
|
+
return { ...agent, platform: { ...agent.platform } };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get all agents currently marked as online.
|
|
110
|
+
*
|
|
111
|
+
* @returns Array of immutable registration copies
|
|
112
|
+
*/
|
|
113
|
+
getActiveAgents() {
|
|
114
|
+
return Array.from(this.agents.values())
|
|
115
|
+
.filter((a) => a.status === 'online')
|
|
116
|
+
.map((a) => ({ ...a, platform: { ...a.platform } }));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get all registered agents regardless of status.
|
|
120
|
+
*
|
|
121
|
+
* @returns Array of immutable registration copies
|
|
122
|
+
*/
|
|
123
|
+
getAllAgents() {
|
|
124
|
+
return Array.from(this.agents.values()).map((a) => ({
|
|
125
|
+
...a,
|
|
126
|
+
platform: { ...a.platform },
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Identify agents whose last heartbeat exceeds the timeout threshold.
|
|
131
|
+
* Marks them as 'stale' in the internal registry.
|
|
132
|
+
*
|
|
133
|
+
* @param timeoutMs - Maximum allowed milliseconds since last heartbeat
|
|
134
|
+
* @returns Array of agents that are now stale
|
|
135
|
+
*/
|
|
136
|
+
getStaleAgents(timeoutMs) {
|
|
137
|
+
const now = Date.now();
|
|
138
|
+
const staleAgents = [];
|
|
139
|
+
for (const [agentId, agent] of this.agents.entries()) {
|
|
140
|
+
if (agent.status === 'offline')
|
|
141
|
+
continue;
|
|
142
|
+
const lastBeat = new Date(agent.lastHeartbeat).getTime();
|
|
143
|
+
const elapsed = now - lastBeat;
|
|
144
|
+
if (elapsed >= timeoutMs) {
|
|
145
|
+
const updated = {
|
|
146
|
+
...agent,
|
|
147
|
+
platform: { ...agent.platform },
|
|
148
|
+
status: 'stale',
|
|
149
|
+
};
|
|
150
|
+
this.agents.set(agentId, updated);
|
|
151
|
+
staleAgents.push({ ...updated, platform: { ...updated.platform } });
|
|
152
|
+
logger.warn(`Agent ${agentId} (${agent.hostname}) is stale ` +
|
|
153
|
+
`(last heartbeat ${Math.round(elapsed / 1000)}s ago) / ` +
|
|
154
|
+
`代理 ${agentId} (${agent.hostname}) 已過期`);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return staleAgents;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Mark an agent as offline.
|
|
161
|
+
*
|
|
162
|
+
* @param agentId - The agent's unique identifier
|
|
163
|
+
* @returns true if the agent was found and marked offline
|
|
164
|
+
*/
|
|
165
|
+
markOffline(agentId) {
|
|
166
|
+
const existing = this.agents.get(agentId);
|
|
167
|
+
if (!existing)
|
|
168
|
+
return false;
|
|
169
|
+
const updated = {
|
|
170
|
+
...existing,
|
|
171
|
+
platform: { ...existing.platform },
|
|
172
|
+
status: 'offline',
|
|
173
|
+
};
|
|
174
|
+
this.agents.set(agentId, updated);
|
|
175
|
+
logger.info(`Agent marked offline: ${agentId} (${existing.hostname}) / ` +
|
|
176
|
+
`代理已標記為離線: ${agentId}`);
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get the count of agents by status.
|
|
181
|
+
*
|
|
182
|
+
* @returns Object with counts for each status
|
|
183
|
+
*/
|
|
184
|
+
getStatusCounts() {
|
|
185
|
+
const counts = {
|
|
186
|
+
online: 0,
|
|
187
|
+
stale: 0,
|
|
188
|
+
offline: 0,
|
|
189
|
+
};
|
|
190
|
+
for (const agent of this.agents.values()) {
|
|
191
|
+
counts[agent.status]++;
|
|
192
|
+
}
|
|
193
|
+
return counts;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Get the total number of registered agents.
|
|
197
|
+
*/
|
|
198
|
+
get size() {
|
|
199
|
+
return this.agents.size;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=agent-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-registry.js","sourceRoot":"","sources":["../src/agent-registry.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Panguard AI - Manager Package
|
|
3
|
+
* Panguard 安全平台 - Manager 套件
|
|
4
|
+
*
|
|
5
|
+
* Central orchestration node for the distributed Guard agent architecture.
|
|
6
|
+
* Manages agent registration, threat correlation, and policy distribution.
|
|
7
|
+
*
|
|
8
|
+
* 分散式 Guard 代理架構的中央協調節點。
|
|
9
|
+
* 管理代理登錄、威脅關聯和策略分發。
|
|
10
|
+
*
|
|
11
|
+
* @module @panguard-ai/manager
|
|
12
|
+
*/
|
|
13
|
+
export { Manager } from './manager.js';
|
|
14
|
+
export { AgentRegistry } from './agent-registry.js';
|
|
15
|
+
export { ThreatAggregator } from './threat-aggregator.js';
|
|
16
|
+
export { PolicyEngine } from './policy-engine.js';
|
|
17
|
+
export { generateAgentId, generateThreatId, generatePolicyId, generateAuthToken, extractSourceIP, extractFileHash, } from './utils.js';
|
|
18
|
+
export type { AgentStatus, AgentPlatformInfo, AgentRegistration, AgentRegistrationRequest, AgentHeartbeat, ThreatEvent, ThreatReport, AggregatedThreat, CorrelationMatch, ThreatSummary, PolicyRule, PolicyUpdate, ManagerConfig, AgentOverview, ManagerOverview, PolicyBroadcastResult, } from './types.js';
|
|
19
|
+
export { DEFAULT_MANAGER_CONFIG } from './types.js';
|
|
20
|
+
/** Manager package version / Manager 套件版本 */
|
|
21
|
+
export declare const MANAGER_VERSION = "0.2.0";
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGlD,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,EACxB,cAAc,EACd,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,YAAY,EACZ,aAAa,EACb,aAAa,EACb,eAAe,EACf,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,6CAA6C;AAC7C,eAAO,MAAM,eAAe,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Panguard AI - Manager Package
|
|
3
|
+
* Panguard 安全平台 - Manager 套件
|
|
4
|
+
*
|
|
5
|
+
* Central orchestration node for the distributed Guard agent architecture.
|
|
6
|
+
* Manages agent registration, threat correlation, and policy distribution.
|
|
7
|
+
*
|
|
8
|
+
* 分散式 Guard 代理架構的中央協調節點。
|
|
9
|
+
* 管理代理登錄、威脅關聯和策略分發。
|
|
10
|
+
*
|
|
11
|
+
* @module @panguard-ai/manager
|
|
12
|
+
*/
|
|
13
|
+
// Main orchestrator / 主協調器
|
|
14
|
+
export { Manager } from './manager.js';
|
|
15
|
+
// Components / 元件
|
|
16
|
+
export { AgentRegistry } from './agent-registry.js';
|
|
17
|
+
export { ThreatAggregator } from './threat-aggregator.js';
|
|
18
|
+
export { PolicyEngine } from './policy-engine.js';
|
|
19
|
+
// Utilities / 工具函式
|
|
20
|
+
export { generateAgentId, generateThreatId, generatePolicyId, generateAuthToken, extractSourceIP, extractFileHash, } from './utils.js';
|
|
21
|
+
// Constants / 常數
|
|
22
|
+
export { DEFAULT_MANAGER_CONFIG } from './types.js';
|
|
23
|
+
/** Manager package version / Manager 套件版本 */
|
|
24
|
+
export const MANAGER_VERSION = '0.2.0';
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,2BAA2B;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAEvC,kBAAkB;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,mBAAmB;AACnB,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,eAAe,GAChB,MAAM,YAAY,CAAC;AAsBpB,iBAAiB;AACjB,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD,6CAA6C;AAC7C,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
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 type { ManagerConfig, AgentRegistrationRequest, AgentRegistration, AgentHeartbeat, ThreatReport, AggregatedThreat, PolicyUpdate, PolicyRule, ManagerOverview, ThreatSummary, PolicyBroadcastResult } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Manager is the main orchestrator for the distributed Guard architecture.
|
|
16
|
+
*
|
|
17
|
+
* It composes AgentRegistry, ThreatAggregator, and PolicyEngine to provide
|
|
18
|
+
* a unified API for managing the entire fleet of Guard agents.
|
|
19
|
+
*/
|
|
20
|
+
export declare class Manager {
|
|
21
|
+
private readonly config;
|
|
22
|
+
private readonly registry;
|
|
23
|
+
private readonly aggregator;
|
|
24
|
+
private readonly policyEngine;
|
|
25
|
+
private running;
|
|
26
|
+
private startTime;
|
|
27
|
+
private staleCheckTimer;
|
|
28
|
+
private purgeTimer;
|
|
29
|
+
private readonly broadcastQueue;
|
|
30
|
+
constructor(config: ManagerConfig);
|
|
31
|
+
/**
|
|
32
|
+
* Start the Manager service.
|
|
33
|
+
* Begins periodic stale agent checking and threat purging.
|
|
34
|
+
*/
|
|
35
|
+
start(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Stop the Manager service.
|
|
38
|
+
* Clears all periodic timers.
|
|
39
|
+
*/
|
|
40
|
+
stop(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Handle a new agent registration request.
|
|
43
|
+
*
|
|
44
|
+
* @param request - Registration data from the Guard agent
|
|
45
|
+
* @returns Immutable copy of the registration record
|
|
46
|
+
* @throws Error if max agents exceeded
|
|
47
|
+
*/
|
|
48
|
+
handleRegistration(request: AgentRegistrationRequest): AgentRegistration;
|
|
49
|
+
/**
|
|
50
|
+
* Handle a heartbeat from a Guard agent.
|
|
51
|
+
* Updates the agent's status and last-seen timestamp.
|
|
52
|
+
*
|
|
53
|
+
* @param heartbeat - Heartbeat data from the agent
|
|
54
|
+
* @returns Updated registration, or undefined if agent unknown
|
|
55
|
+
*/
|
|
56
|
+
handleHeartbeat(heartbeat: AgentHeartbeat): AgentRegistration | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Handle a threat report from a Guard agent.
|
|
59
|
+
* Ingests threats into the aggregator and checks for cross-agent correlation.
|
|
60
|
+
*
|
|
61
|
+
* @param report - Threat report containing one or more events
|
|
62
|
+
* @returns Array of aggregated threats, with correlation data if detected
|
|
63
|
+
*/
|
|
64
|
+
handleThreatReport(report: ThreatReport): readonly AggregatedThreat[];
|
|
65
|
+
/**
|
|
66
|
+
* Remove an agent from the fleet.
|
|
67
|
+
*
|
|
68
|
+
* @param agentId - The agent's unique identifier
|
|
69
|
+
* @returns true if the agent was found and removed
|
|
70
|
+
*/
|
|
71
|
+
handleDeregistration(agentId: string): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Create and optionally broadcast a new security policy.
|
|
74
|
+
*
|
|
75
|
+
* @param rules - Policy rules to include
|
|
76
|
+
* @param broadcast - Whether to queue broadcast to all active agents
|
|
77
|
+
* @returns The created policy
|
|
78
|
+
*/
|
|
79
|
+
createPolicy(rules: readonly PolicyRule[], broadcast?: boolean): PolicyUpdate;
|
|
80
|
+
/**
|
|
81
|
+
* Queue a policy update for broadcast to all active agents.
|
|
82
|
+
*
|
|
83
|
+
* @param policy - The policy to broadcast
|
|
84
|
+
* @returns Broadcast result with target agent list
|
|
85
|
+
*/
|
|
86
|
+
broadcastPolicy(policy: PolicyUpdate): PolicyBroadcastResult;
|
|
87
|
+
/**
|
|
88
|
+
* Get the active global policy.
|
|
89
|
+
*
|
|
90
|
+
* @returns Active policy or null
|
|
91
|
+
*/
|
|
92
|
+
getActivePolicy(): PolicyUpdate | null;
|
|
93
|
+
/**
|
|
94
|
+
* Get the policy applicable to a specific agent.
|
|
95
|
+
*
|
|
96
|
+
* @param agentId - The agent's unique identifier
|
|
97
|
+
* @returns Policy for the agent, or null
|
|
98
|
+
*/
|
|
99
|
+
getPolicyForAgent(agentId: string): PolicyUpdate | null;
|
|
100
|
+
/**
|
|
101
|
+
* Get pending policy broadcast results.
|
|
102
|
+
*
|
|
103
|
+
* @returns Immutable array of broadcast results
|
|
104
|
+
*/
|
|
105
|
+
getPendingBroadcasts(): readonly PolicyBroadcastResult[];
|
|
106
|
+
/**
|
|
107
|
+
* Check for and handle stale agents.
|
|
108
|
+
* Called periodically by the stale check timer.
|
|
109
|
+
*/
|
|
110
|
+
private checkStaleAgents;
|
|
111
|
+
/**
|
|
112
|
+
* Generate a comprehensive overview for the management dashboard.
|
|
113
|
+
*
|
|
114
|
+
* @returns Immutable manager overview object
|
|
115
|
+
*/
|
|
116
|
+
getOverview(): ManagerOverview;
|
|
117
|
+
/**
|
|
118
|
+
* Get threat summary from the aggregator.
|
|
119
|
+
*
|
|
120
|
+
* @returns Immutable threat summary
|
|
121
|
+
*/
|
|
122
|
+
getThreatSummary(): ThreatSummary;
|
|
123
|
+
/**
|
|
124
|
+
* Get threats reported by a specific agent.
|
|
125
|
+
*
|
|
126
|
+
* @param agentId - The agent's unique identifier
|
|
127
|
+
* @returns Array of aggregated threats
|
|
128
|
+
*/
|
|
129
|
+
getThreatsByAgent(agentId: string): readonly AggregatedThreat[];
|
|
130
|
+
/**
|
|
131
|
+
* Get recent threats across all agents.
|
|
132
|
+
*
|
|
133
|
+
* @param since - Date threshold
|
|
134
|
+
* @returns Array of aggregated threats
|
|
135
|
+
*/
|
|
136
|
+
getRecentThreats(since: Date): readonly AggregatedThreat[];
|
|
137
|
+
/**
|
|
138
|
+
* Get a specific agent's registration.
|
|
139
|
+
*
|
|
140
|
+
* @param agentId - The agent's unique identifier
|
|
141
|
+
* @returns Agent registration or undefined
|
|
142
|
+
*/
|
|
143
|
+
getAgent(agentId: string): AgentRegistration | undefined;
|
|
144
|
+
/**
|
|
145
|
+
* Check if the manager is currently running.
|
|
146
|
+
*/
|
|
147
|
+
isRunning(): boolean;
|
|
148
|
+
/**
|
|
149
|
+
* Get the number of registered agents.
|
|
150
|
+
*/
|
|
151
|
+
getAgentCount(): number;
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EACV,aAAa,EACb,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,EACd,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,UAAU,EACV,eAAe,EAEf,aAAa,EACb,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAIpB;;;;;GAKG;AACH,qBAAa,OAAO;IAClB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAmB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAE5C,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAwC;IAC/D,OAAO,CAAC,UAAU,CAAwC;IAG1D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA0B;gBAE7C,MAAM,EAAE,aAAa;IAsBjC;;;OAGG;IACH,KAAK,IAAI,IAAI;IA6Bb;;;OAGG;IACH,IAAI,IAAI,IAAI;IAsBZ;;;;;;OAMG;IACH,kBAAkB,CAChB,OAAO,EAAE,wBAAwB,GAChC,iBAAiB;IAWpB;;;;;;OAMG;IACH,eAAe,CACb,SAAS,EAAE,cAAc,GACxB,iBAAiB,GAAG,SAAS;IAIhC;;;;;;OAMG;IACH,kBAAkB,CAChB,MAAM,EAAE,YAAY,GACnB,SAAS,gBAAgB,EAAE;IAoB9B;;;;;OAKG;IACH,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAM9C;;;;;;OAMG;IACH,YAAY,CACV,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,SAAS,UAAO,GACf,YAAY;IAcf;;;;;OAKG;IACH,eAAe,CAAC,MAAM,EAAE,YAAY,GAAG,qBAAqB;IAuB5D;;;;OAIG;IACH,eAAe,IAAI,YAAY,GAAG,IAAI;IAItC;;;;;OAKG;IACH,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAIvD;;;;OAIG;IACH,oBAAoB,IAAI,SAAS,qBAAqB,EAAE;IASxD;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAexB;;;;OAIG;IACH,WAAW,IAAI,eAAe;IA6B9B;;;;OAIG;IACH,gBAAgB,IAAI,aAAa;IAIjC;;;;;OAKG;IACH,iBAAiB,CACf,OAAO,EAAE,MAAM,GACd,SAAS,gBAAgB,EAAE;IAI9B;;;;;OAKG;IACH,gBAAgB,CAAC,KAAK,EAAE,IAAI,GAAG,SAAS,gBAAgB,EAAE;IAI1D;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAIxD;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
|