Files
certd/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-alb/index.ts
2025-01-19 15:31:37 +08:00

243 lines
7.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 { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
import { CertInfo } from '@certd/plugin-cert';
import { AliyunAccess, AliyunClient, AliyunSslClient, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib';
import { AbstractPlusTaskPlugin } from '@certd/plugin-plus';
@IsTaskPlugin({
name: 'AliyunDeployCertToALB',
title: '阿里云-部署至阿里云ALB',
icon: 'ant-design:aliyun-outlined',
group: pluginGroups.aliyun.key,
desc: '部署证书到阿里云ALB仅更新监听器的默认证书',
needPlus: true,
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class AliyunDeployCertToALB extends AbstractPlusTaskPlugin {
@TaskInput({
title: '域名证书',
helper: '请选择证书申请任务输出的域名证书\n或者选择前置任务“上传证书到阿里云”任务的证书ID可以减少上传到阿里云的证书数量',
component: {
name: 'output-selector',
from: ['CertApply', 'CertApplyLego', 'uploadCertToAliyun'],
},
required: true,
})
cert!: CertInfo | number;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: 'Access授权',
helper: '阿里云授权AccessKeyId、AccessKeySecret',
component: {
name: 'access-selector',
type: 'aliyun',
},
required: true,
})
accessId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: 'ALB所在地区',
typeName: 'AliyunDeployCertToALB',
multi: false,
action: AliyunDeployCertToALB.prototype.onGetRegionList.name,
watches: ['accessId'],
})
)
regionId: string;
@TaskInput(
createRemoteSelectInputDefine({
title: '负载均衡列表',
helper: '要部署证书的ALB负载均衡',
typeName: 'AliyunDeployCertToALB',
action: AliyunDeployCertToALB.prototype.onGetLoadBalanceList.name,
watches: ['regionId'],
})
)
loadBalancers!: string[];
@TaskInput(
createRemoteSelectInputDefine({
title: '监听器列表',
helper: '要部署证书的监听器列表',
typeName: 'AliyunDeployCertToALB',
action: AliyunDeployCertToALB.prototype.onGetListenerList.name,
watches: ['loadBalancers'],
})
)
listeners!: 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;
async onInstance() {}
async getALBClient(access: AliyunAccess, region: string) {
const client = new AliyunClient({ logger: this.logger });
await client.init({
accessKeyId: access.accessKeyId,
accessKeySecret: access.accessKeySecret,
//https://wafopenapi.cn-hangzhou.aliyuncs.com
endpoint: `https://alb.${region}.aliyuncs.com`,
apiVersion: '2020-06-16',
});
return client;
}
async execute(): Promise<void> {
this.logger.info('开始部署证书到阿里云ALB');
const access = await this.accessService.getById<AliyunAccess>(this.accessId);
const certId = await this.getAliyunCertId(access);
const client = await this.getALBClient(access, this.regionId);
for (const listener of this.listeners) {
//查询原来的证书
const params = {
ListenerId: listener,
Certificates: [
{
CertificateId: certId,
},
],
};
const res = await client.request('UpdateListenerAttribute', params);
this.checkRet(res);
this.logger.info(`部署${listener}监听器证书成功`, JSON.stringify(res));
//删除旧证书关联
}
this.logger.info('执行完成');
}
async getAliyunCertId(access: AliyunAccess) {
let certId: any = this.cert;
if (typeof this.cert === 'object') {
const sslClient = new AliyunSslClient({
access,
logger: this.logger,
endpoint: this.casEndpoint,
});
certId = await sslClient.uploadCert({
name: this.appendTimeSuffix('certd'),
cert: this.cert,
});
}
return certId;
}
async onGetRegionList(data: any) {
if (!this.accessId) {
throw new Error('请选择Access授权');
}
const access = await this.accessService.getById<AliyunAccess>(this.accessId);
const client = await this.getALBClient(access, 'cn-shanghai');
const res = await client.request('DescribeRegions', {});
this.checkRet(res);
if (!res?.Regions || res?.Regions.length === 0) {
throw new Error('没有找到Regions列表');
}
return res.Regions.map((item: any) => {
return {
label: item.LocalName,
value: item.RegionId,
endpoint: item.RegionEndpoint,
};
});
}
async onGetLoadBalanceList(data: any) {
if (!this.accessId) {
throw new Error('请先选择Access授权');
}
if (!this.regionId) {
throw new Error('请先选择地区');
}
const access = await this.accessService.getById<AliyunAccess>(this.accessId);
const client = await this.getALBClient(access, this.regionId);
const params = {
MaxResults: 100,
};
const res = await client.request('ListLoadBalancers', params);
this.checkRet(res);
if (!res?.LoadBalancers || res?.LoadBalancers.length === 0) {
throw new Error('没有找到LoadBalancers');
}
return res.LoadBalancers.map((item: any) => {
const label = `${item.LoadBalancerId}<${item.LoadBalancerName}}>`;
return {
label: label,
value: item.LoadBalancerId,
};
});
}
async onGetListenerList(data: any) {
if (!this.accessId) {
throw new Error('请先选择Access授权');
}
if (!this.regionId) {
throw new Error('请先选择地区');
}
const access = await this.accessService.getById<AliyunAccess>(this.accessId);
const client = await this.getALBClient(access, this.regionId);
const params: any = {
MaxResults: 100,
};
if (this.loadBalancers && this.loadBalancers.length > 0) {
params.LoadBalancerIds = this.loadBalancers;
}
const res = await client.request('ListListeners', params);
this.checkRet(res);
if (!res?.Listeners || res?.Listeners.length === 0) {
throw new Error('没有找到HTTPS监听器');
}
return res.Listeners.map((item: any) => {
const label = `${item.ListenerId}<${item.ListenerDescription}}${item.LoadBalancerId}>`;
return {
label: label,
value: item.ListenerId,
lbid: item.LoadBalancerId,
};
});
}
checkRet(ret: any) {
if (ret.Code != null) {
throw new Error(ret.Message);
}
}
}
new AliyunDeployCertToALB();