From c78898e4c10dd1701467d2e42e3f72bd8f2a352f Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Tue, 7 Jul 2026 00:12:37 +0800 Subject: [PATCH] =?UTF-8?q?perf(certd-server):=20=E4=BD=BF=E7=94=A8=20jks-?= =?UTF-8?q?go=E8=BD=AC=E6=8D=A2jks=E8=AF=81=E4=B9=A6=EF=BC=8C=E5=A4=A7?= =?UTF-8?q?=E5=B9=85=E7=B2=BE=E7=AE=80=E9=95=9C=E5=83=8F=E5=A4=A7=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/plugin-lib/src/cert/convert.ts | 101 +++++++++++++++--- packages/ui/Dockerfile | 30 ++++-- packages/ui/certd-server/.env | 1 + packages/ui/certd-server/.gitignore | 1 + packages/ui/certd-server/src/configuration.ts | 2 + .../plugin/cert-plugin/base-convert.ts | 2 +- 6 files changed, 117 insertions(+), 20 deletions(-) diff --git a/packages/plugins/plugin-lib/src/cert/convert.ts b/packages/plugins/plugin-lib/src/cert/convert.ts index 211c7ff17..c458fafe5 100644 --- a/packages/plugins/plugin-lib/src/cert/convert.ts +++ b/packages/plugins/plugin-lib/src/cert/convert.ts @@ -1,4 +1,4 @@ -import { ILogger, sp } from "@certd/basic"; +import { ILogger, sp, http } from "@certd/basic"; import type { CertInfo } from "./cert-reader.js"; import { CertReader, CertReaderHandleContext } from "./cert-reader.js"; import path from "path"; @@ -52,6 +52,81 @@ export class CertConverter { }); } + async getJksGoPath(): Promise { + const osType = process.platform === "win32" ? "windows" : "linux"; + const jksGoDir = path.resolve("./tools/jks-go"); + const JKS_GO_VERSION = process.env.JKS_GO_VERSION || "1.0.0"; + + const versionFile = path.join(jksGoDir, "version"); + const finalPath = path.join(jksGoDir, osType === "windows" ? "jks-go.exe" : "jks-go"); + + let needDownload = false; + if (!fs.existsSync(finalPath)) { + needDownload = true; + } else if (!fs.existsSync(versionFile)) { + needDownload = true; + } else { + const currentVersion = fs.readFileSync(versionFile, "utf-8").trim(); + if (currentVersion !== JKS_GO_VERSION) { + this.logger.info(`jks-go版本不匹配,当前版本:${currentVersion},期望版本:${JKS_GO_VERSION},准备重新下载`); + needDownload = true; + } + } + + if (!needDownload) { + return finalPath; + } + + if (!fs.existsSync(jksGoDir)) { + fs.mkdirSync(jksGoDir, { recursive: true }); + } + + const arch = process.arch; + let platformArch = "amd64"; + if (arch === "arm64") { + platformArch = "arm64"; + } else if (arch === "arm") { + platformArch = "arm_armv7"; + } + + let jksGoFileName = `jks-go_${osType}_${platformArch}`; + if (osType === "windows") { + jksGoFileName += ".exe"; + } + + const jksGoFilePath = path.join(jksGoDir, jksGoFileName); + this.logger.info(`jks-go文件不存在或版本不匹配,准备下载:${jksGoFileName}`); + const downloadUrl = `https://atomgit.com/certd/jks-go/releases/download/v${JKS_GO_VERSION}/${jksGoFileName}`; + // https://atomgit.com/certd/jks-go/releases/download/v1.0.2/jks-go_linux_amd64 + const response = await http.request({ + url: downloadUrl, + method: "GET", + responseType: "arraybuffer", + logRes: false, + logParams: false, + logData: false, + }); + + const buffer = Buffer.from(response); + fs.writeFileSync(jksGoFilePath, buffer); + this.logger.info("下载jks-go成功"); + + if (fs.existsSync(finalPath)) { + fs.unlinkSync(finalPath); + } + fs.copyFileSync(jksGoFilePath, finalPath); + if (osType === "linux") { + await sp.spawn({ + cmd: `chmod +x ${finalPath}`, + }); + } + + fs.writeFileSync(versionFile, JKS_GO_VERSION, "utf-8"); + this.logger.info(`jks-go版本已更新为:${JKS_GO_VERSION}`); + + return finalPath; + } + private async convertPfx(opts: CertReaderHandleContext, pfxPassword: string, pfxArgs: string) { const { tmpCrtPath, tmpKeyPath } = opts; @@ -118,22 +193,22 @@ export class CertConverter { const jksPassword = pfxPassword || "123456"; try { const randomStr = Math.floor(Math.random() * 1000000) + ""; + const { tmpOnePath } = opts; - const p12Path = path.join(os.tmpdir(), "/certd/tmp/", randomStr + `_cert.p12`); - const { tmpCrtPath, tmpKeyPath } = opts; - let passwordArg = "-passout pass:"; - if (jksPassword) { - passwordArg = `-password pass:${jksPassword}`; - } - await this.exec(`openssl pkcs12 -export -in ${tmpCrtPath} -inkey ${tmpKeyPath} -out ${p12Path} -name certd ${passwordArg}`); - - const jksPath = path.join(os.tmpdir(), "/certd/tmp/", randomStr + `_cert.jks`); - const dir = path.dirname(jksPath); + const bundlePath = path.join(os.tmpdir(), "/certd/tmp/", randomStr + `_bundle.pem`); + const dir = path.dirname(bundlePath); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } - await this.exec(`keytool -importkeystore -srckeystore ${p12Path} -srcstoretype PKCS12 -srcstorepass "${jksPassword}" -destkeystore ${jksPath} -deststoretype JKS -deststorepass "${jksPassword}" `); - fs.unlinkSync(p12Path); + + const crtContent = fs.readFileSync(tmpOnePath); + fs.writeFileSync(bundlePath, crtContent); + + const jksPath = path.join(os.tmpdir(), "/certd/tmp/", randomStr + `_cert.jks`); + + const jksGoPath = await this.getJksGoPath(); + await this.exec(`${jksGoPath} -importkeystore -srckeystore ${bundlePath} -srcstoretype PEM -destkeystore ${jksPath} -deststorepass "${jksPassword}"`); + fs.unlinkSync(bundlePath); const fileBuffer = fs.readFileSync(jksPath); const certBase64 = fileBuffer.toString("base64"); diff --git a/packages/ui/Dockerfile b/packages/ui/Dockerfile index 6895e1e9c..1b72ff5e0 100644 --- a/packages/ui/Dockerfile +++ b/packages/ui/Dockerfile @@ -38,21 +38,16 @@ RUN if [ -f /etc/debian_version ]; then \ apt-get update \ && apt-get install -y --no-install-recommends \ ca-certificates \ - gnupg \ wget \ openssl \ netcat-openbsd \ iputils-ping \ dnsutils \ iproute2 \ - && wget -O - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | tee /usr/share/keyrings/adoptium.gpg > /dev/null \ - && echo "deb [signed-by=/usr/share/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb bookworm main" | tee /etc/apt/sources.list.d/adoptium.list \ - && apt-get update \ - && apt-get install -y --no-install-recommends temurin-8-jre \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*; \ elif [ -f /etc/alpine-release ]; then \ - apk add --no-cache openssl openjdk8-jre; \ + apk add --no-cache openssl wget ca-certificates; \ else \ echo "Unsupported base image"; exit 1; \ fi @@ -63,6 +58,9 @@ ENV TERM=xterm ENV LEGO_VERSION=4.30.1 ENV LEGO_DOWNLOAD_DIR=/app/tools/lego +ENV JKS_GO_VERSION=1.0.3 +ENV JKS_GO_DOWNLOAD_DIR=/app/tools/jks-go + ENV ALIYUN_CLIENT_CONNECT_TIMEOUT=10000 ENV ALIYUN_CLIENT_READ_TIMEOUT=20000 @@ -79,6 +77,26 @@ RUN ARCH=$(uname -m) && \ echo "Unsupported architecture: $ARCH"; \ fi +RUN mkdir -p $JKS_GO_DOWNLOAD_DIR + +# 根据架构下载jks-go +RUN ARCH=$(uname -m) && \ + if [ "$ARCH" = "x86_64" ]; then \ + wget -O $JKS_GO_DOWNLOAD_DIR/jks-go_linux_amd64 https://github.com/certd/jks-go/releases/download/v${JKS_GO_VERSION}/jks-go_linux_amd64 && \ + chmod +x $JKS_GO_DOWNLOAD_DIR/jks-go_linux_amd64 && \ + ln -s $JKS_GO_DOWNLOAD_DIR/jks-go_linux_amd64 /usr/local/bin/jks-go; \ + elif [ "$ARCH" = "aarch64" ]; then \ + wget -O $JKS_GO_DOWNLOAD_DIR/jks-go_linux_arm64 https://github.com/certd/jks-go/releases/download/v${JKS_GO_VERSION}/jks-go_linux_arm64 && \ + chmod +x $JKS_GO_DOWNLOAD_DIR/jks-go_linux_arm64 && \ + ln -s $JKS_GO_DOWNLOAD_DIR/jks-go_linux_arm64 /usr/local/bin/jks-go; \ + elif [ "$ARCH" = "armv7l" ]; then \ + wget -O $JKS_GO_DOWNLOAD_DIR/jks-go_linux_arm_armv7 https://github.com/certd/jks-go/releases/download/v${JKS_GO_VERSION}/jks-go_linux_arm_armv7 && \ + chmod +x $JKS_GO_DOWNLOAD_DIR/jks-go_linux_arm_armv7 && \ + ln -s $JKS_GO_DOWNLOAD_DIR/jks-go_linux_arm_armv7 /usr/local/bin/jks-go; \ + else \ + echo "Unsupported architecture: $ARCH"; \ + fi + ENV TZ=Asia/Shanghai ENV NODE_ENV=production ENV MIDWAY_SERVER_ENV=production diff --git a/packages/ui/certd-server/.env b/packages/ui/certd-server/.env index 2a245bd94..f57cefdfc 100644 --- a/packages/ui/certd-server/.env +++ b/packages/ui/certd-server/.env @@ -1,2 +1,3 @@ LEGO_VERSION=4.30.1 +JKS_GO_VERSION=1.0.3 certd_plugin_loadmode=dev \ No newline at end of file diff --git a/packages/ui/certd-server/.gitignore b/packages/ui/certd-server/.gitignore index cc653c1f3..535fc47c2 100755 --- a/packages/ui/certd-server/.gitignore +++ b/packages/ui/certd-server/.gitignore @@ -20,6 +20,7 @@ run/ .env.pgpl.yaml tools/lego/* +tools/jks-go !tools/lego/readme.md test.mjs isolate-*.log diff --git a/packages/ui/certd-server/src/configuration.ts b/packages/ui/certd-server/src/configuration.ts index fda204f11..0c6a20414 100644 --- a/packages/ui/certd-server/src/configuration.ts +++ b/packages/ui/certd-server/src/configuration.ts @@ -132,5 +132,7 @@ export class MainConfiguration { logger.info(text); }); logger.info("当前环境:", this.app.getEnv()); // prod + + } } diff --git a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts index 589bf0024..05cdb4bbb 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts @@ -100,7 +100,7 @@ export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin { } this._result.pipelinePrivateVars.cert = cert; - if (isNew || !cert.pfx) { + if (isNew || !cert.pfx || !cert.der || !cert.jks || !cert.p7b) { try { const converter = new CertConverter({ logger: this.logger }); const res = await converter.convert({