test(09-04): RED — failing splitCerts spec (fullchain PEM, P7B bundle, malformed)

- splitCerts fullchain PEM: expects count 2, two single-PEM-block certs with correct CN
- splitCerts P7B PEM bundle: expects at least one cert in result
- splitCerts malformed input: expects BadRequestException
- All three tests FAIL against NotImplementedException stub (RED confirmed)
- All 16 prior tests still pass
This commit is contained in:
2026-07-02 07:12:37 +02:00
parent da676705d9
commit eec66311a7
@@ -220,3 +220,105 @@ describe('parseCert', () => {
).rejects.toThrow(BadRequestException);
});
});
// ---------------------------------------------------------------------------
// splitCerts — RED tests (CERT-02)
// ---------------------------------------------------------------------------
describe('splitCerts', () => {
let service: CertManagerService;
let cert1Pem: string;
let cert2Pem: string;
let fullchainBuffer: Buffer;
let p7bBuffer: Buffer;
const CN1 = 'split1.example.com';
const CN2 = 'split2.example.com';
beforeAll(() => {
service = new CertManagerService();
// Build cert 1 (RSA-1024 for speed)
const keys1 = forge.pki.rsa.generateKeyPair(1024);
const c1 = forge.pki.createCertificate();
c1.publicKey = keys1.publicKey;
c1.serialNumber = '01';
c1.validity.notBefore = new Date();
c1.validity.notAfter = new Date();
c1.validity.notAfter.setFullYear(c1.validity.notBefore.getFullYear() + 1);
const attrs1 = [{ name: 'commonName', value: CN1 }];
c1.setSubject(attrs1);
c1.setIssuer(attrs1);
c1.sign(keys1.privateKey, forge.md.sha256.create());
cert1Pem = forge.pki.certificateToPem(c1);
// Build cert 2
const keys2 = forge.pki.rsa.generateKeyPair(1024);
const c2 = forge.pki.createCertificate();
c2.publicKey = keys2.publicKey;
c2.serialNumber = '02';
c2.validity.notBefore = new Date();
c2.validity.notAfter = new Date();
c2.validity.notAfter.setFullYear(c2.validity.notBefore.getFullYear() + 1);
const attrs2 = [{ name: 'commonName', value: CN2 }];
c2.setSubject(attrs2);
c2.setIssuer(attrs2);
c2.sign(keys2.privateKey, forge.md.sha256.create());
cert2Pem = forge.pki.certificateToPem(c2);
// Fullchain fixture: two PEMs concatenated
const fullchainPem = cert1Pem + '\n' + cert2Pem;
fullchainBuffer = Buffer.from(fullchainPem, 'utf-8');
// P7B fixture: PEM-wrapped PKCS7 SignedData bundle with both certs
const p7 = forge.pkcs7.createSignedData();
p7.addCertificate(c1);
p7.addCertificate(c2);
const p7DerBytes = forge.asn1.toDer(p7.toAsn1()).getBytes();
const p7PemStr = forge.pem.encode({ type: 'PKCS7', body: p7DerBytes });
p7bBuffer = Buffer.from(p7PemStr, 'utf-8');
}, 30000); // 30s — two RSA-1024 keygens
it('returns count 2 and two certs each with a single PEM block and correct CN for fullchain PEM', async () => {
// RED: splitCerts throws NotImplementedException — FAIL
const result = await (service.splitCerts({
file: { originalname: 'fullchain.pem', buffer: fullchainBuffer },
}) as Promise<any>);
expect(result.count).toBe(2);
expect(result.certs).toHaveLength(2);
// Each cert content decodes to exactly one BEGIN CERTIFICATE block
for (const entry of result.certs) {
const decoded = Buffer.from(entry.content, 'base64').toString('utf-8');
const matches = decoded.match(/-----BEGIN CERTIFICATE-----/g);
expect(matches).toHaveLength(1);
}
// CN values are present
const cns = result.certs.map((c: any) => c.subject.cn);
expect(cns).toContain(CN1);
expect(cns).toContain(CN2);
// validity.notAfter is present and looks like ISO 8601
for (const entry of result.certs) {
expect(entry.validity.notAfter).toMatch(/^\d{4}-\d{2}-\d{2}T/);
}
});
it('returns enclosed certs from a P7B PEM bundle', async () => {
// RED: splitCerts throws NotImplementedException — FAIL
const result = await (service.splitCerts({
file: { originalname: 'bundle.p7b', buffer: p7bBuffer },
}) as Promise<any>);
expect(result.count).toBeGreaterThanOrEqual(1);
expect(result.certs.length).toBeGreaterThanOrEqual(1);
});
it('throws BadRequestException for malformed input', async () => {
// RED: splitCerts throws NotImplementedException (not BadRequestException) — FAIL
await expect(
service.splitCerts({
file: { originalname: 'bad.pem', buffer: Buffer.from('this is garbage') },
}),
).rejects.toThrow(BadRequestException);
});
});