HEX
Server: Apache/2.4.41 (Ubuntu)
System: Linux ip-172-31-42-149 5.15.0-1084-aws #91~20.04.1-Ubuntu SMP Fri May 2 07:00:04 UTC 2025 aarch64
User: ubuntu (1000)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //proc/self/root/usr/local/lib/node_modules/@ionic/cli/commands/ssl/generate.js
"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;