Files
certd/packages/ui/certd-server/src/plugins/plugin-flex/plugins/plugin-refresh-cert.ts

174 lines
5.0 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, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert";
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
import { FlexCDNAccess } from "../access.js";
import { FlexCDNClient } from "../client.js";
import crypto from 'crypto'
@IsTaskPlugin({
//命名规范,插件类型+功能就是目录plugin-demo中的demo大写字母开头驼峰命名
name: "FlexCDNRefreshCert",
title: "FlexCDN-更新证书",
icon: "svg:icon-lucky",
//插件分组
group: pluginGroups.cdn.key,
needPlus: false,
default: {
//默认值配置照抄即可
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed
}
}
})
//类名规范跟上面插件名称name一致
export class FlexCDNRefreshCert extends AbstractTaskPlugin {
//证书选择,此项必须要有
@TaskInput({
title: "域名证书",
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames]
}
// required: true, // 必填
})
cert!: CertInfo;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
//授权选择框
@TaskInput({
title: "FlexCDN授权",
component: {
name: "access-selector",
type: "flexcdn" //固定授权类型
},
required: true //必填
})
accessId!: string;
//
@TaskInput(
createRemoteSelectInputDefine({
title: "证书Id",
helper: "要更新的Flex证书id",
action: FlexCDNRefreshCert.prototype.onGetCertList.name
})
)
certList!: number[];
//插件实例化时执行的方法
async onInstance() {
}
static parseCertInfo(certPem: string) {
const certificateArray = certPem
.trim()
.split('-----END CERTIFICATE-----')
.filter(cert => cert.trim() !== '')
.map(cert => (cert + '-----END CERTIFICATE-----').trim());
const currentInfo = new crypto.X509Certificate(certificateArray[0])
const dnsNames = currentInfo.subjectAltName.split(',')
.map(it => it.trim())
.filter(it => it.startsWith('DNS:'))
.map(it => it.substring(4))
const commonNames = certificateArray.map(it => {
const info = new crypto.X509Certificate(it)
const subjectCN = info.issuer.trim()
.split('\n')
.map(it => it.trim())
.find((part) => part.trim().startsWith('CN='))
?.split('=')[1]
?.trim();
return subjectCN
})
return {
commonNames: commonNames,
dnsNames: dnsNames,
timeBeginAt: Math.floor((new Date(currentInfo.validFrom)).getTime() / 1000),
timeEndAt: Math.floor((new Date(currentInfo.validTo)).getTime() / 1000),
}
}
//插件执行方法
async execute(): Promise<void> {
const access: FlexCDNAccess = await this.getAccess<FlexCDNAccess>(this.accessId);
const client = new FlexCDNClient({
http: this.ctx.http,
logger: this.logger,
access
});
await client.getToken();
for (const item of this.certList) {
this.logger.info(`----------- 开始更新证书:${item}`);
const res = await client.doRequest({
url: `/SSLCertService/findEnabledSSLCertConfig`,
data: {
sslCertId: item
}
});
const sslCert = JSON.parse(this.ctx.utils.hash.base64Decode(res.sslCertJSON))
this.logger.info(`证书信息:${sslCert.name}${sslCert.dnsNames}`);
const body = {
...sslCert, // inherit old cert info like name and description
...FlexCDNRefreshCert.parseCertInfo(this.cert.crt),
name: sslCert.name,
sslCertId: item,
certData: this.ctx.utils.hash.base64(this.cert.crt),
keyData: this.ctx.utils.hash.base64(this.cert.key)
};
await client.doRequest({
url: `/SSLCertService/updateSSLCert`,
data: {
...body
}
});
this.logger.info(`----------- 更新证书${item}成功`);
}
this.logger.info("部署完成");
}
async onGetCertList() {
const access: FlexCDNAccess = await this.getAccess<FlexCDNAccess>(this.accessId);
const client = new FlexCDNClient({
http: this.ctx.http,
logger: this.logger,
access
});
await client.getToken();
const res = await client.doRequest({
url: "/SSLCertService/listSSLCerts",
data: { size: 1000 },
method: "POST"
});
const list = JSON.parse(this.ctx.utils.hash.base64Decode(res.sslCertsJSON));
if (!list || list.length === 0) {
throw new Error("没有找到证书,请先在控制台上传一次证书且关联网站");
}
const options = list.map((item: any) => {
return {
label: `${item.name}<${item.id}-${item.dnsNames[0]}>`,
value: item.id,
domain: item.dnsNames
};
});
return this.ctx.utils.options.buildGroupOptions(options, this.certDomains);
}
}
//实例化一下,注册插件
new FlexCDNRefreshCert();