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:
@@ -220,3 +220,105 @@ describe('parseCert', () => {
|
|||||||
).rejects.toThrow(BadRequestException);
|
).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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user