Files
certd/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-waf/deploy-to-waf-cname.ts
T

254 lines
7.5 KiB
TypeScript

import { AbstractTaskPlugin, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert";
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js";
import { AliyunClient, AliyunSslClient, CasCertInfo } from "../../../plugin-lib/aliyun/lib/index.js";
@IsTaskPlugin({
name: "AliyunDeployCertToWaf",
title: "阿里云-部署至阿里云WAF(cname接入)",
icon: "svg:icon-aliyun",
group: pluginGroups.aliyun.key,
desc: "部署证书到阿里云WAF(cname接入),云资源的请选择另外一个waf插件",
needPlus: false,
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class AliyunDeployCertToWaf extends AbstractTaskPlugin {
@TaskInput({
title: "域名证书",
helper: "请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID,可以减少上传到阿里云的证书数量",
component: {
name: "output-selector",
from: [...CertApplyPluginNames, "uploadCertToAliyun"],
},
required: true,
})
cert!: CertInfo | number | CasCertInfo;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: "WAF接入点",
helper: "不会选就按默认",
value: "cn-hangzhou",
component: {
name: "a-select",
options: [
{ value: "cn-hangzhou", label: "中国大陆-华东1(杭州)" },
{ value: "ap-southeast-1", label: "新加坡" },
],
},
required: true,
})
regionId!: string;
@TaskInput({
title: "证书接入点",
helper: "跟上面保持一致即可",
value: "cas.aliyuncs.com",
component: {
name: "a-select",
options: [
{ value: "cas.aliyuncs.com", label: "中国大陆" },
{ value: "cas.ap-southeast-1.aliyuncs.com", label: "新加坡" },
{ value: "cas.eu-central-1.aliyuncs.com", label: "德国(法兰克福)" },
],
},
required: true,
})
casEndpoint!: string;
@TaskInput({
title: "Access授权",
helper: "阿里云授权AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "aliyun",
},
required: true,
})
accessId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: "CNAME站点",
helper: "请选择要部署证书的CNAME站点",
action: AliyunDeployCertToWaf.prototype.onGetCnameList.name,
watches: ["accessId", "regionId"],
pager: true,
search: true,
})
)
cnameDomains!: string[];
@TaskInput({
title: "TLS版本",
value: "tlsv1.2",
component: {
name: "a-select",
options: [
{ value: "tlsv1", label: "TLSv1" },
{ value: "tlsv1.1", label: "TLSv1.1" },
{ value: "tlsv1.2", label: "TLSv1.2" },
],
},
required: true,
})
tlsVersion!: string;
@TaskInput({
title: "启用TLSv3",
value: true,
component: {
name: "a-switch",
vModel: "checked",
},
required: true,
})
enableTLSv3!: boolean;
async onInstance() {}
async getWafClient(access: AliyunAccess) {
const client = new AliyunClient({ logger: this.logger });
await client.init({
accessKeyId: access.accessKeyId,
accessKeySecret: access.accessKeySecret,
//https://wafopenapi.cn-hangzhou.aliyuncs.com
endpoint: `https://wafopenapi.${this.regionId}.aliyuncs.com`,
apiVersion: "2021-10-01",
});
return client;
}
async getInstanceId(client: AliyunClient) {
const params = {
RegionId: "cn-hangzhou",
};
const res = await client.request("DescribeInstance", params);
this.logger.info("获取实例ID", res.InstanceId);
return res.InstanceId;
}
async execute(): Promise<void> {
this.logger.info("开始部署证书到阿里云");
const access = await this.getAccess<AliyunAccess>(this.accessId);
let certId: any = this.cert;
if (typeof this.cert === "object") {
const sslClient = new AliyunSslClient({
access,
logger: this.logger,
endpoint: this.casEndpoint,
});
const cert = this.cert as CertInfo;
const casCert = this.cert as CasCertInfo;
if (cert.crt) {
const certIdRes = await sslClient.uploadCertificate({
name: this.buildCertName(CertReader.getMainDomain(cert.crt)),
cert: cert,
});
certId = certIdRes.certId as any;
} else if (casCert.certId) {
certId = casCert.certId;
} else {
throw new Error("证书格式错误" + JSON.stringify(this.cert));
}
}
const client = await this.getWafClient(access);
const instanceId = await this.getInstanceId(client);
for (const siteDomain of this.cnameDomains) {
this.logger.info("开始部署", siteDomain);
const params = {
RegionId: this.regionId,
InstanceId: instanceId,
Domain: siteDomain,
};
const siteDetail = await client.request("DescribeDomainDetail", params);
this.logger.info("站点详情", JSON.stringify(siteDetail));
const listen = siteDetail.Listen;
if (!listen) {
throw new Error(`没有找到${siteDomain}的监听器`);
}
/**
* "HttpsPorts": [
* 443
* ],
* "CertId": "14738336-cn-hangzhou",
*/
const redirect = siteDetail.Redirect;
redirect.Backends = redirect.AllBackends;
listen.CertId = certId + "-" + this.regionId;
if (!listen.HttpsPorts || listen.HttpsPorts.length === 0) {
listen.HttpsPorts = [443];
}
const updateParams = {
InstanceId: instanceId,
RegionId: this.regionId,
Redirect: JSON.stringify(redirect),
Listen: JSON.stringify(listen),
Domain: siteDomain,
TLSVersion: this.tlsVersion || "tlsv1.2",
EnableTLSv3: this.enableTLSv3 ?? true,
};
const res = await client.request("ModifyDomain", updateParams);
this.logger.info("部署成功", JSON.stringify(res));
}
}
async onGetCnameList(data: PageSearch) {
if (!this.accessId) {
throw new Error("请选择Access授权");
}
const access = await this.getAccess<AliyunAccess>(this.accessId);
const client = await this.getWafClient(access);
const pager = new Pager(data);
const instanceId = await this.getInstanceId(client);
const params: any = {
RegionId: this.regionId,
InstanceId: instanceId,
PageSize: pager.pageSize,
PageNumber: pager.pageNo,
};
if (data.searchKey) {
params.Domain = data.searchKey;
}
const res = await client.request("DescribeDomains", params);
if (!res?.Domains || res?.Domains.length === 0) {
throw new Error("没有找到CNAME接入的域名站点");
}
const total = res.TotalCount;
const options = res.Domains.map((item: any) => {
return {
label: item.Domain,
value: item.Domain,
title: item.Domain,
domain: item.Domain,
};
});
const list = this.ctx.utils.options.buildGroupOptions(options, this.certDomains);
// const list = [{value:"1",label:"1"},{value:"2",label:"2"}]
// const total = 120
return {
list,
total: total,
pageNo: pager.pageNo,
pageSize: pager.pageSize,
};
}
}
new AliyunDeployCertToWaf();