From 42bde235d3f5a20d09a3945a16a3c1af9e31bc9b Mon Sep 17 00:00:00 2001 From: XiaoJun Date: Wed, 9 Oct 2024 23:06:30 +0800 Subject: [PATCH 01/18] =?UTF-8?q?feat:=E6=B5=81=E6=B0=B4=E7=BA=BF=E6=8F=92?= =?UTF-8?q?=E4=BB=B6,=E5=B0=8F=E4=BC=97CDN=E7=B3=BB=E7=BB=9F=E7=9A=84?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/certd-server/src/plugins/index.ts | 1 + .../src/plugins/plugin-woai/access.ts | 28 ++++++ .../src/plugins/plugin-woai/index.ts | 2 + .../src/plugins/plugin-woai/plugins/index.ts | 1 + .../plugins/plugin-deploy-to-cdn.ts | 94 +++++++++++++++++++ 5 files changed, 126 insertions(+) create mode 100644 packages/ui/certd-server/src/plugins/plugin-woai/access.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-woai/index.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-woai/plugins/index.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-woai/plugins/plugin-deploy-to-cdn.ts diff --git a/packages/ui/certd-server/src/plugins/index.ts b/packages/ui/certd-server/src/plugins/index.ts index 49d2300e..9f59a4b6 100644 --- a/packages/ui/certd-server/src/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/index.ts @@ -10,3 +10,4 @@ export * from './plugin-west/index.js'; export * from './plugin-doge/index.js'; export * from './plugin-qiniu/index.js'; export * from './plugin-jdcloud/index.js'; +export * from './plugin-woai/index.js'; diff --git a/packages/ui/certd-server/src/plugins/plugin-woai/access.ts b/packages/ui/certd-server/src/plugins/plugin-woai/access.ts new file mode 100644 index 00000000..b04cd8e5 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-woai/access.ts @@ -0,0 +1,28 @@ +import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline'; + +@IsAccess({ + name: 'woai', + title: '我爱云授权', + desc: '我爱云CDN', +}) +export class WoaiAccess extends BaseAccess { + @AccessInput({ + title: '账号', + component: { + placeholder: '我爱云的账号', + }, + required: true, + }) + username = ''; + @AccessInput({ + title: '密码', + component: { + placeholder: '我爱云的密码', + }, + required: true, + encrypt: true, + }) + password = ''; +} + +new WoaiAccess(); diff --git a/packages/ui/certd-server/src/plugins/plugin-woai/index.ts b/packages/ui/certd-server/src/plugins/plugin-woai/index.ts new file mode 100644 index 00000000..fdad254f --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-woai/index.ts @@ -0,0 +1,2 @@ +export * from './plugins/index.js'; +export * from './access.js'; diff --git a/packages/ui/certd-server/src/plugins/plugin-woai/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-woai/plugins/index.ts new file mode 100644 index 00000000..cd1308a9 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-woai/plugins/index.ts @@ -0,0 +1 @@ +export * from './plugin-deploy-to-cdn.js'; diff --git a/packages/ui/certd-server/src/plugins/plugin-woai/plugins/plugin-deploy-to-cdn.ts b/packages/ui/certd-server/src/plugins/plugin-woai/plugins/plugin-deploy-to-cdn.ts new file mode 100644 index 00000000..f76e612e --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-woai/plugins/plugin-deploy-to-cdn.ts @@ -0,0 +1,94 @@ +import {AbstractTaskPlugin, HttpClient, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput} from '@certd/pipeline'; +import {CertInfo} from '@certd/plugin-cert'; +import {WoaiAccess} from '../access.js'; + +@IsTaskPlugin({ + name: 'woaiCloud', + title: '部署证书到我爱云 CDN', + desc: '部署证书到我爱云CDN', + icon: 'clarity:plugin-line', + group: pluginGroups.other.key, + default: { + strategy: { + runStrategy: RunStrategy.SkipWhenSucceed, + }, + }, +}) +export class WoaiCdnPlugin extends AbstractTaskPlugin { + @TaskInput({ + title: '证书ID', + helper: '请填写 证书列表 中的证书的ID', + component: {name: 'a-input'}, + required: true, + }) + certId!: string; + @TaskInput({ + title: '域名证书', + helper: '请选择前置任务输出的域名证书', + component: { + name: 'pi-output-selector', + from: ['CertApply', 'CertApplyLego'], + }, + required: true, + }) + cert!: CertInfo; + @TaskInput({ + title: 'Access授权', + helper: '我爱云的用户、密码授权', + component: { + name: 'pi-access-selector', + type: 'woai', + }, + required: true, + }) + accessId!: string; + http!: HttpClient; + private readonly baseApi = 'https://console.edeg.51vs.club'; + + async onInstance() { + this.http = this.ctx.http; + } + + private async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) { + const headers = { + 'Content-Type': 'application/json', + ...(token ? {'Token': token} : {}), + }; + const res = await this.http.request({ + url, + method, + data, + headers, + }); + if (res.code !== 200) { + throw new Error(`${JSON.stringify(res.message)}`); + } + return res; + } + + async execute(): Promise { + const {certId, cert, accessId} = this; + const access = (await this.accessService.getById(accessId)) as WoaiAccess; + // 登录获取token + const loginResponse = await this.doRequestApi(`${this.baseApi}/account/login`, { + username: access.username, + password: access.password, + }); + const token = loginResponse.data.token; + this.logger.info('登录成功,获取到Token:', token); + // 更新证书 + const editCertResponse = await this.doRequestApi( + `${this.baseApi}/certificate/edit`, + { + id: certId, + cert: cert.crt, + key: cert.key, + }, + 'post', + token + ); + this.logger.info('证书更新成功:', editCertResponse.message); + } +} + +new WoaiCdnPlugin(); From afd278e609c4e41642d371a32e0c01033dfacbbf Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Wed, 9 Oct 2024 23:23:52 +0800 Subject: [PATCH 02/18] docs: --- doc/dev/development.md | 28 ++++++++++++++++++++++------ pnpm-workspace.yaml | 6 +++--- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/doc/dev/development.md b/doc/dev/development.md index dc6920e1..ba918ac0 100644 --- a/doc/dev/development.md +++ b/doc/dev/development.md @@ -3,7 +3,7 @@ ## 1.本地调试运行 -安装依赖包: +### 克隆代码 ```shell # 克隆代码 @@ -11,22 +11,38 @@ git clone https://github.com/certd/certd #进入项目目录 cd certd +``` +### 修改pnpm-workspace.yaml文件 +重要:否则无法正确加载专业版的access和plugin +```yaml +# pnpm-workspace.yaml +packages: + - 'packages/**' # <--------------注释掉这一行,PR时不要提交此修改 + - 'packages/ui/**' +``` + +### 安装依赖和初始化: +```shell +# 安装pnpm,如果提示npm命令不存在,就需要先安装nodejs +npm install -g pnpm@8.15.7 --registry=https://registry.npmmirror.com + +# 使用国内镜像源,如果有代理,就不需要 +pnpm config set registry https://registry.npmmirror.com # 安装依赖 -npm install -g pnpm@8.15.7 pnpm install # 初始化构建 npm run init ``` -启动 server: +### 启动 server: ```shell cd packages/ui/certd-server npm run dev ``` -启动 client: +### 启动 client: ```shell cd packages/ui/certd-client npm run dev @@ -48,7 +64,7 @@ npm run dev 这样用户就可以在`certd`后台中创建这种授权凭证了 ### 3. dns-provider -如果域名是这个平台进行解析的,那么你需要实现dns-provider +如果域名是这个平台进行解析的,那么你需要实现dns-provider,(申请证书需要) 参考`plugin-cloudflare/dns-provider.ts` 修改为你要做的平台的`dns-provider` ### 4. plugin-deploy @@ -66,7 +82,7 @@ export * from './plugins/plugin-deploy-to-xx' 在`./src/plugins/index.ts`中增加`import` ```ts -export * from "./plugin-cloudflare" +export * from "./plugin-cloudflare.js" ``` ## 重启服务进行调试 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c1368ed9..ef8aed88 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,5 +1,5 @@ packages: - # all packages in subdirs of packages/ and components/ - - 'packages/**' - # exclude packages that are inside test directories + - 'packages/**' # <--------------开发插件请注释掉这一行,PR时本修改不要提交 + - 'packages/ui/**' - '!**/test/**' + From c5e58770d1c5edc19c6f9ea1618f44b68e091f35 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 10 Oct 2024 13:28:41 +0800 Subject: [PATCH 03/18] =?UTF-8?q?perf:=20=E5=B9=B6=E8=A1=8C=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=90=8D=E7=A7=B0=E6=94=B9=E6=88=90=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=EF=BC=8C=E5=8F=96=E6=B6=88=E5=B9=B6=E8=A1=8C?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E4=BB=A5=E5=9C=A8=E5=90=8C=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E8=8E=B7=E5=8F=96=E4=B8=8A=E4=B8=80=E4=B8=AA?= =?UTF-8?q?task=E7=9A=84=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/common/output-selector/index.vue | 2 ++ .../src/views/certd/pipeline/pipeline/index.vue | 2 +- .../src/views/certd/pipeline/pipeline/type.ts | 13 +++++++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/ui/certd-client/src/components/plugins/common/output-selector/index.vue b/packages/ui/certd-client/src/components/plugins/common/output-selector/index.vue index 76f770c3..0dacf480 100644 --- a/packages/ui/certd-client/src/components/plugins/common/output-selector/index.vue +++ b/packages/ui/certd-client/src/components/plugins/common/output-selector/index.vue @@ -23,6 +23,7 @@ export default { const pipeline = inject("pipeline") as Ref; const currentStageIndex = inject("currentStageIndex") as Ref; + const currentTaskIndex = inject("currentTaskIndex") as Ref; const currentStepIndex = inject("currentStepIndex") as Ref; const currentTask = inject("currentTask") as Ref; @@ -32,6 +33,7 @@ export default { options.value = pluginGroups.getPreStepOutputOptions({ pipeline: pipeline.value, currentStageIndex: currentStageIndex.value, + currentTaskIndex: currentTaskIndex.value, currentStepIndex: currentStepIndex.value, currentTask: currentTask.value }); diff --git a/packages/ui/certd-client/src/views/certd/pipeline/pipeline/index.vue b/packages/ui/certd-client/src/views/certd/pipeline/pipeline/index.vue index 3882c74a..585e769b 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/pipeline/index.vue +++ b/packages/ui/certd-client/src/views/certd/pipeline/pipeline/index.vue @@ -134,7 +134,7 @@ - 并行任务 + 添加任务 diff --git a/packages/ui/certd-client/src/views/certd/pipeline/pipeline/type.ts b/packages/ui/certd-client/src/views/certd/pipeline/pipeline/type.ts index 15db554d..f17c3167 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/pipeline/type.ts +++ b/packages/ui/certd-client/src/views/certd/pipeline/pipeline/type.ts @@ -75,10 +75,11 @@ export class PluginGroups { return this.map[name]; } - getPreStepOutputOptions({ pipeline, currentStageIndex, currentStepIndex, currentTask }: any) { + getPreStepOutputOptions({ pipeline, currentStageIndex, currentTaskIndex, currentStepIndex, currentTask }: any) { const steps = this.collectionPreStepOutputs({ pipeline, currentStageIndex, + currentTaskIndex, currentStepIndex, currentTask }); @@ -96,7 +97,7 @@ export class PluginGroups { return options; } - collectionPreStepOutputs({ pipeline, currentStageIndex, currentStepIndex, currentTask }: any) { + collectionPreStepOutputs({ pipeline, currentStageIndex, currentTaskIndex, currentStepIndex, currentTask }: any) { const steps: any[] = []; // 开始放step for (let i = 0; i < currentStageIndex; i++) { @@ -107,6 +108,14 @@ export class PluginGroups { } } } + //当前阶段之前的task + const currentStage = pipeline.stages[currentStageIndex]; + for (let i = 0; i < currentTaskIndex; i++) { + const task = currentStage.tasks[i]; + for (const step of task.steps) { + steps.push(step); + } + } //放当前任务下的step for (let i = 0; i < currentStepIndex; i++) { const step = currentTask.steps[i]; From 592791d1356fc252fbb70d7f168567aee9585507 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 10 Oct 2024 13:29:08 +0800 Subject: [PATCH 04/18] =?UTF-8?q?perf:=20google=20eab=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E8=87=AA=E5=8A=A8=E8=8E=B7=E5=8F=96=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E8=BF=87=E8=A6=81=E9=85=8D=E7=BD=AE=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/plugins/plugin-cert/package.json | 3 +- .../plugin-cert/src/access/google-access.ts | 97 +++++++++++++++++++ .../plugins/plugin-cert/src/access/index.ts | 1 + .../plugins/plugin-cert/src/libs/google.ts | 62 ++++++++++++ .../src/plugin/cert-plugin/index.ts | 68 ++++++++++++- .../views/certd/pipeline/certd-form/crud.tsx | 2 +- 6 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 packages/plugins/plugin-cert/src/access/google-access.ts create mode 100644 packages/plugins/plugin-cert/src/libs/google.ts diff --git a/packages/plugins/plugin-cert/package.json b/packages/plugins/plugin-cert/package.json index 79e19a1b..f90dd780 100644 --- a/packages/plugins/plugin-cert/package.json +++ b/packages/plugins/plugin-cert/package.json @@ -14,9 +14,10 @@ "preview": "vite preview" }, "dependencies": { - "@certd/basic": "^1.25.9", "@certd/acme-client": "^1.25.9", + "@certd/basic": "^1.25.9", "@certd/pipeline": "^1.25.9", + "@google-cloud/publicca": "^1.3.0", "dayjs": "^1.11.7", "jszip": "^3.10.1", "node-forge": "^0.10.0", diff --git a/packages/plugins/plugin-cert/src/access/google-access.ts b/packages/plugins/plugin-cert/src/access/google-access.ts new file mode 100644 index 00000000..efc66355 --- /dev/null +++ b/packages/plugins/plugin-cert/src/access/google-access.ts @@ -0,0 +1,97 @@ +import { IsAccess, AccessInput, BaseAccess } from "@certd/pipeline"; + +@IsAccess({ + name: "google", + title: "google cloud", + desc: "谷歌云授权", +}) +export class GoogleAccess extends BaseAccess { + @AccessInput({ + title: "密钥类型", + value: "serviceAccount", + component: { + placeholder: "密钥类型", + name: "a-select", + vModel: "value", + options: [ + { value: "serviceAccount", label: "服务账号密钥" }, + { value: "apiKey", label: "ApiKey,暂不可用", disabled: true }, + ], + }, + helper: "密钥类型", + required: true, + encrypt: false, + }) + type = ""; + + @AccessInput({ + title: "项目ID", + component: { + placeholder: "ProjectId", + }, + helper: "ProjectId", + required: true, + encrypt: false, + mergeScript: ` + return { + show:ctx.compute(({form})=>{ + return form.access.type === 'apiKey' + }) + } + `, + }) + projectId = ""; + + @AccessInput({ + title: "ApiKey", + component: { + placeholder: "ApiKey", + }, + helper: "不要选,目前没有用", + required: true, + encrypt: true, + mergeScript: ` + return { + show:ctx.compute(({form})=>{ + return form.access.type === 'apiKey' + }) + } + `, + }) + apiKey = ""; + + @AccessInput({ + title: "服务账号密钥", + component: { + placeholder: "serviceAccountSecret", + name: "a-textarea", + vModel: "value", + rows: 4, + }, + helper: + "[如何创建服务账号](https://cloud.google.com/iam/docs/service-accounts-create?hl=zh-CN) \n[获取密钥](https://console.cloud.google.com/iam-admin/serviceaccounts?hl=zh-cn),点击详情,点击创建密钥,将下载json文件,把内容填在此处", + required: true, + encrypt: true, + mergeScript: ` + return { + show:ctx.compute(({form})=>{ + return form.access.type === 'serviceAccount' + }) + } + `, + }) + serviceAccountSecret = ""; + + @AccessInput({ + title: "https代理", + component: { + placeholder: "http://127.0.0.1:10811", + }, + helper: "Google的请求需要走代理,如果不配置,则会使用环境变量中的全局HTTPS_PROXY配置\n或者服务器本身在海外,则不需要配置", + required: false, + encrypt: false, + }) + httpsProxy = ""; +} + +new GoogleAccess(); diff --git a/packages/plugins/plugin-cert/src/access/index.ts b/packages/plugins/plugin-cert/src/access/index.ts index 4111cb7d..0ea7960a 100644 --- a/packages/plugins/plugin-cert/src/access/index.ts +++ b/packages/plugins/plugin-cert/src/access/index.ts @@ -1 +1,2 @@ export * from "./eab-access.js"; +export * from "./google-access.js"; diff --git a/packages/plugins/plugin-cert/src/libs/google.ts b/packages/plugins/plugin-cert/src/libs/google.ts new file mode 100644 index 00000000..81a24fc1 --- /dev/null +++ b/packages/plugins/plugin-cert/src/libs/google.ts @@ -0,0 +1,62 @@ +import { EabAccess, GoogleAccess } from "../access/index.js"; +import { ILogger } from "@certd/basic"; + +export class GoogleClient { + access: GoogleAccess; + logger: ILogger; + constructor(opts: { logger: ILogger; access: GoogleAccess }) { + this.access = opts.access; + this.logger = opts.logger; + } + async getEab() { + // https://cloud.google.com/docs/authentication/api-keys-use#using-with-client-libs + const { v1 } = await import("@google-cloud/publicca"); + // process.env.HTTPS_PROXY = "http://127.0.0.1:10811"; + const access = this.access; + if (!access.serviceAccountSecret) { + throw new Error("服务账号密钥 不能为空"); + } + const credentials = JSON.parse(access.serviceAccountSecret); + + const client = new v1.PublicCertificateAuthorityServiceClient({ credentials }); + const parent = `projects/${access.projectId}/locations/global`; + const externalAccountKey = {}; + const request = { + parent, + externalAccountKey, + }; + + let envHttpsProxy = ""; + try { + if (this.access.httpsProxy) { + //设置临时使用代理 + envHttpsProxy = process.env.HTTPS_PROXY; + process.env.HTTPS_PROXY = this.access.httpsProxy; + } + this.logger.info("开始获取google eab授权"); + const response = await client.createExternalAccountKey(request); + const { keyId, b64MacKey } = response[0]; + const eabAccess = new EabAccess(); + eabAccess.kid = keyId; + eabAccess.hmacKey = b64MacKey.toString(); + this.logger.info(`google eab授权获取成功,kid: ${eabAccess.kid}`); + return eabAccess; + } finally { + if (envHttpsProxy) { + process.env.HTTPS_PROXY = envHttpsProxy; + } + } + } +} + +// const access = new GoogleAccess(); +// access.projectId = "hip-light-432411-d4"; +// access.serviceAccountSecret = ` +// +// +// `; +// // process.env.HTTPS_PROXY = "http://127.0.0.1:10811"; +// const client = new GoogleClient(access); +// client.getEab().catch((e) => { +// console.error(e); +// }); diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts index 526bd993..7fb6c6a2 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts @@ -5,6 +5,7 @@ import _ from "lodash-es"; import { createDnsProvider, DnsProviderContext, IDnsProvider } from "../../dns-provider/index.js"; import { CertReader } from "./cert-reader.js"; import { CertApplyBasePlugin } from "./base.js"; +import { GoogleClient } from "../../libs/google.js"; export type { CertInfo }; export * from "./cert-reader.js"; @@ -145,18 +146,56 @@ export class CertApplyPlugin extends CertApplyBasePlugin { }, maybeNeed: true, required: true, - helper: - "需要提供EAB授权\nZeroSSL:请前往[zerossl开发者中心](https://app.zerossl.com/developer),生成 'EAB Credentials' \n Google:请查看[google获取eab帮助文档](https://github.com/certd/certd/blob/v2/doc/google/google.md)", + helper: "需要提供EAB授权\nZeroSSL:请前往[zerossl开发者中心](https://app.zerossl.com/developer),生成 'EAB Credentials'", mergeScript: ` return { show: ctx.compute(({form})=>{ - return form.sslProvider === 'zerossl' || form.sslProvider === 'google' + return form.sslProvider === 'zerossl' }) } `, }) eabAccessId!: number; + @TaskInput({ + title: "GoogleEAB授权", + component: { + name: "access-selector", + type: "eab", + }, + maybeNeed: true, + required: false, + helper: + "请查看[google获取eab帮助文档](https://github.com/certd/certd/blob/v2/doc/google/google.md)\n注意此方式获取的EAB授权是一次性的,下次申请需要重新获取授权\n推荐使用Google服务账号授权自动获取EAB", + mergeScript: ` + return { + show: ctx.compute(({form})=>{ + return form.sslProvider === 'google' + }) + } + `, + }) + googleEabAccessId!: number; + + @TaskInput({ + title: "Google服务账号授权", + component: { + name: "access-selector", + type: "google", + }, + maybeNeed: true, + required: false, + helper: "google服务账号授权,需要配置代理或者服务器本身在海外\n代理配置方法:配置环境变量https_proxy", + mergeScript: ` + return { + show: ctx.compute(({form})=>{ + return form.sslProvider === 'google' + }) + } + `, + }) + googleAccessId!: number; + @TaskInput({ title: "加密算法", value: "rsa_2048", @@ -205,9 +244,30 @@ export class CertApplyPlugin extends CertApplyBasePlugin { async onInit() { let eab: any = null; - if (this.eabAccessId) { + + if (this.sslProvider === "google") { + if (this.googleAccessId) { + const googleAccess = await this.ctx.accessService.getById(this.googleAccessId); + const googleClient = new GoogleClient({ + access: googleAccess, + logger: this.logger, + }); + eab = await googleClient.getEab(); + } else if (this.googleEabAccessId || this.eabAccessId) { + this.logger.warn("您正在使用google一次性EAB授权,下次申请证书需要重新获取"); + eab = await this.ctx.accessService.getById(this.googleEabAccessId); + } else { + this.logger.error("google需要配置EAB授权或服务账号授权"); + return; + } + } else if (this.sslProvider === "zerossl") { + if (this.eabAccessId) { + this.logger.error("zerossl需要EAB授权"); + return; + } eab = await this.ctx.accessService.getById(this.eabAccessId); } + this.acme = new AcmeService({ userContext: this.userContext, logger: this.logger, diff --git a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/crud.tsx b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/crud.tsx index 9ea2dbe9..e5228eb8 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/certd-form/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/pipeline/certd-form/crud.tsx @@ -69,7 +69,7 @@ export default function (certPluginGroup: PluginGroup, formWrapperRef: any): Cre return (
  • JS-ACME:使用简单方便,功能强大【推荐】
  • -
  • Lego-ACME:基于Lego实现,支持海量DNS提供商,熟悉LEGO的用户可以使用【即将废弃】
  • +
  • Lego-ACME:基于Lego实现,支持海量DNS提供商,熟悉LEGO的用户可以使用
); } From 5d15d71da8c0f42f79b132be54780eeb0b77f33d Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 10 Oct 2024 13:31:12 +0800 Subject: [PATCH 05/18] chore: 1 --- packages/plugins/plugin-cert/src/libs/google.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/plugin-cert/src/libs/google.ts b/packages/plugins/plugin-cert/src/libs/google.ts index 81a24fc1..79bfcb1e 100644 --- a/packages/plugins/plugin-cert/src/libs/google.ts +++ b/packages/plugins/plugin-cert/src/libs/google.ts @@ -19,7 +19,7 @@ export class GoogleClient { const credentials = JSON.parse(access.serviceAccountSecret); const client = new v1.PublicCertificateAuthorityServiceClient({ credentials }); - const parent = `projects/${access.projectId}/locations/global`; + const parent = `projects/${credentials.projectId}/locations/global`; const externalAccountKey = {}; const request = { parent, From 2ba94d03aa48f411bb40c2a2363848f756b7e6cc Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 10 Oct 2024 13:32:37 +0800 Subject: [PATCH 06/18] chore: 1 --- packages/plugins/plugin-cert/src/libs/google.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugins/plugin-cert/src/libs/google.ts b/packages/plugins/plugin-cert/src/libs/google.ts index 79bfcb1e..8fea2f68 100644 --- a/packages/plugins/plugin-cert/src/libs/google.ts +++ b/packages/plugins/plugin-cert/src/libs/google.ts @@ -19,7 +19,7 @@ export class GoogleClient { const credentials = JSON.parse(access.serviceAccountSecret); const client = new v1.PublicCertificateAuthorityServiceClient({ credentials }); - const parent = `projects/${credentials.projectId}/locations/global`; + const parent = `projects/${credentials.project_id}/locations/global`; const externalAccountKey = {}; const request = { parent, From 0a9ec06fe7f4369dc0cf867465228d7665eed10b Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 10 Oct 2024 13:57:30 +0800 Subject: [PATCH 07/18] chore: 1 --- doc/google/google.md | 37 ++++++++++++++----- .../src/plugin/cert-plugin/index.ts | 9 +++-- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/doc/google/google.md b/doc/google/google.md index f77a8bba..a6d4773f 100644 --- a/doc/google/google.md +++ b/doc/google/google.md @@ -7,16 +7,17 @@ https://console.cloud.google.com/apis/library/publicca.googleapis.com 打开该链接后点击“启用”,随后等待右侧出现“API已启用”则可以关闭该页。 -## 2、 申请Key -随后打开“Google Cloud Shell”(在右上角点击激活CloudShell图标)。 +## 2、 获取授权 +以下两种方式任选其一,有代理的话,推荐选第二种 +### 2.1 直接获取一次性EAB +1. 打开“Google Cloud Shell”(在右上角点击激活CloudShell图标)。 等待分配完成后在 Shell 窗口内输入如下命令: ```shell gcloud beta publicca external-account-keys create ``` -此时会弹出“为 Cloud Shell 提供授权”,点击授权即可。 - +2. 此时会弹出“为 Cloud Shell 提供授权”,点击授权即可。 执行完成后会返回类似如下输出;注意不要在没有收到 Google 的邮件时执行该命令,会返回命令不存在。 ```shell @@ -24,14 +25,30 @@ Created an external account key [b64MacKey: xxxxxxxxxxxxxxxx keyId: xxxxxxxxxxxxx] ``` -记录以上信息备用(注意keyId是不带中括号的) + +3. 到Certd中,创建一条EAB授权记录,填写keyId(=kid) 和 b64MacKey 信息 + 注意:keyId没有`]`结尾,不要把`]`也复制了 + +注意:此方式获取的EAB是一次性的,只能用于申请一次证书,优势是无需代理。 + +### 2.2 通过服务账号获取EAB【推荐】 + +此方式可以自动EAB,需要配置代理 + +1. 创建服务账号 +https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts/create?walkthrough_id=iam--create-service-account&hl=zh-cn#step_index=1 + +2. 选择一个项目,进入创建服务账号页面 +3. 给服务账号起一个名字,点击`创建并继续` +4. 向此服务账号授予对项目的访问权限: `选择角色`->`基本`->`Owner` +5. 点击完成 +6. 点击服务账号,进入服务账号详情页面 +7. 点击`添加密钥`->`创建新密钥`->`JSON`,下载密钥文件 +8. 将json文件内容粘贴到 certd中 Google服务授权输入框中 ## 3、 创建证书流水线 -选择证书提供商为google, 开启使用代理 +选择证书提供商为google, 选择EAB授权 或 服务账号授权 -## 4、 将key信息作为EAB授权信息 -google证书需要EAB授权, 使用第二步中的 keyId 和 b64MacKey 信息创建一条EAB授权记录 -注意:keyId没有`]`结尾,不要把`]`也复制了 -## 5、 其他就跟正常申请证书一样了 +## 4、 其他就跟正常申请证书一样了 diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts index 7fb6c6a2..ed1a44df 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/index.ts @@ -158,7 +158,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin { eabAccessId!: number; @TaskInput({ - title: "GoogleEAB授权", + title: "临时EAB授权", component: { name: "access-selector", type: "eab", @@ -166,7 +166,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin { maybeNeed: true, required: false, helper: - "请查看[google获取eab帮助文档](https://github.com/certd/certd/blob/v2/doc/google/google.md)\n注意此方式获取的EAB授权是一次性的,下次申请需要重新获取授权\n推荐使用Google服务账号授权自动获取EAB", + "请查看[google获取eab帮助文档](https://gitee.com/certd/certd/blob/v2/doc/google/google.md)\n注意此方式获取的EAB授权是一次性的,下次申请需要重新获取授权\n推荐使用Google服务账号授权自动获取EAB", mergeScript: ` return { show: ctx.compute(({form})=>{ @@ -178,14 +178,15 @@ export class CertApplyPlugin extends CertApplyBasePlugin { googleEabAccessId!: number; @TaskInput({ - title: "Google服务账号授权", + title: "服务账号授权", component: { name: "access-selector", type: "google", }, maybeNeed: true, required: false, - helper: "google服务账号授权,需要配置代理或者服务器本身在海外\n代理配置方法:配置环境变量https_proxy", + helper: + "google服务账号授权与google一次性EAB授权选填其中一个,[服务账号授权获取方法](https://gitee.com/certd/certd/blob/v2/doc/google/google.md)\n服务账号授权需要配置代理或者服务器本身在海外", mergeScript: ` return { show: ctx.compute(({form})=>{ From cbd6abb29de3fb3e1944e06640355f97902bac4d Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 10 Oct 2024 14:07:11 +0800 Subject: [PATCH 08/18] chore: 1 --- packages/ui/certd-client/src/views/certd/access/common.tsx | 5 ++++- packages/ui/certd-client/src/views/certd/access/crud.tsx | 5 ++++- .../src/modules/pipeline/service/pipeline-service.ts | 7 ++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/ui/certd-client/src/views/certd/access/common.tsx b/packages/ui/certd-client/src/views/certd/access/common.tsx index 29a8f27a..946432fd 100644 --- a/packages/ui/certd-client/src/views/certd/access/common.tsx +++ b/packages/ui/certd-client/src/views/certd/access/common.tsx @@ -59,7 +59,10 @@ export function getCommonColumnDefine(crudExpose: any, typeRef: any) { show: false }, column: { - width: 120 + width: 200, + component: { + color: "auto" + } }, form: { component: { diff --git a/packages/ui/certd-client/src/views/certd/access/crud.tsx b/packages/ui/certd-client/src/views/certd/access/crud.tsx index 4a164942..05d11d4d 100644 --- a/packages/ui/certd-client/src/views/certd/access/crud.tsx +++ b/packages/ui/certd-client/src/views/certd/access/crud.tsx @@ -51,7 +51,7 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti key: "id", type: "number", column: { - width: 50 + width: 100 }, form: { show: false @@ -65,6 +65,9 @@ export default function ({ crudExpose }: CreateCrudOptionsProps): CreateCrudOpti }, form: { rules: [{ required: true, message: "必填项" }] + }, + column: { + width: 300 } }, ...commonColumnsDefine diff --git a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts index e74bb57d..d0ead818 100644 --- a/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts +++ b/packages/ui/certd-server/src/modules/pipeline/service/pipeline-service.ts @@ -118,10 +118,11 @@ export class PipelineService extends BaseService { const isUpdate = bean.id > 0 && old != null; if (!isPlus()) { let count = await this.repository.count(); - if (isUpdate) { - count -= 1; + if (!isUpdate) { + //如果是添加要加1 + count += 1; } - if (count >= freeCount) { + if (count > freeCount) { throw new NeedVIPException('免费版最多只能创建10个pipeline'); } } From 2a3ca9f552d96594ec6690a1c4c91f598451b9a1 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 10 Oct 2024 14:28:46 +0800 Subject: [PATCH 09/18] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=AE=9D?= =?UTF-8?q?=E5=A1=94=E7=BD=91=E7=AB=99=E9=83=A8=E7=BD=B2=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E8=8E=B7=E5=8F=96=E6=95=B0=E6=8D=AE=E7=9A=84?= =?UTF-8?q?=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/certd-client/src/api/service.ts | 8 ++- .../plugins/common/cert-domains-getter.vue | 10 ++-- .../plugins/common/remote-select.vue | 51 +++++++++++-------- .../src/components/plugins/lib/index.ts | 2 +- .../plugins/synology/device-id-getter.vue | 2 +- .../ui/certd-client/src/style/common.less | 5 +- 6 files changed, 49 insertions(+), 29 deletions(-) diff --git a/packages/ui/certd-client/src/api/service.ts b/packages/ui/certd-client/src/api/service.ts index 412b35ca..b5285cf2 100644 --- a/packages/ui/certd-client/src/api/service.ts +++ b/packages/ui/certd-client/src/api/service.ts @@ -47,7 +47,13 @@ function createService() { return dataAxios.data; default: // 不是正确的 code - errorCreate(`${dataAxios.msg}: ${response.config.url}`); + const errorMessage = dataAxios.msg; + // @ts-ignore + if (response?.config?.onError) { + // @ts-ignore + response.config.onError(new Error(errorMessage)); + } + errorCreate(`${errorMessage}: ${response.config.url}`); return dataAxios; } } diff --git a/packages/ui/certd-client/src/components/plugins/common/cert-domains-getter.vue b/packages/ui/certd-client/src/components/plugins/common/cert-domains-getter.vue index 0f40a017..1b088c10 100644 --- a/packages/ui/certd-client/src/components/plugins/common/cert-domains-getter.vue +++ b/packages/ui/certd-client/src/components/plugins/common/cert-domains-getter.vue @@ -1,3 +1,8 @@ + + - - diff --git a/packages/ui/certd-client/src/components/plugins/common/remote-select.vue b/packages/ui/certd-client/src/components/plugins/common/remote-select.vue index d2bbd2c7..0b1541eb 100644 --- a/packages/ui/certd-client/src/components/plugins/common/remote-select.vue +++ b/packages/ui/certd-client/src/components/plugins/common/remote-select.vue @@ -1,6 +1,28 @@ + - - diff --git a/packages/ui/certd-client/src/components/plugins/lib/index.ts b/packages/ui/certd-client/src/components/plugins/lib/index.ts index b338d562..abbfb3f6 100644 --- a/packages/ui/certd-client/src/components/plugins/lib/index.ts +++ b/packages/ui/certd-client/src/components/plugins/lib/index.ts @@ -14,7 +14,7 @@ export type RequestHandleReq = { input: T; }; -export async function doRequest(req: RequestHandleReq, opts?: any = {}) { +export async function doRequest(req: RequestHandleReq, opts: any = {}) { const url = req.type === "access" ? "/pi/handle/access" : "/pi/handle/plugin"; const { typeName, action, data, input } = req; const res = await request({ diff --git a/packages/ui/certd-client/src/components/plugins/synology/device-id-getter.vue b/packages/ui/certd-client/src/components/plugins/synology/device-id-getter.vue index c7aca533..e80dc889 100644 --- a/packages/ui/certd-client/src/components/plugins/synology/device-id-getter.vue +++ b/packages/ui/certd-client/src/components/plugins/synology/device-id-getter.vue @@ -1,7 +1,7 @@