60 lines
3.2 KiB
JavaScript
60 lines
3.2 KiB
JavaScript
'use strict';
|
|
// Proba CLI-ului Control Plane cap la cap (B1 milestone 2), cu CONTROL NEGATIV: un dosar cu cod vulnerabil produce actiunile
|
|
// corecte; un dosar tot-PQ produce plan gol. Isi face singura fixturile intr-un temp si le sterge.
|
|
// node proba-control-plane.mjs -> 0 toate cum trebuia, 1 altfel
|
|
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { execFileSync } from 'node:child_process';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const AICI = path.dirname(fileURLToPath(import.meta.url));
|
|
const CLI = path.join(AICI, 'control-plane.mjs');
|
|
const T = fs.mkdtempSync(path.join(os.tmpdir(), 'cp-proba-'));
|
|
let rele = 0;
|
|
const cer = (n, c) => { console.log(` [${c ? 'OK ' : 'RAU '}] ${n}`); if (!c) rele++; };
|
|
|
|
function ruleaza(dir, scanFile) {
|
|
const args = [CLI, '--code', dir, '--json'];
|
|
if (scanFile) args.push('--scan', scanFile);
|
|
return JSON.parse(execFileSync(process.execPath, args, { encoding: 'utf8' }));
|
|
}
|
|
|
|
try {
|
|
// fixtura vulnerabila
|
|
const v = path.join(T, 'vuln'); fs.mkdirSync(v);
|
|
fs.writeFileSync(path.join(v, 'a.js'), "const c=require('crypto');\nc.createECDH('prime256v1');\nc.createSign('RSA-SHA256');\n");
|
|
// fixtura PQ
|
|
const pq = path.join(T, 'pq'); fs.mkdirSync(pq);
|
|
fs.writeFileSync(path.join(pq, 'b.js'), "// ML-KEM-768 si ML-DSA-65, doar nume\nconst a='ML-KEM-768', s='ML-DSA-65';\n");
|
|
// scanare de proba (readiness): un schimb de cheie clasic pe un host
|
|
const scanF = path.join(T, 'scan.json');
|
|
fs.writeFileSync(scanF, JSON.stringify({ domain: 'client.test', findings: [{ id: 'hndl-exposed', severity: 'high', title: 'No post-quantum key exchange: harvest-now-decrypt-later exposure' }] }));
|
|
|
|
const pv = ruleaza(v);
|
|
const byRef = Object.fromEntries(pv.actions.map((a) => [a.ref.split(':').slice(0, 3).join(':'), a]));
|
|
cer('dosar vulnerabil: 2 folosiri vulnerabile', pv.inventory.quantumVulnerable === 2);
|
|
cer('dosar vulnerabil: 2 actiuni in plan', pv.summary.total === 2);
|
|
const ecdh = pv.actions.find((a) => /ECDH/i.test(a.name || a.asset));
|
|
const rsa = pv.actions.find((a) => /RSA/i.test(a.name || a.asset));
|
|
cer('ECDH -> gateway (schimb de cheie, auto)', ecdh && ecdh.product === 'gateway' && ecdh.method === 'auto-aere');
|
|
cer('RSA -> pki (semnatura, auto)', rsa && rsa.product === 'pki');
|
|
cer('HNDL: ECDH mai urgent decat RSA', ecdh && rsa && ({ CRITICAL: 0, HIGH: 1, MEDIUM: 2 }[ecdh.urgency] < { CRITICAL: 0, HIGH: 1, MEDIUM: 2 }[rsa.urgency]));
|
|
cer('fiecare actiune are locatia (fisier:linie)', pv.actions.every((a) => a.location && /\.js:\d/.test(a.location)));
|
|
|
|
// cu scanare: apare si actiunea de schimb de cheie TLS (gateway, CRITICA)
|
|
const pvs = ruleaza(v, scanF);
|
|
const kex = pvs.actions.find((a) => /tls-kex/.test(a.ref));
|
|
cer('cu scanare: schimbul de cheie TLS e in plan, gateway CRITICA', kex && kex.product === 'gateway' && kex.urgency === 'CRITICAL');
|
|
|
|
// CONTROL NEGATIV: dosar tot-PQ -> 0 vulnerabile, plan gol
|
|
const ppq = ruleaza(pq);
|
|
cer('CONTROL: dosar tot-PQ -> 0 vulnerabile', ppq.inventory.quantumVulnerable === 0);
|
|
cer('CONTROL: dosar tot-PQ -> plan gol', ppq.summary.total === 0);
|
|
} finally {
|
|
fs.rmSync(T, { recursive: true, force: true });
|
|
}
|
|
console.log(`\nB1 control-plane CLI: ${9 - rele}/9 cum trebuia`);
|
|
process.exit(rele ? 1 : 0);
|