UNPKG

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