41 lines
2.9 KiB
JavaScript
41 lines
2.9 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import {createRequire} from 'node:module';
|
|
import {X509Certificate} from 'node:crypto';
|
|
import https from 'node:https';
|
|
const require=createRequire(import.meta.url);
|
|
const {createSessionCertificates}=require('../apps/network-broker/tls-certificates.cjs');
|
|
test('session leaf has exact SAN, bounded lifetime, valid signature and no CA authority',async()=>{
|
|
const issuer=await createSessionCertificates({current:()=>true,authorized:()=>true});
|
|
try{for(const authority of ['example.com:443','127.0.0.1:443','[::1]:443','[::ffff:c000:201]:443']){
|
|
const leaf=issuer.resolve({authority}),certificate=new X509Certificate(leaf.cert);
|
|
assert.equal(certificate.ca,false);assert.equal(certificate.verify(certificate.publicKey),true);
|
|
assert.equal(certificate.checkHost('attacker.test',{subject:'never'}),undefined);
|
|
assert.ok(Date.parse(certificate.validTo)<=Date.now()+3600000);
|
|
assert.equal(issuer.resolve({authority}),leaf);
|
|
const metadata=issuer.publicMetadata({authority});
|
|
assert.deepEqual(Object.keys(metadata).sort(),['authority','cert','expiresAt','fingerprint256']);
|
|
assert.equal(metadata.fingerprint256,certificate.fingerprint256);
|
|
}}finally{issuer.close();}
|
|
assert.throws(()=>issuer.resolve({authority:'example.com:443'}),/broker-certificate-unavailable/);
|
|
});
|
|
test('deny, revocation and cache exhaustion do not issue or reuse leaves',async()=>{
|
|
let active=true,allowed=true;
|
|
const issuer=await createSessionCertificates({maxAuthorities:1,current:()=>active,authorized:()=>allowed});
|
|
try{issuer.resolve({authority:'example.com:443'});
|
|
assert.throws(()=>issuer.resolve({authority:'other.test:443'}),/broker-certificate-unavailable/);
|
|
allowed=false;assert.throws(()=>issuer.resolve({authority:'example.com:443'}),/broker-certificate-unavailable/);
|
|
allowed=true;active=false;assert.throws(()=>issuer.resolve({authority:'example.com:443'}),/broker-certificate-unavailable/);
|
|
}finally{issuer.close();}
|
|
});
|
|
test('generated certificate works with verified physical HTTPS and rejects a different hostname',async()=>{
|
|
const issuer=await createSessionCertificates({current:()=>true,authorized:()=>true});
|
|
const leaf=issuer.resolve({authority:'localhost:443'});
|
|
const server=https.createServer({key:leaf.key,cert:leaf.cert},(_request,response)=>response.end('public'));
|
|
try{await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve));
|
|
const request=servername=>new Promise((resolve,reject)=>{https.get({host:'127.0.0.1',port:server.address().port,servername,ca:leaf.cert,agent:false},response=>{let body='';response.on('data',part=>body+=part);response.on('end',()=>resolve(body));}).on('error',reject);});
|
|
assert.equal(await request('localhost'),'public');
|
|
await assert.rejects(request('attacker.test'),{code:'ERR_TLS_CERT_ALTNAME_INVALID'});
|
|
}finally{await new Promise(resolve=>server.close(resolve));issuer.close();}
|
|
});
|