mirror of https://github.com/certd/certd
Merge remote-tracking branch 'origin/v2' into v2
commit
af388ec39f
|
@ -1,34 +1,37 @@
|
|||
version: '3.3'
|
||||
services:
|
||||
certd:
|
||||
# 镜像 # ↓↓↓↓↓ --- 1、 镜像版本号,建议改成固定版本号【可选】
|
||||
# 镜像 # ↓↓↓↓↓ --- 镜像版本号,建议改成固定版本号【可选】
|
||||
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||
container_name: certd # 容器名
|
||||
restart: unless-stopped # 自动重启
|
||||
volumes:
|
||||
# ↓↓↓↓↓ ------------------------------------------------------- 2、 数据库以及证书存储路径,默认存在宿主机的/data/certd/目录下【可选】
|
||||
# ↓↓↓↓↓ -------------------------------------------------------- 数据库以及证书存储路径,默认存在宿主机的/data/certd/目录下【可选】
|
||||
- /data/certd:/app/data
|
||||
ports: # 端口映射
|
||||
# ↓↓↓↓ ----------------------------------------------------------3、如果端口有冲突,可以修改第一个7001为其他不冲突的端口号【可选】
|
||||
# ↓↓↓↓ ---------------------------------------------------------- 如果端口有冲突,可以修改第一个7001为其他不冲突的端口号【可选】
|
||||
- "7001:7001"
|
||||
dns:
|
||||
# 如果出现getaddrinfo ENOTFOUND等错误,可以尝试修改或注释dns配置
|
||||
- 223.5.5.5
|
||||
- 223.6.6.6
|
||||
# ↓↓↓↓ ----------------------------------------------------------如果你服务器部署在国外,可以用8.8.8.8替换上面的dns【可选】
|
||||
# ↓↓↓↓ ---------------------------------------------------------- 如果你服务器部署在国外,可以用8.8.8.8替换上面的dns【可选】
|
||||
# - 8.8.8.8
|
||||
# - 8.8.4.4
|
||||
environment: # 环境变量
|
||||
- TZ=Asia/Shanghai
|
||||
#- HTTPS_PROXY=http://xxxxxx:xx
|
||||
#- HTTP_PROXY=http://xxxxxx:xx
|
||||
# ↑↑↑↑↑ ------------------------------------- 这里可以设置http代理【可选】
|
||||
- certd_system_resetAdminPasswd=false
|
||||
# ↑↑↑↑↑---------------------------4、如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false【可选】
|
||||
# ↑↑↑↑↑--------------------------- 如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false【可选】
|
||||
- certd_cron_immediateTriggerOnce=false
|
||||
# ↑↑↑↑↑---------------------------5、如果设置为true,启动后所有配置了cron的流水线任务都将被立即触发一次【可选】
|
||||
# ↑↑↑↑↑--------------------------- 如果设置为true,启动后所有配置了cron的流水线任务都将被立即触发一次【可选】
|
||||
- VITE_APP_ICP_NO=
|
||||
# ↑↑↑↑↑ -----------------------------------------6、这里可以设置备案号【可选】
|
||||
# ↑↑↑↑↑ ----------------------------------------- 这里可以设置备案号【可选】
|
||||
#- certd_koa_key=./data/ssl/cert.key
|
||||
#- certd_koa_cert=./data/ssl/cert.crt
|
||||
# ↑↑↑↑↑ -----------------------------------------7、配置证书和key,则表示https方式启动,访问网址要使用 https://your.domain:7001【可选】
|
||||
# ↑↑↑↑↑ ----------------------------------------- 配置证书和key,则表示https方式启动,访问网址要使用 https://your.domain:7001【可选】
|
||||
|
||||
# 设置环境变量即可自定义certd配置
|
||||
# 服务端配置项见: packages/ui/certd-server/src/config/config.default.ts
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
current_pwd=$(pwd)
|
||||
|
||||
echo "开始设置git配置"
|
||||
|
||||
read -p "请输入username:" username
|
||||
git config user.name $username
|
||||
|
||||
read -p "请输入email:" email
|
||||
git config user.email $email
|
||||
|
||||
git config credential.helper "store --file=$current_pwd/.git/credential.store"
|
||||
echo "已设置记住git账号密码"
|
||||
|
||||
git config core.autocrlf input
|
||||
echo "已设置auto crlf = input"
|
||||
|
||||
git config core.filemode false
|
||||
echo "已设置忽略文件模式变化"
|
||||
|
||||
echo "git配置完成"
|
|
@ -24,7 +24,7 @@
|
|||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.7.2",
|
||||
"lodash": "^4.17.21"
|
||||
"lodash-es": "^4.17.21"
|
||||
},
|
||||
"workspaces": [
|
||||
"packages/**"
|
||||
|
|
|
@ -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);
|
||||
if(this.pfxEnabled){
|
||||
// 调用openssl 转pfx
|
||||
await this.convertPfx(opts);
|
||||
}else{
|
||||
this.logger.info("pfx证书已禁用");
|
||||
}
|
||||
|
||||
// 转der
|
||||
await this.convertDer(opts);
|
||||
if(this.pfxEnabled){
|
||||
// 转der
|
||||
await this.convertDer(opts);
|
||||
}else{
|
||||
this.logger.info("der证书已禁用");
|
||||
}
|
||||
};
|
||||
|
||||
await certReader.readCertFile({ logger: this.logger, handle });
|
||||
|
@ -86,6 +119,11 @@ 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}`;
|
||||
|
@ -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",
|
||||
|
|
|
@ -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',
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue