Skip to content

Commit b225a04

Browse files
committed
chore: ensure verbose output is configurable
1 parent dc7bafe commit b225a04

File tree

3 files changed

+62
-61
lines changed

3 files changed

+62
-61
lines changed

src/certificate.ts

Lines changed: 59 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ export function randomSerialNumber(): string {
2727
* Get the Not Before Date for a Certificate (will be valid from 2 days ago)
2828
* @returns The Not Before Date for the Certificate
2929
*/
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)
3232
const twoDaysAgo = new Date(Date.now() - 60 * 60 * 24 * 2 * 1000)
3333
const year = twoDaysAgo.getFullYear()
3434
const month = (twoDaysAgo.getMonth() + 1).toString().padStart(2, '0')
3535
const day = twoDaysAgo.getDate().toString().padStart(2, '0')
3636
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)
3838
return date
3939
}
4040

@@ -43,16 +43,16 @@ export function getCertNotBefore(): Date {
4343
* @param notBefore - The Not Before Date for the Certificate
4444
* @returns The Not After Date for the Certificate
4545
*/
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)
4848
const validityDays = config.validityDays // defaults to 180 days
4949
const daysInMillis = validityDays * 60 * 60 * 24 * 1000
5050
const notAfterDate = new Date(notBefore.getTime() + daysInMillis)
5151
const year = notAfterDate.getFullYear()
5252
const month = (notAfterDate.getMonth() + 1).toString().padStart(2, '0')
5353
const day = notAfterDate.getDate().toString().padStart(2, '0')
5454
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)
5656
return date
5757
}
5858

@@ -61,13 +61,13 @@ export function getCertNotAfter(notBefore: Date): Date {
6161
* @param notBefore - The Not Before Date for the CA
6262
* @returns The Not After Date for the CA
6363
*/
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)
6666
const year = notBefore.getFullYear() + 100
6767
const month = (notBefore.getMonth() + 1).toString().padStart(2, '0')
6868
const day = notBefore.getDate().toString().padStart(2, '0')
6969
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)
7171
return date
7272
}
7373

@@ -76,16 +76,16 @@ export function getCANotAfter(notBefore: Date): Date {
7676
* @returns The Root CA Certificate
7777
*/
7878
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)
8181
const { privateKey, publicKey } = pki.rsa.generateKeyPair(2048)
8282

8383
const mergedOptions = {
8484
...config,
8585
...(options || {}),
8686
}
8787

88-
debugLog('ca', 'Setting certificate attributes')
88+
debugLog('ca', 'Setting certificate attributes', options?.verbose)
8989
const attributes = [
9090
{ shortName: 'C', value: mergedOptions.countryName },
9191
{ shortName: 'ST', value: mergedOptions.stateName },
@@ -94,7 +94,7 @@ export async function createRootCA(options?: TlsOption): Promise<GenerateCertRet
9494
{ shortName: 'CN', value: 'Local Development Root CA' },
9595
]
9696

97-
debugLog('ca', 'Setting certificate extensions')
97+
debugLog('ca', 'Setting certificate extensions', options?.verbose)
9898
const extensions = [
9999
{
100100
name: 'basicConstraints',
@@ -112,23 +112,23 @@ export async function createRootCA(options?: TlsOption): Promise<GenerateCertRet
112112
},
113113
]
114114

115-
debugLog('ca', 'Creating CA certificate')
115+
debugLog('ca', 'Creating CA certificate', options?.verbose)
116116
const caCert = pki.createCertificate()
117117
caCert.publicKey = publicKey
118118
caCert.serialNumber = randomSerialNumber()
119119
caCert.validity.notBefore = getCertNotBefore()
120-
caCert.validity.notAfter = getCANotAfter(caCert.validity.notBefore)
120+
caCert.validity.notAfter = getCANotAfter(caCert.validity.notBefore, options?.verbose)
121121
caCert.setSubject(attributes)
122122
caCert.setIssuer(attributes)
123123
caCert.setExtensions(extensions)
124124

