101 lines
3.6 KiB
JavaScript
101 lines
3.6 KiB
JavaScript
'use strict';
|
|
|
|
const crypto = require('crypto');
|
|
const agentManager = require('../utils/agent_manager');
|
|
|
|
describe('AgentManager PROTOCOL.md v1.1.0 Compliance', () => {
|
|
let mockWs;
|
|
let sentMessages;
|
|
|
|
beforeEach(() => {
|
|
sentMessages = [];
|
|
mockWs = {
|
|
readyState: 1, // OPEN
|
|
send: jest.fn((msg) => sentMessages.push(JSON.parse(msg))),
|
|
close: jest.fn()
|
|
};
|
|
});
|
|
|
|
test('registers agent and tracks initial connection state', () => {
|
|
const record = agentManager.registerAgent('test-token-123', mockWs, '192.168.1.100');
|
|
expect(record.token).toBe('test-token-123');
|
|
expect(record.ipAddress).toBe('192.168.1.100');
|
|
|
|
const agents = agentManager.getConnectedAgents();
|
|
const found = agents.find(a => a.token === 'test-token-123');
|
|
expect(found).toBeDefined();
|
|
expect(found.isOnline).toBe(true);
|
|
});
|
|
|
|
test('processes discovery payload per PROTOCOL.md v1.1.0 Section 3.1', () => {
|
|
agentManager.registerAgent('test-token-123', mockWs, '192.168.1.100');
|
|
|
|
const discoveryPayload = {
|
|
hostname: 'node-01.local',
|
|
ip_addresses: ['192.168.1.100', '10.0.0.5'],
|
|
os: 'Ubuntu 24.04 LTS',
|
|
kernel: '6.8.0-31-generic',
|
|
cpu: 'AMD EPYC 7763',
|
|
ram_total_gb: 32.0,
|
|
disk_total_gb: 500.0,
|
|
location: 'dc-chicago-rack-4'
|
|
};
|
|
|
|
agentManager.handleDiscovery('test-token-123', discoveryPayload);
|
|
|
|
const agents = agentManager.getConnectedAgents();
|
|
const agent = agents.find(a => a.token === 'test-token-123');
|
|
expect(agent.hostname).toBe('node-01.local');
|
|
expect(agent.discovery.os).toBe('Ubuntu 24.04 LTS');
|
|
expect(agent.discovery.ip_addresses).toEqual(['192.168.1.100', '10.0.0.5']);
|
|
});
|
|
|
|
test('processes telemetry payload per PROTOCOL.md v1.1.0 Section 3.2', () => {
|
|
agentManager.registerAgent('test-token-123', mockWs, '192.168.1.100');
|
|
|
|
const telemetryPayload = {
|
|
cpu_usage_percent: 14.5,
|
|
ram_usage_percent: 42.1,
|
|
disk_usage_percent: 68.0,
|
|
zfs_health: 'ONLINE',
|
|
gpu_usage_percent: -1.0,
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
|
|
agentManager.handleTelemetry('test-token-123', telemetryPayload);
|
|
|
|
const agents = agentManager.getConnectedAgents();
|
|
const agent = agents.find(a => a.token === 'test-token-123');
|
|
expect(agent.telemetry.cpu_usage_percent).toBe(14.5);
|
|
expect(agent.telemetry.zfs_health).toBe('ONLINE');
|
|
});
|
|
|
|
test('responds to heartbeat with heartbeat_ack per Section 3.3', () => {
|
|
agentManager.registerAgent('test-token-123', mockWs, '192.168.1.100');
|
|
|
|
agentManager.handleHeartbeat('test-token-123', { timestamp: new Date().toISOString() }, mockWs);
|
|
|
|
expect(mockWs.send).toHaveBeenCalled();
|
|
const lastMsg = sentMessages[sentMessages.length - 1];
|
|
expect(lastMsg.type).toBe('heartbeat_ack');
|
|
expect(lastMsg.payload.timestamp).toBeDefined();
|
|
});
|
|
|
|
test('canonicalizes payload and signs high-risk commands using Ed25519 per Section 5', () => {
|
|
agentManager.registerAgent('test-token-123', mockWs, '192.168.1.100');
|
|
|
|
const rawPayload = { script: 'uptime', location: 'datacenter' };
|
|
const msg = agentManager.sendCommand('test-token-123', 'arbitrary_bash', rawPayload, true);
|
|
|
|
expect(msg.type).toBe('arbitrary_bash');
|
|
expect(msg.payload.signature).toBeDefined();
|
|
expect(typeof msg.payload.signature).toBe('string');
|
|
|
|
// Verify signature with public key
|
|
const signatureBuffer = Buffer.from(msg.payload.signature, 'base64');
|
|
const canonicalStr = agentManager.canonicalize(rawPayload);
|
|
const isValid = crypto.verify(null, Buffer.from(canonicalStr, 'utf8'), agentManager.publicKeyPem, signatureBuffer);
|
|
expect(isValid).toBe(true);
|
|
});
|
|
});
|