smartproxy/test/test.certprovisioner.unit.ts

140 lines
4.7 KiB
TypeScript
Raw Permalink Normal View History

import { tap, expect } from '@push.rocks/tapbundle';
import * as plugins from '../ts/plugins.js';
import { CertProvisioner } from '../ts/smartproxy/classes.pp.certprovisioner.js';
import type { IDomainConfig, ISmartProxyCertProvisionObject } from '../ts/smartproxy/classes.pp.interfaces.js';
import type { ICertificateData } from '../ts/port80handler/classes.port80handler.js';
// Fake Port80Handler stub
class FakePort80Handler extends plugins.EventEmitter {
public domainsAdded: string[] = [];
public renewCalled: string[] = [];
addDomain(opts: { domainName: string; sslRedirect: boolean; acmeMaintenance: boolean }) {
this.domainsAdded.push(opts.domainName);
}
async renewCertificate(domain: string): Promise<void> {
this.renewCalled.push(domain);
}
}
// Fake NetworkProxyBridge stub
class FakeNetworkProxyBridge {
public appliedCerts: ICertificateData[] = [];
applyExternalCertificate(cert: ICertificateData) {
this.appliedCerts.push(cert);
}
}
tap.test('CertProvisioner handles static provisioning', async () => {
const domain = 'static.com';
const domainConfigs: IDomainConfig[] = [{ domains: [domain], allowedIPs: [] }];
const fakePort80 = new FakePort80Handler();
const fakeBridge = new FakeNetworkProxyBridge();
// certProvider returns static certificate
const certProvider = async (d: string): Promise<ISmartProxyCertProvisionObject> => {
expect(d).toEqual(domain);
return {
domainName: domain,
publicKey: 'CERT',
privateKey: 'KEY',
validUntil: Date.now() + 3600 * 1000
};
};
const prov = new CertProvisioner(
domainConfigs,
fakePort80 as any,
fakeBridge as any,
certProvider,
1, // low renew threshold
1, // short interval
false // disable auto renew for unit test
);
const events: any[] = [];
prov.on('certificate', (data) => events.push(data));
await prov.start();
// Static flow: no addDomain, certificate applied via bridge
expect(fakePort80.domainsAdded.length).toEqual(0);
expect(fakeBridge.appliedCerts.length).toEqual(1);
expect(events.length).toEqual(1);
const evt = events[0];
expect(evt.domain).toEqual(domain);
expect(evt.certificate).toEqual('CERT');
expect(evt.privateKey).toEqual('KEY');
expect(evt.isRenewal).toEqual(false);
expect(evt.source).toEqual('static');
});
tap.test('CertProvisioner handles http01 provisioning', async () => {
const domain = 'http01.com';
const domainConfigs: IDomainConfig[] = [{ domains: [domain], allowedIPs: [] }];
const fakePort80 = new FakePort80Handler();
const fakeBridge = new FakeNetworkProxyBridge();
// certProvider returns http01 directive
const certProvider = async (): Promise<ISmartProxyCertProvisionObject> => 'http01';
const prov = new CertProvisioner(
domainConfigs,
fakePort80 as any,
fakeBridge as any,
certProvider,
1,
1,
false
);
const events: any[] = [];
prov.on('certificate', (data) => events.push(data));
await prov.start();
// HTTP-01 flow: addDomain called, no static cert applied
expect(fakePort80.domainsAdded).toEqual([domain]);
expect(fakeBridge.appliedCerts.length).toEqual(0);
expect(events.length).toEqual(0);
});
tap.test('CertProvisioner on-demand http01 renewal', async () => {
const domain = 'renew.com';
const domainConfigs: IDomainConfig[] = [{ domains: [domain], allowedIPs: [] }];
const fakePort80 = new FakePort80Handler();
const fakeBridge = new FakeNetworkProxyBridge();
const certProvider = async (): Promise<ISmartProxyCertProvisionObject> => 'http01';
const prov = new CertProvisioner(
domainConfigs,
fakePort80 as any,
fakeBridge as any,
certProvider,
1,
1,
false
);
// requestCertificate should call renewCertificate
await prov.requestCertificate(domain);
expect(fakePort80.renewCalled).toEqual([domain]);
});
tap.test('CertProvisioner on-demand static provisioning', async () => {
const domain = 'ondemand.com';
const domainConfigs: IDomainConfig[] = [{ domains: [domain], allowedIPs: [] }];
const fakePort80 = new FakePort80Handler();
const fakeBridge = new FakeNetworkProxyBridge();
const certProvider = async (): Promise<ISmartProxyCertProvisionObject> => ({
domainName: domain,
publicKey: 'PKEY',
privateKey: 'PRIV',
validUntil: Date.now() + 1000
});
const prov = new CertProvisioner(
domainConfigs,
fakePort80 as any,
fakeBridge as any,
certProvider,
1,
1,
false
);
const events: any[] = [];
prov.on('certificate', (data) => events.push(data));
await prov.requestCertificate(domain);
expect(fakeBridge.appliedCerts.length).toEqual(1);
expect(events.length).toEqual(1);
expect(events[0].domain).toEqual(domain);
expect(events[0].source).toEqual('static');
});
export default tap.start();