125-
debugLog('ca', 'Signing certificate with SHA-256')
125+
debugLog('ca', 'Signing certificate with SHA-256', options?.verbose)
126126
caCert.sign(privateKey, forge.md.sha256.create())
127127

128128
const pemCert = pki.certificateToPem(caCert)
129129
const pemKey = pki.privateKeyToPem(privateKey)
130130

131-
debugLog('ca', 'Root CA Certificate created successfully')
131+
debugLog('ca', 'Root CA Certificate created successfully', options?.verbose)
132132
return {
133133
certificate: pemCert,
134134
privateKey: pemKey,
@@ -143,30 +143,30 @@ export async function createRootCA(options?: TlsOption): Promise<GenerateCertRet
143143
* @returns The generated certificate
144144
*/
145145
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)
148148

149149
if (!options?.hostCertCN?.trim()) {
150-
debugLog('cert', 'Error: hostCertCN is required')
150+
debugLog('cert', 'Error: hostCertCN is required', options?.verbose)
151151
throw new Error('"hostCertCN" must be a String')
152152
}
153153
if (!options.domain?.trim()) {
154-
debugLog('cert', 'Error: domain is required')
154+
debugLog('cert', 'Error: domain is required', options?.verbose)
155155
throw new Error('"domain" must be a String')
156156
}
157157
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)
159159
throw new Error('"rootCAObject" must be an Object with the properties "certificate" & "privateKey"')
160160
}
161161

162-
debugLog('cert', 'Converting Root CA PEM to forge objects')
162+
debugLog('cert', 'Converting Root CA PEM to forge objects', options?.verbose)
163163
const caCert = pki.certificateFromPem(options.rootCAObject.certificate)
164164
const caKey = pki.privateKeyFromPem(options.rootCAObject.privateKey)
165165

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)
167167
const hostKeys = pki.rsa.generateKeyPair(2048)
168168

169-
debugLog('cert', 'Setting certificate attributes')
169+
debugLog('cert', 'Setting certificate attributes', options?.verbose)
170170
const attributes = [
171171
{ shortName: 'C', value: config.countryName },
172172
{ shortName: 'ST', value: config.stateName },
@@ -175,7 +175,7 @@ export async function generateCert(options?: CertOption): Promise<GenerateCertRe
175175
{ shortName: 'CN', value: '*.localhost' },
176176
]
177177

178-
debugLog('cert', 'Setting certificate extensions')
178+
debugLog('cert', 'Setting certificate extensions', options?.verbose)
179179
const extensions = [
180180
{
181181
name: 'basicConstraints',
@@ -204,26 +204,26 @@ export async function generateCert(options?: CertOption): Promise<GenerateCertRe
204204
},
205205
]
206206

207-
debugLog('cert', 'Creating new host certificate')
207+
debugLog('cert', 'Creating new host certificate', options?.verbose)
208208
const newHostCert = pki.createCertificate()
209209
newHostCert.publicKey = hostKeys.publicKey
210210

211-
debugLog('cert', 'Setting certificate properties')
211+
debugLog('cert', 'Setting certificate properties', options?.verbose)
212212
newHostCert.serialNumber = randomSerialNumber()
213213
newHostCert.validity.notBefore = getCertNotBefore()
214-
newHostCert.validity.notAfter = getCertNotAfter(newHostCert.validity.notBefore)
214+
newHostCert.validity.notAfter = getCertNotAfter(newHostCert.validity.notBefore, options?.verbose)
215215
newHostCert.setSubject(attributes)
216216
newHostCert.setIssuer(caCert.subject.attributes)
217217
newHostCert.setExtensions(extensions)
218218

219-
debugLog('cert', 'Signing certificate with SHA-256')
219+
debugLog('cert', 'Signing certificate with SHA-256', options?.verbose)
220220
newHostCert.sign(caKey, forge.md.sha256.create())
221221

