perf: 新增阿里云证书清理插件

This commit is contained in:
xiaojunnuo
2026-03-23 00:02:46 +08:00
parent 2951f0030d
commit 4b7eeaa6e0
3 changed files with 174 additions and 1 deletions

View File

@@ -96,6 +96,19 @@ input:
选择要部署证书的监听器 选择要部署证书的监听器
需要在监听器中选择证书中心,进行跨服务访问授权 需要在监听器中选择证书中心,进行跨服务访问授权
order: 0 order: 0
certType:
title: 证书部署类型
helper: 选择部署默认证书还是扩展证书
component:
name: a-select
options:
- label: 默认证书
value: default
- label: 扩展证书
value: extension
value: default
required: true
order: 0
output: {} output: {}
pluginType: deploy pluginType: deploy
type: builtIn type: builtIn

View File

@@ -0,0 +1,159 @@
import { IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
import { AbstractPlusTaskPlugin } from "@certd/plugin-plus";
import dayjs from 'dayjs';
import { AliyunAccess } from '../../../plugin-lib/aliyun/access/index.js';
import { AliyunSslClient } from '../../../plugin-lib/aliyun/lib/index.js';
@IsTaskPlugin({
name: 'AliyunDeleteExpiringCert',
title: '阿里云-删除即将过期证书',
icon: 'ant-design:aliyun-outlined',
group: pluginGroups.aliyun.key,
desc: '仅删除未使用的证书',
default: {
strategy: {
runStrategy: RunStrategy.AlwaysRun,
},
},
needPlus: true,
})
export class AliyunDeleteExpiringCert extends AbstractPlusTaskPlugin {
@TaskInput({
title: 'Access提供者',
helper: 'access 授权',
component: {
name: 'access-selector',
type: 'aliyun',
},
required: true,
})
accessId!: string;
@TaskInput({
title: '地域',
helper: '阿里云CAS证书服务地域',
component: {
name: 'a-select',
options: [
{ value: 'cas.aliyuncs.com', label: '中国大陆' },
{ value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' },
],
},
required: true,
value: 'cas.aliyuncs.com',
})
endpoint!: string;
// @TaskInput({
// title: '关键字筛选',
// helper: '仅匹配证书名称、域名包含关键字的证书,可以不填',
// required: false,
// component: {
// name: 'a-input',
// },
// })
// searchKey!: string;
@TaskInput({
title: '最大删除数量',
helper: '单次运行最大删除数量',
value: 100,
component: {
name: 'a-input-number',
vModel: 'value',
},
required: true,
})
maxCount!: number;
@TaskInput({
title: '即将过期天数',
helper: '仅删除有效期小于此天数的证书,0表示完全过期时才删除',
value: 0,
component: {
name: 'a-input-number',
vModel: 'value',
},
required: true,
})
expiringDays!: number;
@TaskInput({
title: '检查超时时间',
helper: '检查删除任务结果超时时间,单位分钟',
value: 10,
component: {
name: 'a-input-number',
vModel: 'value',
},
required: true,
})
checkTimeout!: number;
async onInstance() {}
async execute(): Promise<void> {
const access = await this.getAccess<AliyunAccess>(this.accessId);
const sslClient = new AliyunSslClient({
access,
logger: this.logger,
endpoint: this.endpoint,
});
const params = {
ShowSize: 100,
CurrentPage: 1,
// Keyword: this.searchKey,
};
const certificates: any[] = [];
while(true){
const res = await sslClient.doRequest('ListCertificates', params, {
method: 'POST',
});
let list = res?.CertificateList;
if (!list || list.length === 0) {
break;
}
this.logger.info(`查询第${params.CurrentPage}页,每页${params.ShowSize}个证书,当前页共${list.length}个证书`);
const lastDay = dayjs().add(this.expiringDays, 'day');
list = list.filter((item: any) => {
const notAfter = item.NotAfter;
const usingProducts = item.UsingProductList;
return dayjs(notAfter).isBefore(lastDay) && (!usingProducts || usingProducts.length === 0);
});
for (const item of list) {
this.logger.info(`证书ID:${item.CertificateId}, 过期时间:${item.NotAfter},名称:${item.CertificateName},证书域名:${item.Domain}`);
certificates.push(item);
}
params.CurrentPage++;
}
this.logger.info(`即将过期的证书数量:${certificates.length}`);
if (certificates.length === 0) {
this.logger.info('没有即将过期的证书, 无需删除');
return;
}
this.logger.info(`开始删除证书,共${certificates.length}个证书`);
let successCount = 0;
let failedCount = 0;
for (const certificate of certificates) {
try {
const deleteRes = await sslClient.doRequest('DeleteUserCertificate', {
CertId: certificate.CertificateId,
}, { method: 'POST' });
this.logger.info(`删除证书成功证书ID:${certificate.CertificateId}, 名称:${certificate.CertificateName}, requestId:${deleteRes?.RequestId}`);
successCount++;
} catch (error: any) {
this.logger.error(`删除证书失败证书ID:${certificate.CertificateId}, 名称:${certificate.CertificateName}, 错误:${error.message}`);
failedCount++;
}
}
this.logger.info(`证书删除完成,成功:${successCount}, 失败:${failedCount}`);
}
}
new AliyunDeleteExpiringCert();

View File

@@ -13,4 +13,5 @@ export * from './deploy-to-vod/index.js';
export * from './deploy-to-apigateway/index.js'; export * from './deploy-to-apigateway/index.js';
export * from './deploy-to-apig/index.js'; export * from './deploy-to-apig/index.js';
export * from './deploy-to-ack/index.js'; export * from './deploy-to-ack/index.js';
export * from './deploy-to-all/index.js'; export * from './deploy-to-all/index.js';
export * from './delete-expiring-cert/index.js';