mirror of
https://github.com/certd/certd.git
synced 2026-06-16 14:27:32 +08:00
276 lines
9.3 KiB
TypeScript
276 lines
9.3 KiB
TypeScript
import { AbstractTaskPlugin, IsTaskPlugin, Pager, PageSearch, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
|
|
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
|
|
import { AliyunAccess } from "../../../plugin-lib/aliyun/access/index.js";
|
|
import { AliyunSslClient, CasCertId } from "../../../plugin-lib/aliyun/lib/ssl-client.js";
|
|
import { CertApplyPluginNames, CertInfo, CertReader } from "@certd/plugin-cert";
|
|
import { optionsUtils } from "@certd/basic";
|
|
|
|
@IsTaskPlugin({
|
|
name: "DeployCertToAliyunApig",
|
|
title: "阿里云-部署至云原生API网关/AI网关",
|
|
icon: "svg:icon-aliyun",
|
|
group: pluginGroups.aliyun.key,
|
|
desc: "自动部署域名证书至云原生API网关、AI网关",
|
|
default: {
|
|
strategy: {
|
|
runStrategy: RunStrategy.SkipWhenSucceed,
|
|
},
|
|
},
|
|
})
|
|
export class DeployCertToAliyunApig extends AbstractTaskPlugin {
|
|
@TaskInput({
|
|
title: "域名证书",
|
|
helper: "请选择前置任务输出的域名证书",
|
|
component: {
|
|
name: "output-selector",
|
|
from: [...CertApplyPluginNames, "uploadCertToAliyun"],
|
|
},
|
|
required: true,
|
|
})
|
|
cert!: CertInfo | CasCertId | number;
|
|
|
|
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
|
|
certDomains!: string[];
|
|
|
|
@TaskInput({
|
|
title: "Access授权",
|
|
helper: "阿里云授权",
|
|
component: {
|
|
name: "access-selector",
|
|
type: "aliyun",
|
|
},
|
|
required: true,
|
|
})
|
|
accessId!: string;
|
|
|
|
@TaskInput(
|
|
createRemoteSelectInputDefine({
|
|
title: "区域",
|
|
helper: "请选择区域",
|
|
action: DeployCertToAliyunApig.prototype.onGetRegionList.name,
|
|
watches: ["certDomains", "accessId"],
|
|
required: true,
|
|
component: {
|
|
name: "remote-auto-complete",
|
|
},
|
|
})
|
|
)
|
|
regionEndpoint!: string;
|
|
|
|
@TaskInput({
|
|
title: "网关类型",
|
|
component: {
|
|
name: "a-select",
|
|
vModel: "value",
|
|
options: [
|
|
{ value: "AI", label: "AI" },
|
|
{ value: "API", label: "API" },
|
|
],
|
|
},
|
|
required: true, //必填
|
|
})
|
|
gatewayType!: string;
|
|
|
|
@TaskInput(
|
|
createRemoteSelectInputDefine({
|
|
title: "绑定域名",
|
|
helper: "请选择域名",
|
|
action: DeployCertToAliyunApig.prototype.onGetDomainList.name,
|
|
watches: ["region", "accessId", "gatewayType"],
|
|
required: true,
|
|
pager: true,
|
|
search: true,
|
|
})
|
|
)
|
|
domainList!: string[];
|
|
|
|
@TaskInput({
|
|
title: "强制HTTPS",
|
|
component: {
|
|
name: "a-select",
|
|
vModel: "value",
|
|
options: [
|
|
{ value: true, label: "强制HTTPS" },
|
|
{ value: false, label: "不强制HTTPS" },
|
|
],
|
|
},
|
|
required: true, //必填
|
|
})
|
|
forceHttps!: boolean;
|
|
|
|
@TaskInput({
|
|
title: "证书服务接入点",
|
|
helper: "不会选就按默认",
|
|
value: "cn-hangzhou",
|
|
component: {
|
|
name: "a-select",
|
|
options: [
|
|
{ value: "cn-hangzhou", label: "中国大陆" },
|
|
{ value: "ap-southeast-1", label: "新加坡" },
|
|
],
|
|
},
|
|
required: true,
|
|
})
|
|
casRegion!: string;
|
|
|
|
async onInstance() {}
|
|
async execute(): Promise<void> {
|
|
this.logger.info("开始部署证书到云原生Api网关");
|
|
if (!this.domainList) {
|
|
throw new Error("您还未选择域名");
|
|
}
|
|
const access = await this.getAccess<AliyunAccess>(this.accessId);
|
|
const client = access.getClient(this.regionEndpoint);
|
|
|
|
let certId: any = this.cert;
|
|
if (typeof this.cert === "object") {
|
|
const sslClient = new AliyunSslClient({
|
|
access,
|
|
logger: this.logger,
|
|
region: this.casRegion,
|
|
});
|
|
const certInfo = this.cert as CertInfo;
|
|
const casCert = this.cert as CasCertId;
|
|
if (casCert.certId) {
|
|
certId = casCert.certId;
|
|
} else if (certInfo.crt) {
|
|
certId = await sslClient.uploadCert({
|
|
name: this.buildCertName(CertReader.getMainDomain(certInfo.crt)),
|
|
cert: certInfo,
|
|
});
|
|
} else {
|
|
throw new Error("证书格式错误" + JSON.stringify(this.cert));
|
|
}
|
|
}
|
|
|
|
const certIdentify = `${certId}-${this.casRegion}`;
|
|
|
|
for (const domainId of this.domainList) {
|
|
this.logger.info(`[${domainId}]开始部署`);
|
|
await this.updateCert(client, domainId, certIdentify);
|
|
this.logger.info(`[${domainId}]部署成功`);
|
|
}
|
|
|
|
this.logger.info("部署完成");
|
|
}
|
|
|
|
async updateCert(client: any, domainId: string, certIdentify: string) {
|
|
const domainInfoRes = await client.doRequest({
|
|
action: "GetDomain",
|
|
version: "2024-03-27",
|
|
protocol: "HTTPS",
|
|
method: "GET",
|
|
authType: "AK",
|
|
style: "ROA",
|
|
pathname: `/v1/domains/${domainId}`,
|
|
});
|
|
|
|
const tlsCipherSuitesConfig = domainInfoRes.data?.tlsCipherSuitesConfig;
|
|
|
|
const ret = await client.doRequest({
|
|
action: "UpdateDomain",
|
|
version: "2024-03-27",
|
|
method: "PUT",
|
|
style: "ROA",
|
|
pathname: `/v1/domains/${domainId}`,
|
|
data: {
|
|
body: {
|
|
certIdentifier: certIdentify,
|
|
protocol: "HTTPS",
|
|
forceHttps: this.forceHttps,
|
|
tlsCipherSuitesConfig,
|
|
},
|
|
},
|
|
});
|
|
this.logger.info(`设置${domainId}证书成功:`, ret.requestId);
|
|
}
|
|
|
|
async onGetDomainList(data: PageSearch) {
|
|
if (!this.accessId) {
|
|
throw new Error("请选择Access授权");
|
|
}
|
|
if (!this.regionEndpoint) {
|
|
throw new Error("请选择区域");
|
|
}
|
|
if (!this.gatewayType) {
|
|
throw new Error("请选择网关类型");
|
|
}
|
|
|
|
const pager = new Pager(data);
|
|
const access = await this.getAccess<AliyunAccess>(this.accessId);
|
|
|
|
const client = access.getClient(this.regionEndpoint);
|
|
|
|
const res = await client.doRequest({
|
|
action: "ListDomains",
|
|
version: "2024-03-27",
|
|
method: "GET",
|
|
style: "ROA",
|
|
pathname: `/v1/domains`,
|
|
data: {
|
|
query: {
|
|
nameLike: data.searchKey,
|
|
pageSize: pager.pageSize,
|
|
pageNumber: pager.pageNo,
|
|
gatewayType: this.gatewayType,
|
|
},
|
|
},
|
|
});
|
|
const list = res?.data?.items;
|
|
if (!list || list.length === 0) {
|
|
return [];
|
|
}
|
|
const options = list.map((item: any) => {
|
|
return {
|
|
value: item.domainId,
|
|
label: `${item.name}<${item.domainId}>`,
|
|
domain: item.name,
|
|
};
|
|
});
|
|
const records = optionsUtils.buildGroupOptions(options, this.certDomains);
|
|
return {
|
|
list: records,
|
|
total: res?.data?.totalSize || 0,
|
|
}
|
|
}
|
|
|
|
async onGetRegionList(data: any) {
|
|
const list = [
|
|
{ value: "cn-qingdao", label: "华北1(青岛)", endpoint: "apig.cn-qingdao.aliyuncs.com" },
|
|
{ value: "cn-beijing", label: "华北2(北京)", endpoint: "apig.cn-beijing.aliyuncs.com" },
|
|
{ value: "cn-zhangjiakou", label: "华北3(张家口)", endpoint: "apig.cn-zhangjiakou.aliyuncs.com" },
|
|
{ value: "cn-wulanchabu", label: "华北6(乌兰察布)", endpoint: "apig.cn-wulanchabu.aliyuncs.com" },
|
|
{ value: "cn-hangzhou", label: "华东1(杭州)", endpoint: "apig.cn-hangzhou.aliyuncs.com" },
|
|
{ value: "cn-shanghai", label: "华东2(上海)", endpoint: "apig.cn-shanghai.aliyuncs.com" },
|
|
{ value: "cn-shenzhen", label: "华南1(深圳)", endpoint: "apig.cn-shenzhen.aliyuncs.com" },
|
|
{ value: "cn-heyuan", label: "华南2(河源)", endpoint: "apig.cn-heyuan.aliyuncs.com" },
|
|
{ value: "cn-guangzhou", label: "华南3(广州)", endpoint: "apig.cn-guangzhou.aliyuncs.com" },
|
|
{ value: "ap-southeast-2", label: "澳大利亚(悉尼)已关停", endpoint: "apig.ap-southeast-2.aliyuncs.com" },
|
|
{ value: "ap-southeast-6", label: "菲律宾(马尼拉)", endpoint: "apig.ap-southeast-6.aliyuncs.com" },
|
|
{ value: "ap-northeast-2", label: "韩国(首尔)", endpoint: "apig.ap-northeast-2.aliyuncs.com" },
|
|
{ value: "ap-southeast-3", label: "马来西亚(吉隆坡)", endpoint: "apig.ap-southeast-3.aliyuncs.com" },
|
|
{ value: "ap-northeast-1", label: "日本(东京)", endpoint: "apig.ap-northeast-1.aliyuncs.com" },
|
|
{ value: "ap-southeast-7", label: "泰国(曼谷)", endpoint: "apig.ap-southeast-7.aliyuncs.com" },
|
|
{ value: "cn-chengdu", label: "西南1(成都)", endpoint: "apig.cn-chengdu.aliyuncs.com" },
|
|
{ value: "ap-southeast-1", label: "新加坡", endpoint: "apig.ap-southeast-1.aliyuncs.com" },
|
|
{ value: "ap-southeast-5", label: "印度尼西亚(雅加达)", endpoint: "apig.ap-southeast-5.aliyuncs.com" },
|
|
{ value: "cn-hongkong", label: "中国香港", endpoint: "apig.cn-hongkong.aliyuncs.com" },
|
|
{ value: "eu-central-1", label: "德国(法兰克福)", endpoint: "apig.eu-central-1.aliyuncs.com" },
|
|
{ value: "us-east-1", label: "美国(弗吉尼亚)", endpoint: "apig.us-east-1.aliyuncs.com" },
|
|
{ value: "us-west-1", label: "美国(硅谷)", endpoint: "apig.us-west-1.aliyuncs.com" },
|
|
{ value: "eu-west-1", label: "英国(伦敦)", endpoint: "apig.eu-west-1.aliyuncs.com" },
|
|
{ value: "me-east-1", label: "阿联酋(迪拜)", endpoint: "apig.me-east-1.aliyuncs.com" },
|
|
{ value: "me-central-1", label: "沙特(利雅得)", endpoint: "apig.me-central-1.aliyuncs.com" },
|
|
];
|
|
return list.map((item: any) => {
|
|
return {
|
|
value: item.endpoint,
|
|
label: item.label,
|
|
endpoint: item.endpoint,
|
|
regionId: item.value,
|
|
};
|
|
});
|
|
}
|
|
}
|
|
new DeployCertToAliyunApig();
|