@@ -27,14 +27,14 @@ export function randomSerialNumber(): string {
27
27
* Get the Not Before Date for a Certificate (will be valid from 2 days ago)
28
28
* @returns The Not Before Date for the Certificate
29
29
*/
30
- export function getCertNotBefore ( ) : Date {
31
- debugLog ( 'cert' , 'Calculating certificate not-before date' )
30
+ export function getCertNotBefore ( verbose ?: boolean ) : Date {
31
+ debugLog ( 'cert' , 'Calculating certificate not-before date' , verbose )
32
32
const twoDaysAgo = new Date ( Date . now ( ) - 60 * 60 * 24 * 2 * 1000 )
33
33
const year = twoDaysAgo . getFullYear ( )
34
34
const month = ( twoDaysAgo . getMonth ( ) + 1 ) . toString ( ) . padStart ( 2 , '0' )
35
35
const day = twoDaysAgo . getDate ( ) . toString ( ) . padStart ( 2 , '0' )
36
36
const date = new Date ( `${ year } -${ month } -${ day } T23:59:59Z` )
37
- debugLog ( 'cert' , `Certificate not-before date: ${ date . toISOString ( ) } ` )
37
+ debugLog ( 'cert' , `Certificate not-before date: ${ date . toISOString ( ) } ` , verbose )
38
38
return date
39
39
}
40
40
@@ -43,16 +43,16 @@ export function getCertNotBefore(): Date {
43
43
* @param notBefore - The Not Before Date for the Certificate
44
44
* @returns The Not After Date for the Certificate
45
45
*/
46
- export function getCertNotAfter ( notBefore : Date ) : Date {
47
- debugLog ( 'cert' , 'Calculating certificate not-after date' )
46
+ export function getCertNotAfter ( notBefore : Date , verbose ?: boolean ) : Date {
47
+ debugLog ( 'cert' , 'Calculating certificate not-after date' , verbose )
48
48
const validityDays = config . validityDays // defaults to 180 days
49
49
const daysInMillis = validityDays * 60 * 60 * 24 * 1000
50
50
const notAfterDate = new Date ( notBefore . getTime ( ) + daysInMillis )
51
51
const year = notAfterDate . getFullYear ( )
52
52
const month = ( notAfterDate . getMonth ( ) + 1 ) . toString ( ) . padStart ( 2 , '0' )
53
53
const day = notAfterDate . getDate ( ) . toString ( ) . padStart ( 2 , '0' )
54
54
const date = new Date ( `${ year } -${ month } -${ day } T23:59:59Z` )
55
- debugLog ( 'cert' , `Certificate not-after date: ${ date . toISOString ( ) } (${ validityDays } days validity)` )
55
+ debugLog ( 'cert' , `Certificate not-after date: ${ date . toISOString ( ) } (${ validityDays } days validity)` , verbose )
56
56
return date
57
57
}
58
58
@@ -61,13 +61,13 @@ export function getCertNotAfter(notBefore: Date): Date {
61
61
* @param notBefore - The Not Before Date for the CA
62
62
* @returns The Not After Date for the CA
63
63
*/
64
- export function getCANotAfter ( notBefore : Date ) : Date {
65
- debugLog ( 'cert' , 'Calculating CA not-after date' )
64
+ export function getCANotAfter ( notBefore : Date , verbose ?: boolean ) : Date {
65
+ debugLog ( 'cert' , 'Calculating CA not-after date' , verbose )
66
66
const year = notBefore . getFullYear ( ) + 100
67
67
const month = ( notBefore . getMonth ( ) + 1 ) . toString ( ) . padStart ( 2 , '0' )
68
68
const day = notBefore . getDate ( ) . toString ( ) . padStart ( 2 , '0' )
69
69
const date = new Date ( `${ year } -${ month } -${ day } T23:59:59Z` )
70
- debugLog ( 'cert' , `CA not-after date: ${ date . toISOString ( ) } (100 years validity)` )
70
+ debugLog ( 'cert' , `CA not-after date: ${ date . toISOString ( ) } (100 years validity)` , verbose )
71
71
return date
72
72
}
73
73
@@ -76,16 +76,16 @@ export function getCANotAfter(notBefore: Date): Date {
76
76
* @returns The Root CA Certificate
77
77
*/
78
78
export async function createRootCA ( options ?: TlsOption ) : Promise < GenerateCertReturn > {
79
- debugLog ( 'ca' , 'Creating new Root CA Certificate' )
80
- debugLog ( 'ca' , 'Generating 2048-bit RSA key pair' )
79
+ debugLog ( 'ca' , 'Creating new Root CA Certificate' , options ?. verbose )
80
+ debugLog ( 'ca' , 'Generating 2048-bit RSA key pair' , options ?. verbose )
81
81
const { privateKey, publicKey } = pki . rsa . generateKeyPair ( 2048 )
82
82
83
83
const mergedOptions = {
84
84
...config ,
85
85
...( options || { } ) ,
86
86
}
87
87
88
- debugLog ( 'ca' , 'Setting certificate attributes' )
88
+ debugLog ( 'ca' , 'Setting certificate attributes' , options ?. verbose )
89
89
const attributes = [
90
90
{ shortName : 'C' , value : mergedOptions . countryName } ,
91
91
{ shortName : 'ST' , value : mergedOptions . stateName } ,
@@ -94,7 +94,7 @@ export async function createRootCA(options?: TlsOption): Promise<GenerateCertRet
94
94
{ shortName : 'CN' , value : 'Local Development Root CA' } ,
95
95
]
96
96
97
- debugLog ( 'ca' , 'Setting certificate extensions' )
97
+ debugLog ( 'ca' , 'Setting certificate extensions' , options ?. verbose )
98
98
const extensions = [
99
99
{
100
100
name : 'basicConstraints' ,
@@ -112,23 +112,23 @@ export async function createRootCA(options?: TlsOption): Promise<GenerateCertRet
112
112
} ,
113
113
]
114
114
115
- debugLog ( 'ca' , 'Creating CA certificate' )
115
+ debugLog ( 'ca' , 'Creating CA certificate' , options ?. verbose )
116
116
const caCert = pki . createCertificate ( )
117
117
caCert . publicKey = publicKey
118
118
caCert . serialNumber = randomSerialNumber ( )
119
119
caCert . validity . notBefore = getCertNotBefore ( )
120
- caCert . validity . notAfter = getCANotAfter ( caCert . validity . notBefore )
120
+ caCert . validity . notAfter = getCANotAfter ( caCert . validity . notBefore , options ?. verbose )
121
121
caCert . setSubject ( attributes )
122
122
caCert . setIssuer ( attributes )
123
123
caCert . setExtensions ( extensions )
124
124
125
- debugLog ( 'ca' , 'Signing certificate with SHA-256' )
125
+ debugLog ( 'ca' , 'Signing certificate with SHA-256' , options ?. verbose )
126
126
caCert . sign ( privateKey , forge . md . sha256 . create ( ) )
127
127
128
128
const pemCert = pki . certificateToPem ( caCert )
129
129
const pemKey = pki . privateKeyToPem ( privateKey )
130
130
131
- debugLog ( 'ca' , 'Root CA Certificate created successfully' )
131
+ debugLog ( 'ca' , 'Root CA Certificate created successfully' , options ?. verbose )
132
132
return {
133
133
certificate : pemCert ,
134
134
privateKey : pemKey ,
@@ -143,30 +143,30 @@ export async function createRootCA(options?: TlsOption): Promise<GenerateCertRet
143
143
* @returns The generated certificate
144
144
*/
145
145
export async function generateCert ( options ?: CertOption ) : Promise < GenerateCertReturn > {
146
- debugLog ( 'cert' , 'Generating new host certificate' )
147
- debugLog ( 'cert' , `Options: ${ JSON . stringify ( options ) } ` )
146
+ debugLog ( 'cert' , 'Generating new host certificate' , options ?. verbose )
147
+ debugLog ( 'cert' , `Options: ${ JSON . stringify ( options ) } ` , options ?. verbose )
148
148
149
149
if ( ! options ?. hostCertCN ?. trim ( ) ) {
150
- debugLog ( 'cert' , 'Error: hostCertCN is required' )
150
+ debugLog ( 'cert' , 'Error: hostCertCN is required' , options ?. verbose )
151
151
throw new Error ( '"hostCertCN" must be a String' )
152
152
}
153
153
if ( ! options . domain ?. trim ( ) ) {
154
- debugLog ( 'cert' , 'Error: domain is required' )
154
+ debugLog ( 'cert' , 'Error: domain is required' , options ?. verbose )
155
155
throw new Error ( '"domain" must be a String' )
156
156
}
157
157
if ( ! options . rootCAObject || ! options . rootCAObject . certificate || ! options . rootCAObject . privateKey ) {
158
- debugLog ( 'cert' , 'Error: rootCAObject is invalid or missing' )
158
+ debugLog ( 'cert' , 'Error: rootCAObject is invalid or missing' , options ?. verbose )
159
159
throw new Error ( '"rootCAObject" must be an Object with the properties "certificate" & "privateKey"' )
160
160
}
161
161
162
- debugLog ( 'cert' , 'Converting Root CA PEM to forge objects' )
162
+ debugLog ( 'cert' , 'Converting Root CA PEM to forge objects' , options ?. verbose )
163
163
const caCert = pki . certificateFromPem ( options . rootCAObject . certificate )
164
164
const caKey = pki . privateKeyFromPem ( options . rootCAObject . privateKey )
165
165
166
- debugLog ( 'cert' , 'Generating 2048-bit RSA key pair for host certificate' )
166
+ debugLog ( 'cert' , 'Generating 2048-bit RSA key pair for host certificate' , options ?. verbose )
167
167
const hostKeys = pki . rsa . generateKeyPair ( 2048 )
168
168
169
- debugLog ( 'cert' , 'Setting certificate attributes' )
169
+ debugLog ( 'cert' , 'Setting certificate attributes' , options ?. verbose )
170
170
const attributes = [
171
171
{ shortName : 'C' , value : config . countryName } ,
172
172
{ shortName : 'ST' , value : config . stateName } ,
@@ -175,7 +175,7 @@ export async function generateCert(options?: CertOption): Promise<GenerateCertRe
175
175
{ shortName : 'CN' , value : '*.localhost' } ,
176
176
]
177
177
178
- debugLog ( 'cert' , 'Setting certificate extensions' )
178
+ debugLog ( 'cert' , 'Setting certificate extensions' , options ?. verbose )
179
179
const extensions = [
180
180
{
181
181
name : 'basicConstraints' ,
@@ -204,26 +204,26 @@ export async function generateCert(options?: CertOption): Promise<GenerateCertRe
204
204
} ,
205
205
]
206
206
207
- debugLog ( 'cert' , 'Creating new host certificate' )
207
+ debugLog ( 'cert' , 'Creating new host certificate' , options ?. verbose )
208
208
const newHostCert = pki . createCertificate ( )
209
209
newHostCert . publicKey = hostKeys . publicKey
210
210
211
- debugLog ( 'cert' , 'Setting certificate properties' )
211
+ debugLog ( 'cert' , 'Setting certificate properties' , options ?. verbose )
212
212
newHostCert . serialNumber = randomSerialNumber ( )
213
213
newHostCert . validity . notBefore = getCertNotBefore ( )
214
- newHostCert . validity . notAfter = getCertNotAfter ( newHostCert . validity . notBefore )
214
+ newHostCert . validity . notAfter = getCertNotAfter ( newHostCert . validity . notBefore , options ?. verbose )
215
215
newHostCert . setSubject ( attributes )
216
216
newHostCert . setIssuer ( caCert . subject . attributes )
217
217
newHostCert . setExtensions ( extensions )
218
218
219
- debugLog ( 'cert' , 'Signing certificate with SHA-256' )
219
+ debugLog ( 'cert' , 'Signing certificate with SHA-256' , options ?. verbose )
220
220
newHostCert . sign ( caKey , forge . md . sha256 . create ( ) )
221
221
222
- debugLog ( 'cert' , 'Converting certificate to PEM format' )
222
+ debugLog ( 'cert' , 'Converting certificate to PEM format' , options ?. verbose )
223
223
const pemHostCert = pki . certificateToPem ( newHostCert )
224
224
const pemHostKey = pki . privateKeyToPem ( hostKeys . privateKey )
225
225
226
- debugLog ( 'cert' , 'Host certificate generated successfully' )
226
+ debugLog ( 'cert' , 'Host certificate generated successfully' , options ?. verbose )
227
227
return {
228
228
certificate : pemHostCert ,
229
229
privateKey : pemHostKey ,
@@ -240,90 +240,90 @@ export async function generateCert(options?: CertOption): Promise<GenerateCertRe
240
240
* @returns The path to the stored certificate
241
241
*/
242
242
export async function addCertToSystemTrustStoreAndSaveCert ( cert : Cert , caCert : string , options ?: AddCertOption ) : Promise < string > {
243
- debugLog ( 'trust' , 'Adding certificate to system trust store' )
243
+ debugLog ( 'trust' , 'Adding certificate to system trust store' , options ?. verbose )
244
244
245
- debugLog ( 'trust' , 'Storing certificate and private key' )
245
+ debugLog ( 'trust' , 'Storing certificate and private key' , options ?. verbose )
246
246
const certPath = storeCert ( cert , options )
247
247
248
- debugLog ( 'trust' , 'Storing CA certificate' )
248
+ debugLog ( 'trust' , 'Storing CA certificate' , options ?. verbose )
249
249
const caCertPath = storeCACert ( caCert , options )
250
250
251
251
const platform = os . platform ( )
252
- debugLog ( 'trust' , `Detected platform: ${ platform } ` )
252
+ debugLog ( 'trust' , `Detected platform: ${ platform } ` , options ?. verbose )
253
253
const args = 'TC, C, C'
254
254
255
255
if ( platform === 'darwin' ) {
256
- debugLog ( 'trust' , 'Adding certificate to macOS keychain' )
256
+ debugLog ( 'trust' , 'Adding certificate to macOS keychain' , options ?. verbose )
257
257
await runCommand (
258
258
`sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${ caCertPath } ` ,
259
259
)
260
260
}
261
261
else if ( platform === 'win32' ) {
262
- debugLog ( 'trust' , 'Adding certificate to Windows certificate store' )
262
+ debugLog ( 'trust' , 'Adding certificate to Windows certificate store' , options ?. verbose )
263
263
await runCommand ( `certutil -f -v -addstore -enterprise Root ${ caCertPath } ` )
264
264
}
265
265
else if ( platform === 'linux' ) {
266
- debugLog ( 'trust' , 'Adding certificate to Linux certificate store' )
266
+ debugLog ( 'trust' , 'Adding certificate to Linux certificate store' , options ?. verbose )
267
267
const rootDirectory = os . homedir ( )
268
268
const targetFileName = 'cert9.db'
269
- debugLog ( 'trust' , `Searching for certificate databases in ${ rootDirectory } ` )
269
+ debugLog ( 'trust' , `Searching for certificate databases in ${ rootDirectory } ` , options ?. verbose )
270
270
const foldersWithFile = findFoldersWithFile ( rootDirectory , targetFileName )
271
271
272
272
for ( const folder of foldersWithFile ) {
273
- debugLog ( 'trust' , `Processing certificate database in ${ folder } ` )
273
+ debugLog ( 'trust' , `Processing certificate database in ${ folder } ` , options ?. verbose )
274
274
try {
275
- debugLog ( 'trust' , `Attempting to delete existing cert for ${ config . commonName } ` )
275
+ debugLog ( 'trust' , `Attempting to delete existing cert for ${ config . commonName } ` , options ?. verbose )
276
276
await runCommand ( `certutil -d sql:${ folder } -D -n ${ config . commonName } ` )
277
277
}
278
278
catch ( error ) {
279
- debugLog ( 'trust' , `Warning: Error deleting existing cert: ${ error } ` )
279
+ debugLog ( 'trust' , `Warning: Error deleting existing cert: ${ error } ` , options ?. verbose )
280
280
console . warn ( `Error deleting existing cert: ${ error } ` )
281
281
}
282
282
283
- debugLog ( 'trust' , `Adding new certificate to ${ folder } ` )
283
+ debugLog ( 'trust' , `Adding new certificate to ${ folder } ` , options ?. verbose )
284
284
await runCommand ( `certutil -d sql:${ folder } -A -t ${ args } -n ${ config . commonName } -i ${ caCertPath } ` )
285
285
286
286
log . info ( `Cert added to ${ folder } ` )
287
287
}
288
288
}
289
289
else {
290
- debugLog ( 'trust' , `Error: Unsupported platform ${ platform } ` )
290
+ debugLog ( 'trust' , `Error: Unsupported platform ${ platform } ` , options ?. verbose )
291
291
throw new Error ( `Unsupported platform: ${ platform } ` )
292
292
}
293
293
294
- debugLog ( 'trust' , 'Certificate successfully added to system trust store' )
294
+ debugLog ( 'trust' , 'Certificate successfully added to system trust store' , options ?. verbose )
295
295
return certPath
296
296
}
297
297
298
298
export function storeCert ( cert : Cert , options ?: AddCertOption ) : string {
299
- debugLog ( 'storage' , 'Storing certificate and private key' )
299
+ debugLog ( 'storage' , 'Storing certificate and private key' , options ?. verbose )
300
300
const certPath = options ?. customCertPath || config . certPath
301
301
const certKeyPath = options ?. customCertPath || config . keyPath
302
302
303
- debugLog ( 'storage' , `Certificate path: ${ certPath } ` )
304
- debugLog ( 'storage' , `Private key path: ${ certKeyPath } ` )
303
+ debugLog ( 'storage' , `Certificate path: ${ certPath } ` , options ?. verbose )
304
+ debugLog ( 'storage' , `Private key path: ${ certKeyPath } ` , options ?. verbose )
305
305
306
306
// Ensure the directory exists before writing the file
307
307
const certDir = path . dirname ( certPath )
308
308
if ( ! fs . existsSync ( certDir ) ) {
309
- debugLog ( 'storage' , `Creating certificate directory: ${ certDir } ` )
309
+ debugLog ( 'storage' , `Creating certificate directory: ${ certDir } ` , options ?. verbose )
310
310
fs . mkdirSync ( certDir , { recursive : true } )
311
311
}
312
312
313
- debugLog ( 'storage' , 'Writing certificate file' )
313
+ debugLog ( 'storage' , 'Writing certificate file' , options ?. verbose )
314
314
fs . writeFileSync ( certPath , cert . certificate )
315
315
316
316
// Ensure the directory exists before writing the file
317
317
const certKeyDir = path . dirname ( certKeyPath )
318
318
if ( ! fs . existsSync ( certKeyDir ) ) {
319
- debugLog ( 'storage' , `Creating private key directory: ${ certKeyDir } ` )
319
+ debugLog ( 'storage' , `Creating private key directory: ${ certKeyDir } ` , options ?. verbose )
320
320
fs . mkdirSync ( certKeyDir , { recursive : true } )
321
321
}
322
322
323
- debugLog ( 'storage' , 'Writing private key file' )
323
+ debugLog ( 'storage' , 'Writing private key file' , options ?. verbose )
324
324
fs . writeFileSync ( certKeyPath , cert . privateKey )
325
325
326
- debugLog ( 'storage' , 'Certificate and private key stored successfully' )
326
+ debugLog ( 'storage' , 'Certificate and private key stored successfully' , options ?. verbose )
327
327
return certPath
328
328
}
329
329
@@ -334,22 +334,22 @@ export function storeCert(cert: Cert, options?: AddCertOption): string {
334
334
* @returns The path to the CA Certificate
335
335
*/
336
336
export function storeCACert ( caCert : string , options ?: AddCertOption ) : string {
337
- debugLog ( 'storage' , 'Storing CA certificate' )
337
+ debugLog ( 'storage' , 'Storing CA certificate' , options ?. verbose )
338
338
const caCertPath = options ?. customCertPath || config . caCertPath
339
339
340
- debugLog ( 'storage' , `CA certificate path: ${ caCertPath } ` )
340
+ debugLog ( 'storage' , `CA certificate path: ${ caCertPath } ` , options ?. verbose )
341
341
342
342
// Ensure the directory exists before writing the file
343
343
const caCertDir = path . dirname ( caCertPath )
344
344
if ( ! fs . existsSync ( caCertDir ) ) {
345
- debugLog ( 'storage' , `Creating CA certificate directory: ${ caCertDir } ` )
345
+ debugLog ( 'storage' , `Creating CA certificate directory: ${ caCertDir } ` , options ?. verbose )
346
346
fs . mkdirSync ( caCertDir , { recursive : true } )
347
347
}
348
348
349
- debugLog ( 'storage' , 'Writing CA certificate file' )
349
+ debugLog ( 'storage' , 'Writing CA certificate file' , options ?. verbose )
350
350
fs . writeFileSync ( caCertPath , caCert )
351
351
352
- debugLog ( 'storage' , 'CA certificate stored successfully' )
352
+ debugLog ( 'storage' , 'CA certificate stored successfully' , options ?. verbose )
353
353
return caCertPath
354
354
}
355
355
0 commit comments