222-
debugLog('cert', 'Converting certificate to PEM format')
222+
debugLog('cert', 'Converting certificate to PEM format', options?.verbose)
223223
const pemHostCert = pki.certificateToPem(newHostCert)
224224
const pemHostKey = pki.privateKeyToPem(hostKeys.privateKey)
225225

226-
debugLog('cert', 'Host certificate generated successfully')
226+
debugLog('cert', 'Host certificate generated successfully', options?.verbose)
227227
return {
228228
certificate: pemHostCert,
229229
privateKey: pemHostKey,
@@ -240,90 +240,90 @@ export async function generateCert(options?: CertOption): Promise<GenerateCertRe
240240
* @returns The path to the stored certificate
241241
*/
242242
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)
244244

245-
debugLog('trust', 'Storing certificate and private key')
245+
debugLog('trust', 'Storing certificate and private key', options?.verbose)
246246
const certPath = storeCert(cert, options)
247247

248-
debugLog('trust', 'Storing CA certificate')
248+
debugLog('trust', 'Storing CA certificate', options?.verbose)
249249
const caCertPath = storeCACert(caCert, options)
250250

251251
const platform = os.platform()
252-
debugLog('trust', `Detected platform: ${platform}`)
252+
debugLog('trust', `Detected platform: ${platform}`, options?.verbose)
253253
const args = 'TC, C, C'
254254

255255
if (platform === 'darwin') {
256-
debugLog('trust', 'Adding certificate to macOS keychain')
256+
debugLog('trust', 'Adding certificate to macOS keychain', options?.verbose)
257257
await runCommand(
258258
`sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ${caCertPath}`,
259259
)
260260
}
261261
else if (platform === 'win32') {
262-
debugLog('trust', 'Adding certificate to Windows certificate store')
262+
debugLog('trust', 'Adding certificate to Windows certificate store', options?.verbose)
263263
await runCommand(`certutil -f -v -addstore -enterprise Root ${caCertPath}`)
264264
}
265265
else if (platform === 'linux') {
266-
debugLog('trust', 'Adding certificate to Linux certificate store')
266+
debugLog('trust', 'Adding certificate to Linux certificate store', options?.verbose)
267267
const rootDirectory = os.homedir()
268268
const targetFileName = 'cert9.db'
269-
debugLog('trust', `Searching for certificate databases in ${rootDirectory}`)
269+
debugLog('trust', `Searching for certificate databases in ${rootDirectory}`, options?.verbose)
270270
const foldersWithFile = findFoldersWithFile(rootDirectory, targetFileName)
271271

272272
for (const folder of foldersWithFile) {
273-
debugLog('trust', `Processing certificate database in ${folder}`)
273+
debugLog('trust', `Processing certificate database in ${folder}`, options?.verbose)
274274
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)
276276
await runCommand(`certutil -d sql:${folder} -D -n ${config.commonName}`)
277277
}
278278
catch (error) {
279-
debugLog('trust', `Warning: Error deleting existing cert: ${error}`)
279+
debugLog('trust', `Warning: Error deleting existing cert: ${error}`, options?.verbose)
280280
console.warn(`Error deleting existing cert: ${error}`)
281281
}
282282

283-
debugLog('trust', `Adding new certificate to ${folder}`)
283+
debugLog('trust', `Adding new certificate to ${folder}`, options?.verbose)
284284
await runCommand(`certutil -d sql:${folder} -A -t ${args} -n ${config.commonName} -i ${caCertPath}`)
285285

286286
log.info(`Cert added to ${folder}`)
287287
}
288288
}
289289
else {
290-
debugLog('trust', `Error: Unsupported platform ${platform}`)
290+
debugLog('trust', `Error: Unsupported platform ${platform}`, options?.verbose)
291291
throw new Error(`Unsupported platform: ${platform}`)
292292
}
293293

