@harperfast/integration-testing 0.1.0 → 0.3.0-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -5
- package/dist/harperLifecycle.d.ts +176 -0
- package/dist/harperLifecycle.js +71 -40
- package/dist/harperLifecycle.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/loopbackAddressPool.d.ts +50 -0
- package/dist/run.d.ts +2 -0
- package/dist/security/certGenUtils.d.ts +52 -0
- package/dist/security/certGenUtils.js +170 -0
- package/dist/security/certGenUtils.js.map +1 -0
- package/dist/security/crl/generate-test-certs.d.ts +34 -0
- package/dist/security/crl/generate-test-certs.js +81 -0
- package/dist/security/crl/generate-test-certs.js.map +1 -0
- package/dist/security/ocsp/generate-test-certs.d.ts +55 -0
- package/dist/security/ocsp/generate-test-certs.js +106 -0
- package/dist/security/ocsp/generate-test-certs.js.map +1 -0
- package/dist/security/ocspServer.d.ts +18 -0
- package/dist/security/ocspServer.js +132 -0
- package/dist/security/ocspServer.js.map +1 -0
- package/dist/securityServices.d.ts +49 -0
- package/dist/securityServices.js +120 -0
- package/dist/securityServices.js.map +1 -0
- package/dist/src/harperLifecycle.d.ts +156 -0
- package/dist/src/harperLifecycle.js +315 -0
- package/dist/src/harperLifecycle.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/loopbackAddressPool.d.ts +50 -0
- package/dist/src/loopbackAddressPool.js +337 -0
- package/dist/src/loopbackAddressPool.js.map +1 -0
- package/dist/src/run.d.ts +2 -0
- package/dist/src/run.js +94 -0
- package/dist/src/run.js.map +1 -0
- package/dist/src/security/certGenUtils.d.ts +52 -0
- package/dist/src/security/certGenUtils.js +170 -0
- package/dist/src/security/certGenUtils.js.map +1 -0
- package/dist/src/security/crl/generate-test-certs.d.ts +34 -0
- package/dist/src/security/crl/generate-test-certs.js +81 -0
- package/dist/src/security/crl/generate-test-certs.js.map +1 -0
- package/dist/src/security/ocsp/generate-test-certs.d.ts +55 -0
- package/dist/src/security/ocsp/generate-test-certs.js +106 -0
- package/dist/src/security/ocsp/generate-test-certs.js.map +1 -0
- package/dist/src/security/ocspServer.d.ts +18 -0
- package/dist/src/security/ocspServer.js +132 -0
- package/dist/src/security/ocspServer.js.map +1 -0
- package/dist/src/securityServices.d.ts +49 -0
- package/dist/src/securityServices.js +120 -0
- package/dist/src/securityServices.js.map +1 -0
- package/dist/src/targz.d.ts +6 -0
- package/dist/src/targz.js +20 -0
- package/dist/src/targz.js.map +1 -0
- package/dist/targz.d.ts +6 -0
- package/package.json +5 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"certGenUtils.js","sourceRoot":"","sources":["../../../src/security/certGenUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate test certificates for CRL integration testing
|
|
3
|
+
*
|
|
4
|
+
* Uses pure Node.js (webcrypto + pkijs) — no openssl CLI dependency.
|
|
5
|
+
*/
|
|
6
|
+
export interface CrlCertificates {
|
|
7
|
+
/** Path to CA certificate */
|
|
8
|
+
ca: string;
|
|
9
|
+
/** Valid client certificate paths */
|
|
10
|
+
valid: {
|
|
11
|
+
/** Path to valid client certificate chain (cert + CA) */
|
|
12
|
+
cert: string;
|
|
13
|
+
/** Path to valid client private key */
|
|
14
|
+
key: string;
|
|
15
|
+
};
|
|
16
|
+
/** Revoked client certificate paths */
|
|
17
|
+
revoked: {
|
|
18
|
+
/** Path to revoked client certificate chain (cert + CA) */
|
|
19
|
+
cert: string;
|
|
20
|
+
/** Path to revoked client private key */
|
|
21
|
+
key: string;
|
|
22
|
+
};
|
|
23
|
+
/** Path to Certificate Revocation List */
|
|
24
|
+
crl: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Generate CRL test certificates using pure Node.js (no openssl CLI).
|
|
28
|
+
*
|
|
29
|
+
* Serial numbers:
|
|
30
|
+
* 1 = CA
|
|
31
|
+
* 2 = valid client
|
|
32
|
+
* 3 = revoked client
|
|
33
|
+
*/
|
|
34
|
+
export declare function generateCrlCertificates(outputDir: string, crlHost: string, crlPort: number): Promise<CrlCertificates>;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate test certificates for CRL integration testing
|
|
3
|
+
*
|
|
4
|
+
* Uses pure Node.js (webcrypto + pkijs) — no openssl CLI dependency.
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { generateEd25519KeyPair, createCertificate, createCRL, makeCRLDistributionPointsExt, certToPem, crlToPem, CLIENT_AUTH_OID, makeExtKeyUsageExt, } from "../certGenUtils.js";
|
|
9
|
+
/**
|
|
10
|
+
* Generate CRL test certificates using pure Node.js (no openssl CLI).
|
|
11
|
+
*
|
|
12
|
+
* Serial numbers:
|
|
13
|
+
* 1 = CA
|
|
14
|
+
* 2 = valid client
|
|
15
|
+
* 3 = revoked client
|
|
16
|
+
*/
|
|
17
|
+
export async function generateCrlCertificates(outputDir, crlHost, crlPort) {
|
|
18
|
+
const crlUrl = `http://${crlHost}:${crlPort}/test.crl`;
|
|
19
|
+
// --- CA ---
|
|
20
|
+
const caKey = await generateEd25519KeyPair();
|
|
21
|
+
const caKeyPath = path.join(outputDir, 'harper-ca.key');
|
|
22
|
+
fs.writeFileSync(caKeyPath, caKey.privateKeyPem);
|
|
23
|
+
const caCert = await createCertificate({
|
|
24
|
+
serialNumber: 1,
|
|
25
|
+
subject: { CN: 'Harper Test CA', O: 'Harper CRL Test' },
|
|
26
|
+
issuer: { CN: 'Harper Test CA', O: 'Harper CRL Test' },
|
|
27
|
+
validDays: 365,
|
|
28
|
+
issuerKey: caKey.privateKey,
|
|
29
|
+
subjectPublicKey: caKey.publicKey,
|
|
30
|
+
isCA: true,
|
|
31
|
+
});
|
|
32
|
+
const caCertPath = path.join(outputDir, 'harper-ca.crt');
|
|
33
|
+
fs.writeFileSync(caCertPath, certToPem(caCert));
|
|
34
|
+
// --- Valid client cert ---
|
|
35
|
+
const validKey = await generateEd25519KeyPair();
|
|
36
|
+
const validKeyPath = path.join(outputDir, 'client-valid.key');
|
|
37
|
+
fs.writeFileSync(validKeyPath, validKey.privateKeyPem);
|
|
38
|
+
const validCert = await createCertificate({
|
|
39
|
+
serialNumber: 2,
|
|
40
|
+
subject: { CN: 'Valid CRL Client', O: 'Harper CRL Test' },
|
|
41
|
+
issuer: { CN: 'Harper Test CA', O: 'Harper CRL Test' },
|
|
42
|
+
validDays: 30,
|
|
43
|
+
issuerKey: caKey.privateKey,
|
|
44
|
+
subjectPublicKey: validKey.publicKey,
|
|
45
|
+
extensions: [makeCRLDistributionPointsExt(crlUrl), makeExtKeyUsageExt([CLIENT_AUTH_OID])],
|
|
46
|
+
});
|
|
47
|
+
const validCertPath = path.join(outputDir, 'client-valid.crt');
|
|
48
|
+
fs.writeFileSync(validCertPath, certToPem(validCert));
|
|
49
|
+
// Build chain: client cert + CA cert
|
|
50
|
+
const validChainPath = path.join(outputDir, 'client-valid-chain.crt');
|
|
51
|
+
fs.writeFileSync(validChainPath, certToPem(validCert) + certToPem(caCert));
|
|
52
|
+
// --- Revoked client cert ---
|
|
53
|
+
const revokedKey = await generateEd25519KeyPair();
|
|
54
|
+
const revokedKeyPath = path.join(outputDir, 'client-revoked.key');
|
|
55
|
+
fs.writeFileSync(revokedKeyPath, revokedKey.privateKeyPem);
|
|
56
|
+
const revokedCert = await createCertificate({
|
|
57
|
+
serialNumber: 3,
|
|
58
|
+
subject: { CN: 'Revoked CRL Client', O: 'Harper CRL Test' },
|
|
59
|
+
issuer: { CN: 'Harper Test CA', O: 'Harper CRL Test' },
|
|
60
|
+
validDays: 30,
|
|
61
|
+
issuerKey: caKey.privateKey,
|
|
62
|
+
subjectPublicKey: revokedKey.publicKey,
|
|
63
|
+
extensions: [makeCRLDistributionPointsExt(crlUrl), makeExtKeyUsageExt([CLIENT_AUTH_OID])],
|
|
64
|
+
});
|
|
65
|
+
const revokedCertPath = path.join(outputDir, 'client-revoked.crt');
|
|
66
|
+
fs.writeFileSync(revokedCertPath, certToPem(revokedCert));
|
|
67
|
+
// Build chain: client cert + CA cert
|
|
68
|
+
const revokedChainPath = path.join(outputDir, 'client-revoked-chain.crt');
|
|
69
|
+
fs.writeFileSync(revokedChainPath, certToPem(revokedCert) + certToPem(caCert));
|
|
70
|
+
// --- CRL (serial 3 = revoked) ---
|
|
71
|
+
const crl = await createCRL(caCert, caKey.privateKey, [3]);
|
|
72
|
+
const crlPath = path.join(outputDir, 'test.crl');
|
|
73
|
+
fs.writeFileSync(crlPath, crlToPem(crl));
|
|
74
|
+
return {
|
|
75
|
+
ca: caCertPath,
|
|
76
|
+
valid: { cert: validChainPath, key: validKeyPath },
|
|
77
|
+
revoked: { cert: revokedChainPath, key: revokedKeyPath },
|
|
78
|
+
crl: crlPath,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=generate-test-certs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-test-certs.js","sourceRoot":"","sources":["../../../../src/security/crl/generate-test-certs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate test certificates for OCSP integration testing
|
|
3
|
+
*
|
|
4
|
+
* Uses pure Node.js (webcrypto + pkijs) — no openssl CLI dependency.
|
|
5
|
+
*/
|
|
6
|
+
import * as pkijs from 'pkijs';
|
|
7
|
+
import { type Ed25519KeyPair } from '../certGenUtils.ts';
|
|
8
|
+
export interface OcspCertificates {
|
|
9
|
+
/** Path to CA certificate */
|
|
10
|
+
ca: string;
|
|
11
|
+
/** Valid client certificate paths */
|
|
12
|
+
valid: {
|
|
13
|
+
/** Path to valid client certificate chain (cert + CA) */
|
|
14
|
+
cert: string;
|
|
15
|
+
/** Path to valid client private key */
|
|
16
|
+
key: string;
|
|
17
|
+
};
|
|
18
|
+
/** Revoked client certificate paths */
|
|
19
|
+
revoked: {
|
|
20
|
+
/** Path to revoked client certificate chain (cert + CA) */
|
|
21
|
+
cert: string;
|
|
22
|
+
/** Path to revoked client private key */
|
|
23
|
+
key: string;
|
|
24
|
+
};
|
|
25
|
+
/** OCSP responder certificate paths */
|
|
26
|
+
ocsp: {
|
|
27
|
+
/** Path to OCSP responder certificate */
|
|
28
|
+
cert: string;
|
|
29
|
+
/** Path to OCSP responder private key */
|
|
30
|
+
key: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/** In-memory cert data needed by the OCSP server */
|
|
34
|
+
export interface OcspServerCerts {
|
|
35
|
+
caCert: pkijs.Certificate;
|
|
36
|
+
ocspKeyPair: Ed25519KeyPair;
|
|
37
|
+
ocspCert: pkijs.Certificate;
|
|
38
|
+
/** Maps decimal serial number string → status */
|
|
39
|
+
statusMap: Map<string, 'good' | 'revoked'>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Generate OCSP test certificates using pure Node.js (no openssl CLI).
|
|
43
|
+
*
|
|
44
|
+
* Serial numbers:
|
|
45
|
+
* 1 = CA
|
|
46
|
+
* 2 = OCSP responder
|
|
47
|
+
* 3 = valid client
|
|
48
|
+
* 4 = revoked client
|
|
49
|
+
*
|
|
50
|
+
* Returns both file paths (for test code) and in-memory objects (for OCSP server).
|
|
51
|
+
*/
|
|
52
|
+
export declare function generateOcspCertificates(outputDir: string, ocspHost: string, ocspPort: number): Promise<{
|
|
53
|
+
files: OcspCertificates;
|
|
54
|
+
serverCerts: OcspServerCerts;
|
|
55
|
+
}>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate test certificates for OCSP integration testing
|
|
3
|
+
*
|
|
4
|
+
* Uses pure Node.js (webcrypto + pkijs) — no openssl CLI dependency.
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'node:fs';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import * as pkijs from 'pkijs';
|
|
9
|
+
import { generateEd25519KeyPair, createCertificate, makeOCSPAIAExt, makeExtKeyUsageExt, certToPem, OCSP_SIGNING_OID, CLIENT_AUTH_OID, } from "../certGenUtils.js";
|
|
10
|
+
/**
|
|
11
|
+
* Generate OCSP test certificates using pure Node.js (no openssl CLI).
|
|
12
|
+
*
|
|
13
|
+
* Serial numbers:
|
|
14
|
+
* 1 = CA
|
|
15
|
+
* 2 = OCSP responder
|
|
16
|
+
* 3 = valid client
|
|
17
|
+
* 4 = revoked client
|
|
18
|
+
*
|
|
19
|
+
* Returns both file paths (for test code) and in-memory objects (for OCSP server).
|
|
20
|
+
*/
|
|
21
|
+
export async function generateOcspCertificates(outputDir, ocspHost, ocspPort) {
|
|
22
|
+
const ocspUrl = `http://${ocspHost}:${ocspPort}`;
|
|
23
|
+
// --- CA ---
|
|
24
|
+
const caKey = await generateEd25519KeyPair();
|
|
25
|
+
const caKeyPath = path.join(outputDir, 'harper-ca.key');
|
|
26
|
+
fs.writeFileSync(caKeyPath, caKey.privateKeyPem);
|
|
27
|
+
const caCert = await createCertificate({
|
|
28
|
+
serialNumber: 1,
|
|
29
|
+
subject: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
|
|
30
|
+
issuer: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
|
|
31
|
+
validDays: 365,
|
|
32
|
+
issuerKey: caKey.privateKey,
|
|
33
|
+
subjectPublicKey: caKey.publicKey,
|
|
34
|
+
isCA: true,
|
|
35
|
+
});
|
|
36
|
+
const caCertPath = path.join(outputDir, 'harper-ca.crt');
|
|
37
|
+
fs.writeFileSync(caCertPath, certToPem(caCert));
|
|
38
|
+
// --- OCSP responder cert ---
|
|
39
|
+
const ocspKey = await generateEd25519KeyPair();
|
|
40
|
+
const ocspKeyPath = path.join(outputDir, 'ocsp.key');
|
|
41
|
+
fs.writeFileSync(ocspKeyPath, ocspKey.privateKeyPem);
|
|
42
|
+
const ocspCert = await createCertificate({
|
|
43
|
+
serialNumber: 2,
|
|
44
|
+
subject: { CN: 'OCSP Responder', O: 'Harper OCSP Test' },
|
|
45
|
+
issuer: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
|
|
46
|
+
validDays: 365,
|
|
47
|
+
issuerKey: caKey.privateKey,
|
|
48
|
+
subjectPublicKey: ocspKey.publicKey,
|
|
49
|
+
extensions: [makeExtKeyUsageExt([OCSP_SIGNING_OID])],
|
|
50
|
+
});
|
|
51
|
+
const ocspCertPath = path.join(outputDir, 'ocsp.crt');
|
|
52
|
+
fs.writeFileSync(ocspCertPath, certToPem(ocspCert));
|
|
53
|
+
// --- Valid client cert ---
|
|
54
|
+
const validKey = await generateEd25519KeyPair();
|
|
55
|
+
const validKeyPath = path.join(outputDir, 'client-valid.key');
|
|
56
|
+
fs.writeFileSync(validKeyPath, validKey.privateKeyPem);
|
|
57
|
+
const validCert = await createCertificate({
|
|
58
|
+
serialNumber: 3,
|
|
59
|
+
subject: { CN: 'Valid Client', O: 'Harper OCSP Test' },
|
|
60
|
+
issuer: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
|
|
61
|
+
validDays: 365,
|
|
62
|
+
issuerKey: caKey.privateKey,
|
|
63
|
+
subjectPublicKey: validKey.publicKey,
|
|
64
|
+
extensions: [makeOCSPAIAExt(ocspUrl), makeExtKeyUsageExt([CLIENT_AUTH_OID])],
|
|
65
|
+
});
|
|
66
|
+
const validCertPath = path.join(outputDir, 'client-valid.crt');
|
|
67
|
+
fs.writeFileSync(validCertPath, certToPem(validCert));
|
|
68
|
+
const validChainPath = path.join(outputDir, 'client-valid-chain.crt');
|
|
69
|
+
fs.writeFileSync(validChainPath, certToPem(validCert) + certToPem(caCert));
|
|
70
|
+
// --- Revoked client cert ---
|
|
71
|
+
const revokedKey = await generateEd25519KeyPair();
|
|
72
|
+
const revokedKeyPath = path.join(outputDir, 'client-revoked.key');
|
|
73
|
+
fs.writeFileSync(revokedKeyPath, revokedKey.privateKeyPem);
|
|
74
|
+
const revokedCert = await createCertificate({
|
|
75
|
+
serialNumber: 4,
|
|
76
|
+
subject: { CN: 'Revoked Client', O: 'Harper OCSP Test' },
|
|
77
|
+
issuer: { CN: 'Harper Test CA', O: 'Harper OCSP Test' },
|
|
78
|
+
validDays: 365,
|
|
79
|
+
issuerKey: caKey.privateKey,
|
|
80
|
+
subjectPublicKey: revokedKey.publicKey,
|
|
81
|
+
extensions: [makeOCSPAIAExt(ocspUrl), makeExtKeyUsageExt([CLIENT_AUTH_OID])],
|
|
82
|
+
});
|
|
83
|
+
const revokedCertPath = path.join(outputDir, 'client-revoked.crt');
|
|
84
|
+
fs.writeFileSync(revokedCertPath, certToPem(revokedCert));
|
|
85
|
+
const revokedChainPath = path.join(outputDir, 'client-revoked-chain.crt');
|
|
86
|
+
fs.writeFileSync(revokedChainPath, certToPem(revokedCert) + certToPem(caCert));
|
|
87
|
+
const statusMap = new Map([
|
|
88
|
+
['3', 'good'], // valid client serial
|
|
89
|
+
['4', 'revoked'], // revoked client serial
|
|
90
|
+
]);
|
|
91
|
+
return {
|
|
92
|
+
files: {
|
|
93
|
+
ca: caCertPath,
|
|
94
|
+
valid: { cert: validChainPath, key: validKeyPath },
|
|
95
|
+
revoked: { cert: revokedChainPath, key: revokedKeyPath },
|
|
96
|
+
ocsp: { cert: ocspCertPath, key: ocspKeyPath },
|
|
97
|
+
},
|
|
98
|
+
serverCerts: {
|
|
99
|
+
caCert,
|
|
100
|
+
ocspKeyPair: ocspKey,
|
|
101
|
+
ocspCert,
|
|
102
|
+
statusMap,
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=generate-test-certs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-test-certs.js","sourceRoot":"","sources":["../../../../src/security/ocsp/generate-test-certs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js OCSP (Online Certificate Status Protocol) responder
|
|
3
|
+
*
|
|
4
|
+
* A pure-Node.js replacement for `openssl ocsp`. Handles OCSP requests using pkijs
|
|
5
|
+
* for ASN.1 encoding and certGenUtils for Ed25519 signatures.
|
|
6
|
+
*/
|
|
7
|
+
import { type Server } from 'node:http';
|
|
8
|
+
import type { OcspServerCerts } from './ocsp/generate-test-certs.ts';
|
|
9
|
+
/**
|
|
10
|
+
* Start a Node.js HTTP OCSP responder.
|
|
11
|
+
*
|
|
12
|
+
* @param port - Port to listen on
|
|
13
|
+
* @param certs - In-memory certificate and key data for the responder
|
|
14
|
+
* @returns Promise resolving to the HTTP server (already listening)
|
|
15
|
+
*/
|
|
16
|
+
export declare function startOcspServer(port: number, certs: OcspServerCerts): Promise<Server>;
|
|
17
|
+
/** Stop a running OCSP server */
|
|
18
|
+
export declare function stopOcspServer(server: Server): Promise<void>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js OCSP (Online Certificate Status Protocol) responder
|
|
3
|
+
*
|
|
4
|
+
* A pure-Node.js replacement for `openssl ocsp`. Handles OCSP requests using pkijs
|
|
5
|
+
* for ASN.1 encoding and certGenUtils for Ed25519 signatures.
|
|
6
|
+
*/
|
|
7
|
+
import { createServer } from 'node:http';
|
|
8
|
+
import * as pkijs from 'pkijs';
|
|
9
|
+
import * as asn1js from 'asn1js';
|
|
10
|
+
import { signBasicOCSPResponse } from "./certGenUtils.js";
|
|
11
|
+
const OCSP_BASIC_RESPONSE_OID = '1.3.6.1.5.5.7.48.1.1';
|
|
12
|
+
/**
|
|
13
|
+
* Build a DER-encoded OCSPResponse for the given DER-encoded OCSPRequest.
|
|
14
|
+
*/
|
|
15
|
+
async function buildOcspResponse(requestBody, certs) {
|
|
16
|
+
// Parse incoming OCSP request
|
|
17
|
+
const asn1 = asn1js.fromBER(requestBody);
|
|
18
|
+
if (asn1.offset === -1) {
|
|
19
|
+
throw new Error('Failed to parse OCSP request');
|
|
20
|
+
}
|
|
21
|
+
const ocspRequest = new pkijs.OCSPRequest({ schema: asn1.result });
|
|
22
|
+
const now = new Date();
|
|
23
|
+
const nextUpdate = new Date(now.getTime() + 60 * 60 * 1000); // 1 hour
|
|
24
|
+
// Build SingleResponse for each requested certificate
|
|
25
|
+
const singleResponses = ocspRequest.tbsRequest.requestList.map((req) => {
|
|
26
|
+
// Extract the decimal serial number to look up status
|
|
27
|
+
const serialDec = req.reqCert.serialNumber.valueBlock.valueDec;
|
|
28
|
+
const status = certs.statusMap.get(String(serialDec));
|
|
29
|
+
// certStatus ASN.1 encoding:
|
|
30
|
+
// good [0] IMPLICIT NULL
|
|
31
|
+
// revoked [1] IMPLICIT RevokedInfo (SEQUENCE with revocation time)
|
|
32
|
+
// unknown [2] IMPLICIT UnknownInfo
|
|
33
|
+
let certStatus;
|
|
34
|
+
if (status === 'good') {
|
|
35
|
+
certStatus = new asn1js.Primitive({
|
|
36
|
+
idBlock: { tagClass: 3, tagNumber: 0 },
|
|
37
|
+
valueHex: new ArrayBuffer(0),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else if (status === 'revoked') {
|
|
41
|
+
certStatus = new asn1js.Constructed({
|
|
42
|
+
idBlock: { tagClass: 3, tagNumber: 1 },
|
|
43
|
+
value: [new asn1js.GeneralizedTime({ valueDate: now })],
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// unknown
|
|
48
|
+
certStatus = new asn1js.Primitive({
|
|
49
|
+
idBlock: { tagClass: 3, tagNumber: 2 },
|
|
50
|
+
valueHex: new ArrayBuffer(0),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return new pkijs.SingleResponse({
|
|
54
|
+
certID: req.reqCert, // echo back the same certID
|
|
55
|
+
certStatus,
|
|
56
|
+
thisUpdate: now,
|
|
57
|
+
nextUpdate,
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
// Use the OCSP responder cert's subject as the responderID (byName, tagNumber=1)
|
|
61
|
+
const responseData = new pkijs.ResponseData({
|
|
62
|
+
responderID: certs.ocspCert.subject,
|
|
63
|
+
producedAt: now,
|
|
64
|
+
responses: singleResponses,
|
|
65
|
+
});
|
|
66
|
+
// Create BasicOCSPResponse and sign it
|
|
67
|
+
const basicResponse = new pkijs.BasicOCSPResponse({
|
|
68
|
+
tbsResponseData: responseData,
|
|
69
|
+
certs: [certs.ocspCert, certs.caCert],
|
|
70
|
+
});
|
|
71
|
+
await signBasicOCSPResponse(basicResponse, certs.ocspKeyPair.privateKey);
|
|
72
|
+
// Encode BasicOCSPResponse to DER, wrap in OCSPResponse
|
|
73
|
+
const basicDer = basicResponse.toSchema().toBER();
|
|
74
|
+
const ocspResponse = new pkijs.OCSPResponse({
|
|
75
|
+
responseStatus: new asn1js.Enumerated({ value: 0 }), // successful
|
|
76
|
+
responseBytes: new pkijs.ResponseBytes({
|
|
77
|
+
responseType: OCSP_BASIC_RESPONSE_OID,
|
|
78
|
+
response: new asn1js.OctetString({ valueHex: basicDer }),
|
|
79
|
+
}),
|
|
80
|
+
});
|
|
81
|
+
return Buffer.from(ocspResponse.toSchema().toBER());
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Start a Node.js HTTP OCSP responder.
|
|
85
|
+
*
|
|
86
|
+
* @param port - Port to listen on
|
|
87
|
+
* @param certs - In-memory certificate and key data for the responder
|
|
88
|
+
* @returns Promise resolving to the HTTP server (already listening)
|
|
89
|
+
*/
|
|
90
|
+
export async function startOcspServer(port, certs) {
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
const server = createServer((req, res) => {
|
|
93
|
+
if (req.method !== 'POST' && req.method !== 'GET') {
|
|
94
|
+
res.writeHead(405);
|
|
95
|
+
res.end();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const chunks = [];
|
|
99
|
+
req.on('data', (chunk) => chunks.push(chunk));
|
|
100
|
+
req.on('end', async () => {
|
|
101
|
+
try {
|
|
102
|
+
const body = Buffer.concat(chunks);
|
|
103
|
+
const response = await buildOcspResponse(body, certs);
|
|
104
|
+
res.writeHead(200, { 'Content-Type': 'application/ocsp-response' });
|
|
105
|
+
res.end(response);
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
console.error('OCSP server error:', err);
|
|
109
|
+
// Return an "internalError" response
|
|
110
|
+
const errResponse = new pkijs.OCSPResponse({
|
|
111
|
+
responseStatus: new asn1js.Enumerated({ value: 2 }), // internalError
|
|
112
|
+
});
|
|
113
|
+
const errDer = Buffer.from(errResponse.toSchema().toBER());
|
|
114
|
+
res.writeHead(200, { 'Content-Type': 'application/ocsp-response' });
|
|
115
|
+
res.end(errDer);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
req.on('error', (err) => {
|
|
119
|
+
console.error('OCSP request error:', err);
|
|
120
|
+
res.writeHead(500);
|
|
121
|
+
res.end();
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
server.on('error', reject);
|
|
125
|
+
server.listen(port, '127.0.0.1', () => resolve(server));
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/** Stop a running OCSP server */
|
|
129
|
+
export async function stopOcspServer(server) {
|
|
130
|
+
return new Promise((resolve) => server.close(() => resolve()));
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=ocspServer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocspServer.js","sourceRoot":"","sources":["../../../src/security/ocspServer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Services Utilities for Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for managing OCSP responders, CRL servers,
|
|
5
|
+
* and certificate generation for security-related integration tests.
|
|
6
|
+
*
|
|
7
|
+
* All certificate generation and OCSP responding is done in pure Node.js
|
|
8
|
+
* using webcrypto + pkijs — no openssl CLI dependency.
|
|
9
|
+
*/
|
|
10
|
+
import { type Server } from 'node:http';
|
|
11
|
+
import type { OcspCertificates } from './security/ocsp/generate-test-certs.ts';
|
|
12
|
+
import type { CrlCertificates } from './security/crl/generate-test-certs.ts';
|
|
13
|
+
export interface OcspResponderContext {
|
|
14
|
+
server: Server;
|
|
15
|
+
port: number;
|
|
16
|
+
certsPath: string;
|
|
17
|
+
certs: OcspCertificates;
|
|
18
|
+
}
|
|
19
|
+
export interface CrlServerContext {
|
|
20
|
+
server: Server;
|
|
21
|
+
port: number;
|
|
22
|
+
certsPath: string;
|
|
23
|
+
certs: CrlCertificates;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Stop an OCSP responder server
|
|
27
|
+
*/
|
|
28
|
+
export declare function stopOcspResponder(ctx: OcspResponderContext): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Start a Node.js HTTP server to serve CRL files
|
|
31
|
+
*/
|
|
32
|
+
export declare function startCrlServer(certsPath: string, port: number, certs: CrlCertificates): Promise<CrlServerContext>;
|
|
33
|
+
/**
|
|
34
|
+
* Stop a CRL server
|
|
35
|
+
*/
|
|
36
|
+
export declare function stopCrlServer(ctx: CrlServerContext): Promise<void>;
|
|
37
|
+
export { generateOcspCertificates, type OcspCertificates } from './security/ocsp/generate-test-certs.ts';
|
|
38
|
+
export { generateCrlCertificates, type CrlCertificates } from './security/crl/generate-test-certs.ts';
|
|
39
|
+
/**
|
|
40
|
+
* Setup CRL server with automatic port allocation and retry on conflict
|
|
41
|
+
*/
|
|
42
|
+
export declare function setupCrlServerWithCerts(certsPath: string, hostname?: string, maxRetries?: number): Promise<CrlServerContext>;
|
|
43
|
+
/**
|
|
44
|
+
* Setup OCSP responder with automatic port allocation and retry on conflict
|
|
45
|
+
*
|
|
46
|
+
* Generates certificates with OCSP URL embedded, then starts the Node.js
|
|
47
|
+
* OCSP responder on the same port.
|
|
48
|
+
*/
|
|
49
|
+
export declare function setupOcspResponderWithCerts(certsPath: string, hostname?: string, maxRetries?: number): Promise<OcspResponderContext>;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Security Services Utilities for Integration Tests
|
|
3
|
+
*
|
|
4
|
+
* This module provides utilities for managing OCSP responders, CRL servers,
|
|
5
|
+
* and certificate generation for security-related integration tests.
|
|
6
|
+
*
|
|
7
|
+
* All certificate generation and OCSP responding is done in pure Node.js
|
|
8
|
+
* using webcrypto + pkijs — no openssl CLI dependency.
|
|
9
|
+
*/
|
|
10
|
+
import { createServer } from 'node:http';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import { readFileSync } from 'node:fs';
|
|
13
|
+
import { startOcspServer, stopOcspServer } from "./security/ocspServer.js";
|
|
14
|
+
/**
|
|
15
|
+
* Stop an OCSP responder server
|
|
16
|
+
*/
|
|
17
|
+
export async function stopOcspResponder(ctx) {
|
|
18
|
+
return stopOcspServer(ctx.server);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Start a Node.js HTTP server to serve CRL files
|
|
22
|
+
*/
|
|
23
|
+
export async function startCrlServer(certsPath, port, certs) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const server = createServer((req, res) => {
|
|
26
|
+
if (req.url === '/test.crl') {
|
|
27
|
+
try {
|
|
28
|
+
const crl = readFileSync(join(certsPath, 'test.crl'));
|
|
29
|
+
res.writeHead(200, {
|
|
30
|
+
'Content-Type': 'application/pkix-crl',
|
|
31
|
+
'Cache-Control': 'no-cache',
|
|
32
|
+
});
|
|
33
|
+
res.end(crl);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
res.writeHead(500);
|
|
37
|
+
res.end('Internal Server Error');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (req.url === '/health') {
|
|
41
|
+
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
|
42
|
+
res.end('OK');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
res.writeHead(404);
|
|
46
|
+
res.end('Not Found');
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
server.on('error', reject);
|
|
50
|
+
server.listen(port, () => {
|
|
51
|
+
const address = server.address();
|
|
52
|
+
if (!address || typeof address === 'string') {
|
|
53
|
+
reject(new Error('Server did not bind to a network port'));
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
resolve({
|
|
57
|
+
server,
|
|
58
|
+
port: address.port,
|
|
59
|
+
certsPath,
|
|
60
|
+
certs,
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Stop a CRL server
|
|
67
|
+
*/
|
|
68
|
+
export async function stopCrlServer(ctx) {
|
|
69
|
+
return new Promise((resolve) => {
|
|
70
|
+
ctx.server.close(() => resolve());
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
// Re-export certificate generation functions and types
|
|
74
|
+
export { generateOcspCertificates } from "./security/ocsp/generate-test-certs.js";
|
|
75
|
+
export { generateCrlCertificates } from "./security/crl/generate-test-certs.js";
|
|
76
|
+
/**
|
|
77
|
+
* Setup CRL server with automatic port allocation and retry on conflict
|
|
78
|
+
*/
|
|
79
|
+
export async function setupCrlServerWithCerts(certsPath, hostname = '127.0.0.1', maxRetries = 5) {
|
|
80
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
81
|
+
const port = 50000 + Math.floor(Math.random() * 10000);
|
|
82
|
+
try {
|
|
83
|
+
const { generateCrlCertificates } = await import("./security/crl/generate-test-certs.js");
|
|
84
|
+
const certs = await generateCrlCertificates(certsPath, hostname, port);
|
|
85
|
+
return startCrlServer(certsPath, port, certs);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error.code === 'EADDRINUSE' && attempt < maxRetries - 1) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
throw new Error(`Failed to setup CRL server after ${attempt + 1} attempts: ${error.message}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
throw new Error(`Failed to setup CRL server after ${maxRetries} attempts`);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Setup OCSP responder with automatic port allocation and retry on conflict
|
|
98
|
+
*
|
|
99
|
+
* Generates certificates with OCSP URL embedded, then starts the Node.js
|
|
100
|
+
* OCSP responder on the same port.
|
|
101
|
+
*/
|
|
102
|
+
export async function setupOcspResponderWithCerts(certsPath, hostname = '127.0.0.1', maxRetries = 5) {
|
|
103
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
104
|
+
const port = 50000 + Math.floor(Math.random() * 10000);
|
|
105
|
+
try {
|
|
106
|
+
const { generateOcspCertificates } = await import("./security/ocsp/generate-test-certs.js");
|
|
107
|
+
const { files, serverCerts } = await generateOcspCertificates(certsPath, hostname, port);
|
|
108
|
+
const server = await startOcspServer(port, serverCerts);
|
|
109
|
+
return { server, port, certsPath, certs: files };
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
if (error.code === 'EADDRINUSE' && attempt < maxRetries - 1) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
throw new Error(`Failed to setup OCSP responder after ${attempt + 1} attempts: ${error.message}`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
throw new Error(`Failed to setup OCSP responder after ${maxRetries} attempts`);
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=securityServices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"securityServices.js","sourceRoot":"","sources":["../../src/securityServices.ts"],"names":[],"mappings":"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"}
|