From 37db58b816d85f3aac51f88d679e860f8c51a99d Mon Sep 17 00:00:00 2001 From: Schalli Date: Thu, 2 Jul 2026 07:35:51 +0200 Subject: [PATCH] test(09-05): add failing convertCert spec (RED) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PEM→DER round-trip identity test (re-parses DER base64 → verify CN) - DER→PEM round-trip identity test (re-parses PEM base64 → verify CN) - PEM→P7B: asserts mimeType + P7B contains ≥1 cert - malformed input: expects BadRequestException - All 4 fail against NotImplementedException stub (RED confirmed) --- .../cert-manager/cert-manager.service.spec.ts | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/apps/api/src/cert-manager/cert-manager.service.spec.ts b/apps/api/src/cert-manager/cert-manager.service.spec.ts index b22a1e6..e0a4ba2 100644 --- a/apps/api/src/cert-manager/cert-manager.service.spec.ts +++ b/apps/api/src/cert-manager/cert-manager.service.spec.ts @@ -322,3 +322,90 @@ describe('splitCerts', () => { ).rejects.toThrow(BadRequestException); }); }); + +// --------------------------------------------------------------------------- +// convertCert — RED tests (CERT-04) +// --------------------------------------------------------------------------- + +describe('convertCert', () => { + let service: CertManagerService; + let certPem: string; + let certDerBuffer: Buffer; + const CN = 'convert.example.com'; + + beforeAll(() => { + service = new CertManagerService(); + + // RSA-1024 self-signed cert (fast for tests) + const keys = forge.pki.rsa.generateKeyPair(1024); + const cert = forge.pki.createCertificate(); + cert.publicKey = keys.publicKey; + cert.serialNumber = '01'; + cert.validity.notBefore = new Date(); + cert.validity.notAfter = new Date(); + cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1); + + const attrs = [{ name: 'commonName', value: CN }]; + cert.setSubject(attrs); + cert.setIssuer(attrs); + cert.sign(keys.privateKey, forge.md.sha256.create()); + + // PEM fixture + certPem = forge.pki.certificateToPem(cert); + + // DER fixture — binary encoding required (Pitfall 1) + const derBytes = forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes(); + certDerBuffer = Buffer.from(derBytes, 'binary'); + }, 15000); + + it('PEM→DER: returns FileResponse with correct mimeType and round-trip identity', async () => { + // RED: convertCert throws NotImplementedException — this test will FAIL + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const result = await (service.convertCert({ pemText: certPem, targetFormat: 'der' } as any) as Promise); + expect(result.mimeType).toBe('application/x-x509-ca-cert'); + expect(result.filename).toContain('converted'); + expect(result.content).toBeTruthy(); + + // Round-trip identity: decode base64 DER → re-parse → verify CN matches original + const derBuf = Buffer.from(result.content as string, 'base64'); + const asn1 = forge.asn1.fromDer(forge.util.createBuffer(derBuf.toString('binary'))); + const reparsed = forge.pki.certificateFromAsn1(asn1); + expect(reparsed.subject.getField('CN')?.value).toBe(CN); + }); + + it('DER→PEM: returned PEM parses to cert with same CN (round-trip identity)', async () => { + // RED: convertCert throws NotImplementedException — this test will FAIL + const result = await (service.convertCert({ + file: { originalname: 'c.der', buffer: certDerBuffer }, + targetFormat: 'pem', + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } as any) as Promise); + expect(result.mimeType).toBe('application/x-pem-file'); + + // Decode base64 PEM content → parse → verify CN matches original + const pemStr = Buffer.from(result.content as string, 'base64').toString('utf-8'); + const reparsed = forge.pki.certificateFromPem(pemStr); + expect(reparsed.subject.getField('CN')?.value).toBe(CN); + }); + + it('PEM→P7B: returned P7B contains the original certificate', async () => { + // RED: convertCert throws NotImplementedException — this test will FAIL + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const result = await (service.convertCert({ pemText: certPem, targetFormat: 'p7b' } as any) as Promise); + expect(result.mimeType).toBe('application/x-pkcs7-certificates'); + expect(result.filename).toContain('converted'); + + // Decode base64 P7B (PEM-wrapped PKCS7) and verify at least 1 cert enclosed + const p7bContent = Buffer.from(result.content as string, 'base64').toString('utf-8'); + const p7 = forge.pkcs7.messageFromPem(p7bContent); + expect((p7.certificates as forge.pki.Certificate[]).length).toBeGreaterThanOrEqual(1); + }); + + it('throws BadRequestException for malformed PEM input', async () => { + // RED: convertCert throws NotImplementedException (not BadRequestException) — FAIL + await expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + service.convertCert({ pemText: 'garbage input not a cert', targetFormat: 'der' } as any), + ).rejects.toThrow(BadRequestException); + }); +});