mirror of
https://github.com/certd/certd.git
synced 2026-04-03 14:10:54 +08:00
perf: 新增阿里云证书清理插件
This commit is contained in:
@@ -96,6 +96,19 @@ input:
|
||||
选择要部署证书的监听器
|
||||
需要在监听器中选择证书中心,进行跨服务访问授权
|
||||
order: 0
|
||||
certType:
|
||||
title: 证书部署类型
|
||||
helper: 选择部署默认证书还是扩展证书
|
||||
component:
|
||||
name: a-select
|
||||
options:
|
||||
- label: 默认证书
|
||||
value: default
|
||||
- label: 扩展证书
|
||||
value: extension
|
||||
value: default
|
||||
required: true
|
||||
order: 0
|
||||
output: {}
|
||||
pluginType: deploy
|
||||
type: builtIn
|
||||
|
||||
@@ -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();
|
||||
@@ -13,4 +13,5 @@ export * from './deploy-to-vod/index.js';
|
||||
export * from './deploy-to-apigateway/index.js';
|
||||
export * from './deploy-to-apig/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';
|
||||
Reference in New Issue
Block a user