294-
debugLog('trust', 'Certificate successfully added to system trust store')
294+
debugLog('trust', 'Certificate successfully added to system trust store', options?.verbose)
295295
return certPath
296296
}
297297

298298
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)
300300
const certPath = options?.customCertPath || config.certPath
301301
const certKeyPath = options?.customCertPath || config.keyPath
302302

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)
305305

306306
// Ensure the directory exists before writing the file
307307
const certDir = path.dirname(certPath)
308308
if (!fs.existsSync(certDir)) {
309-
debugLog('storage', `Creating certificate directory: ${certDir}`)
309+
debugLog('storage', `Creating certificate directory: ${certDir}`, options?.verbose)
310310
fs.mkdirSync(certDir, { recursive: true })
311311
}
312312

313-
debugLog('storage', 'Writing certificate file')
313+
debugLog('storage', 'Writing certificate file', options?.verbose)
314314
fs.writeFileSync(certPath, cert.certificate)
315315

316316
// Ensure the directory exists before writing the file
317317
const certKeyDir = path.dirname(certKeyPath)
318318
if (!fs.existsSync(certKeyDir)) {
319-
debugLog('storage', `Creating private key directory: ${certKeyDir}`)
319+
debugLog('storage', `Creating private key directory: ${certKeyDir}`, options?.verbose)
320320
fs.mkdirSync(certKeyDir, { recursive: true })
321321
}
322322

323-
debugLog('storage', 'Writing private key file')
323+
debugLog('storage', 'Writing private key file', options?.verbose)
324324
fs.writeFileSync(certKeyPath, cert.privateKey)
325325

326-
debugLog('storage', 'Certificate and private key stored successfully')
326+
debugLog('storage', 'Certificate and private key stored successfully', options?.verbose)
327327
return certPath
328328
}
329329

@@ -334,22 +334,22 @@ export function storeCert(cert: Cert, options?: AddCertOption): string {
334334
* @returns The path to the CA Certificate
335335
*/
336336
export function storeCACert(caCert: string, options?: AddCertOption): string {
337-
debugLog('storage', 'Storing CA certificate')
337+
debugLog('storage', 'Storing CA certificate', options?.verbose)
338338
const caCertPath = options?.customCertPath || config.caCertPath
339339

340-
debugLog('storage', `CA certificate path: ${caCertPath}`)
340+
debugLog('storage', `CA certificate path: ${caCertPath}`, options?.verbose)
341341

342342
// Ensure the directory exists before writing the file
343343
const caCertDir = path.dirname(caCertPath)
344344
if (!fs.existsSync(caCertDir)) {
345-
debugLog('storage', `Creating CA certificate directory: ${caCertDir}`)
345+
debugLog('storage', `Creating CA certificate directory: ${caCertDir}`, options?.verbose)
346346
fs.mkdirSync(caCertDir, { recursive: true })
347347
}
348348

349-
debugLog('storage', 'Writing CA certificate file')
349+
debugLog('storage', 'Writing CA certificate file', options?.verbose)
350350
fs.writeFileSync(caCertPath, caCert)
351351

352-
debugLog('storage', 'CA certificate stored successfully')
352+
debugLog('storage', 'CA certificate stored successfully', options?.verbose)
353353
return caCertPath
354354
}
355355

src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export interface CertDetails {
4040

4141
export interface AddCertOption {
4242
customCertPath?: string
43+
verbose?: boolean
4344
}
4445

4546
export interface GenerateCertReturn {

src/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ export function findFoldersWithFile(rootDir: string, fileName: string): string[]
173173
return result
174174
}
175175

176-
export function debugLog(category: string, message: string): void {
177-
if (config.verbose) {
176+
export function debugLog(category: string, message: string, verbose?: boolean): void {
177+
if (verbose || config.verbose) {
178178
// eslint-disable-next-line no-console
179179
console.debug(`[rpx:${category}] ${message}`)
180180
}

0 commit comments

Comments
 (0)