Files
certd/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-fc/index.ts
xiaojunnuo 1db1ffde99 perf: 添加阿里云 ESA证书部署插件
- 新增 AliyunDeployCertToESA 插件类,实现证书上传和部署到阿里云 ESA 功能
- 优化证书名称生成逻辑,支持通配符域名
- 重构部分代码,提高可复用性和可维护性
- 更新相关依赖版本,确保兼容性
2025-05-22 23:21:50 +08:00

229 lines
7.6 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, CertReader } from "@certd/plugin-cert";
import { AliyunAccess, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
@IsTaskPlugin({
name: 'AliyunDeployCertToFC',
title: '阿里云-部署至阿里云FC(3.0)',
icon: 'svg:icon-aliyun',
group: pluginGroups.aliyun.key,
desc: '部署证书到阿里云函数计算FC3.0,【注意】证书的加密算法必须选择【pkcs1旧版】',
needPlus: false,
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class AliyunDeployCertToFC extends AbstractTaskPlugin {
@TaskInput({
title: '域名证书',
helper: '请选择证书申请任务输出的域名证书',
component: {
name: 'output-selector',
from: [...CertApplyPluginNames],
},
required: true,
})
cert!: CertInfo;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: 'FC大区',
value: 'cn-hangzhou',
component: {
name: 'a-auto-complete',
vModel: 'value',
options: [
{ value: 'cn-qingdao', label: '华北1青岛' },
{ value: 'cn-beijing', label: '华北2北京' },
{ value: 'cn-zhangjiakou', label: '华北 3张家口' },
{ value: 'cn-huhehaote', label: '华北5呼和浩特' },
{ value: 'cn-hangzhou', label: '华东1杭州' },
{ value: 'cn-shanghai', label: '华东2上海' },
{ value: 'cn-shenzhen', label: '华南1深圳' },
{ value: 'ap-southeast-2', label: '澳大利亚(悉尼)' },
{ value: 'eu-central-1', label: '德国(法兰克福)' },
{ value: 'ap-southeast-3', label: '马来西亚(吉隆坡)' },
{ value: 'us-east-1', label: '美国(弗吉尼亚)' },
{ value: 'us-west-1', label: '美国(硅谷)' },
{ value: 'ap-northeast-1', label: '日本(东京)' },
{ value: 'ap-southeast-7', label: '泰国(曼谷)' },
{ value: 'cn-chengdu', label: '西南1成都' },
{ value: 'ap-southeast-1', label: '新加坡' },
{ value: 'ap-south-1', label: '印度(孟买)' },
{ value: 'ap-southeast-5', label: '印度尼西亚(雅加达)' },
{ value: 'eu-west-1', label: '英国(伦敦)' },
{ value: 'cn-hongkong', label: '中国香港' },
],
},
required: true,
})
regionId!: string;
@TaskInput({
title: '阿里云账号id',
helper: '阿里云主账号ID右上角头像下方获取',
component: {
name: 'a-input',
vModel:"value"
},
required: true,
})
accountId!: string;
@TaskInput({
title: 'Access授权',
helper: '阿里云授权AccessKeyId、AccessKeySecret',
component: {
name: 'access-selector',
type: 'aliyun',
},
required: true,
})
accessId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: 'FC域名',
helper: "请选择要部署证书的域名\n【注意】证书的加密算法必须选择【pkcs1旧版】否则会报'private key' has to be in PEM format错误",
typeName: 'AliyunDeployCertToFC',
action: AliyunDeployCertToFC.prototype.onGetDomainList.name,
watches: ['accessId', 'regionId'],
})
)
fcDomains!: string[];
@TaskInput({
title: '域名支持的协议类型',
component: {
name: 'a-select',
value: '',
options: [
{ value: '', label: '保持原样适用于原来已经开启了HTTPS' },
{ value: 'HTTPS', label: '仅HTTPS' },
{ value: 'HTTP,HTTPS', label: 'HTTP与HTTPS同时支持' },
],
},
})
protocol!: string;
async onInstance() {}
async execute(): Promise<void> {
this.logger.info('开始部署证书到阿里云');
const access = await this.getAccess<AliyunAccess>(this.accessId);
const client = await this.getClient(access);
const $Util = await import('@alicloud/tea-util');
const $OpenApi = await import('@alicloud/openapi-client');
for (const domainName of this.fcDomains) {
const params = new $OpenApi.Params({
// 接口名称
action: 'UpdateCustomDomain',
// 接口版本
version: '2023-03-30',
// 接口协议
protocol: 'HTTPS',
// 接口 HTTP 方法
method: 'PUT',
authType: 'AK',
style: 'FC',
// 接口 PATH
pathname: `/2023-03-30/custom-domains/${domainName}`,
// 接口请求体内容格式
reqBodyType: 'json',
// 接口响应体内容格式
bodyType: 'json',
});
// body params
const certName = this.buildCertName(CertReader.getMainDomain(this.cert.crt))
const body: { [key: string]: any } = {
certConfig: {
certName: certName,
certificate: this.cert.crt,
privateKey: this.cert.key,
},
};
if (this.protocol) {
body.protocol = this.protocol;
}
const runtime = new $Util.RuntimeOptions({});
const request = new $OpenApi.OpenApiRequest({ body });
// 复制代码运行请自行打印 API 的返回值
// 返回值实际为 Map 类型,可从 Map 中获得三类数据:响应体 body、响应头 headers、HTTP 返回的状态码 statusCode。
await client.callApi(params, request, runtime);
this.logger.info(`部署[${domainName}]成功`);
}
}
async getClient(access: AliyunAccess) {
const $OpenApi = await import('@alicloud/openapi-client');
const config = new $OpenApi.Config({
accessKeyId: access.accessKeyId,
accessKeySecret: access.accessKeySecret,
});
// Endpoint 请参考 https://api.aliyun.com/product/FC
config.endpoint = `${this.accountId}.${this.regionId}.fc.aliyuncs.com`;
return new $OpenApi.default.default(config);
}
async onGetDomainList(data: any) {
if (!this.accessId) {
throw new Error('请选择Access授权');
}
const access = await this.getAccess<AliyunAccess>(this.accessId);
const client = await this.getClient(access);
const $OpenApi = await import('@alicloud/openapi-client');
const $Util = await import('@alicloud/tea-util');
const params = new $OpenApi.Params({
// 接口名称
action: 'ListCustomDomains',
// 接口版本
version: '2023-03-30',
// 接口协议
protocol: 'HTTPS',
// 接口 HTTP 方法
method: 'GET',
authType: 'AK',
style: 'FC',
// 接口 PATH
pathname: `/2023-03-30/custom-domains`,
// 接口请求体内容格式
reqBodyType: 'json',
// 接口响应体内容格式
bodyType: 'json',
});
const runtime = new $Util.RuntimeOptions({});
const request = new $OpenApi.OpenApiRequest({});
// 复制代码运行请自行打印 API 的返回值
// 返回值实际为 Map 类型,可从 Map 中获得三类数据:响应体 body、响应头 headers、HTTP 返回的状态码 statusCode。
const res = await client.callApi(params, request, runtime);
const list = res?.body?.customDomains;
if (!list || list.length === 0) {
throw new Error('没有找到FC域名请先创建FC域名');
}
const options = list.map((item: any) => {
return {
label: item.domainName,
value: item.domainName,
title: item.domainName,
domain: item.domainName,
};
});
return this.ctx.utils.options.buildGroupOptions(options, this.certDomains);
}
}
new AliyunDeployCertToFC();