UNPKG

devcert

Version:

Generate trusted local SSL/TLS certificates for local SSL development

119 lines (102 loc) 4.51 kB
import path from 'path'; import { unlinkSync as rm, writeFileSync as writeFile, readFileSync as readFile } from 'fs'; import { sync as mkdirp } from 'mkdirp'; import { template as makeTemplate } from 'lodash'; import applicationConfigPath = require('application-config-path'); import eol from 'eol'; import {mktmp, numericHash} from './utils'; // Platform shortcuts export const isMac = process.platform === 'darwin'; export const isLinux = process.platform === 'linux'; export const isWindows = process.platform === 'win32'; // Common paths export const configDir = applicationConfigPath('devcert'); export const configPath: (...pathSegments: string[]) => string = path.join.bind(path, configDir); const getFilteredDomains = (domains: string[]) => Array.from( domains .sort((a, b) => b.length - a.length) .reduce((filteredList, domain) => Array.from(filteredList) .reduce((matches, item) => { if (item.indexOf(domain) > -1) { matches.add(domain); } else if (domain.indexOf(item) === -1 && item.indexOf(domain) === -1) { matches.add(item); matches.add(domain); } else { matches.add(item); } return matches; }, new Set() ), new Set([domains[0]]) ) ).sort(); export const getStableDomainPath = (domains: string[]) => domains.length === 1 ? domains[0] : 'san-' + numericHash(getFilteredDomains(domains).join('')); export const domainsDir = configPath('domains'); export const pathForDomain: (domain: string, ...pathSegments: string[]) => string = path.join.bind(path, domainsDir) export const caVersionFile = configPath('devcert-ca-version'); export const opensslSerialFilePath = configPath('certificate-authority', 'serial'); export const opensslDatabaseFilePath = configPath('certificate-authority', 'index.txt'); export const caSelfSignConfig = path.join(__dirname, '../openssl-configurations/certificate-authority-self-signing.conf'); function generateSubjectAltNames(domains: string[]): string { return domains .reduce((dnsEntries, domain) => dnsEntries.concat([ `DNS.${dnsEntries.length + 1} = ${domain}`, `DNS.${dnsEntries.length + 2} = *.${domain}`, ]), [] as string[]) .join("\r\n"); } export function withDomainSigningRequestConfig(domains: string[], cb: (filepath: string) => void) { const domain = domains[0]; const subjectAltNames = generateSubjectAltNames(domains); let tmpFile = mktmp(); let source = readFile(path.join(__dirname, '../openssl-configurations/domain-certificate-signing-requests.conf'), 'utf-8'); let template = makeTemplate(source); let result = template({domain, subjectAltNames}); writeFile(tmpFile, eol.auto(result)); cb(tmpFile); rm(tmpFile); } export function withDomainCertificateConfig(domains: string[], cb: (filepath: string) => void) { const domainPath = getStableDomainPath(domains); const subjectAltNames = generateSubjectAltNames(domains); let tmpFile = mktmp(); let source = readFile(path.join(__dirname, '../openssl-configurations/domain-certificates.conf'), 'utf-8'); let template = makeTemplate(source); let result = template({ subjectAltNames, serialFile: opensslSerialFilePath, databaseFile: opensslDatabaseFilePath, domainDir: pathForDomain(domainPath) }); writeFile(tmpFile, eol.auto(result)); cb(tmpFile); rm(tmpFile); } // confTemplate = confTemplate.replace(/DATABASE_PATH/, configPath('index.txt').replace(/\\/g, '\\\\')); // confTemplate = confTemplate.replace(/SERIAL_PATH/, configPath('serial').replace(/\\/g, '\\\\')); // confTemplate = eol.auto(confTemplate); export const rootCADir = configPath('certificate-authority'); export const rootCAKeyPath = configPath('certificate-authority', 'private-key.key'); export const rootCACertPath = configPath('certificate-authority', 'certificate.cert'); // Exposed for uninstallation purposes. export function getLegacyConfigDir(): string { if (isWindows && process.env.LOCALAPPDATA) { return path.join(process.env.LOCALAPPDATA, 'devcert', 'config'); } else { let uid = process.getuid && process.getuid(); let userHome = (isLinux && uid === 0) ? path.resolve('/usr/local/share') : require('os').homedir(); return path.join(userHome, '.config', 'devcert'); } } export function ensureConfigDirs() { mkdirp(configDir); mkdirp(domainsDir); mkdirp(rootCADir); } ensureConfigDirs();