Files
certd/packages/ui/certd-server/src/plugins/plugin-cert/plugin/cert-plugin/base-convert.ts
T

159 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { AbstractTaskPlugin, IContext, Step, TaskInput, TaskOutput } from "@certd/pipeline";
import { CertConverter, CertReader, EVENT_CERT_APPLY_SUCCESS } from "@certd/plugin-lib";
import dayjs from "dayjs";
import type { CertInfo } from "./acme.js";
export abstract class CertApplyBaseConvertPlugin extends AbstractTaskPlugin {
@TaskInput({
title: "证书域名",
component: {
name: "domain-selector",
vModel: "value",
mode: "tags",
// open: false,
placeholder: "请输入证书域名/IP,比如:foo.com , *.foo.com , *.sub.foo.com , *.bar.com , 123.123.123.123",
tokenSeparators: [",", " ", "", "、", "|"],
search: true,
pager: true,
},
rules: [{ type: "domains" }],
required: true,
col: {
span: 24,
},
order: -999,
helper:
"1、支持多个域名打到一个证书上,例如: foo.com*.foo.com*.bar.com\n" +
"2、子域名被通配符包含的不要填写,例如:www.foo.com已经被*.foo.com包含,不要填写www.foo.com\n" +
"3、泛域名只能通配*号那一级(*.foo.com的证书不能用于foo.com且不能用于xxx.yyy.foo.com\n" +
"4、输入一个,空格之后,再输入下一个 \n" +
"5、如果设置了子域托管解析(比如免费的二级域名托管在CF或者阿里云),请先[设置托管子域名](#/certd/pipeline/subDomain)",
})
domains!: string[];
@TaskInput({
title: "证书加密密码",
component: {
name: "input-password",
vModel: "value",
},
required: false,
order: 100,
helper: "转换成PFX、jks格式证书是否需要加密\n不传则pfx格式默认空密码,jks格式默认123456",
})
pfxPassword!: string;
@TaskInput({
title: "PFX证书转换参数",
value: "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES",
component: {
name: "a-auto-complete",
vModel: "value",
options: [
{ value: "", label: "兼容 Windows Server 最新" },
{ value: "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES", label: "兼容 Windows Server 2016" },
{ value: "-nomac -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES", label: "兼容 Windows Server 2008" },
],
},
required: false,
order: 100,
maybeNeed: true,
helper: "兼容Windows Server各个版本",
})
pfxArgs = "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES";
userContext!: IContext;
lastStatus!: Step;
@TaskOutput({
title: "域名证书",
type: "cert",
})
cert?: CertInfo;
async onInstance() {
this.userContext = this.ctx.userContext;
this.lastStatus = this.ctx.lastStatus as Step;
await this.onInit();
}
abstract onInit(): Promise<void>;
//必须output之后执行
async emitCertApplySuccess() {
const emitter = this.ctx.emitter;
const value = {
cert: this.cert,
};
await emitter.emit(EVENT_CERT_APPLY_SUCCESS, value);
}
async output(certReader: CertReader, isNew: boolean) {
const cert: CertInfo = certReader.toCertInfo();
this.cert = cert;
this._result.pipelineVars.certEffectiveTime = dayjs(certReader.detail.notBefore).valueOf();
this._result.pipelineVars.certExpiresTime = dayjs(certReader.detail.notAfter).valueOf();
this._result.pipelineVars.certDomains = certReader.getAllDomains();
if (!this._result.pipelinePrivateVars) {
this._result.pipelinePrivateVars = {};
}
this._result.pipelinePrivateVars.cert = cert;
if (isNew || !cert.pfx) {
try {
const converter = new CertConverter({ logger: this.logger });
const res = await converter.convert({
cert,
pfxPassword: this.pfxPassword,
pfxArgs: this.pfxArgs,
});
if (cert.pfx == null && res.pfx) {
cert.pfx = res.pfx;
}
if (cert.der == null && res.der) {
cert.der = res.der;
}
if (cert.jks == null && res.jks) {
cert.jks = res.jks;
}
if (cert.p7b == null && res.p7b) {
cert.p7b = res.p7b;
}
this.logger.info("转换证书格式成功");
} catch (e) {
this.logger.error("转换证书格式失败", e);
}
}
}
formatCert(pem: string) {
pem = pem.replace(/\r/g, "");
pem = pem.replace(/\n\n/g, "\n");
pem = pem.replace(/\n$/g, "");
return pem;
}
formatCerts(cert: { crt: string; key: string; csr?: string }) {
const newCert: CertInfo = {
crt: this.formatCert(cert.crt),
key: this.formatCert(cert.key),
csr: this.formatCert(cert.csr),
};
return newCert;
}
async readLastCert(): Promise<CertReader | undefined> {
const cert = this.lastStatus?.status?.output?.cert;
if (cert == null) {
this.logger.info("没有找到上次的证书");
return undefined;
}
return new CertReader(cert);
}
}