Skip to content

Commit 595b0a2

Browse files
AndrewAndrew
authored andcommitted
adjusted PolicyEngine
1 parent 0dc5aea commit 595b0a2

File tree

1 file changed

+97
-8
lines changed

1 file changed

+97
-8
lines changed

src/PolicyEngine.js

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,93 @@ class PolicyEngine {
4646

4747
/**
4848
* Build common headers for API requests
49+
* Includes machine identification for first-time registration
4950
* @returns {Object}
5051
*/
5152
buildApiHeaders() {
5253
const authToken = this.configManager.get('authToken');
54+
const agentId = this.configManager.get('agentId');
55+
56+
// Get machine ID for first-time registration
57+
const machineId = this.getMachineId();
58+
const hostname = require('os').hostname();
59+
5360
return {
5461
'Authorization': `Bearer ${authToken}`,
5562
'Content-Type': 'application/json',
5663
'X-Agent-Version': this.getAgentVersion(),
57-
'X-Agent-Platform': process.platform
64+
'X-Agent-Platform': process.platform,
65+
'X-Machine-Id': machineId,
66+
'X-Hostname': hostname,
67+
'X-Agent-Id': agentId || ''
5868
};
5969
}
6070

71+
/**
72+
* Get or generate a stable machine ID
73+
* Uses platform-specific unique identifiers
74+
* @returns {string}
75+
*/
76+
getMachineId() {
77+
// Check if we have a cached machine ID
78+
let machineId = this.configManager.get('machineId');
79+
if (machineId) return machineId;
80+
81+
// Generate machine ID from system info
82+
const os = require('os');
83+
const crypto = require('crypto');
84+
85+
// Create a hash from stable system properties
86+
const components = [
87+
os.hostname(),
88+
os.platform(),
89+
os.arch(),
90+
os.cpus()[0]?.model || 'unknown'
91+
];
92+
93+
// Add network interface MACs for uniqueness
94+
const networkInterfaces = os.networkInterfaces();
95+
for (const iface of Object.values(networkInterfaces)) {
96+
for (const addr of iface) {
97+
if (!addr.internal && addr.mac && addr.mac !== '00:00:00:00:00:00') {
98+
components.push(addr.mac);
99+
break; // Only use first non-internal MAC
100+
}
101+
}
102+
}
103+
104+
machineId = crypto.createHash('sha256')
105+
.update(components.join(':'))
106+
.digest('hex')
107+
.substring(0, 32);
108+
109+
// Cache the machine ID
110+
this.configManager.set('machineId', machineId);
111+
this.logger.info('Generated machine ID', { machineId });
112+
113+
return machineId;
114+
}
115+
116+
/**
117+
* Handle JWT upgrade from parent
118+
* When parent returns a new JWT token, store it for future requests
119+
* @param {Response} response - Fetch response object
120+
*/
121+
handleTokenUpgrade(response) {
122+
const newToken = response.headers.get('X-Agent-Token');
123+
const newAgentId = response.headers.get('X-Agent-Id');
124+
125+
if (newToken) {
126+
this.configManager.set('authToken', newToken);
127+
this.logger.info('Received and stored new auth token from parent');
128+
}
129+
130+
if (newAgentId) {
131+
this.configManager.set('agentId', newAgentId);
132+
this.logger.info('Received and stored new agent ID from parent', { agentId: newAgentId });
133+
}
134+
}
135+
61136
/**
62137
* Load policies from configuration cache
63138
*/
@@ -295,12 +370,15 @@ class PolicyEngine {
295370
}
296371

297372
try {
298-
// Use common headers with X-Agent-Version
299-
const response = await fetch(`${parentApiUrl}/api/agents/${agentId}/policies`, {
373+
// Use common headers with machine info for auto-registration
374+
const response = await fetch(`${parentApiUrl}/api/agent/policies`, {
300375
method: 'GET',
301376
headers: this.buildApiHeaders()
302377
});
303378

379+
// Check for token upgrade (first-time registration)
380+
this.handleTokenUpgrade(response);
381+
304382
if (!response.ok) {
305383
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
306384
}
@@ -365,14 +443,19 @@ class PolicyEngine {
365443
offlineDurationSeconds: Math.round(offlineDuration / 1000)
366444
});
367445

368-
await fetch(`${parentApiUrl}/api/agents/${agentId}/offline-recovery`, {
446+
const response = await fetch(`${parentApiUrl}/api/agent/heartbeat`, {
369447
method: 'POST',
370448
headers: this.buildApiHeaders(),
371449
body: JSON.stringify({
372-
offlineDuration,
373-
recoveredAt: Date.now()
450+
metadata: {
451+
offlineRecovery: true,
452+
offlineDuration,
453+
recoveredAt: Date.now()
454+
}
374455
})
375456
});
457+
// Handle token upgrade
458+
this.handleTokenUpgrade(response);
376459
} catch (error) {
377460
// Non-critical - log and continue
378461
this.logger.warn('Failed to report offline recovery', {
@@ -422,6 +505,9 @@ class PolicyEngine {
422505
})
423506
});
424507

508+
// Handle token upgrade
509+
this.handleTokenUpgrade(response);
510+
425511
if (response.ok) {
426512
// Clear synced data
427513
this.pluginExtensionManager.clearQueuedData();
@@ -469,13 +555,16 @@ class PolicyEngine {
469555
action: 'terminated'
470556
};
471557

472-
// Use common headers with X-Agent-Version
473-
const response = await fetch(`${parentApiUrl}/api/violations`, {
558+
// Use common headers with machine info
559+
const response = await fetch(`${parentApiUrl}/api/agent/violations`, {
474560
method: 'POST',
475561
headers: this.buildApiHeaders(),
476562
body: JSON.stringify(violation)
477563
});
478564

565+
// Handle token upgrade
566+
this.handleTokenUpgrade(response);
567+
479568
if (!response.ok) {
480569
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
481570
}

0 commit comments

Comments
 (0)