Files

29 lines
2.8 KiB
JavaScript
Raw Permalink Normal View History

import test from 'node:test';
import assert from 'node:assert/strict';
import {mkdtemp,mkdir,copyFile,readFile,writeFile,rm} from 'node:fs/promises';
import {tmpdir} from 'node:os';
import path from 'node:path';
import {createHash} from 'node:crypto';
import {fork} from 'node:child_process';
import {createRequire} from 'node:module';
import {BROKER_RUNTIME} from '../scripts/provision-broker-runtime.mjs';
const {createBrokerSupervisor}=createRequire(import.meta.url)('../apps/browser/broker-supervisor.cjs');
test('actual pinned bundled Node private IPC startup and confirmed terminal shutdown',{skip:process.platform!=='win32'||process.env.SAFETYNET_BROKER_SUPERVISOR_NATIVE!=='1'},async()=>{
const runtime=path.resolve('.runtime/windows/broker/node.exe');
const hash=bytes=>createHash('sha256').update(bytes).digest('hex');
assert.equal(hash(await readFile(runtime)),BROKER_RUNTIME.executableSha256);
const root=await mkdtemp(path.join(tmpdir(),'safetynet-supervisor-'));
let child,exited=false,quarantines=0; const savedOptions=process.env.NODE_OPTIONS; process.env.NODE_OPTIONS="--require C:/safetynet-nonexistent-injection.cjs";
try{
await mkdir(path.join(root,'apps/network-broker'),{recursive:true});await copyFile(runtime,path.join(root,'node.exe'));
const fixture=`'use strict';if(process.version!=='v${BROKER_RUNTIME.version}'||process.env.NODE_OPTIONS||process.env.NODE_PATH||process.env.ELECTRON_RUN_AS_NODE)process.exit(91);process.on('message',m=>{if(m.type==='start')process.send({type:'ready',version:1,generation:m.generation,policyVersion:m.policyVersion,authMode:'basic',sequence:0,port:m.config.brokerPort,credentials:{username:'safetynet-'+ 'a'.repeat(32),password:'b'.repeat(43)}});});setInterval(()=>{},1000);`;
await writeFile(path.join(root,'apps/network-broker/production-entry.cjs'),fixture);
const supervisor=createBrokerSupervisor({resourceRoot:root,verifyPackage:async target=>target===root&&hash(await readFile(path.join(target,'node.exe')))===BROKER_RUNTIME.executableSha256&&await readFile(path.join(target,'apps/network-broker/production-entry.cjs'),'utf8')===fixture,persistAudit:()=>{throw Error();},acceptCertificate:()=>false,onQuarantine:()=>quarantines++,spawn:(...args)=>{assert.equal(args[2].env.NODE_OPTIONS,undefined);child=fork(...args);child.once('exit',()=>{exited=true;});return child;}});
const ready=await supervisor.start({policyVersion:1,port:43871,config:{brokerPort:43871}});assert.equal(ready.port,43871);
await supervisor.close();assert.equal(exited,true);assert.notEqual(child.exitCode===null&&child.signalCode===null,true);assert.equal(quarantines,0);
}finally{
if(savedOptions===undefined)delete process.env.NODE_OPTIONS;else process.env.NODE_OPTIONS=savedOptions;
if(child&&!exited){child.kill('SIGKILL');await new Promise(resolve=>child.once('exit',resolve));}
await rm(root,{recursive:true,force:true});
}
});