@lark-project/cli
Version:
飞书项目插件开发工具
107 lines (106 loc) • 4.17 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTempCert = void 0;
const path_1 = __importDefault(require("path"));
const os_1 = __importDefault(require("os"));
const fs_extra_1 = require("fs-extra");
const cert_parser_1 = require("./cert-parser");
const key_chain_1 = require("./key-chain");
const mkcert_1 = require("mkcert");
const fs_extra_2 = require("fs-extra");
const logger_1 = require("../logger");
const ROOT_CA_DIR = path_1.default.join(os_1.default.homedir(), '.Meegle_Developer_Platform_CA');
const ROOT_CA_FILE_NAME = 'meegle_root_ca';
const ROOT_CA_COMMON_NAME = 'MeegleDeveloperPlatform';
const ROOT_CA_KEY_PATH = path_1.default.join(ROOT_CA_DIR, `${ROOT_CA_FILE_NAME}.key`);
const ROOT_CA_CERT_PATH = path_1.default.join(ROOT_CA_DIR, `${ROOT_CA_FILE_NAME}.crt`);
const ROOT_CA_OPTIONS = {
organization: ROOT_CA_COMMON_NAME,
countryCode: 'CN',
state: 'ZJ',
locality: 'HZ',
validity: 365,
};
async function getRemoteCA() {
const caCertUrl = 'https://sf3-cn.feishucdn.com/obj/meego-static/front/isv/meegle_root_ca.crt';
const caKeyUrl = 'https://sf3-cn.feishucdn.com/obj/meego-static/front/isv/meegle_root_ca.key';
const [cert, key] = await Promise.all([
fetch(caCertUrl).then(res => res.text()),
fetch(caKeyUrl).then(res => res.text()),
]);
return {
key,
cert,
};
}
async function getOrCreateCA() {
try {
// 本机已添加并信任根证书
if ((0, key_chain_1.isTrustedCert)(ROOT_CA_COMMON_NAME)) {
const keyStr = (0, fs_extra_1.readFileSync)(ROOT_CA_KEY_PATH).toString();
const certStr = (0, fs_extra_1.readFileSync)(ROOT_CA_CERT_PATH).toString();
const cert = (0, cert_parser_1.readCertFromCertStr)(certStr);
// 如 CA 已过期则走重新生成证书的逻辑
if ((0, cert_parser_1.isValidCert)(cert)) {
logger_1.logger.info(`Root CA ${ROOT_CA_COMMON_NAME} has been trusted.`);
return {
key: keyStr,
cert: certStr,
};
}
else {
logger_1.logger.warn(`Root CA ${ROOT_CA_COMMON_NAME} has expired, will regenerate it.`);
}
}
}
catch (e) {
// do nothing, 钥匙串有证书,实际文件被删除,读取不存在文件异常则走重新生成证书的逻辑
}
try {
// 本地自签生成
const CA = await (0, mkcert_1.createCA)(ROOT_CA_OPTIONS);
// 写入本地文件
if (!(0, fs_extra_2.existsSync)(ROOT_CA_DIR)) {
(0, fs_extra_2.mkdirSync)(ROOT_CA_DIR);
}
(0, fs_extra_2.writeFileSync)(ROOT_CA_KEY_PATH, CA.key);
(0, fs_extra_2.writeFileSync)(ROOT_CA_CERT_PATH, CA.cert);
console.log(`Root CA generated into ${ROOT_CA_DIR}`);
try {
(0, key_chain_1.addToKeyChain)(ROOT_CA_CERT_PATH);
}
catch (e) {
console.warn('Root CA add to key chain failed, please Please add and trust manually');
}
return CA;
}
catch (e) {
// 兜底从远端拉根证书
const remoteCA = await getRemoteCA();
const pkiCert = (0, cert_parser_1.readCertFromCertStr)(Buffer.from(remoteCA.cert, 'utf8').toString());
if ((0, cert_parser_1.isValidCert)(pkiCert)) {
return remoteCA;
}
else {
console.error(`Please submit an issue to ask for help: 'Update remote ${ROOT_CA_COMMON_NAME} CA immediately'`);
throw new Error(`Remote ${ROOT_CA_COMMON_NAME} CA has expired`);
}
}
}
async function createTempCert(domains = ['localhost', '127.0.0.1', '0.0.0.0']) {
const CA = await getOrCreateCA();
const { cert, key } = await (0, mkcert_1.createCert)({
domains,
validity: 365,
ca: CA,
});
return {
cert,
key,
ca: CA.cert,
};
}
exports.createTempCert = createTempCert;