UNPKG

2.78 kBJavaScriptView Raw
1// @flow
2import type {FileSystem} from '@parcel/fs';
3import forge from 'node-forge';
4import path from 'path';
5import logger from '@parcel/logger';
6
7export default async function generateCertificate(
8 fs: FileSystem,
9 cacheDir: string
10) {
11 let certDirectory = cacheDir;
12
13 const privateKeyPath = path.join(certDirectory, 'private.pem');
14 const certPath = path.join(certDirectory, 'primary.crt');
15 const cachedKey =
16 (await fs.exists(privateKeyPath)) && (await fs.readFile(privateKeyPath));
17 const cachedCert =
18 (await fs.exists(certPath)) && (await fs.readFile(certPath));
19
20 if (cachedKey && cachedCert) {
21 return {
22 key: cachedKey,
23 cert: cachedCert
24 };
25 }
26
27 logger.progress('Generating SSL Certificate...');
28
29 const pki = forge.pki;
30 const keys = pki.rsa.generateKeyPair(2048);
31 const cert = pki.createCertificate();
32
33 cert.publicKey = keys.publicKey;
34 cert.serialNumber = Date.now().toString();
35 cert.validity.notBefore = new Date();
36 cert.validity.notAfter = new Date();
37 cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 1);
38
39 const attrs = [
40 {
41 name: 'commonName',
42 value: 'parceljs.org'
43 },
44 {
45 name: 'countryName',
46 value: 'US'
47 },
48 {
49 shortName: 'ST',
50 value: 'Virginia'
51 },
52 {
53 name: 'localityName',
54 value: 'Blacksburg'
55 },
56 {
57 name: 'organizationName',
58 value: 'parcelBundler'
59 },
60 {
61 shortName: 'OU',
62 value: 'Test'
63 }
64 ];
65
66 cert.setSubject(attrs);
67 cert.setIssuer(attrs);
68 cert.setExtensions([
69 {
70 name: 'basicConstraints',
71 cA: true
72 },
73 {
74 name: 'keyUsage',
75 keyCertSign: true,
76 digitalSignature: true,
77 nonRepudiation: true,
78 keyEncipherment: true,
79 dataEncipherment: true
80 },
81 {
82 name: 'extKeyUsage',
83 serverAuth: true,
84 clientAuth: true,
85 codeSigning: true,
86 emailProtection: true,
87 timeStamping: true
88 },
89 {
90 name: 'nsCertType',
91 client: true,
92 server: true,
93 email: true,
94 objsign: true,
95 sslCA: true,
96 emailCA: true,
97 objCA: true
98 },
99 {
100 name: 'subjectAltName',
101 altNames: [
102 {
103 type: 6, // URI
104 value: 'http://example.org/webid#me'
105 },
106 {
107 type: 7, // IP
108 ip: '127.0.0.1'
109 }
110 ]
111 },
112 {
113 name: 'subjectKeyIdentifier'
114 }
115 ]);
116
117 cert.sign(keys.privateKey, forge.md.sha256.create());
118
119 const privPem = pki.privateKeyToPem(keys.privateKey);
120 const certPem = pki.certificateToPem(cert);
121
122 await fs.mkdirp(certDirectory);
123 await fs.writeFile(privateKeyPath, privPem);
124 await fs.writeFile(certPath, certPem);
125
126 return {
127 key: privPem,
128 cert: certPem
129 };
130}