| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.SSLGenerateCommand = void 0;
- const tslib_1 = require("tslib");
- const utils_fs_1 = require("@ionic/utils-fs");
- const utils_terminal_1 = require("@ionic/utils-terminal");
- const lodash = tslib_1.__importStar(require("lodash"));
- const path = tslib_1.__importStar(require("path"));
- const color_1 = require("../../lib/color");
- const errors_1 = require("../../lib/errors");
- const base_1 = require("./base");
- const DEFAULT_BITS = '2048';
- const DEFAULT_COUNTRY_NAME = 'US';
- const DEFAULT_STATE_OR_PROVINCE_NAME = 'Wisconsin';
- const DEFAULT_LOCALITY_NAME = 'Madison';
- const DEFAULT_ORGANIZATION_NAME = 'Ionic';
- const DEFAULT_COMMON_NAME = 'localhost';
- const DEFAULT_KEY_FILE = '.ionic/ssl/key.pem';
- const DEFAULT_CERT_FILE = '.ionic/ssl/cert.pem';
- class SSLGenerateCommand extends base_1.SSLBaseCommand {
- getDefaultKeyPath() {
- return path.resolve(this.project ? this.project.directory : '', DEFAULT_KEY_FILE);
- }
- getDefaultCertPath() {
- return path.resolve(this.project ? this.project.directory : '', DEFAULT_CERT_FILE);
- }
- async getMetadata() {
- const defaultKeyPath = (0, utils_terminal_1.prettyPath)(this.getDefaultKeyPath());
- const defaultCertPath = (0, utils_terminal_1.prettyPath)(this.getDefaultCertPath());
- return {
- name: 'generate',
- type: 'project',
- summary: 'Generates an SSL key & certificate',
- // TODO: document how to add trusted certs
- description: `
- Uses OpenSSL to create a self-signed certificate for ${(0, color_1.strong)('localhost')} (by default).
- After the certificate is generated, you will still need to add it to your system or browser as a trusted certificate.
- The default directory for ${(0, color_1.input)('--key-path')} and ${(0, color_1.input)('--cert-path')} is ${(0, color_1.input)('.ionic/ssl/')}.
- Deprecated. Developers should generate an SSL certificate locally and then configure it using their project tooling such as Vite or Angular CLI.
- `,
- options: [
- {
- name: 'key-path',
- summary: 'Destination of private key file',
- default: defaultKeyPath,
- spec: { value: 'path' },
- },
- {
- name: 'cert-path',
- summary: 'Destination of certificate file',
- default: defaultCertPath,
- spec: { value: 'path' },
- },
- {
- name: 'country-name',
- summary: 'The country name (C) of the SSL certificate',
- default: DEFAULT_COUNTRY_NAME,
- groups: ["advanced" /* MetadataGroup.ADVANCED */],
- spec: { value: 'C' },
- },
- {
- name: 'state-or-province-name',
- summary: 'The state or province name (ST) of the SSL certificate',
- default: DEFAULT_STATE_OR_PROVINCE_NAME,
- groups: ["advanced" /* MetadataGroup.ADVANCED */],
- spec: { value: 'ST' },
- },
- {
- name: 'locality-name',
- summary: 'The locality name (L) of the SSL certificate',
- default: DEFAULT_LOCALITY_NAME,
- groups: ["advanced" /* MetadataGroup.ADVANCED */],
- spec: { value: 'L' },
- },
- {
- name: 'organization-name',
- summary: 'The organization name (O) of the SSL certificate',
- default: DEFAULT_ORGANIZATION_NAME,
- groups: ["advanced" /* MetadataGroup.ADVANCED */],
- spec: { value: 'O' },
- },
- {
- name: 'common-name',
- summary: 'The common name (CN) of the SSL certificate',
- default: DEFAULT_COMMON_NAME,
- groups: ["advanced" /* MetadataGroup.ADVANCED */],
- spec: { value: 'CN' },
- },
- {
- name: 'bits',
- summary: 'Number of bits in the key',
- aliases: ['b'],
- default: DEFAULT_BITS,
- groups: ["advanced" /* MetadataGroup.ADVANCED */],
- },
- ],
- groups: ["deprecated" /* MetadataGroup.DEPRECATED */],
- };
- }
- async preRun(inputs, options) {
- await this.checkForOpenSSL();
- }
- async run(inputs, options) {
- if (!this.project) {
- throw new errors_1.FatalException(`Cannot run ${(0, color_1.input)('ionic ssl generate')} outside a project directory.`);
- }
- const keyPath = path.resolve(options['key-path'] ? String(options['key-path']) : this.getDefaultKeyPath());
- const keyPathDir = path.dirname(keyPath);
- const certPath = path.resolve(options['cert-path'] ? String(options['cert-path']) : this.getDefaultCertPath());
- const certPathDir = path.dirname(certPath);
- const bits = options['bits'] ? String(options['bits']) : DEFAULT_BITS;
- const countryName = options['country-name'] ? String(options['country-name']) : DEFAULT_COUNTRY_NAME;
- const stateOrProvinceName = options['state-or-province-name'] ? String(options['state-or-province-name']) : DEFAULT_STATE_OR_PROVINCE_NAME;
- const localityName = options['locality-name'] ? String(options['locality-name']) : DEFAULT_LOCALITY_NAME;
- const organizationName = options['organization-name'] ? String(options['organization-name']) : DEFAULT_ORGANIZATION_NAME;
- const commonName = options['common-name'] ? String(options['common-name']) : DEFAULT_COMMON_NAME;
- await this.ensureDirectory(keyPathDir);
- await this.ensureDirectory(certPathDir);
- const overwriteKeyPath = await this.checkExistingFile(keyPath);
- const overwriteCertPath = await this.checkExistingFile(certPath);
- if (overwriteKeyPath) {
- await (0, utils_fs_1.unlink)(keyPath);
- }
- if (overwriteCertPath) {
- await (0, utils_fs_1.unlink)(certPath);
- }
- const cnf = { bits, countryName, stateOrProvinceName, localityName, organizationName, commonName };
- const cnfPath = await this.writeConfig(cnf);
- await this.env.shell.run('openssl', ['req', '-x509', '-newkey', `rsa:${bits}`, '-nodes', '-subj', this.formatSubj(cnf), '-reqexts', 'SAN', '-extensions', 'SAN', '-config', cnfPath, '-days', '365', '-keyout', keyPath, '-out', certPath], {});
- this.env.log.nl();
- this.env.log.rawmsg(`Key: ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(keyPath))}\n` +
- `Cert: ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(certPath))}\n\n`);
- this.env.log.ok('Generated key & certificate!');
- }
- formatSubj(cnf) {
- const subjNames = new Map([
- ['countryName', 'C'],
- ['stateOrProvinceName', 'ST'],
- ['localityName', 'L'],
- ['organizationName', 'O'],
- ['commonName', 'CN'],
- ]);
- return '/' + lodash.toPairs(cnf).filter(([k]) => subjNames.has(k)).map(([k, v]) => `${subjNames.get(k)}=${v}`).join('/');
- }
- async ensureDirectory(p) {
- if (!(await (0, utils_fs_1.pathExists)(p))) {
- await (0, utils_fs_1.mkdirp)(p, 0o700);
- this.env.log.msg(`Created ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(p))} directory for you.`);
- }
- }
- async checkExistingFile(p) {
- if (await (0, utils_fs_1.pathExists)(p)) {
- const confirm = await this.env.prompt({
- type: 'confirm',
- name: 'confirm',
- message: `Key ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(p))} exists. Overwrite?`,
- });
- if (confirm) {
- return true;
- }
- else {
- throw new errors_1.FatalException(`Not overwriting ${(0, color_1.strong)((0, utils_terminal_1.prettyPath)(p))}.`);
- }
- }
- }
- async writeConfig({ bits, countryName, stateOrProvinceName, localityName, organizationName, commonName }) {
- const cnf = `
- [req]
- default_bits = ${bits}
- distinguished_name = req_distinguished_name
- [req_distinguished_name]
- countryName = ${countryName}
- stateOrProvinceName = ${stateOrProvinceName}
- localityName = ${localityName}
- organizationName = ${organizationName}
- commonName = ${commonName}
- [SAN]
- subjectAltName=DNS:${commonName}
- `.trim();
- const p = (0, utils_fs_1.tmpfilepath)('ionic-ssl');
- await (0, utils_fs_1.writeFile)(p, cnf, { encoding: 'utf8' });
- return p;
- }
- }
- exports.SSLGenerateCommand = SSLGenerateCommand;
|