mirror of
https://github.com/certd/certd.git
synced 2026-06-28 14:37:32 +08:00
feat: 新增证书申请参数模版管理,开放接口支持使用证书参数模版和指定证书申请参数
This commit is contained in:
@@ -134,5 +134,7 @@ export class MainConfiguration {
|
||||
});
|
||||
|
||||
logger.info("当前环境:", this.app.getEnv()); // prod
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ export type CertGetReq = {
|
||||
domains?: string;
|
||||
certId: number;
|
||||
autoApply?: boolean;
|
||||
autoApplyTemplateId?: number;
|
||||
autoApplyParams?: Record<string, any> | string;
|
||||
format?: string; //默认是所有,pem,der,p12,pfx,jks,one,p7b
|
||||
};
|
||||
|
||||
@@ -43,6 +45,8 @@ export class OpenCertController extends BaseOpenController {
|
||||
domains: req.domains,
|
||||
certId: req.certId,
|
||||
autoApply: req.autoApply ?? false,
|
||||
autoApplyTemplateId: req.autoApplyTemplateId,
|
||||
autoApplyParams: typeof req.autoApplyParams === "string" ? JSON.parse(req.autoApplyParams) : req.autoApplyParams,
|
||||
format: req.format,
|
||||
projectId,
|
||||
});
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { ALL, Body, Controller, Inject, Post, Provide, Query } from "@midwayjs/core";
|
||||
import { Constants, CrudController } from "@certd/lib-server";
|
||||
import { ApiTags } from "@midwayjs/swagger";
|
||||
import { CertApplyTemplateService } from "../../../modules/cert/service/cert-apply-template-service.js";
|
||||
|
||||
@Provide()
|
||||
@Controller("/api/cert/apply-template")
|
||||
@ApiTags(["cert"])
|
||||
export class CertApplyTemplateController extends CrudController<CertApplyTemplateService> {
|
||||
@Inject()
|
||||
service: CertApplyTemplateService;
|
||||
|
||||
getService(): CertApplyTemplateService {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
@Post("/page", { description: Constants.per.authOnly, summary: "查询证书申请参数模版分页列表" })
|
||||
async page(@Body(ALL) body: any) {
|
||||
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||
body.query = body.query ?? {};
|
||||
body.query.projectId = projectId;
|
||||
body.query.userId = userId;
|
||||
return super.page(body);
|
||||
}
|
||||
|
||||
@Post("/list", { description: Constants.per.authOnly, summary: "查询证书申请参数模版列表" })
|
||||
async list(@Body(ALL) body: any) {
|
||||
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||
body.query = body.query ?? {};
|
||||
body.query.projectId = projectId;
|
||||
body.query.userId = userId;
|
||||
body.query.disabled = false;
|
||||
return super.list(body);
|
||||
}
|
||||
|
||||
@Post("/add", { description: Constants.per.authOnly, summary: "添加证书申请参数模版" })
|
||||
async add(@Body(ALL) bean: any) {
|
||||
const { projectId, userId } = await this.getProjectUserIdWrite();
|
||||
bean.projectId = projectId;
|
||||
bean.userId = userId;
|
||||
return super.add(bean);
|
||||
}
|
||||
|
||||
@Post("/update", { description: Constants.per.authOnly, summary: "更新证书申请参数模版" })
|
||||
async update(@Body(ALL) bean: any) {
|
||||
await this.checkOwner(this.getService(), bean.id, "write");
|
||||
delete bean.userId;
|
||||
delete bean.projectId;
|
||||
return super.update(bean);
|
||||
}
|
||||
|
||||
@Post("/info", { description: Constants.per.authOnly, summary: "查询证书申请参数模版详情" })
|
||||
async info(@Query("id") id: number) {
|
||||
await this.checkOwner(this.getService(), id, "read");
|
||||
return super.info(id);
|
||||
}
|
||||
|
||||
@Post("/delete", { description: Constants.per.authOnly, summary: "删除证书申请参数模版" })
|
||||
async delete(@Query("id") id: number) {
|
||||
await this.checkOwner(this.getService(), id, "write");
|
||||
return super.delete(id);
|
||||
}
|
||||
|
||||
@Post("/setDefault", { description: Constants.per.authOnly, summary: "设置默认证书申请参数模版" })
|
||||
async setDefault(@Body("id") id: number) {
|
||||
const { projectId, userId } = await this.getProjectUserIdWrite();
|
||||
return this.ok(await this.service.setDefault(id, userId, projectId));
|
||||
}
|
||||
|
||||
@Post("/default", { description: Constants.per.authOnly, summary: "查询默认证书申请参数模版" })
|
||||
async getDefault() {
|
||||
const { projectId, userId } = await this.getProjectUserIdRead();
|
||||
return this.ok(await this.service.getDefault(userId, projectId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||
|
||||
/**
|
||||
* 证书申请参数模版
|
||||
*/
|
||||
@Entity("cd_cert_apply_template")
|
||||
export class CertApplyTemplateEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({ comment: "用户ID", name: "user_id" })
|
||||
userId: number;
|
||||
|
||||
@Column({ name: "project_id", comment: "项目ID" })
|
||||
projectId: number;
|
||||
|
||||
@Column({ comment: "模版名称", length: 100 })
|
||||
name: string;
|
||||
|
||||
@Column({ comment: "配置", type: "text" })
|
||||
content: string;
|
||||
|
||||
@Column({ name: "is_default", comment: "是否默认模版", default: false })
|
||||
isDefault: boolean;
|
||||
|
||||
@Column({ comment: "是否禁用", default: false })
|
||||
disabled: boolean;
|
||||
|
||||
@Column({
|
||||
comment: "创建时间",
|
||||
name: "create_time",
|
||||
default: () => "CURRENT_TIMESTAMP",
|
||||
})
|
||||
createTime: Date;
|
||||
|
||||
@Column({
|
||||
comment: "修改时间",
|
||||
name: "update_time",
|
||||
default: () => "CURRENT_TIMESTAMP",
|
||||
})
|
||||
updateTime: Date;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { pickCertApplyCustomParams, pickCertApplyTemplateParams } from "./cert-apply-template-fields.js";
|
||||
|
||||
describe("cert apply template fields", () => {
|
||||
it("keeps certificate apply and domain verify params but drops domains and verify plan for template", () => {
|
||||
const params = pickCertApplyTemplateParams({
|
||||
domains: ["example.com"],
|
||||
challengeType: "dns",
|
||||
dnsProviderType: "aliyun",
|
||||
dnsProviderAccess: 1,
|
||||
dnsProviderAccessType: "aliyun",
|
||||
domainsVerifyPlan: [{ domain: "example.com", type: "dns" }],
|
||||
sslProvider: "google",
|
||||
acmeAccountAccessId: 2,
|
||||
privateKeyType: "ec_256",
|
||||
pfxPassword: "secret",
|
||||
renewDays: 15,
|
||||
preferredChain: "GTS Root R1",
|
||||
newApplyParam: "kept",
|
||||
});
|
||||
|
||||
assert.deepEqual(params, {
|
||||
challengeType: "dns",
|
||||
dnsProviderType: "aliyun",
|
||||
dnsProviderAccess: 1,
|
||||
dnsProviderAccessType: "aliyun",
|
||||
sslProvider: "google",
|
||||
acmeAccountAccessId: 2,
|
||||
privateKeyType: "ec_256",
|
||||
pfxPassword: "secret",
|
||||
renewDays: 15,
|
||||
preferredChain: "GTS Root R1",
|
||||
newApplyParam: "kept",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps domain verify plan for custom auto apply params", () => {
|
||||
const params = pickCertApplyCustomParams({
|
||||
domains: ["example.com"],
|
||||
domainsVerifyPlan: [{ domain: "example.com", type: "dns" }],
|
||||
challengeType: "dns",
|
||||
});
|
||||
|
||||
assert.deepEqual(params, {
|
||||
domainsVerifyPlan: [{ domain: "example.com", type: "dns" }],
|
||||
challengeType: "dns",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
export type CertApplyTemplateParams = Record<string, any>;
|
||||
|
||||
export const certApplyTemplateExcludeParamFields = ["domains", "domainsVerifyPlan"] as const;
|
||||
export const certApplyCustomExcludeParamFields = ["domains"] as const;
|
||||
|
||||
const certApplyTemplateExcludeParamFieldSet = new Set<string>(certApplyTemplateExcludeParamFields);
|
||||
const certApplyCustomExcludeParamFieldSet = new Set<string>(certApplyCustomExcludeParamFields);
|
||||
|
||||
export function pickCertApplyTemplateParams(input: CertApplyTemplateParams = {}) {
|
||||
return pickCertApplyParams(input, certApplyTemplateExcludeParamFieldSet);
|
||||
}
|
||||
|
||||
export function pickCertApplyCustomParams(input: CertApplyTemplateParams = {}) {
|
||||
return pickCertApplyParams(input, certApplyCustomExcludeParamFieldSet);
|
||||
}
|
||||
|
||||
function pickCertApplyParams(input: CertApplyTemplateParams = {}, excludeFieldSet: Set<string>) {
|
||||
const params: CertApplyTemplateParams = {};
|
||||
for (const key of Object.keys(input)) {
|
||||
if (!excludeFieldSet.has(key) && input[key] !== undefined) {
|
||||
params[key] = input[key];
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { CertApplyTemplateService } from "./cert-apply-template-service.js";
|
||||
|
||||
function createService(list: any[]) {
|
||||
const service = new CertApplyTemplateService();
|
||||
(service as any).repository = {
|
||||
async findOne({ where }: any) {
|
||||
return list.find(item => {
|
||||
if (where.id != null && item.id !== where.id) {
|
||||
return false;
|
||||
}
|
||||
if (where.userId != null && item.userId !== where.userId) {
|
||||
return false;
|
||||
}
|
||||
if (where.projectId != null && item.projectId !== where.projectId) {
|
||||
return false;
|
||||
}
|
||||
if (where.isDefault != null && item.isDefault !== where.isDefault) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
},
|
||||
};
|
||||
return service;
|
||||
}
|
||||
|
||||
describe("CertApplyTemplateService", () => {
|
||||
it("does not apply default template when template id is not specified", async () => {
|
||||
const service = createService([
|
||||
{
|
||||
id: 1,
|
||||
userId: 10,
|
||||
projectId: 20,
|
||||
isDefault: true,
|
||||
content: JSON.stringify({
|
||||
sslProvider: "google",
|
||||
privateKeyType: "ec_256",
|
||||
renewDays: 10,
|
||||
domains: ["bad.example.com"],
|
||||
challengeType: "dns",
|
||||
}),
|
||||
},
|
||||
]);
|
||||
|
||||
const params = await service.resolveApplyParams({
|
||||
userId: 10,
|
||||
projectId: 20,
|
||||
});
|
||||
|
||||
assert.deepEqual(params, {});
|
||||
});
|
||||
|
||||
it("uses selected template when auto apply uses integer template id", async () => {
|
||||
const service = createService([
|
||||
{
|
||||
id: 2,
|
||||
userId: 10,
|
||||
projectId: 20,
|
||||
isDefault: false,
|
||||
content: JSON.stringify({
|
||||
sslProvider: "zerossl",
|
||||
acmeAccountAccessId: 8,
|
||||
preferredChain: "ZeroSSL RSA Domain Secure Site CA",
|
||||
}),
|
||||
},
|
||||
]);
|
||||
|
||||
const params = await service.resolveApplyParams({
|
||||
userId: 10,
|
||||
projectId: 20,
|
||||
templateId: 2,
|
||||
});
|
||||
|
||||
assert.deepEqual(params, {
|
||||
sslProvider: "zerossl",
|
||||
acmeAccountAccessId: 8,
|
||||
preferredChain: "ZeroSSL RSA Domain Secure Site CA",
|
||||
});
|
||||
});
|
||||
|
||||
it("uses custom params only when template id is not specified", async () => {
|
||||
const service = createService([
|
||||
{
|
||||
id: 1,
|
||||
userId: 10,
|
||||
projectId: 20,
|
||||
isDefault: true,
|
||||
content: JSON.stringify({
|
||||
sslProvider: "google",
|
||||
renewDays: 10,
|
||||
}),
|
||||
},
|
||||
]);
|
||||
|
||||
const params = await service.resolveApplyParams({
|
||||
userId: 10,
|
||||
projectId: 20,
|
||||
params: {
|
||||
renewDays: 30,
|
||||
privateKeyType: "rsa_4096",
|
||||
dnsProviderType: "cloudflare",
|
||||
domainsVerifyPlan: [{ domain: "example.com", type: "dns" }],
|
||||
domains: ["example.com"],
|
||||
challengeType: "auto",
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(params, {
|
||||
renewDays: 30,
|
||||
privateKeyType: "rsa_4096",
|
||||
dnsProviderType: "cloudflare",
|
||||
challengeType: "auto",
|
||||
domainsVerifyPlan: [{ domain: "example.com", type: "dns" }],
|
||||
});
|
||||
});
|
||||
|
||||
it("merges selected template and custom params when both are specified", async () => {
|
||||
const service = createService([
|
||||
{
|
||||
id: 2,
|
||||
userId: 10,
|
||||
projectId: 20,
|
||||
isDefault: false,
|
||||
content: JSON.stringify({
|
||||
sslProvider: "zerossl",
|
||||
acmeAccountAccessId: 8,
|
||||
preferredChain: "ZeroSSL RSA Domain Secure Site CA",
|
||||
renewDays: 10,
|
||||
}),
|
||||
},
|
||||
]);
|
||||
|
||||
const params = await service.resolveApplyParams({
|
||||
userId: 10,
|
||||
projectId: 20,
|
||||
templateId: 2,
|
||||
params: {
|
||||
renewDays: 30,
|
||||
privateKeyType: "rsa_4096",
|
||||
},
|
||||
});
|
||||
|
||||
assert.deepEqual(params, {
|
||||
sslProvider: "zerossl",
|
||||
acmeAccountAccessId: 8,
|
||||
preferredChain: "ZeroSSL RSA Domain Secure Site CA",
|
||||
renewDays: 30,
|
||||
privateKeyType: "rsa_4096",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,112 @@
|
||||
import { Provide, Scope, ScopeEnum } from "@midwayjs/core";
|
||||
import { InjectEntityModel } from "@midwayjs/typeorm";
|
||||
import { BaseService, ValidateException } from "@certd/lib-server";
|
||||
import { Repository } from "typeorm";
|
||||
import { CertApplyTemplateEntity } from "../entity/cert-apply-template.js";
|
||||
import { CertApplyTemplateParams, pickCertApplyCustomParams, pickCertApplyTemplateParams } from "./cert-apply-template-fields.js";
|
||||
|
||||
export type ResolveApplyTemplateReq = {
|
||||
userId: number;
|
||||
projectId?: number;
|
||||
templateId?: number;
|
||||
params?: CertApplyTemplateParams;
|
||||
};
|
||||
|
||||
@Provide()
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
export class CertApplyTemplateService extends BaseService<CertApplyTemplateEntity> {
|
||||
@InjectEntityModel(CertApplyTemplateEntity)
|
||||
repository: Repository<CertApplyTemplateEntity>;
|
||||
|
||||
getRepository(): Repository<CertApplyTemplateEntity> {
|
||||
return this.repository;
|
||||
}
|
||||
|
||||
async add(param: any) {
|
||||
param.content = this.stringifyContent(param.content);
|
||||
const res = await super.add(param);
|
||||
if (param.isDefault) {
|
||||
await this.setDefault(res.id, param.userId, param.projectId);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
async update(param: any) {
|
||||
if (param.content != null) {
|
||||
param.content = this.stringifyContent(param.content);
|
||||
}
|
||||
await super.update(param);
|
||||
if (param.isDefault === true) {
|
||||
const entity = await this.info(param.id);
|
||||
await this.setDefault(param.id, entity.userId, entity.projectId);
|
||||
}
|
||||
}
|
||||
|
||||
async setDefault(id: number, userId: number, projectId?: number) {
|
||||
const entity = await this.getTemplateById(id, userId, projectId);
|
||||
if (entity.disabled) {
|
||||
throw new ValidateException("禁用的模版不能设为默认");
|
||||
}
|
||||
await this.repository.update({ userId, projectId }, { isDefault: false });
|
||||
await this.repository.update({ id: entity.id, userId, projectId }, { isDefault: true });
|
||||
return entity;
|
||||
}
|
||||
|
||||
async getDefault(userId: number, projectId?: number) {
|
||||
return await this.repository.findOne({
|
||||
where: {
|
||||
userId,
|
||||
projectId,
|
||||
isDefault: true,
|
||||
disabled: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async resolveApplyParams(req: ResolveApplyTemplateReq) {
|
||||
const templateParams = await this.getTemplateParams(req);
|
||||
const customParams = pickCertApplyCustomParams(req.params || {});
|
||||
return {
|
||||
...templateParams,
|
||||
...customParams,
|
||||
};
|
||||
}
|
||||
|
||||
private async getTemplateParams(req: ResolveApplyTemplateReq) {
|
||||
if (!req.templateId) {
|
||||
return {};
|
||||
}
|
||||
const template = await this.getTemplateById(req.templateId, req.userId, req.projectId);
|
||||
if (!template) {
|
||||
return {};
|
||||
}
|
||||
return this.parseContent(template.content);
|
||||
}
|
||||
|
||||
private async getTemplateById(id: number, userId: number, projectId?: number) {
|
||||
const template = await this.repository.findOne({
|
||||
where: {
|
||||
id,
|
||||
userId,
|
||||
projectId,
|
||||
},
|
||||
});
|
||||
if (!template) {
|
||||
throw new ValidateException("证书申请参数模版不存在");
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
||||
private stringifyContent(content: any) {
|
||||
const params = this.parseContent(content);
|
||||
return JSON.stringify(params);
|
||||
}
|
||||
|
||||
private parseContent(content: any) {
|
||||
if (!content) {
|
||||
return {};
|
||||
}
|
||||
const raw = typeof content === "string" ? JSON.parse(content) : content;
|
||||
return pickCertApplyTemplateParams(raw);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import { PipelineEntity } from "../../pipeline/entity/pipeline.js";
|
||||
import { CertInfoService } from "../service/cert-info-service.js";
|
||||
import { DomainService } from "../../cert/service/domain-service.js";
|
||||
import { DomainVerifierGetter } from "../../pipeline/service/getter/domain-verifier-getter.js";
|
||||
import { CertApplyTemplateService } from "../../cert/service/cert-apply-template-service.js";
|
||||
import { CertApplyTemplateParams } from "../../cert/service/cert-apply-template-fields.js";
|
||||
|
||||
@Provide("CertInfoFacade")
|
||||
@Scope(ScopeEnum.Request, { allowDowngrade: true })
|
||||
@@ -25,7 +27,10 @@ export class CertInfoFacade {
|
||||
@Inject()
|
||||
userSettingsService: UserSettingsService;
|
||||
|
||||
async getCertInfo(req: { domains?: string; certId?: number; userId: number; projectId: number; autoApply?: boolean; format?: string }) {
|
||||
@Inject()
|
||||
certApplyTemplateService: CertApplyTemplateService;
|
||||
|
||||
async getCertInfo(req: { domains?: string; certId?: number; userId: number; projectId: number; autoApply?: boolean; format?: string; autoApplyTemplateId?: number; autoApplyParams?: CertApplyTemplateParams }) {
|
||||
const { domains, certId, userId, projectId } = req;
|
||||
if (certId) {
|
||||
return await this.certInfoService.getCertInfoById({ id: certId, userId, projectId });
|
||||
@@ -43,7 +48,13 @@ export class CertInfoFacade {
|
||||
if (matchedList.length === 0) {
|
||||
if (req.autoApply === true) {
|
||||
//自动申请,先创建自动申请流水线
|
||||
const pipeline: PipelineEntity = await this.createAutoPipeline({ domains: domainArr, userId, projectId });
|
||||
const pipeline: PipelineEntity = await this.createAutoPipeline({
|
||||
domains: domainArr,
|
||||
userId,
|
||||
projectId,
|
||||
autoApplyTemplateId: req.autoApplyTemplateId,
|
||||
autoApplyParams: req.autoApplyParams,
|
||||
});
|
||||
await this.triggerApplyPipeline({ pipelineId: pipeline.id });
|
||||
} else {
|
||||
throw new CodeException({
|
||||
@@ -98,7 +109,7 @@ export class CertInfoFacade {
|
||||
return matched;
|
||||
}
|
||||
|
||||
async createAutoPipeline(req: { domains: string[]; userId: number; projectId: number }) {
|
||||
async createAutoPipeline(req: { domains: string[]; userId: number; projectId: number; autoApplyTemplateId?: number; autoApplyParams?: CertApplyTemplateParams }) {
|
||||
const verifierGetter = new DomainVerifierGetter(req.userId, req.projectId, this.domainService);
|
||||
|
||||
const allDomains = [];
|
||||
@@ -123,6 +134,12 @@ export class CertInfoFacade {
|
||||
throw new CodeException(Constants.res.openEmailNotFound);
|
||||
}
|
||||
const email = userEmailSetting.list[0];
|
||||
const applyParams = await this.certApplyTemplateService.resolveApplyParams({
|
||||
userId: req.userId,
|
||||
projectId: req.projectId,
|
||||
templateId: req.autoApplyTemplateId,
|
||||
params: req.autoApplyParams,
|
||||
});
|
||||
|
||||
return await this.pipelineService.createAutoPipeline({
|
||||
domains: req.domains,
|
||||
@@ -130,6 +147,7 @@ export class CertInfoFacade {
|
||||
projectId: req.projectId,
|
||||
userId: req.userId,
|
||||
from: "OpenAPI",
|
||||
applyParams,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import parser from "cron-parser";
|
||||
import { ProjectService } from "../../sys/enterprise/service/project-service.js";
|
||||
import { CertApplyStepInputPatch, updateCertApplyStepInputs } from "./pipeline-batch-update.js";
|
||||
import { calcNextSuiteCountUsed } from "./pipeline-suite-limit.js";
|
||||
import { CertApplyTemplateParams } from "../../cert/service/cert-apply-template-fields.js";
|
||||
const runningTasks: Map<string | number, Executor> = new Map();
|
||||
|
||||
/**
|
||||
@@ -1298,7 +1299,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
}
|
||||
}
|
||||
|
||||
async createAutoPipeline(req: { domains: string[]; email: string; userId: number; projectId?: number; from: string }) {
|
||||
async createAutoPipeline(req: { domains: string[]; email: string; userId: number; projectId?: number; from: string; applyParams?: CertApplyTemplateParams }) {
|
||||
const randomHour = Math.floor(Math.random() * 6);
|
||||
const randomMin = Math.floor(Math.random() * 60);
|
||||
const randomCron = `0 ${randomMin} ${randomHour} * * *`;
|
||||
@@ -1343,9 +1344,6 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
runnableType: "step",
|
||||
input: {
|
||||
renewDays: 20,
|
||||
domains: req.domains,
|
||||
email: req.email,
|
||||
challengeType: "auto",
|
||||
sslProvider: "letsencrypt",
|
||||
privateKeyType: "rsa_2048",
|
||||
certProfile: "classic",
|
||||
@@ -1356,6 +1354,10 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
||||
waitDnsDiffuseTime: 30,
|
||||
pfxArgs: "-macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES",
|
||||
successNotify: true,
|
||||
...req.applyParams,
|
||||
domains: req.domains,
|
||||
email: req.email,
|
||||
challengeType: "auto",
|
||||
},
|
||||
strategy: {
|
||||
runStrategy: 0, // 正常执行
|
||||
|
||||
Reference in New Issue
Block a user