mirror of
https://github.com/certd/certd.git
synced 2026-04-24 12:27:25 +08:00
1
This commit is contained in:
@@ -111,7 +111,7 @@ async function verifyDnsChallenge(authz, challenge, keyAuthorization, prefix = '
|
||||
log(`DNS query finished successfully, found ${recordValues.length} TXT records`);
|
||||
|
||||
if (!recordValues.length || !recordValues.includes(keyAuthorization)) {
|
||||
throw new Error(`Authorization not found in DNS TXT record: ${recordName}`);
|
||||
throw new Error(`Authorization not found in DNS TXT record: ${recordName},need:${keyAuthorization},found:${recordValues}`);
|
||||
}
|
||||
|
||||
log(`Key authorization match for ${challenge.type}/${recordName}, ACME challenge verified`);
|
||||
|
||||
@@ -66,6 +66,8 @@ async function spawn(opts: SpawnOption): Promise<string> {
|
||||
cmd = item;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
cmd = opts.cmd
|
||||
}
|
||||
log.info(`执行命令: ${cmd}`);
|
||||
let stdout = "";
|
||||
|
||||
@@ -42,10 +42,35 @@ export class CertConvertPlugin extends AbstractTaskPlugin {
|
||||
name: "a-input-password",
|
||||
vModel: "value",
|
||||
},
|
||||
required: true,
|
||||
required: false,
|
||||
})
|
||||
pfxPassword!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: "输出PFX",
|
||||
value:true,
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
pfxEnabled: boolean = true;
|
||||
|
||||
|
||||
@TaskInput({
|
||||
title: "输出DER",
|
||||
value:true,
|
||||
component: {
|
||||
name: "a-switch",
|
||||
vModel: "checked",
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
derEnabled: boolean = true;
|
||||
|
||||
|
||||
|
||||
@TaskOutput({
|
||||
title: "pfx格式证书",
|
||||
type: "PfxCert",
|
||||
@@ -64,11 +89,19 @@ export class CertConvertPlugin extends AbstractTaskPlugin {
|
||||
const certReader = new CertReader(this.cert);
|
||||
|
||||
const handle = async (opts: CertReaderHandleContext) => {
|
||||
// 调用openssl 转pfx
|
||||
await this.convertPfx(opts);
|
||||
|
||||
// 转der
|
||||
await this.convertDer(opts);
|
||||
if(this.pfxEnabled){
|
||||
// 调用openssl 转pfx
|
||||
await this.convertPfx(opts);
|
||||
}else{
|
||||
this.logger.info("pfx证书已禁用");
|
||||
}
|
||||
|
||||
if(this.pfxEnabled){
|
||||
// 转der
|
||||
await this.convertDer(opts);
|
||||
}else{
|
||||
this.logger.info("der证书已禁用");
|
||||
}
|
||||
};
|
||||
|
||||
await certReader.readCertFile({ logger: this.logger, handle });
|
||||
@@ -86,13 +119,18 @@ export class CertConvertPlugin extends AbstractTaskPlugin {
|
||||
|
||||
const pfxPath = path.join(os.tmpdir(), "/certd/tmp/", Math.floor(Math.random() * 1000000) + "", "cert.pfx");
|
||||
|
||||
const dir = path.dirname(pfxPath)
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
let passwordArg = "-passout pass:";
|
||||
if (this.pfxPassword) {
|
||||
passwordArg = `-password pass:${this.pfxPassword}`;
|
||||
}
|
||||
await this.exec(`openssl pkcs12 -export -out ${pfxPath} -inkey ${tmpKeyPath} -in ${tmpCrtPath} ${passwordArg}`);
|
||||
this.pfxCert = pfxPath;
|
||||
|
||||
|
||||
const applyTime = new Date().getTime();
|
||||
const filename = reader.buildCertFileName("pfx", applyTime);
|
||||
const fileBuffer = fs.readFileSync(pfxPath);
|
||||
@@ -102,6 +140,13 @@ export class CertConvertPlugin extends AbstractTaskPlugin {
|
||||
private async convertDer(opts: CertReaderHandleContext) {
|
||||
const { reader, tmpCrtPath } = opts;
|
||||
const derPath = path.join(os.tmpdir(), "/certd/tmp/", Math.floor(Math.random() * 1000000) + "", `cert.der`);
|
||||
|
||||
const dir = path.dirname(derPath)
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
|
||||
|
||||
await this.exec(`openssl x509 -outform der -in ${tmpCrtPath} -out ${derPath}`);
|
||||
this.derCert = derPath;
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import os from "os";
|
||||
import path from "path";
|
||||
import { crypto } from "@certd/acme-client";
|
||||
import { ILogger } from "@certd/pipeline";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export type CertReaderHandleContext = { reader: CertReader; tmpCrtPath: string; tmpKeyPath: string };
|
||||
export type CertReaderHandle = (ctx: CertReaderHandleContext) => Promise<void>;
|
||||
@@ -78,6 +79,7 @@ export class CertReader implements CertInfo {
|
||||
const detail = this.getCrtDetail();
|
||||
let domain = detail.detail.domains.commonName;
|
||||
domain = domain.replace(".", "_").replace("*", "_");
|
||||
return `${prefix}_${domain}_${applyTime}.${suffix}`;
|
||||
const timeStr = dayjs(applyTime).format("YYYYMMDDHHmmss");
|
||||
return `${prefix}_${domain}_${timeStr}.${suffix}`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
"cron-parser": "^4.9.0",
|
||||
"dayjs": "^1.11.7",
|
||||
"glob": "^10.4.5",
|
||||
"https-proxy-agent": "^7.0.4",
|
||||
"https-proxy-agent": "^7.0.5",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
|
||||
+7
-4
@@ -1,6 +1,7 @@
|
||||
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||
import { Autowire, ILogger } from '@certd/pipeline';
|
||||
import { AliyunAccess } from '@certd/plugin-plus';
|
||||
import { AliyunAccess, AliyunClient } from '@certd/plugin-plus';
|
||||
|
||||
@IsDnsProvider({
|
||||
name: 'aliyun',
|
||||
title: '阿里云',
|
||||
@@ -15,13 +16,14 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
|
||||
logger!: ILogger;
|
||||
async onInstance() {
|
||||
const access: any = this.access;
|
||||
const Core = await import('@alicloud/pop-core');
|
||||
this.client = new Core.default({
|
||||
|
||||
this.client = new AliyunClient({logger:this.logger})
|
||||
await this.client.init({
|
||||
accessKeyId: access.accessKeyId,
|
||||
accessKeySecret: access.accessKeySecret,
|
||||
endpoint: 'https://alidns.aliyuncs.com',
|
||||
apiVersion: '2015-01-09',
|
||||
});
|
||||
})
|
||||
}
|
||||
//
|
||||
// async getDomainList() {
|
||||
@@ -99,6 +101,7 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
|
||||
// Line: 'oversea' // 海外
|
||||
};
|
||||
|
||||
|
||||
const requestOption = {
|
||||
method: 'POST',
|
||||
};
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, utils } from '@certd/pipeline';
|
||||
import { AliyunAccess } from '@certd/plugin-plus';
|
||||
import { AliyunAccess, AliyunClient } from '@certd/plugin-plus';
|
||||
import { appendTimeSuffix } from '../../utils/index.js';
|
||||
import { CertInfo } from '@certd/plugin-cert';
|
||||
|
||||
@@ -200,14 +200,15 @@ export class DeployCertToAliyunAckIngressPlugin extends AbstractTaskPlugin {
|
||||
}
|
||||
|
||||
async getClient(aliyunProvider: any, regionId: string) {
|
||||
const Core = await import('@alicloud/pop-core');
|
||||
|
||||
return new Core.default({
|
||||
const client = new AliyunClient({logger:this.logger})
|
||||
await client.init({
|
||||
accessKeyId: aliyunProvider.accessKeyId,
|
||||
accessKeySecret: aliyunProvider.accessKeySecret,
|
||||
endpoint: `https://cs.${regionId}.aliyuncs.com`,
|
||||
apiVersion: '2015-12-15',
|
||||
});
|
||||
})
|
||||
return client
|
||||
}
|
||||
|
||||
async getKubeConfig(client: any, clusterId: string, isPrivateIpAddress = false) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
||||
import dayjs from 'dayjs';
|
||||
import { AliyunAccess } from "@certd/plugin-plus";
|
||||
import { AliyunAccess, AliyunClient } from "@certd/plugin-plus";
|
||||
@IsTaskPlugin({
|
||||
name: 'DeployCertToAliyunCDN',
|
||||
title: '部署证书至阿里云CDN',
|
||||
@@ -59,14 +59,14 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin {
|
||||
}
|
||||
|
||||
async getClient(access: AliyunAccess) {
|
||||
const Core = await import('@alicloud/pop-core');
|
||||
|
||||
return new Core.default({
|
||||
const client = new AliyunClient({logger:this.logger})
|
||||
await client.init({
|
||||
accessKeyId: access.accessKeyId,
|
||||
accessKeySecret: access.accessKeySecret,
|
||||
endpoint: 'https://cdn.aliyuncs.com',
|
||||
apiVersion: '2018-05-10',
|
||||
});
|
||||
})
|
||||
return client
|
||||
}
|
||||
|
||||
async buildParams() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
||||
import dayjs from 'dayjs';
|
||||
import { AliyunAccess } from "@certd/plugin-plus";
|
||||
import { AliyunAccess, AliyunClient } from "@certd/plugin-plus";
|
||||
@IsTaskPlugin({
|
||||
name: 'DeployCertToAliyunDCDN',
|
||||
title: '部署证书至阿里云DCDN',
|
||||
@@ -59,13 +59,14 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
|
||||
}
|
||||
|
||||
async getClient(access: AliyunAccess) {
|
||||
const sdk = await import('@alicloud/pop-core');
|
||||
return new sdk.default({
|
||||
const client = new AliyunClient({logger:this.logger})
|
||||
await client.init({
|
||||
accessKeyId: access.accessKeyId,
|
||||
accessKeySecret: access.accessKeySecret,
|
||||
endpoint: 'https://dcdn.aliyuncs.com',
|
||||
apiVersion: '2018-01-15',
|
||||
});
|
||||
})
|
||||
return client
|
||||
}
|
||||
|
||||
async buildParams() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from '@certd/pipeline';
|
||||
import { appendTimeSuffix, checkRet } from '../../utils/index.js';
|
||||
import { AliyunAccess } from "@certd/plugin-plus";
|
||||
import { AliyunAccess, AliyunClient } from "@certd/plugin-plus";
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: 'uploadCertToAliyun',
|
||||
@@ -86,13 +86,14 @@ export class UploadCertToAliyun extends AbstractTaskPlugin {
|
||||
}
|
||||
|
||||
async getClient(aliyunProvider: AliyunAccess) {
|
||||
const Core = await import('@alicloud/pop-core');
|
||||
return new Core.default({
|
||||
const client = new AliyunClient({logger:this.logger})
|
||||
await client.init({
|
||||
accessKeyId: aliyunProvider.accessKeyId,
|
||||
accessKeySecret: aliyunProvider.accessKeySecret,
|
||||
endpoint: 'https://cas.aliyuncs.com',
|
||||
apiVersion: '2018-07-13',
|
||||
});
|
||||
})
|
||||
return client
|
||||
}
|
||||
}
|
||||
//注册插件
|
||||
|
||||
@@ -21,6 +21,7 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
component: {
|
||||
placeholder: './tmp/cert.pem',
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
crtPath!: string;
|
||||
@TaskInput({
|
||||
@@ -29,6 +30,7 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
component: {
|
||||
placeholder: './tmp/cert.key',
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
keyPath!: string;
|
||||
@TaskInput({
|
||||
@@ -36,7 +38,7 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
helper: '请选择前置任务输出的域名证书',
|
||||
component: {
|
||||
name: 'pi-output-selector',
|
||||
from: 'CertApply',
|
||||
from: ['CertApply','CertConvert'],
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
@@ -44,11 +46,13 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
|
||||
|
||||
@TaskOutput({
|
||||
title: '证书保存路径',
|
||||
type:"HostCrtPath"
|
||||
})
|
||||
hostCrtPath!: string;
|
||||
|
||||
@TaskOutput({
|
||||
title: '私钥保存路径',
|
||||
type:"HostKeyPath"
|
||||
})
|
||||
hostKeyPath!: string;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user