-
Notifications
You must be signed in to change notification settings - Fork 73
/
index.ts
94 lines (80 loc) · 3.11 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { readFileSync as readFile, readdirSync as readdir, existsSync as exists } from 'fs';
import createDebug from 'debug';
import { sync as commandExists } from 'command-exists';
import rimraf from 'rimraf';
import {
isMac,
isLinux,
isWindows,
pathForDomain,
domainsDir,
rootCAKeyPath
} from './constants';
import currentPlatform from './platforms';
import installCertificateAuthority from './certificate-authority';
import generateDomainCertificate from './certificates';
import UI, { UserInterface } from './user-interface';
const debug = createDebug('devcert');
export interface Options {
skipCertutilInstall?: true,
skipHostsFile?: true,
ui?: UserInterface
}
/**
* Request an SSL certificate for the given app name signed by the devcert root
* certificate authority. If devcert has previously generated a certificate for
* that app name on this machine, it will reuse that certificate.
*
* If this is the first time devcert is being run on this machine, it will
* generate and attempt to install a root certificate authority.
*
* Returns a promise that resolves with { key, cert }, where `key` and `cert`
* are Buffers with the contents of the certificate private key and certificate
* file, respectively
*/
export async function certificateFor(domains: string | string[], options: Options = {}) {
const domain = Array.isArray(domains) ? domains[0] : domains;
debug(`Certificate requested for ${ domains }. Skipping certutil install: ${ Boolean(options.skipCertutilInstall) }. Skipping hosts file: ${ Boolean(options.skipHostsFile) }`);
if (options.ui) {
Object.assign(UI, options.ui);
}
if (!isMac && !isLinux && !isWindows) {
throw new Error(`Platform not supported: "${ process.platform }"`);
}
if (!commandExists('openssl')) {
throw new Error('OpenSSL not found: OpenSSL is required to generate SSL certificates - make sure it is installed and available in your PATH');
}
let domainKeyPath = pathForDomain(domain, `private-key.key`);
let domainCertPath = pathForDomain(domain, `certificate.crt`);
if (!exists(rootCAKeyPath)) {
debug('Root CA is not installed yet, so it must be our first run. Installing root CA ...');
await installCertificateAuthority(options);
}
if (!exists(pathForDomain(domain, `certificate.crt`))) {
debug(`Can't find certificate file for ${ domains }, so it must be the first request for ${ domains }. Generating and caching ...`);
await generateDomainCertificate(domains);
}
if (!options.skipHostsFile) {
if (Array.isArray(domains)) {
domains.forEach(async (domain) => {
await currentPlatform.addDomainToHostFileIfMissing(domain);
})
} else {
await currentPlatform.addDomainToHostFileIfMissing(domain);
}
}
debug(`Returning domain certificate`);
return {
key: readFile(domainKeyPath),
cert: readFile(domainCertPath)
};
}
export function hasCertificateFor(domain: string) {
return exists(pathForDomain(domain, `certificate.crt`));
}
export function configuredDomains() {
return readdir(domainsDir);
}
export function removeDomain(domain: string) {
return rimraf.sync(pathForDomain(domain));
}