Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fbd774266 | ||
|
|
bdec010d2e | ||
|
|
05a00b7b78 | ||
|
|
eaf23c3034 | ||
|
|
276a8b35e5 | ||
|
|
466d659f6e | ||
|
|
84e26381b5 | ||
|
|
469b5a5f69 | ||
|
|
ad77ebd2f9 | ||
|
|
b75543c3bc | ||
|
|
0677275742 | ||
|
|
0c3724e0ad | ||
|
|
803083d23c | ||
|
|
f4f8067a12 | ||
|
|
caa9f084d6 | ||
|
|
81407b65d1 | ||
|
|
8a24293fd7 | ||
|
|
8f1886a585 | ||
|
|
0a64e5fa67 | ||
|
|
7a70603971 | ||
|
|
0d5e00e744 | ||
|
|
91ba1433af | ||
|
|
12e56d14f2 | ||
|
|
7326119f52 | ||
|
|
136983cf14 | ||
|
|
105a1b80ae | ||
|
|
b8000ca533 | ||
|
|
c3e374e6e5 | ||
|
|
a9b6e87249 | ||
|
|
61de5422bf | ||
|
|
f96697f619 | ||
|
|
b4560d6370 | ||
|
|
a7bcde8d82 | ||
|
|
34bb4d54c2 | ||
|
|
e0116a1a03 | ||
|
|
12fec7939d |
4
.gitignore
vendored
@@ -14,3 +14,7 @@ node_modules/
|
|||||||
|
|
||||||
/packages/*/node_modules
|
/packages/*/node_modules
|
||||||
/packages/ui/certd-server/tmp/
|
/packages/ui/certd-server/tmp/
|
||||||
|
/packages/ui/certd-ui/dist/
|
||||||
|
/other
|
||||||
|
/dev-sidecar-test
|
||||||
|
/packages/core/certd/yarn.lock
|
||||||
|
|||||||
101
README.md
@@ -26,88 +26,31 @@ CertD 是一个帮助你全自动申请和部署SSL证书的工具。
|
|||||||
## 快速开始
|
## 快速开始
|
||||||
本案例演示,如何配置自动申请证书,并部署到阿里云CDN,然后快要到期前自动更新证书并重新部署
|
本案例演示,如何配置自动申请证书,并部署到阿里云CDN,然后快要到期前自动更新证书并重新部署
|
||||||
|
|
||||||
|
|
||||||
1. 环境准备
|
1. 环境准备
|
||||||
安装[nodejs](https://nodejs.org/zh-cn/)
|
安装[nodejs](https://nodejs.org/zh-cn/)
|
||||||
|
|
||||||
2. 创建任务项目
|
|
||||||
|
2. 生成node项目
|
||||||
|
|
||||||
|
通过ui生成: https://certd.docmirror.cn/
|
||||||
|
|
||||||
|
开始生成证书,先填写域名,支持将多个域名打到一个证书上
|
||||||
|

|
||||||
|
|
||||||
|
配置证书详细信息
|
||||||
|

|
||||||
|
|
||||||
|
配置证书部署流程
|
||||||
|

|
||||||
|
|
||||||
|
配置好之后,点击导出按钮,导出一个node项目包
|
||||||
|
|
||||||
|
4. 运行
|
||||||
|
将导出的压缩包解压,然后执行如下命令,即可开始申请证书并部署
|
||||||
```
|
```
|
||||||
mkdir certd-run # 项目名称可以任意命名
|
npm install
|
||||||
cd certd-run -y
|
npm run certd
|
||||||
npm install @certd/executor -s --production
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 创建index.js
|
|
||||||
|
|
||||||
参数配置分几个部分
|
|
||||||
args: 运行时参数
|
|
||||||
accessProviders: 授权提供者,提供dns验证与部署任务的授权
|
|
||||||
cert: 证书申请的配置
|
|
||||||
deploy: 证书部署流程
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { Executor } from '@certd/executor'
|
|
||||||
const options = {
|
|
||||||
args: { // 运行时参数
|
|
||||||
forceDeploy: true,
|
|
||||||
},
|
|
||||||
accessProviders: { //授权提供者
|
|
||||||
aliyun: { // 阿里云accessKey,用于dns验证和上传证书到阿里云,并部署到cdn
|
|
||||||
providerType: 'aliyun',
|
|
||||||
accessKeyId: 'Your accessKeyId',
|
|
||||||
accessKeySecret: 'Your accessKeySecret'
|
|
||||||
},
|
|
||||||
},
|
|
||||||
cert: { //免费证书申请配置
|
|
||||||
domains: [ //可以在一张证书上绑定多个域名(前提是他们的验证方式要一样,目前仅支持dns验证)
|
|
||||||
'*.yourdomain.com',
|
|
||||||
'*.test.yourdomain.com',
|
|
||||||
'yourdomain.com'
|
|
||||||
],
|
|
||||||
email: 'Your email',
|
|
||||||
dnsProvider: 'aliyun', //上方accessProviders里面配置的
|
|
||||||
csrInfo: { //证书csr信息
|
|
||||||
country: 'CN',
|
|
||||||
state: 'GuangDong',
|
|
||||||
locality: 'ShengZhen',
|
|
||||||
organization: 'Your company Org.',
|
|
||||||
organizationUnit: 'IT Department',
|
|
||||||
emailAddress: 'Your email'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
deploy: [ //部署流程配置,数组,可以配置多条流程
|
|
||||||
{
|
|
||||||
deployName: '流程1-部署到阿里云CDN',
|
|
||||||
tasks: [ //流程任务,一个流程下可以包含多个部署任务,并且将按顺序执行
|
|
||||||
{ //任务1
|
|
||||||
taskName: '上传到阿里云', //任务名称
|
|
||||||
type: 'uploadCertToAliyun', //任务插件名称
|
|
||||||
props: { //任务插件参数
|
|
||||||
accessProvider: 'aliyun'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ // 任务2
|
|
||||||
taskName: '部署证书到CDN',
|
|
||||||
type: 'deployCertToAliyunCDN', //任务插件名称
|
|
||||||
props:{
|
|
||||||
domainName: 'your cdn domain 全称', //cdn域名全称
|
|
||||||
certName: 'certd自动部署',//证书名称前缀
|
|
||||||
accessProvider: 'aliyun'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const executor = new Executor()
|
|
||||||
await executor.run(options)
|
|
||||||
```
|
|
||||||
|
|
||||||
4. 运行
|
|
||||||
```
|
|
||||||
node index.js
|
|
||||||
```
|
```
|
||||||
5. 执行效果
|
5. 执行效果
|
||||||
生成的证书默认会存储在 `${home}/.certd/${email}/certs/${domain}/current`目录下
|
生成的证书默认会存储在 `${home}/.certd/${email}/certs/${domain}/current`目录下
|
||||||
@@ -129,7 +72,7 @@ node index.js
|
|||||||
所以当你临时需要将证书部署到其他地方时,直接追加部署任务,然后再次运行即可
|
所以当你临时需要将证书部署到其他地方时,直接追加部署任务,然后再次运行即可
|
||||||
|
|
||||||
## CI/DI集成与自动续期重新部署
|
## CI/DI集成与自动续期重新部署
|
||||||
集成前,将以上代码提交到内网git仓库,或者私有git仓库(由于包含敏感信息,不要提交到公开git仓库)
|
集成前,将以上导出的node项目提交到内网git仓库,或者私有git仓库(由于包含敏感信息,不要提交到公开git仓库)
|
||||||
|
|
||||||
### jenkins任务
|
### jenkins任务
|
||||||
1. 创建任务
|
1. 创建任务
|
||||||
|
|||||||
BIN
doc/step1.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
doc/step2.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
doc/step3.png
Normal file
|
After Width: | Height: | Size: 92 KiB |
BIN
doc/tasks.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
@@ -2,5 +2,5 @@
|
|||||||
"packages": [
|
"packages": [
|
||||||
"packages/*/*"
|
"packages/*/*"
|
||||||
],
|
],
|
||||||
"version": "0.1.17"
|
"version": "0.2.0"
|
||||||
}
|
}
|
||||||
|
|||||||
2
packages/core/api/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/api",
|
"name": "@certd/api",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/api",
|
"name": "@certd/api",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
7
packages/core/certd/.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.vscode/
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
yarn.lock
|
||||||
|
package-lock.json
|
||||||
|
/.idea/
|
||||||
2
packages/core/certd/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/certd",
|
"name": "@certd/certd",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/certd",
|
"name": "@certd/certd",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"description": "a ssl cert keeper",
|
"description": "a ssl cert keeper",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -10,8 +10,8 @@
|
|||||||
"author": "Greper",
|
"author": "Greper",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/acme-client": "^0.1.6",
|
"@certd/acme-client": "^0.2.0",
|
||||||
"@certd/api": "^0.1.17",
|
"@certd/api": "^0.2.0",
|
||||||
"dayjs": "^1.9.7",
|
"dayjs": "^1.9.7",
|
||||||
"lodash-es": "^4.17.20",
|
"lodash-es": "^4.17.20",
|
||||||
"node-forge": "^0.10.0"
|
"node-forge": "^0.10.0"
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ export class CertStore {
|
|||||||
this.domains = domains
|
this.domains = domains
|
||||||
this.domain = this.getMainDomain(this.domains)
|
this.domain = this.getMainDomain(this.domains)
|
||||||
this.safetyDomain = this.getSafetyDomain(this.domain)
|
this.safetyDomain = this.getSafetyDomain(this.domain)
|
||||||
// this.domainDir = this.safetyDomain + '-' + md5(this.getDomainStr(this.domains))
|
this.domainDir = this.safetyDomain + '-' + md5(this.getDomainStr(this.domains))
|
||||||
this.domainDir = this.safetyDomain
|
// this.domainDir = this.safetyDomain
|
||||||
this.certsRootPath = this.store.buildKey(this.email, 'certs')
|
this.certsRootPath = this.store.buildKey(this.email, 'certs')
|
||||||
|
|
||||||
this.currentMarkPath = this.store.buildKey(this.certsRootPath, this.domainDir, 'current.json')
|
this.currentMarkPath = this.store.buildKey(this.certsRootPath, this.domainDir, 'current.json')
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ describe('Certd', function () {
|
|||||||
const certd = new Certd(options)
|
const certd = new Certd(options)
|
||||||
const currentRootPath = certd.certStore.currentMarkPath
|
const currentRootPath = certd.certStore.currentMarkPath
|
||||||
console.log('rootDir', currentRootPath)
|
console.log('rootDir', currentRootPath)
|
||||||
expect(currentRootPath).match(/xiaojunnuo@qq.com\\certs\\_.docmirror.club\w*\\current.json/)
|
expect(currentRootPath).match(/xiaojunnuo@qq.com\\certs\\_.docmirror.club-\w*\\current.json/)
|
||||||
})
|
})
|
||||||
it('#writeAndReadCert', async function () {
|
it('#writeAndReadCert', async function () {
|
||||||
const options = createOptions()
|
const options = createOptions()
|
||||||
|
|||||||
9652
packages/core/executor/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/executor",
|
"name": "@certd/executor",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -10,15 +10,15 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/api": "^0.1.17",
|
"@certd/api": "^0.2.0",
|
||||||
"@certd/certd": "^0.1.17",
|
"@certd/certd": "^0.2.0",
|
||||||
"dayjs": "^1.9.7",
|
"dayjs": "^1.9.7",
|
||||||
"lodash-es": "^4.17.20"
|
"lodash-es": "^4.17.20"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/plugin-aliyun": "^0.1.17",
|
"@certd/plugin-aliyun": "^0.2.0",
|
||||||
"@certd/plugin-host": "^0.1.17",
|
"@certd/plugin-host": "^0.2.0",
|
||||||
"@certd/plugin-tencent": "^0.1.17",
|
"@certd/plugin-tencent": "^0.2.0",
|
||||||
"@rollup/plugin-commonjs": "^17.0.0",
|
"@rollup/plugin-commonjs": "^17.0.0",
|
||||||
"@rollup/plugin-json": "^4.1.0",
|
"@rollup/plugin-json": "^4.1.0",
|
||||||
"@rollup/plugin-node-resolve": "^11.0.1",
|
"@rollup/plugin-node-resolve": "^11.0.1",
|
||||||
|
|||||||
@@ -58,14 +58,14 @@ export class Executor {
|
|||||||
logger.info('----------------------')
|
logger.info('----------------------')
|
||||||
if (!cert.isNew) {
|
if (!cert.isNew) {
|
||||||
// 如果没有更新
|
// 如果没有更新
|
||||||
if (!options.args.forceDeploy && !options.args.forceRedeploy) {
|
if (options.args.forceRedeploy) {
|
||||||
// 且不需要强制运行deploy
|
// 强制重新部署,清空保存的状态
|
||||||
|
await certd.certStore.setCurrentFile('context.json', '{}')
|
||||||
|
} else if (!options.args.forceDeploy) {
|
||||||
|
// 且不需要强制deploy
|
||||||
logger.info('证书无更新,无需重新部署')
|
logger.info('证书无更新,无需重新部署')
|
||||||
logger.info('任务完成')
|
logger.info('任务完成')
|
||||||
return { cert }
|
return { cert }
|
||||||
} else {
|
|
||||||
// 强制重新运行,清空保存的状态
|
|
||||||
await certd.certStore.setCurrentFile('context.json', '{}')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 读取上次执行进度
|
// 读取上次执行进度
|
||||||
@@ -88,15 +88,16 @@ export class Executor {
|
|||||||
logger.info('任务完成')
|
logger.info('任务完成')
|
||||||
trace.print()
|
trace.print()
|
||||||
const result = resultTrace.get({ })
|
const result = resultTrace.get({ })
|
||||||
const returnData = {
|
if (result) {
|
||||||
|
if (result.status === 'error' && options.args.doNotThrowError === false) {
|
||||||
|
throw new Error(result.remark)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
cert,
|
cert,
|
||||||
context,
|
context,
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
if (result.status === 'error' && options.args.doNotThrowError === false) {
|
|
||||||
throw new Error(result.remark)
|
|
||||||
}
|
|
||||||
return returnData
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async runCertd (certd) {
|
async runCertd (certd) {
|
||||||
|
|||||||
@@ -76,7 +76,9 @@ export class Trace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const result = this.get({ type: 'result' })
|
const result = this.get({ type: 'result' })
|
||||||
this.printTraceLine(result, 'result', '')
|
if (result) {
|
||||||
|
this.printTraceLine(result, 'result', '')
|
||||||
|
}
|
||||||
const mainContext = {}
|
const mainContext = {}
|
||||||
_.merge(mainContext, context)
|
_.merge(mainContext, context)
|
||||||
delete mainContext.__trace__
|
delete mainContext.__trace__
|
||||||
|
|||||||
2
packages/plugins/plugin-aliyun/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-aliyun",
|
"name": "@certd/plugin-aliyun",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-aliyun",
|
"name": "@certd/plugin-aliyun",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alicloud/pop-core": "^1.7.10",
|
"@alicloud/pop-core": "^1.7.10",
|
||||||
"@certd/api": "^0.1.17",
|
"@certd/api": "^0.2.0",
|
||||||
"dayjs": "^1.9.7",
|
"dayjs": "^1.9.7",
|
||||||
"lodash-es": "^4.17.20"
|
"lodash-es": "^4.17.20"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/certd": "^0.1.17",
|
"@certd/certd": "^0.2.0",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"eslint": "^7.15.0",
|
"eslint": "^7.15.0",
|
||||||
"eslint-config-standard": "^16.0.2",
|
"eslint-config-standard": "^16.0.2",
|
||||||
|
|||||||
2
packages/plugins/plugin-host/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-host",
|
"name": "@certd/plugin-host",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-host",
|
"name": "@certd/plugin-host",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/api": "^0.1.17",
|
"@certd/api": "^0.2.0",
|
||||||
"dayjs": "^1.9.7",
|
"dayjs": "^1.9.7",
|
||||||
"lodash-es": "^4.17.20",
|
"lodash-es": "^4.17.20",
|
||||||
"ssh2": "^0.8.9"
|
"ssh2": "^0.8.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/certd": "^0.1.17",
|
"@certd/certd": "^0.2.0",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"eslint": "^7.15.0",
|
"eslint": "^7.15.0",
|
||||||
"eslint-config-standard": "^16.0.2",
|
"eslint-config-standard": "^16.0.2",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export class SSHAccessProvider {
|
|||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
password: { desc: '登录密码' },
|
password: { desc: '登录密码' },
|
||||||
publicKey: {
|
privateKey: {
|
||||||
desc: '密钥,密码或此项必填一项'
|
desc: '密钥,密码或此项必填一项'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,4 +36,17 @@ describe('HostShellExecute', function () {
|
|||||||
expect(ret).ok
|
expect(ret).ok
|
||||||
console.log('-----' + JSON.stringify(ret))
|
console.log('-----' + JSON.stringify(ret))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('#execute-publicKey-login', async function () {
|
||||||
|
this.timeout(10000)
|
||||||
|
const options = createOptions()
|
||||||
|
const plugin = new HostShellExecute(options)
|
||||||
|
const shellOpts = {
|
||||||
|
props: { script: ['ls'], accessProvider: 'tencent-ssh-base01' },
|
||||||
|
context: {}
|
||||||
|
}
|
||||||
|
const ret = await plugin.doExecute(shellOpts)
|
||||||
|
expect(ret).ok
|
||||||
|
console.log('-----' + JSON.stringify(ret))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-tencent",
|
"name": "@certd/plugin-tencent",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-tencent",
|
"name": "@certd/plugin-tencent",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/api": "^0.1.17",
|
"@certd/api": "^0.2.0",
|
||||||
"dayjs": "^1.9.7",
|
"dayjs": "^1.9.7",
|
||||||
"kubernetes-client": "^9.0.0",
|
"kubernetes-client": "^9.0.0",
|
||||||
"lodash-es": "^4.17.20",
|
"lodash-es": "^4.17.20",
|
||||||
"tencentcloud-sdk-nodejs": "^4.0.44"
|
"tencentcloud-sdk-nodejs": "^4.0.44"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/certd": "^0.1.17",
|
"@certd/certd": "^0.2.0",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
"eslint": "^7.15.0",
|
"eslint": "^7.15.0",
|
||||||
"eslint-config-standard": "^16.0.2",
|
"eslint-config-standard": "^16.0.2",
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class DnspodDnsProvider extends AbstractDnsProvider {
|
|||||||
this.loginToken = accessProvider.id + ',' + accessProvider.token
|
this.loginToken = accessProvider.id + ',' + accessProvider.token
|
||||||
}
|
}
|
||||||
|
|
||||||
async doRequest (options) {
|
async doRequest (options, successCodes = []) {
|
||||||
const config = {
|
const config = {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
formData: {
|
formData: {
|
||||||
@@ -43,8 +43,11 @@ export class DnspodDnsProvider extends AbstractDnsProvider {
|
|||||||
_.merge(config, options)
|
_.merge(config, options)
|
||||||
|
|
||||||
const ret = await request(config)
|
const ret = await request(config)
|
||||||
if (!ret || !ret.status || ret.status.code !== '1') {
|
if (!ret || !ret.status) {
|
||||||
throw new Error('请求失败:' + ret.status.message + ',api=' + config.url)
|
const code = ret.status.code
|
||||||
|
if (code !== '1' || !successCodes.includes(code)) {
|
||||||
|
throw new Error('请求失败:' + ret.status.message + ',api=' + config.url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@@ -73,7 +76,7 @@ export class DnspodDnsProvider extends AbstractDnsProvider {
|
|||||||
value: value,
|
value: value,
|
||||||
mx: 1
|
mx: 1
|
||||||
}
|
}
|
||||||
})
|
}, ['104'])// 104错误码为记录已存在,无需再次添加
|
||||||
this.logger.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret.record))
|
this.logger.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret.record))
|
||||||
return ret.record
|
return ret.record
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
|
|||||||
label: 'ingress名称',
|
label: 'ingress名称',
|
||||||
desc: '支持多个(传入数组)'
|
desc: '支持多个(传入数组)'
|
||||||
},
|
},
|
||||||
|
ingressClass: {
|
||||||
|
type: String,
|
||||||
|
label: 'ingress类型',
|
||||||
|
desc: '可选 qcloud / nginx'
|
||||||
|
},
|
||||||
clusterIp: {
|
clusterIp: {
|
||||||
type: String,
|
type: String,
|
||||||
label: '集群内网ip',
|
label: '集群内网ip',
|
||||||
@@ -86,7 +91,13 @@ export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
|
|||||||
// 修改内网解析ip地址
|
// 修改内网解析ip地址
|
||||||
k8sClient.setLookup({ [clusterDomain]: { ip: props.clusterIp } })
|
k8sClient.setLookup({ [clusterDomain]: { ip: props.clusterIp } })
|
||||||
}
|
}
|
||||||
await this.patchCertSecret({ k8sClient, props, context })
|
const ingressType = props.ingressClass || 'qcloud'
|
||||||
|
if (ingressType === 'qcloud') {
|
||||||
|
await this.patchQcloudCertSecret({ k8sClient, props, context })
|
||||||
|
} else {
|
||||||
|
await this.patchNginxCertSecret({ cert, k8sClient, props, context })
|
||||||
|
}
|
||||||
|
|
||||||
await this.sleep(2000) // 停留2秒,等待secret部署完成
|
await this.sleep(2000) // 停留2秒,等待secret部署完成
|
||||||
await this.restartIngress({ k8sClient, props })
|
await this.restartIngress({ k8sClient, props })
|
||||||
return true
|
return true
|
||||||
@@ -121,7 +132,7 @@ export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
|
|||||||
return ret.Kubeconfig
|
return ret.Kubeconfig
|
||||||
}
|
}
|
||||||
|
|
||||||
async patchCertSecret ({ k8sClient, props, context }) {
|
async patchQcloudCertSecret ({ k8sClient, props, context }) {
|
||||||
const { tencentCertId } = context
|
const { tencentCertId } = context
|
||||||
if (tencentCertId == null) {
|
if (tencentCertId == null) {
|
||||||
throw new Error('请先将【上传证书到腾讯云】作为前置任务')
|
throw new Error('请先将【上传证书到腾讯云】作为前置任务')
|
||||||
@@ -151,6 +162,35 @@ export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async patchNginxCertSecret ({ cert, k8sClient, props, context }) {
|
||||||
|
const crt = cert.crt
|
||||||
|
const key = cert.key
|
||||||
|
const crtBase64 = Buffer.from(crt).toString('base64')
|
||||||
|
const keyBase64 = Buffer.from(key).toString('base64')
|
||||||
|
|
||||||
|
const { namespace, secretName } = props
|
||||||
|
|
||||||
|
const body = {
|
||||||
|
data: {
|
||||||
|
'tls.crt': crtBase64,
|
||||||
|
'tls.key': keyBase64
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
labels: {
|
||||||
|
certd: this.appendTimeSuffix('certd')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let secretNames = secretName
|
||||||
|
if (typeof secretName === 'string') {
|
||||||
|
secretNames = [secretName]
|
||||||
|
}
|
||||||
|
for (const secret of secretNames) {
|
||||||
|
await k8sClient.patchSecret({ namespace, secretName: secret, body })
|
||||||
|
this.logger.info(`CertSecret已更新:${secret}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async restartIngress ({ k8sClient, props }) {
|
async restartIngress ({ k8sClient, props }) {
|
||||||
const { namespace, ingressName } = props
|
const { namespace, ingressName } = props
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import pkg from 'chai'
|
||||||
|
import { DeployCertToTencentTKEIngress } from '../../src/plugins/deploy-to-tke-ingress/index.js'
|
||||||
|
import { Certd } from '@certd/certd'
|
||||||
|
import { createOptions } from '../../../../../test/options.js'
|
||||||
|
import { K8sClient } from '../../src/utils/util.k8s.client.js'
|
||||||
|
|
||||||
|
const { expect } = pkg
|
||||||
|
|
||||||
|
async function getOptions () {
|
||||||
|
const options = createOptions()
|
||||||
|
options.args.test = false
|
||||||
|
options.cert.email = 'xiaojunnuo@qq.com'
|
||||||
|
options.cert.domains = ['*.docmirror.cn']
|
||||||
|
const certd = new Certd(options)
|
||||||
|
const cert = await certd.readCurrentCert()
|
||||||
|
const context = {}
|
||||||
|
const deployOpts = {
|
||||||
|
accessProviders: options.accessProviders,
|
||||||
|
cert,
|
||||||
|
props: {
|
||||||
|
accessProvider: 'tencent-yonsz',
|
||||||
|
region: 'ap-guangzhou',
|
||||||
|
clusterId: 'cls-6lbj1vee'
|
||||||
|
},
|
||||||
|
context
|
||||||
|
}
|
||||||
|
return { options, deployOpts }
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('DeployCertToTencentTKEIngressNginx', function () {
|
||||||
|
it('#getTKESecrets', async function () {
|
||||||
|
this.timeout(50000)
|
||||||
|
const { options, deployOpts } = await getOptions()
|
||||||
|
const plugin = new DeployCertToTencentTKEIngress(options)
|
||||||
|
const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
|
||||||
|
const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props.clusterId)
|
||||||
|
|
||||||
|
const k8sClient = new K8sClient(kubeConfig)
|
||||||
|
k8sClient.setLookup({
|
||||||
|
'cls-6lbj1vee.ccs.tencent-cloud.com': { ip: '13.123.123.123' }
|
||||||
|
})
|
||||||
|
const secrets = await k8sClient.getSecret({ namespace: 'stress' })
|
||||||
|
|
||||||
|
console.log('secrets:', secrets)
|
||||||
|
})
|
||||||
|
it('#execute', async function () {
|
||||||
|
this.timeout(5000)
|
||||||
|
|
||||||
|
const { options, deployOpts } = await getOptions()
|
||||||
|
deployOpts.props.ingressName = 'stress-ingress-nginx'
|
||||||
|
deployOpts.props.ingressClass = 'nginx'
|
||||||
|
deployOpts.props.secretName = 'stress-all'
|
||||||
|
deployOpts.props.namespace = 'stress'
|
||||||
|
const plugin = new DeployCertToTencentTKEIngress(options)
|
||||||
|
|
||||||
|
const ret = await plugin.doExecute(deployOpts)
|
||||||
|
console.log('sucess', ret)
|
||||||
|
})
|
||||||
|
})
|
||||||
6
packages/ui/certd-server/Dockerfile
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
FROM registry.cn-shenzhen.aliyuncs.com/greper/node:15.8.0-alpine
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
EXPOSE 3000
|
||||||
|
ADD ./ /app/
|
||||||
|
RUN cd /app/ && ls
|
||||||
|
ENTRYPOINT node /app/bin/www.js
|
||||||
@@ -7,6 +7,8 @@ import Static from 'koa-static'
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import _ from 'lodash-es'
|
import _ from 'lodash-es'
|
||||||
import './install.js'
|
import './install.js'
|
||||||
|
import pathUtil from './utils/util.path.js'
|
||||||
|
import compress from 'koa-compress'
|
||||||
const app = new Koa()
|
const app = new Koa()
|
||||||
|
|
||||||
// error handler
|
// error handler
|
||||||
@@ -18,8 +20,14 @@ app.use(bodyparser({
|
|||||||
}))
|
}))
|
||||||
app.use(json())
|
app.use(json())
|
||||||
app.use(logger())
|
app.use(logger())
|
||||||
|
// gzip
|
||||||
|
// app.use(compress({ threshold: 5120 }))
|
||||||
|
|
||||||
app.use(Static(new URL('public', import.meta.url).pathname))
|
const staticPlugin = Static(pathUtil.join('public'), {
|
||||||
|
maxage: 30 * 24 * 60 * 3600,
|
||||||
|
gzip: true
|
||||||
|
})
|
||||||
|
app.use(staticPlugin)
|
||||||
|
|
||||||
// logger
|
// logger
|
||||||
app.use(async (ctx, next) => {
|
app.use(async (ctx, next) => {
|
||||||
@@ -29,8 +37,6 @@ app.use(async (ctx, next) => {
|
|||||||
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
|
console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('url', import.meta.url)
|
|
||||||
|
|
||||||
// routes
|
// routes
|
||||||
const files = fs.readdirSync(new URL('controllers/', import.meta.url))
|
const files = fs.readdirSync(new URL('controllers/', import.meta.url))
|
||||||
// 过滤出.js文件:
|
// 过滤出.js文件:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { accessProviderRegistry } from '@certd/api'
|
|||||||
import _ from 'lodash-es'
|
import _ from 'lodash-es'
|
||||||
import { Ret } from '../models/Ret.js'
|
import { Ret } from '../models/Ret.js'
|
||||||
const router = Router()
|
const router = Router()
|
||||||
router.prefix('/access-providers')
|
router.prefix('/api/access-providers')
|
||||||
|
|
||||||
router.get('/list', function (ctx, next) {
|
router.get('/list', function (ctx, next) {
|
||||||
const list = []
|
const list = []
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { dnsProviderRegistry } from '@certd/api'
|
|||||||
import _ from 'lodash-es'
|
import _ from 'lodash-es'
|
||||||
import { Ret } from '../models/Ret.js'
|
import { Ret } from '../models/Ret.js'
|
||||||
const router = Router()
|
const router = Router()
|
||||||
router.prefix('/dns-providers')
|
router.prefix('/api/dns-providers')
|
||||||
|
|
||||||
router.get('/list', function (ctx, next) {
|
router.get('/list', function (ctx, next) {
|
||||||
const list = []
|
const list = []
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import fs from 'fs'
|
|||||||
import exportsService from '../service/exports-service.js'
|
import exportsService from '../service/exports-service.js'
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
router.prefix('/exports')
|
router.prefix('/api/exports')
|
||||||
|
|
||||||
router.post('/toZip', async function (ctx, next) {
|
router.post('/toZip', async function (ctx, next) {
|
||||||
// const request = ctx.request
|
// const request = ctx.request
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Router from 'koa-router'
|
import Router from 'koa-router'
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
router.get('/', async (ctx, next) => {
|
router.get('/api/', async (ctx, next) => {
|
||||||
await ctx.render('index', {
|
await ctx.render('index', {
|
||||||
title: 'Hello CertD!'
|
title: 'Hello CertD!'
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { pluginRegistry } from '@certd/api'
|
|||||||
import _ from 'lodash-es'
|
import _ from 'lodash-es'
|
||||||
import { Ret } from '../models/Ret.js'
|
import { Ret } from '../models/Ret.js'
|
||||||
const router = Router()
|
const router = Router()
|
||||||
router.prefix('/plugins')
|
router.prefix('/api/plugins')
|
||||||
|
|
||||||
router.get('/list', function (ctx, next) {
|
router.get('/list', function (ctx, next) {
|
||||||
const list = []
|
const list = []
|
||||||
|
|||||||
901
packages/ui/certd-server/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/server",
|
"name": "@certd/server",
|
||||||
"version": "0.1.17",
|
"version": "0.2.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -10,16 +10,17 @@
|
|||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/api": "^0.1.17",
|
"@certd/api": "^0.2.0",
|
||||||
"@certd/executor": "^0.1.17",
|
"@certd/executor": "^0.2.0",
|
||||||
"@certd/plugin-aliyun": "^0.1.17",
|
"@certd/plugin-aliyun": "^0.2.0",
|
||||||
"@certd/plugin-host": "^0.1.17",
|
"@certd/plugin-host": "^0.2.0",
|
||||||
"@certd/plugin-tencent": "^0.1.17",
|
"@certd/plugin-tencent": "^0.2.0",
|
||||||
"compressing": "^1.5.1",
|
"compressing": "^1.5.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
"fs-extra": "^9.1.0",
|
"fs-extra": "^9.1.0",
|
||||||
"koa": "^2.7.0",
|
"koa": "^2.7.0",
|
||||||
"koa-bodyparser": "^4.2.1",
|
"koa-bodyparser": "^4.2.1",
|
||||||
|
"koa-compress": "^5.0.1",
|
||||||
"koa-convert": "^1.2.0",
|
"koa-convert": "^1.2.0",
|
||||||
"koa-json": "^2.0.2",
|
"koa-json": "^2.0.2",
|
||||||
"koa-logger": "^3.2.0",
|
"koa-logger": "^3.2.0",
|
||||||
@@ -31,7 +32,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"eslint": "^7.18.0",
|
"eslint": "^7.19.0",
|
||||||
"eslint-config-standard": "^16.0.2",
|
"eslint-config-standard": "^16.0.2",
|
||||||
"eslint-plugin-import": "^2.22.1",
|
"eslint-plugin-import": "^2.22.1",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
|||||||
BIN
packages/ui/certd-server/public/favicon.ico
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
packages/ui/certd-server/public/logo/logo-lang.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
packages/ui/certd-server/public/logo/logo-svg.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
17
packages/ui/certd-server/public/logo/logo.svg
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||||
|
fill="#2c3e50"
|
||||||
|
transform="translate(124, 60) scale(4,4)"
|
||||||
|
></path>
|
||||||
|
<path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23 9-15.62L9-15.62Q7.65-14.08 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17 11.81-4.93Q12.87-4.68 14.76-4.68L14.76-4.68L21.24-4.68L21.24 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35 4.32-3.01L4.32-3.01Q1.48-6.17 1.48-11.03L1.48-11.03Q1.48-16.88 4.86-19.75L4.86-19.75Q6.21-20.93 8.10-21.42Q9.99-21.91 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"
|
||||||
|
fill="#2c3e50"
|
||||||
|
transform="translate(28, 430) scale(4,4)"
|
||||||
|
|
||||||
|
></path>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -1,8 +0,0 @@
|
|||||||
body {
|
|
||||||
padding: 50px;
|
|
||||||
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #00B7FF;
|
|
||||||
}
|
|
||||||
@@ -27,11 +27,12 @@ export default {
|
|||||||
fs.writeJsonSync(optionsFilePath, options)
|
fs.writeJsonSync(optionsFilePath, options)
|
||||||
|
|
||||||
// 依赖版本
|
// 依赖版本
|
||||||
const exePkgJson = fs.readFileSync('node_modules/@certd/executor/package.json')
|
const exePkgJson = fs.readFileSync(pathUtil.join('node_modules/@certd/executor/package.json'))
|
||||||
const executorPkg = JSON.parse(exePkgJson)
|
const executorPkg = JSON.parse(exePkgJson)
|
||||||
const currentVersion = executorPkg.version
|
const currentVersion = executorPkg.version
|
||||||
|
|
||||||
const templatePkg = require('../templates/certd-run/package.json')
|
const templatePkgJson = fs.readFileSync(pathUtil.join('templates/certd-run/package.json'))
|
||||||
|
const templatePkg = JSON.parse(templatePkgJson)
|
||||||
templatePkg.dependencies['@certd/executor'] = '^' + currentVersion
|
templatePkg.dependencies['@certd/executor'] = '^' + currentVersion
|
||||||
templatePkg.dependencies['@certd/plugin-aliyun'] = '^' + currentVersion
|
templatePkg.dependencies['@certd/plugin-aliyun'] = '^' + currentVersion
|
||||||
templatePkg.dependencies['@certd/plugin-host'] = '^' + currentVersion
|
templatePkg.dependencies['@certd/plugin-host'] = '^' + currentVersion
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import os from 'os'
|
|||||||
export default {
|
export default {
|
||||||
join (...dirs) {
|
join (...dirs) {
|
||||||
const url = new URL('../' + dirs.join('/'), import.meta.url)
|
const url = new URL('../' + dirs.join('/'), import.meta.url)
|
||||||
console.log('url', url)
|
|
||||||
let path = url.pathname
|
let path = url.pathname
|
||||||
if (os.type() === 'Windows_NT') {
|
if (os.type() === 'Windows_NT') {
|
||||||
path = path.substring(1)
|
path = path.substring(1)
|
||||||
|
|||||||
1
packages/ui/certd-ui/.env
Normal file
@@ -0,0 +1 @@
|
|||||||
|
VUE_APP_API=/api
|
||||||
@@ -2,4 +2,8 @@ module.exports = {
|
|||||||
presets: [
|
presets: [
|
||||||
'@vue/cli-plugin-babel/preset'
|
'@vue/cli-plugin-babel/preset'
|
||||||
]
|
]
|
||||||
|
// plugins: [['import', {
|
||||||
|
// libraryName: 'ant-design-vue',
|
||||||
|
// style: true // or 'css'
|
||||||
|
// }]]
|
||||||
}
|
}
|
||||||
|
|||||||
1268
packages/ui/certd-ui/package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/certd-ui",
|
"name": "@certd/certd-ui",
|
||||||
"version": "0.1.16",
|
"version": "0.2.0",
|
||||||
"private": false,
|
"private": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vue-cli-service serve",
|
"dev": "vue-cli-service serve",
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/dns-providers": "^0.1.13",
|
"@ant-design/icons-vue": "^6.0.1",
|
||||||
"@certd/plugins": "^0.1.13",
|
|
||||||
"ant-design-vue": "^2.0.0",
|
"ant-design-vue": "^2.0.0",
|
||||||
|
"axios": "^0.21.1",
|
||||||
"core-js": "^3.8.1",
|
"core-js": "^3.8.1",
|
||||||
"lodash-es": "^4.17.20",
|
"lodash-es": "^4.17.20",
|
||||||
"vue": "^3.0.4",
|
"vue": "^3.0.4",
|
||||||
@@ -31,7 +31,9 @@
|
|||||||
"@vue/eslint-config-standard": "^6.0.0",
|
"@vue/eslint-config-standard": "^6.0.0",
|
||||||
"@vue/test-utils": "^2.0.0-0",
|
"@vue/test-utils": "^2.0.0-0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
|
"babel-plugin-import": "^1.13.3",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.2.0",
|
||||||
|
"compression-webpack-plugin": "^5.0.1",
|
||||||
"eslint": "^7.15.0",
|
"eslint": "^7.15.0",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.20.2",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 17 KiB |
86
packages/ui/certd-ui/src/antdv.js
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
import _ from 'lodash'
|
||||||
|
import {
|
||||||
|
AutoComplete,
|
||||||
|
Alert,
|
||||||
|
Avatar,
|
||||||
|
Badge,
|
||||||
|
Button,
|
||||||
|
Calendar,
|
||||||
|
Card,
|
||||||
|
Cascader,
|
||||||
|
Checkbox,
|
||||||
|
Col,
|
||||||
|
DatePicker,
|
||||||
|
Divider,
|
||||||
|
Dropdown,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
InputNumber,
|
||||||
|
Layout,
|
||||||
|
List,
|
||||||
|
LocaleProvider,
|
||||||
|
Modal,
|
||||||
|
Radio,
|
||||||
|
Row,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Tabs,
|
||||||
|
Tag,
|
||||||
|
TimePicker,
|
||||||
|
Tooltip,
|
||||||
|
Drawer,
|
||||||
|
// ColorPicker,
|
||||||
|
ConfigProvider,
|
||||||
|
Descriptions,
|
||||||
|
Space
|
||||||
|
} from 'ant-design-vue'
|
||||||
|
|
||||||
|
const list = {
|
||||||
|
AutoComplete,
|
||||||
|
Alert,
|
||||||
|
Avatar,
|
||||||
|
Badge,
|
||||||
|
Button,
|
||||||
|
Calendar,
|
||||||
|
Card,
|
||||||
|
Cascader,
|
||||||
|
Checkbox,
|
||||||
|
Col,
|
||||||
|
DatePicker,
|
||||||
|
Divider,
|
||||||
|
Dropdown,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
InputNumber,
|
||||||
|
Layout,
|
||||||
|
List,
|
||||||
|
LocaleProvider,
|
||||||
|
TimePicker,
|
||||||
|
Modal,
|
||||||
|
Radio,
|
||||||
|
Row,
|
||||||
|
Select,
|
||||||
|
Switch,
|
||||||
|
Tabs,
|
||||||
|
Tag,
|
||||||
|
Tooltip,
|
||||||
|
Drawer,
|
||||||
|
// ColorPicker,
|
||||||
|
ConfigProvider,
|
||||||
|
Descriptions,
|
||||||
|
Space
|
||||||
|
}
|
||||||
|
export default function (app) {
|
||||||
|
_.forEach(list, item => {
|
||||||
|
app.use(item)
|
||||||
|
//
|
||||||
|
// app.config.globalProperties.$message = message
|
||||||
|
// app.config.globalProperties.$notification = notification
|
||||||
|
app.config.globalProperties.$info = Modal.info
|
||||||
|
app.config.globalProperties.$success = Modal.success
|
||||||
|
app.config.globalProperties.$error = Modal.error
|
||||||
|
app.config.globalProperties.$warning = Modal.warning
|
||||||
|
app.config.globalProperties.$confirm = Modal.confirm
|
||||||
|
app.config.globalProperties.$destroyAll = Modal.destroyAll
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -55,10 +55,8 @@ export function errorLog (error) {
|
|||||||
// 打印到控制台
|
// 打印到控制台
|
||||||
console.log(error)
|
console.log(error)
|
||||||
// 显示提示
|
// 显示提示
|
||||||
notification({
|
notification.error({
|
||||||
message: error.message,
|
message: error.message
|
||||||
type: 'error',
|
|
||||||
duration: 5 * 1000
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
packages/ui/certd-ui/src/assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
packages/ui/certd-ui/src/assets/logo-svg.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB |
17
packages/ui/certd-ui/src/assets/logo.svg
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="500" height="500" viewBox="0 0 500.000000 500.000000"
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<path d="M28.34 56.68h28.34V36.12H28.34a7.79 7.79 0 1 1 0-15.58h19.84v9.05h8.5V12H28.34a16.29 16.29 0 0 0 0 32.58h19.84v3.56H28.34a19.84 19.84 0 0 1 0-39.68h28.34V0H28.34a28.34 28.34 0 0 0 0 56.68z"
|
||||||
|
fill="#2c3e50"
|
||||||
|
transform="translate(124, 60) scale(4,4)"
|
||||||
|
></path>
|
||||||
|
<path d="M13.00-21.91L21.24-21.91L21.24-17.23L14.04-17.23Q10.39-17.23 9-15.62L9-15.62Q7.65-14.08 7.65-10.93L7.65-10.93Q7.65-7.42 9.86-5.80L9.86-5.80Q10.75-5.17 11.81-4.93Q12.87-4.68 14.76-4.68L14.76-4.68L21.24-4.68L21.24 0L13.00 0Q9.67 0 7.74-0.67Q5.80-1.35 4.32-3.01L4.32-3.01Q1.48-6.17 1.48-11.03L1.48-11.03Q1.48-16.88 4.86-19.75L4.86-19.75Q6.21-20.93 8.10-21.42Q9.99-21.91 13.00-21.91L13.00-21.91ZM31.05-13.32L43.74-13.32L43.74-8.64L31.05-8.64Q31.23-6.48 32.44-5.58Q33.66-4.68 36.41-4.68L36.41-4.68L43.74-4.68L43.74 0L35.73 0Q33.12 0 31.48-0.47Q29.83-0.94 28.39-2.02L28.39-2.02Q24.39-5.13 24.39-11.25L24.39-11.25Q24.39-15.21 26.50-18.18L26.50-18.18Q27.94-20.20 29.97-21.06Q31.99-21.91 35.28-21.91L35.28-21.91L43.74-21.91L43.74-17.23L35.73-17.23Q33.25-17.23 32.27-16.40Q31.27-15.57 31.05-13.32L31.05-13.32ZM48.64 0L48.64-21.91L57.55-21.91Q60.30-21.91 61.81-21.53Q63.31-21.15 64.31-20.25L64.31-20.25Q65.30-19.35 65.70-18Q66.10-16.65 66.10-14.13L66.10-14.13L66.10-12.01L60.30-12.01L60.30-13.18Q60.30-15.52 59.49-16.38Q58.68-17.23 56.38-17.23L56.38-17.23L54.67-17.23L54.67 0L48.64 0ZM67.50-21.91L71.33-21.91L71.33-30.02L77.36-30.02L77.36-21.91L82.94-21.91L82.94-17.23L77.36-17.23L77.36-9.27Q77.36-6.48 77.85-5.76L77.85-5.76Q78.61-4.68 80.55-4.68L80.55-4.68L82.94-4.68L82.94 0L78.57 0Q74.66 0 72.99-1.89Q71.33-3.78 71.33-8.23L71.33-8.23L71.33-17.23L67.50-17.23L67.50-21.91ZM96.08-21.91L101.75-21.91L101.75-30.02L107.73-30.02L107.73 0L97.38 0Q94.23 0 92.61-0.49L92.61-0.49Q88.78-1.71 86.90-5.26L86.90-5.26Q85.59-7.65 85.59-11.12L85.59-11.12Q85.59-16.74 89.37-19.84L89.37-19.84Q91.84-21.91 96.08-21.91L96.08-21.91ZM97.38-4.68L101.75-4.68L101.75-17.23L97.38-17.23Q94.50-17.23 93.02-15.30L93.02-15.30Q91.71-13.68 91.71-11.12L91.71-11.12Q91.71-7.38 93.87-5.76L93.87-5.76Q95.36-4.68 97.38-4.68L97.38-4.68Z"
|
||||||
|
fill="#2c3e50"
|
||||||
|
transform="translate(28, 430) scale(4,4)"
|
||||||
|
|
||||||
|
></path>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -20,7 +20,7 @@ const icons = {
|
|||||||
DeleteOutlined
|
DeleteOutlined
|
||||||
}
|
}
|
||||||
export default function (app) {
|
export default function (app) {
|
||||||
_.forEach(icons, item => {
|
_.forEach(icons, (item, key) => {
|
||||||
app.component(item.name, item)
|
app.component(key, item)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import components from './components'
|
|||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
app.config.productionTip = false
|
app.config.productionTip = false
|
||||||
app.use(i18n)
|
app.use(i18n)
|
||||||
app.use(Antd)
|
|
||||||
icons(app)
|
icons(app)
|
||||||
|
app.use(Antd)
|
||||||
app.use(components)
|
app.use(components)
|
||||||
app.use(router).mount('#app')
|
app.use(router).mount('#app')
|
||||||
|
|||||||
@@ -160,10 +160,10 @@
|
|||||||
|
|
||||||
<d-container>
|
<d-container>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div><a-button @click="exportsToZip">导出可执行项目</a-button></div>
|
<div><a-button @click="exportsToZip">导出为可执行项目</a-button></div>
|
||||||
<br/>
|
|
||||||
<div> <a-button @click="exportsToJson">复制options.json</a-button></div>
|
|
||||||
<br/>
|
<br/>
|
||||||
|
<!-- <div> <a-button @click="exportsToJson">复制options.json</a-button></div>-->
|
||||||
|
<!-- <br/>-->
|
||||||
</template>
|
</template>
|
||||||
<pre class="json">{{options}}</pre>
|
<pre class="json">{{options}}</pre>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,47 @@
|
|||||||
|
const CompressionWebpackPlugin = require('compression-webpack-plugin')
|
||||||
|
|
||||||
|
// 设置不参与构建的库
|
||||||
|
const externals = {}
|
||||||
|
// cdnDependencies.forEach(pkg => { externals[pkg.name] = pkg.library })
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
lintOnSave: true,
|
||||||
|
pages: {
|
||||||
|
index: {
|
||||||
|
entry: 'src/main.js',
|
||||||
|
// template 中的 title 标签需要是 <title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
title: 'Cert-D'
|
||||||
|
}
|
||||||
|
},
|
||||||
devServer: {
|
devServer: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/': {
|
'/': {
|
||||||
target: 'http://localhost:3000/'
|
target: 'http://localhost:3000/'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
css: {
|
||||||
|
loaderOptions: {
|
||||||
|
less: {
|
||||||
|
javascriptEnabled: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
configureWebpack: config => {
|
||||||
|
const configNew = {}
|
||||||
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
configNew.externals = externals
|
||||||
|
configNew.plugins = [
|
||||||
|
// gzip
|
||||||
|
new CompressionWebpackPlugin({
|
||||||
|
filename: '[path].gz[query]',
|
||||||
|
test: new RegExp('\\.(' + ['js', 'css'].join('|') + ')$'),
|
||||||
|
threshold: 5120,
|
||||||
|
minRatio: 0.8,
|
||||||
|
deleteOriginalAssets: false
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
return configNew
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||