test(09-01): add failing spec for cert-manager seed + helpers (RED)
- Test: seedCertManagerModule calls seedModule with slug='cert-manager', category='security-tools', isSystem=true - Test: detectFormat returns pem/der/pfx/p7b based on extension + content sniff - Test: getFingerprint returns uppercase colon-separated hex (sha1 + sha256) - Test: parsePemChain returns array of length 2 for two concatenated PEMs
This commit is contained in:
@@ -0,0 +1,130 @@
|
|||||||
|
import * as forge from 'node-forge';
|
||||||
|
import { beforeAll, describe, expect, it, vi } from 'vitest';
|
||||||
|
import { seedCertManagerModule } from './cert-manager.seed';
|
||||||
|
import { CertManagerService } from './cert-manager.service';
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Test helpers
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Generate a self-signed X.509 cert via node-forge (RSA 1024 — fast for tests) */
|
||||||
|
function generateSelfSignedCert(): forge.pki.Certificate {
|
||||||
|
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: 'test.example.com' }];
|
||||||
|
cert.setSubject(attrs);
|
||||||
|
cert.setIssuer(attrs);
|
||||||
|
cert.sign(keys.privateKey, forge.md.sha256.create());
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Tests
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe('seedCertManagerModule', () => {
|
||||||
|
it('calls moduleRegistryService.seedModule once with cert-manager slug', async () => {
|
||||||
|
const mockSeedModule = vi.fn().mockResolvedValue(undefined);
|
||||||
|
const mockModuleRegistryService = { seedModule: mockSeedModule } as any;
|
||||||
|
|
||||||
|
await seedCertManagerModule(mockModuleRegistryService);
|
||||||
|
|
||||||
|
expect(mockSeedModule).toHaveBeenCalledTimes(1);
|
||||||
|
const arg = mockSeedModule.mock.calls[0][0];
|
||||||
|
expect(arg.slug).toBe('cert-manager');
|
||||||
|
expect(arg.category).toBe('security-tools');
|
||||||
|
expect(arg.isSystem).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('CertManagerService helpers', () => {
|
||||||
|
let service: CertManagerService;
|
||||||
|
let testCert: forge.pki.Certificate;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
service = new CertManagerService();
|
||||||
|
testCert = generateSelfSignedCert();
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// detectFormat
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe('detectFormat', () => {
|
||||||
|
it('returns "pfx" for .pfx extension', () => {
|
||||||
|
const buf = Buffer.from([0x30, 0x82]); // arbitrary binary
|
||||||
|
expect(service.detectFormat('cert.pfx', buf)).toBe('pfx');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns "p7b" for .p7b extension', () => {
|
||||||
|
const buf = Buffer.from([0x30, 0x82]);
|
||||||
|
expect(service.detectFormat('cert.p7b', buf)).toBe('p7b');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns "der" for .der extension', () => {
|
||||||
|
const buf = Buffer.from([0x30, 0x82]);
|
||||||
|
expect(service.detectFormat('cert.der', buf)).toBe('der');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns "pem" for .pem extension', () => {
|
||||||
|
const buf = Buffer.from('-----BEGIN CERTIFICATE-----\nfake\n-----END CERTIFICATE-----');
|
||||||
|
expect(service.detectFormat('cert.pem', buf)).toBe('pem');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns "pem" for .cer extension with PEM content', () => {
|
||||||
|
const buf = Buffer.from('-----BEGIN CERTIFICATE-----\nfake\n-----END CERTIFICATE-----');
|
||||||
|
expect(service.detectFormat('cert.cer', buf)).toBe('pem');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns "der" for .cer extension with binary (non-PEM) content', () => {
|
||||||
|
const buf = Buffer.from([0x30, 0x82, 0x01, 0x00]);
|
||||||
|
expect(service.detectFormat('cert.cer', buf)).toBe('der');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// getFingerprint
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe('getFingerprint', () => {
|
||||||
|
it('returns uppercase colon-separated hex for sha256', () => {
|
||||||
|
const fp = service.getFingerprint(testCert, 'sha256');
|
||||||
|
// e.g. "AA:BB:CC:..."
|
||||||
|
expect(fp).toMatch(/^[0-9A-F]{2}(:[0-9A-F]{2})+$/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns uppercase colon-separated hex for sha1', () => {
|
||||||
|
const fp = service.getFingerprint(testCert, 'sha1');
|
||||||
|
expect(fp).toMatch(/^[0-9A-F]{2}(:[0-9A-F]{2})+$/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
// parsePemChain
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
describe('parsePemChain', () => {
|
||||||
|
it('returns array of length 2 for two concatenated cert PEMs', () => {
|
||||||
|
const cert1 = generateSelfSignedCert();
|
||||||
|
const cert2 = generateSelfSignedCert();
|
||||||
|
const pem1 = forge.pki.certificateToPem(cert1);
|
||||||
|
const pem2 = forge.pki.certificateToPem(cert2);
|
||||||
|
const chain = pem1 + '\n' + pem2;
|
||||||
|
|
||||||
|
const parsed = service.parsePemChain(chain);
|
||||||
|
expect(parsed).toHaveLength(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns array of length 1 for a single PEM', () => {
|
||||||
|
const pem = forge.pki.certificateToPem(testCert);
|
||||||
|
const parsed = service.parsePemChain(pem);
|
||||||
|
expect(parsed).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user