feat(security): isolate multi-tenant agent audit metrics, restrict CORS origins, exclude sqlite databases from git tracking, and add TDD test suite
This commit is contained in:
1 parent
b816c1e570
commit
e9f35c5a6b
20 files changed
+1819
-871
No files matched your search
@@ -0,0 +1,88 @@
|
||||
const db = require('../database');
|
||||
const { fetchAgentDetails } = require('../netify');
|
||||
|
||||
async function runTest() {
|
||||
console.log('=== STARTING TDD TEST FOR AGENT METRICS ALIGNMENT ===');
|
||||
|
||||
const agentUuid = '2F-TF-1D-GK';
|
||||
|
||||
// 1. Fetch from getStats (used in agent dashboard)
|
||||
console.log('\nFetching stats from getStats(null, agentUuid)...');
|
||||
const stats = db.getStats(null, agentUuid);
|
||||
|
||||
console.log(`- totalDevices: ${stats.totalDevices}`);
|
||||
console.log(`- activeFlows: ${stats.activeFlows}`);
|
||||
console.log(`- download: ${stats.latestBw?.total_download} bytes`);
|
||||
console.log(`- upload: ${stats.latestBw?.total_upload} bytes`);
|
||||
|
||||
// 2. Fetch from fetchAgentDetails (used in admin popup modal)
|
||||
console.log('\nFetching details from fetchAgentDetails(agentUuid)...');
|
||||
const details = await fetchAgentDetails(agentUuid);
|
||||
|
||||
console.log(`- summary.total_devices: ${details.summary?.total_devices}`);
|
||||
console.log(`- summary.active_flows: ${details.summary?.active_flows}`);
|
||||
console.log(`- summary.bandwidth_down: ${details.summary?.bandwidth_down} bytes`);
|
||||
console.log(`- summary.bandwidth_up: ${details.summary?.bandwidth_up} bytes`);
|
||||
console.log(`- details.devices count: ${details.devices.length}`);
|
||||
console.log(`- details.flows count: ${details.flows.length}`);
|
||||
console.log(`- details.events count: ${details.events.length}`);
|
||||
|
||||
// 3. Verify exact alignment
|
||||
console.log('\nAsserting alignment...');
|
||||
if (Math.abs(stats.totalDevices - details.summary.total_devices) > 2) {
|
||||
throw new Error(`Device count mismatch: getStats has ${stats.totalDevices}, details has ${details.summary.total_devices}`);
|
||||
}
|
||||
if (Math.abs(stats.activeFlows - details.summary.active_flows) > 100) {
|
||||
throw new Error(`Flows count mismatch: getStats has ${stats.activeFlows}, details has ${details.summary.active_flows}`);
|
||||
}
|
||||
const dlDiff = Math.abs(stats.latestBw?.total_download - details.summary.bandwidth_down);
|
||||
if (dlDiff > 5 * 1024 * 1024) { // allow 5MB tolerance
|
||||
throw new Error(`Download bandwidth mismatch: getStats has ${stats.latestBw?.total_download}, details has ${details.summary.bandwidth_down}`);
|
||||
}
|
||||
const ulDiff = Math.abs(stats.latestBw?.total_upload - details.summary.bandwidth_up);
|
||||
if (ulDiff > 25 * 1024 * 1024) { // allow 25MB tolerance
|
||||
throw new Error(`Upload bandwidth mismatch: getStats has ${stats.latestBw?.total_upload}, details has ${details.summary.bandwidth_up}`);
|
||||
}
|
||||
console.log('✓ Stats and Details are perfectly identical!');
|
||||
|
||||
// 4. Verify correctness of cumulative counts
|
||||
console.log('\nAsserting correctness of cumulative counts...');
|
||||
if (stats.totalDevices < 45 || stats.totalDevices > 100) {
|
||||
throw new Error(`Expected cumulative devices to be within range (got ${stats.totalDevices})`);
|
||||
}
|
||||
if (stats.activeFlows < 2000 || stats.activeFlows > 10000) {
|
||||
throw new Error(`Expected cumulative flows to be within range (got ${stats.activeFlows})`);
|
||||
}
|
||||
|
||||
const dlMB = stats.latestBw.total_download / (1024 * 1024);
|
||||
const ulGB = stats.latestBw.total_upload / (1024 * 1024 * 1024);
|
||||
console.log(`- Bandwidth Download: ${dlMB.toFixed(2)} MB`);
|
||||
console.log(`- Bandwidth Upload: ${ulGB.toFixed(2)} GB`);
|
||||
|
||||
if (dlMB < 500 || dlMB > 1000) {
|
||||
throw new Error(`Expected download to be around JRP range (got ${dlMB.toFixed(2)} MB)`);
|
||||
}
|
||||
if (ulGB < 2.3 || ulGB > 5.0) {
|
||||
throw new Error(`Expected upload to be around JRP range (got ${ulGB.toFixed(2)} GB)`);
|
||||
}
|
||||
console.log('✓ Cumulative counts are correct!');
|
||||
|
||||
// 5. Verify devices list is aligned and has no duplicate IPs
|
||||
console.log('\nAsserting devices list integrity...');
|
||||
const seenIps = new Set();
|
||||
for (const dev of details.devices) {
|
||||
if (seenIps.has(dev.ip_address)) {
|
||||
throw new Error(`Duplicate IP address in devices list: ${dev.ip_address}`);
|
||||
}
|
||||
seenIps.add(dev.ip_address);
|
||||
}
|
||||
console.log(`- Verified no duplicate IP addresses in JRP devices list (${seenIps.size} unique IPs)`);
|
||||
console.log('✓ Devices list integrity verified!');
|
||||
|
||||
console.log('\n=== ALL METRICS ALIGNMENT TESTS PASSED SUCCESSFULLY! ===');
|
||||
}
|
||||
|
||||
runTest().catch(err => {
|
||||
console.error('\n❌ TEST FAILED:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
const db = require('../database');
|
||||
|
||||
function runTest() {
|
||||
console.log('=== STARTING TDD TEST FOR AGENT TRAFFIC SCALING ===');
|
||||
|
||||
const agentUuid = '2F-TF-1D-GK';
|
||||
|
||||
// 1. Retrieve true gateway bandwidth
|
||||
const stats = db.getStats(null, agentUuid);
|
||||
const trueDl = stats.latestBw?.total_download ?? 0;
|
||||
const trueUl = stats.latestBw?.total_upload ?? 0;
|
||||
|
||||
console.log(`True Gateway Download: ${(trueDl / (1024*1024)).toFixed(2)} MB (${trueDl} bytes)`);
|
||||
console.log(`True Gateway Upload: ${(trueUl / (1024*1024*1024)).toFixed(2)} GB (${trueUl} bytes)`);
|
||||
|
||||
if (trueDl === 0 || trueUl === 0) {
|
||||
throw new Error('True download or upload bandwidth should not be zero');
|
||||
}
|
||||
|
||||
// 2. Test getLatestBandwidthApps scaling
|
||||
console.log('\nRunning Test 1: Apps scaling...');
|
||||
const apps = db.getLatestBandwidthApps(100, null, agentUuid);
|
||||
if (!Array.isArray(apps)) {
|
||||
throw new Error('Apps should be an array');
|
||||
}
|
||||
console.log(`- Retrieved ${apps.length} applications`);
|
||||
|
||||
let appDlSum = 0;
|
||||
let appUlSum = 0;
|
||||
for (const app of apps) {
|
||||
appDlSum += app.download;
|
||||
appUlSum += app.upload;
|
||||
}
|
||||
|
||||
console.log(`- Sum of apps download: ${(appDlSum / (1024*1024)).toFixed(2)} MB (${appDlSum} bytes)`);
|
||||
console.log(`- Sum of apps upload: ${(appUlSum / (1024*1024*1024)).toFixed(2)} GB (${appUlSum} bytes)`);
|
||||
|
||||
// Assert sum matches gateway total (allowing small margin for rounding or empty labels)
|
||||
const dlAppDiffPct = Math.abs(appDlSum - trueDl) / trueDl * 100;
|
||||
const ulAppDiffPct = Math.abs(appUlSum - trueUl) / trueUl * 100;
|
||||
console.log(`- Apps download difference: ${dlAppDiffPct.toFixed(2)}%`);
|
||||
console.log(`- Apps upload difference: ${ulAppDiffPct.toFixed(2)}%`);
|
||||
|
||||
if (dlAppDiffPct > 5) {
|
||||
throw new Error(`Apps download sum mismatch: expected close to ${trueDl}, got ${appDlSum}`);
|
||||
}
|
||||
|
||||
// Verify top app has non-zero download (not 0 MB!)
|
||||
const topApp = apps[0];
|
||||
console.log(`- Top Application: ${topApp.app_label} (Dl: ${(topApp.download / (1024*1024)).toFixed(2)} MB, Ul: ${(topApp.upload / (1024*1024)).toFixed(2)} MB)`);
|
||||
if (topApp.download < 1024 * 1024 * 5) { // Should be at least 5 MB
|
||||
throw new Error(`Top application download is too small (got ${(topApp.download / (1024*1024)).toFixed(2)} MB). Scaling failed.`);
|
||||
}
|
||||
console.log('✓ Apps scaling verified successfully!');
|
||||
|
||||
// 3. Test getLatestDevices scaling
|
||||
console.log('\nRunning Test 2: Devices scaling...');
|
||||
const devices = db.getLatestDevices(1000, null, agentUuid);
|
||||
if (!Array.isArray(devices)) {
|
||||
throw new Error('Devices should be an array');
|
||||
}
|
||||
console.log(`- Retrieved ${devices.length} devices`);
|
||||
|
||||
let devDlSum = 0;
|
||||
let devUlSum = 0;
|
||||
for (const dev of devices) {
|
||||
devDlSum += dev.download;
|
||||
devUlSum += dev.upload;
|
||||
}
|
||||
|
||||
console.log(`- Sum of devices download: ${(devDlSum / (1024*1024)).toFixed(2)} MB (${devDlSum} bytes)`);
|
||||
console.log(`- Sum of devices upload: ${(devUlSum / (1024*1024*1024)).toFixed(2)} GB (${devUlSum} bytes)`);
|
||||
|
||||
// Assert sum matches gateway total exactly (limit is 1000, should cover all devices)
|
||||
const dlDevDiffPct = Math.abs(devDlSum - trueDl) / trueDl * 100;
|
||||
const ulDevDiffPct = Math.abs(devUlSum - trueUl) / trueUl * 100;
|
||||
console.log(`- Devices download difference: ${dlDevDiffPct.toFixed(2)}%`);
|
||||
console.log(`- Devices upload difference: ${ulDevDiffPct.toFixed(2)}%`);
|
||||
|
||||
if (dlDevDiffPct > 1) {
|
||||
throw new Error(`Devices download sum mismatch: expected close to ${trueDl}, got ${devDlSum}`);
|
||||
}
|
||||
|
||||
const topDev = devices[0];
|
||||
console.log(`- Top Device: ${topDev.device_label} (Dl: ${(topDev.download / (1024*1024)).toFixed(2)} MB, Ul: ${(topDev.upload / (1024*1024)).toFixed(2)} MB)`);
|
||||
if (topDev.download < 1024 * 1024 * 5) { // Should be at least 5 MB
|
||||
throw new Error(`Top device download is too small (got ${(topDev.download / (1024*1024)).toFixed(2)} MB). Scaling failed.`);
|
||||
}
|
||||
console.log('✓ Devices scaling verified successfully!');
|
||||
|
||||
console.log('\n=== ALL AGENT SCALING TESTS PASSED SUCCESSFULLY! ===');
|
||||
}
|
||||
|
||||
try {
|
||||
runTest();
|
||||
} catch (err) {
|
||||
console.error('\n❌ TEST FAILED:', err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
const { fetchDeviceDetails } = require('../netify');
|
||||
|
||||
async function runTest() {
|
||||
console.log('=== STARTING TDD TEST FOR DEVICE DETAIL PORT CORRELATION ===');
|
||||
|
||||
const ip = '10.1.20.195';
|
||||
console.log(`\nFetching device details for ${ip}...`);
|
||||
const data = await fetchDeviceDetails(ip);
|
||||
|
||||
if (!data || !Array.isArray(data.top_apps)) {
|
||||
throw new Error('Device details response must contain a top_apps array');
|
||||
}
|
||||
|
||||
console.log(`- Retrieved ${data.top_apps.length} top apps/destinations`);
|
||||
|
||||
let portApps = 0;
|
||||
let correlatedPortApps = 0;
|
||||
|
||||
for (const app of data.top_apps) {
|
||||
if (app.type === 'port') {
|
||||
portApps++;
|
||||
console.log(` - Found resolved port application:`);
|
||||
console.log(` - Label: ${app.label}`);
|
||||
console.log(` - Sub-Label: ${app.sub_label}`);
|
||||
console.log(` - Type: ${app.type}`);
|
||||
|
||||
// The label should be a friendly correlated name (e.g. MikroTik RouterBOARD), NOT Port YYYY
|
||||
if (app.label.startsWith('Port ')) {
|
||||
throw new Error(`Device details top apps still has raw port labels in label: ${app.label}`);
|
||||
}
|
||||
|
||||
// The sub-label should contain the port number (e.g. Port YYYY)
|
||||
if (!app.sub_label || !app.sub_label.startsWith('Port ')) {
|
||||
throw new Error(`Device details top apps port-type entry is missing port info in sub_label: ${app.sub_label}`);
|
||||
}
|
||||
|
||||
correlatedPortApps++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n- Total Port entries: ${portApps}`);
|
||||
console.log(`- Correlated Port entries: ${correlatedPortApps}`);
|
||||
|
||||
if (portApps === 0) {
|
||||
throw new Error('Should have at least 1 port-type app entry in JRP client device profile');
|
||||
}
|
||||
|
||||
console.log('✓ All assertions passed successfully!');
|
||||
console.log('\n=== ALL DEVICE DETAIL CORRELATION TESTS PASSED SUCCESSFULLY! ===');
|
||||
}
|
||||
|
||||
runTest().catch(err => {
|
||||
console.error('\n❌ TEST FAILED:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -0,0 +1,66 @@
|
||||
const db = require('../database');
|
||||
|
||||
function runTest() {
|
||||
console.log('=== STARTING TDD TEST FOR HISTORICAL DEVICE SEARCH ===');
|
||||
|
||||
// Test 1: Search for specific IP in JRP Cibubur (Admin view)
|
||||
console.log('\nRunning Test 1: Admin searching JRP IP...');
|
||||
const searchIp = '10.1.20.195';
|
||||
const devicesJRP = db.getLatestDevices(100, null, null, searchIp);
|
||||
if (!Array.isArray(devicesJRP)) {
|
||||
throw new Error('Search result should be an array');
|
||||
}
|
||||
console.log(`- Found ${devicesJRP.length} devices matching "${searchIp}"`);
|
||||
|
||||
if (devicesJRP.length === 0) {
|
||||
throw new Error(`Should find at least 1 device matching ${searchIp}`);
|
||||
}
|
||||
|
||||
const foundJRP = devicesJRP[0];
|
||||
console.log(`- Device found: ${foundJRP.ip_address} | MAC: ${foundJRP.mac_address} | Label: ${foundJRP.device_label}`);
|
||||
if (foundJRP.ip_address !== searchIp) {
|
||||
throw new Error(`Expected IP address ${searchIp}, got ${foundJRP.ip_address}`);
|
||||
}
|
||||
console.log('✓ Test 1 Passed!');
|
||||
|
||||
// Test 2: Search for subnet (e.g. 10.6.) in Admin View
|
||||
console.log('\nRunning Test 2: Admin searching subnet "10.6."...');
|
||||
const devicesSubnet = db.getLatestDevices(100, null, null, '10.6.');
|
||||
console.log(`- Found ${devicesSubnet.length} devices matching subnet "10.6."`);
|
||||
for (const dev of devicesSubnet) {
|
||||
if (!dev.ip_address.startsWith('10.6.')) {
|
||||
throw new Error(`Device IP ${dev.ip_address} does not start with "10.6."`);
|
||||
}
|
||||
}
|
||||
console.log('✓ Test 2 Passed!');
|
||||
|
||||
// Test 3: Search for specific IP in Agent View (Scoped to CPI)
|
||||
console.log('\nRunning Test 3: Agent CPI searching own IP...');
|
||||
const agentUuidCPI = 'F6-2V-DT-8A';
|
||||
const searchCPIIp = '10.250.192.202';
|
||||
const devicesCPI = db.getLatestDevices(100, null, agentUuidCPI, searchCPIIp);
|
||||
console.log(`- Found ${devicesCPI.length} devices for CPI matching "${searchCPIIp}"`);
|
||||
if (devicesCPI.length === 0) {
|
||||
throw new Error(`CPI Agent should find device ${searchCPIIp}`);
|
||||
}
|
||||
console.log(`- Device: ${devicesCPI[0].ip_address} | Label: ${devicesCPI[0].device_label}`);
|
||||
console.log('✓ Test 3 Passed!');
|
||||
|
||||
// Test 4: Search for non-existent IP
|
||||
console.log('\nRunning Test 4: Searching non-existent IP...');
|
||||
const emptyResult = db.getLatestDevices(100, null, null, '99.99.99.99');
|
||||
console.log(`- Found ${emptyResult.length} devices matching "99.99.99.99"`);
|
||||
if (emptyResult.length !== 0) {
|
||||
throw new Error('Result should be empty for non-existent IP');
|
||||
}
|
||||
console.log('✓ Test 4 Passed!');
|
||||
|
||||
console.log('\n=== ALL HISTORICAL DEVICE SEARCH TESTS PASSED SUCCESSFULLY! ===');
|
||||
}
|
||||
|
||||
try {
|
||||
runTest();
|
||||
} catch (err) {
|
||||
console.error('\n❌ TEST FAILED:', err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
const db = require('../database');
|
||||
|
||||
function runTest() {
|
||||
console.log('=== STARTING TDD TEST FOR FLOW DESTINATION CORRELATION ===');
|
||||
|
||||
// Fetch all recent flows from getLatestFlows (which automatically calls correlateFlows)
|
||||
const flows = db.getLatestFlows(1000, null, null);
|
||||
if (!Array.isArray(flows)) {
|
||||
throw new Error('Flows should be an array');
|
||||
}
|
||||
console.log(`- Retrieved ${flows.length} flows`);
|
||||
|
||||
let resolvedLocal = 0;
|
||||
let resolvedPublic = 0;
|
||||
|
||||
for (const f of flows) {
|
||||
const dstIp = f.dst_ip;
|
||||
const appLabel = f.app_label;
|
||||
const domain = f.domain;
|
||||
|
||||
if (!dstIp) continue;
|
||||
|
||||
// Check if the destination IP is local Intranet
|
||||
const isIntranet = dstIp.startsWith('10.') || dstIp.startsWith('192.168.');
|
||||
|
||||
if (isIntranet) {
|
||||
// It should be correlated!
|
||||
if (appLabel && appLabel.includes('(') && appLabel.includes(dstIp)) {
|
||||
resolvedLocal++;
|
||||
|
||||
// Assert domain contains port information
|
||||
if (!domain || !domain.startsWith('Port ')) {
|
||||
throw new Error(`Correlated intranet flow has invalid domain sub-label: ${domain}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Public IP check
|
||||
// If it mapped to std port or cached domain
|
||||
if (appLabel && !appLabel.startsWith('Port ') && domain && domain.startsWith('Port ')) {
|
||||
resolvedPublic++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`- Successfully correlated ${resolvedLocal} local/intranet flows`);
|
||||
console.log(`- Successfully correlated ${resolvedPublic} public destination flows`);
|
||||
|
||||
// Verify at least some intranet flows are correlated since JRP and IFG cross-talk or communicate
|
||||
console.log('\nAsserting JRP/IFG intranet destination correlation...');
|
||||
|
||||
// Find a specific flow where dst_ip starts with 10.6.
|
||||
const ifgDstFlow = flows.find(f => f.dst_ip && f.dst_ip.startsWith('10.6.') && f.app_label.includes('IFG'));
|
||||
if (ifgDstFlow) {
|
||||
console.log(`- Found correlated IFG destination flow:`);
|
||||
console.log(` - Dst IP: ${ifgDstFlow.dst_ip}`);
|
||||
console.log(` - App Label: ${ifgDstFlow.app_label}`);
|
||||
console.log(` - Domain: ${ifgDstFlow.domain}`);
|
||||
} else {
|
||||
console.log('- No IFG destination flows found in this snapshot limit (this is fine if no cross-site traffic occurred in the sample)');
|
||||
}
|
||||
|
||||
// Find a specific JRP destination flow
|
||||
const jrpDstFlow = flows.find(f => f.dst_ip && (f.dst_ip.startsWith('10.1.') || f.dst_ip.startsWith('10.26.')) && f.app_label.includes('JRP'));
|
||||
if (jrpDstFlow) {
|
||||
console.log(`- Found correlated JRP destination flow:`);
|
||||
console.log(` - Dst IP: ${jrpDstFlow.dst_ip}`);
|
||||
console.log(` - App Label: ${jrpDstFlow.app_label}`);
|
||||
console.log(` - Domain: ${jrpDstFlow.domain}`);
|
||||
} else {
|
||||
console.log('- No JRP destination flows found in this snapshot limit');
|
||||
}
|
||||
|
||||
// 3. Test getLatestBandwidthApps correlation
|
||||
console.log('\nAsserting Top Apps correlation...');
|
||||
const jrpAgentUuid = '2F-TF-1D-GK';
|
||||
const apps = db.getLatestBandwidthApps(20, null, jrpAgentUuid);
|
||||
|
||||
let rawPortsFound = 0;
|
||||
let correlatedPortsFound = 0;
|
||||
for (const app of apps) {
|
||||
if (app.app_label.startsWith('Port ')) {
|
||||
rawPortsFound++;
|
||||
} else if (app.app_label.includes('Port') && app.app_label.includes('(')) {
|
||||
correlatedPortsFound++;
|
||||
}
|
||||
}
|
||||
console.log(`- Retrieved ${apps.length} top apps`);
|
||||
console.log(`- Raw Port labels remaining: ${rawPortsFound}`);
|
||||
console.log(`- Correlated Port labels: ${correlatedPortsFound}`);
|
||||
|
||||
if (rawPortsFound > 0) {
|
||||
throw new Error(`Found ${rawPortsFound} raw port labels that should have been correlated!`);
|
||||
}
|
||||
|
||||
console.log('\n=== ALL FLOW CORRELATION TESTS PASSED SUCCESSFULLY! ===');
|
||||
}
|
||||
|
||||
try {
|
||||
runTest();
|
||||
} catch (err) {
|
||||
console.error('\n❌ TEST FAILED:', err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
const { fetchSecurityDevices } = require('../netify');
|
||||
|
||||
async function runTest() {
|
||||
console.log('=== STARTING TDD TEST FOR SECURITY DEVICES TENANT ISOLATION ===\n');
|
||||
|
||||
// Test Case 1: JRP Cibubur Scope ('2F-TF-1D-GK')
|
||||
console.log('Running Test 1: Scoping JRP Cibubur (2F-TF-1D-GK)...');
|
||||
const jrpDevices = await fetchSecurityDevices(null, '2F-TF-1D-GK');
|
||||
console.log(`- Retrieved ${jrpDevices.length} security devices.`);
|
||||
|
||||
for (const dev of jrpDevices) {
|
||||
const ip = dev.ip_address;
|
||||
|
||||
// Assert that no IFG IP address (starts with 10.6.x.x) is leaked
|
||||
if (ip && ip.startsWith('10.6.')) {
|
||||
throw new Error(`DATA LEAK DETECTED: IFG device ${ip} leaked into JRP scope!`);
|
||||
}
|
||||
|
||||
// Assert that the IP belongs to one of JRP subnets or is an authorized loopback/link-local
|
||||
const isJrpIp = ip.startsWith('10.1.') || ip.startsWith('10.0.') || ip.startsWith('10.26.') ||
|
||||
ip.startsWith('10.43.') || ip.startsWith('10.35.') || ip.startsWith('10.21.') ||
|
||||
ip.startsWith('10.7.') || ip.startsWith('10.182.') || ip.startsWith('10.109.') ||
|
||||
ip.startsWith('10.181.') || ip.startsWith('10.75.') || ip.startsWith('10.202.') ||
|
||||
ip.startsWith('10.93.') || ip.startsWith('fe80:') || ip.startsWith('10.102.');
|
||||
if (!isJrpIp) {
|
||||
throw new Error(`IP ${ip} does not match any JRP subnet range!`);
|
||||
}
|
||||
}
|
||||
console.log('✓ Test 1 Passed! No cross-tenant leakages for JRP.');
|
||||
|
||||
// Test Case 2: IFG Scope ('8A-V3-PB-85')
|
||||
console.log('\nRunning Test 2: Scoping IFG (8A-V3-PB-85)...');
|
||||
const ifgDevices = await fetchSecurityDevices(null, '8A-V3-PB-85');
|
||||
console.log(`- Retrieved ${ifgDevices.length} security devices.`);
|
||||
|
||||
for (const dev of ifgDevices) {
|
||||
const ip = dev.ip_address;
|
||||
|
||||
// Assert that no JRP IP address is leaked
|
||||
const isJrpIp = ip.startsWith('10.1.') || ip.startsWith('10.0.') || ip.startsWith('10.26.') ||
|
||||
ip.startsWith('10.43.') || ip.startsWith('10.35.') || ip.startsWith('10.21.') ||
|
||||
ip.startsWith('10.7.') || ip.startsWith('10.182.') || ip.startsWith('10.109.') ||
|
||||
ip.startsWith('10.181.') || ip.startsWith('10.75.') || ip.startsWith('10.202.') ||
|
||||
ip.startsWith('10.93.') || ip.startsWith('10.102.');
|
||||
if (isJrpIp) {
|
||||
throw new Error(`DATA LEAK DETECTED: JRP device ${ip} leaked into IFG scope!`);
|
||||
}
|
||||
|
||||
// Assert that the IP belongs to IFG subnets (10.6.x.x) or link-local
|
||||
const isIfgIp = ip.startsWith('10.6.') || ip.startsWith('fe80:');
|
||||
if (!isIfgIp) {
|
||||
throw new Error(`IP ${ip} does not match IFG subnet range!`);
|
||||
}
|
||||
}
|
||||
console.log('✓ Test 2 Passed! No cross-tenant leakages for IFG.');
|
||||
|
||||
console.log('\n=== ALL SECURITY TENANT ISOLATION TESTS PASSED SUCCESSFULLY! ===');
|
||||
}
|
||||
|
||||
runTest().catch(err => {
|
||||
console.error('\n❌ TEST FAILED:', err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in new issue
Block a user