Compare commits

...

63 Commits

Author SHA1 Message Date
xiaojunnuo
caa9f084d6 v0.1.18 2021-03-15 11:54:09 +08:00
xiaojunnuo
81407b65d1 refactor: dir with md5 2021-02-26 15:27:34 +08:00
xiaojunnuo
8a24293fd7 refactor: dir with md5 2021-02-26 15:25:04 +08:00
xiaojunnuo
8f1886a585 refactor: dir with suffix 2021-02-26 15:23:53 +08:00
xiaojunnuo
0a64e5fa67 refactor: md5 dir 2021-02-26 15:22:21 +08:00
xiaojunnuo
7a70603971 refactor: doc 2021-02-09 21:23:58 +08:00
xiaojunnuo
0d5e00e744 refactor: doc 2021-02-09 21:22:07 +08:00
xiaojunnuo
91ba1433af refactor: doc 2021-02-09 21:20:41 +08:00
xiaojunnuo
12e56d14f2 refactor: icons 2021-02-09 21:13:19 +08:00
xiaojunnuo
7326119f52 refactor: export 2021-02-09 21:07:19 +08:00
xiaojunnuo
136983cf14 refactor: export 2021-02-09 19:01:15 +08:00
xiaojunnuo
105a1b80ae refactor: export 2021-02-09 18:40:39 +08:00
xiaojunnuo
b8000ca533 refactor: export 2021-02-09 18:40:29 +08:00
xiaojunnuo
c3e374e6e5 refactor: export 2021-02-09 18:05:01 +08:00
xiaojunnuo
a9b6e87249 refactor: 按需加载 2021-02-09 17:19:00 +08:00
xiaojunnuo
61de5422bf refactor: logo 2021-02-09 16:30:59 +08:00
xiaojunnuo
f96697f619 refactor: logo 2021-02-09 15:42:10 +08:00
xiaojunnuo
b4560d6370 refactor: docker 2021-02-09 11:03:11 +08:00
xiaojunnuo
a7bcde8d82 refactor: host 2021-02-09 10:57:08 +08:00
xiaojunnuo
34bb4d54c2 refactor: deploy image 2021-02-08 23:01:07 +08:00
xiaojunnuo
e0116a1a03 refactor: deploy image 2021-02-08 22:37:54 +08:00
xiaojunnuo
12fec7939d refactor: deploy 2021-02-08 21:16:56 +08:00
xiaojunnuo
ff8e02cceb v0.1.17 2021-02-08 18:19:45 +08:00
xiaojunnuo
8122bed97f refactor: host 2021-02-08 18:18:23 +08:00
xiaojunnuo
991c3dbb76 v0.1.16 2021-02-08 15:46:27 +08:00
xiaojunnuo
399c23623d refactor: host 2021-02-08 15:46:03 +08:00
xiaojunnuo
2232f21b48 refactor: transfer 2021-02-08 15:12:35 +08:00
xiaojunnuo
e41c084381 refactor: transfer 2021-02-08 15:00:04 +08:00
xiaojunnuo
520b27e0dc refactor: ui 2021-02-08 14:31:12 +08:00
xiaojunnuo
ace7e0247a v0.1.15 2021-02-08 14:18:14 +08:00
xiaojunnuo
9ae414b1c6 refactor: 重构 2021-02-08 14:00:28 +08:00
xiaojunnuo
cb8c8186f1 refactor: 重构 2021-02-08 13:40:28 +08:00
xiaojunnuo
82f86d9556 refactor: move 2021-02-08 00:21:36 +08:00
xiaojunnuo
cfb1034450 refactor: host 2021-02-07 23:17:44 +08:00
xiaojunnuo
2a07442a85 refactor: ui 2021-02-07 18:32:38 +08:00
xiaojunnuo
68c1eff81d refactor: fix 2021-02-07 13:53:30 +08:00
xiaojunnuo
baec15dfc6 refactor: fix 2021-02-07 13:47:09 +08:00
xiaojunnuo
6eb9817296 refactor: fix 2021-02-07 10:54:55 +08:00
xiaojunnuo
b9d5d33aaa refactor: delete task 2021-02-05 18:20:33 +08:00
xiaojunnuo
560519894c refactor: fix bug 2021-02-05 18:13:24 +08:00
xiaojunnuo
9f434b0968 v0.1.14 2021-02-05 17:19:35 +08:00
xiaojunnuo
07066dde87 refactor: exitCode 2021-02-05 17:19:20 +08:00
xiaojunnuo
074c8f7cd0 v0.1.13 2021-02-05 17:08:11 +08:00
xiaojunnuo
e9df2355f4 refactor: fix bug 2021-02-05 17:07:49 +08:00
xiaojunnuo
45547d6f94 refactor: 0.1.12 2021-02-05 14:45:53 +08:00
xiaojunnuo
4a421d5b14 v0.1.12 2021-02-05 14:32:14 +08:00
xiaojunnuo
7b9825eb40 refactor: 重构优化 2021-02-05 14:31:52 +08:00
xiaojunnuo
5cde165f0b refactor: 重构优化 2021-02-05 14:30:31 +08:00
xiaojunnuo
305824ff1a refactor: ui 2021-02-04 22:07:01 +08:00
xiaojunnuo
86ddb72227 refactor: ui 2021-02-04 21:24:07 +08:00
xiaojunnuo
cca33478e4 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	ui/certd-ui/src/api/util.input.handler.js
2021-02-04 20:32:34 +08:00
xiaojunnuo
a8f41d3c48 refactor: form input 2021-02-04 20:31:04 +08:00
xiaojunnuo
a25a15ca6e refactor: 重构优化 2021-02-04 18:44:16 +08:00
xiaojunnuo
a39dac4dbd refactor: rename ui 2021-02-04 11:17:54 +08:00
xiaojunnuo
eab0c3be60 refactor: form input 2021-01-31 02:09:54 +08:00
xiaojunnuo
b4ee3d0dfc refactor: input render 2021-01-30 00:06:50 +08:00
xiaojunnuo
2f03e18c59 refactor: ui 2021-01-28 01:09:17 +08:00
xiaojunnuo
232cd7215e refactor: ui 2021-01-28 01:07:56 +08:00
xiaojunnuo
86b1e9959b refactor: ui 2021-01-28 01:00:06 +08:00
xiaojunnuo
fd130f86fd refactor: define 2021-01-26 00:58:00 +08:00
xiaojunnuo
2669f509e1 refactor: ui 2021-01-24 00:36:53 +08:00
xiaojunnuo
d3619ad60f refactor: ui prepare 2021-01-21 23:59:06 +08:00
xiaojunnuo
c26417d769 refactor: release 2021-01-18 22:31:45 +08:00
170 changed files with 63924 additions and 1568 deletions

12
.gitignore vendored
View File

@@ -5,7 +5,13 @@ out
gen
node_modules/
/test/*.private.*
/other/node-acme-client/.idea/
/*.log
/other/certd-run
/other/node-acme-client
/packages/ui/*/.idea
/packages/ui/*/node_modules
/packages/*/node_modules
/packages/ui/certd-server/tmp/
/packages/ui/certd-ui/dist/

101
README.md
View File

@@ -26,88 +26,31 @@ CertD 是一个帮助你全自动申请和部署SSL证书的工具。
## 快速开始
本案例演示如何配置自动申请证书并部署到阿里云CDN然后快要到期前自动更新证书并重新部署
1. 环境准备
安装[nodejs](https://nodejs.org/zh-cn/)
2. 创建任务项目
2. 生成node项目
通过ui生成 https://certd.docmirror.cn/
开始生成证书,先填写域名,支持将多个域名打到一个证书上
![](./doc/step1.png)
配置证书详细信息
![](./doc/step2.png)
配置证书部署流程
![](./doc/step3.png)
配置好之后点击导出按钮导出一个node项目包
4. 运行
将导出的压缩包解压,然后执行如下命令,即可开始申请证书并部署
```
mkdir certd-run # 项目名称可以任意命名
cd certd-run -y
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
npm install
npm run certd
```
5. 执行效果
生成的证书默认会存储在 `${home}/.certd/${email}/certs/${domain}/current`目录下
@@ -129,7 +72,7 @@ node index.js
所以当你临时需要将证书部署到其他地方时,直接追加部署任务,然后再次运行即可
## CI/DI集成与自动续期重新部署
集成前,将以上代码提交到内网git仓库或者私有git仓库由于包含敏感信息不要提交到公开git仓库
集成前,将以上导出的node项目提交到内网git仓库或者私有git仓库由于包含敏感信息不要提交到公开git仓库
### jenkins任务
1. 创建任务

BIN
doc/step1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
doc/step2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
doc/step3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

BIN
doc/tasks.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -1,6 +1,6 @@
{
"packages": [
"packages/*"
"packages/*/*"
],
"version": "0.1.11"
"version": "0.1.18"
}

22168
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,8 @@
"lerna": "^3.18.4"
},
"scripts": {
"start": "lerna bootstrap --hoist",
"i-all": "lerna link && lerna exec npm install "
},
"license": "MIT",
"dependencies": {

View File

@@ -1,4 +0,0 @@
export { AbstractDnsProvider } from './dns-provider/index.js'
export { Store } from './store/store.js'
export { util } from './utils/index.js'
export { AbstractPlugin } from './plugin/index.js'

View File

@@ -0,0 +1,17 @@
{
"extends": "standard",
"env": {
"mocha": true
},
"parserOptions": {
"ecmaVersion": 2020
},
"overrides": [
{
"files": ["*.test.js", "*.spec.js"],
"rules": {
"no-unused-expressions": "off"
}
}
]
}

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/api",
"version": "0.1.11",
"version": "0.1.17",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,8 +1,8 @@
{
"name": "@certd/api",
"version": "0.1.11",
"version": "0.1.17",
"description": "",
"main": "./src/index.js",
"main": "src/index.js",
"type": "module",
"author": "Greper",
"license": "MIT",
@@ -21,5 +21,6 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"mocha": "^8.2.1"
}
},
"gitHead": "4a421d5b142d453203c68ce6d1036e168ea2455b"
}

View File

@@ -0,0 +1,2 @@
import { Registry } from '../registry/registry.js'
export const accessProviderRegistry = new Registry()

View File

@@ -1,8 +1,10 @@
import _ from 'lodash-es'
import logger from '../utils/util.log.js'
import commonUtil from '../utils/util.common.js'
export class AbstractDnsProvider {
constructor () {
constructor ({ accessProviders }) {
this.logger = logger
this.accessProviders = commonUtil.arrayToMap(accessProviders)
}
async createRecord ({ fullRecord, type, value }) {
@@ -31,4 +33,15 @@ export class AbstractDnsProvider {
}
return domain
}
getAccessProvider (accessProvider, accessProviders = this.accessProviders) {
let access = accessProvider
if (typeof accessProvider === 'string' && accessProviders) {
access = accessProviders[accessProvider]
}
if (access == null) {
throw new Error(`accessProvider ${accessProvider}不存在`)
}
return access
}
}

View File

@@ -0,0 +1,4 @@
import { Registry } from '../registry/registry.js'
export { AbstractDnsProvider } from './abstract-dns-provider.js'
export const dnsProviderRegistry = new Registry()

View File

@@ -0,0 +1,6 @@
export * from './dns-provider/index.js'
export * from './plugin/index.js'
export * from './access-provider/index.js'
export { Store } from './store/store.js'
export { util } from './utils/index.js'
// module.createRequireFromPath()

View File

@@ -2,10 +2,15 @@ import fs from 'fs'
import logger from '../utils/util.log.js'
import dayjs from 'dayjs'
import Sleep from '../utils/util.sleep.js'
import commonUtil from '../utils/util.common.js'
export class AbstractPlugin {
constructor ({ accessProviders }) {
constructor (options) {
if (options == null) {
throw new Error('插件安装失败:参数不允许为空')
}
const { accessProviders } = options
this.logger = logger
this.accessProviders = accessProviders
this.accessProviders = commonUtil.arrayToMap(accessProviders)
}
appendTimeSuffix (name) {
@@ -52,7 +57,7 @@ export class AbstractPlugin {
}
/**
* 回退如有必要
* 回退用于单元测试
* @param options
*/
async rollback (options) {
@@ -60,10 +65,14 @@ export class AbstractPlugin {
}
getAccessProvider (accessProvider, accessProviders = this.accessProviders) {
let access = accessProvider
if (typeof accessProvider === 'string' && accessProviders) {
accessProvider = accessProviders[accessProvider]
access = accessProviders[accessProvider]
}
return accessProvider
if (access == null) {
throw new Error(`accessProvider ${accessProvider}不存在`)
}
return access
}
async sleep (time) {

View File

@@ -0,0 +1,3 @@
import { Registry } from '../registry/registry.js'
export { AbstractPlugin } from './abstract-plugin.js'
export const pluginRegistry = new Registry()

View File

@@ -0,0 +1,46 @@
export class Registry {
constructor () {
this.collection = {}
}
install (target) {
if (target == null) {
return
}
if (this.collection == null) {
this.collection = {}
}
let defineName = target.define ? target.define().name : null
if (defineName == null) {
defineName = target.name
}
this.register(defineName, target)
}
register (key, value) {
if (!key || value == null) {
return
}
this.collection[key] = value
}
get (name) {
if (!name) {
throw new Error('插件名称不能为空')
}
if (!this.collection) {
this.collection = {}
}
const plugin = this.collection[name]
if (!plugin) {
throw new Error(`插件${name}还未注册`)
}
return plugin
}
getCollection () {
return this.collection
}
}

View File

@@ -2,6 +2,7 @@ import logger from './util.log.js'
import path from './util.path.js'
import { request } from './util.request.js'
import sleep from './util.sleep.js'
import common from './util.common.js'
export const util = {
logger, path, request, sleep
logger, path, request, sleep, common
}

View File

@@ -0,0 +1,33 @@
import _ from 'lodash-es'
export default {
arrayToMap (array) {
if (!array) {
return {}
}
if (!_.isArray(array)) {
return array
}
const map = {}
for (const item of array) {
if (item.key) {
map[item.key] = item
}
}
return map
},
mapToArray (map) {
if (!map) {
return []
}
if (_.isArray(map)) {
return map
}
const array = []
for (const key in map) {
const item = map[key]
item.key = key
array.push(item)
}
return array
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,17 @@
{
"name": "@certd/certd",
"version": "0.1.11",
"description": "",
"main": "./src/index.js",
"version": "0.1.18",
"description": "a ssl cert keeper",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "echo \\\"Error: no test specified\\\" && exit 1"
},
"type": "module",
"author": "Greper",
"license": "MIT",
"dependencies": {
"@certd/acme-client": "^0.1.6",
"@certd/api": "^0.1.11",
"@certd/providers": "^0.1.11",
"@certd/api": "^0.1.17",
"dayjs": "^1.9.7",
"lodash-es": "^4.17.20",
"node-forge": "^0.10.0"
@@ -25,5 +24,6 @@
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"mocha": "^8.2.1"
}
},
"gitHead": "4a421d5b142d453203c68ce6d1036e168ea2455b"
}

View File

@@ -1,27 +1,12 @@
import { util, Store } from '@certd/api'
import { util, Store, dnsProviderRegistry } from '@certd/api'
import { AcmeService } from './acme.js'
import { FileStore } from './store/file-store.js'
import { CertStore } from './store/cert-store.js'
import dayjs from 'dayjs'
import forge from 'node-forge'
import DefaultProviders from '@certd/providers'
import _ from 'lodash-es'
const logger = util.logger
const AccessProviderClasses = {}
function install (providerClass) {
AccessProviderClasses[providerClass.name()] = providerClass
}
logger.info('use')
_.forEach(DefaultProviders, item => {
logger.info('use:', item.name())
install(item)
})
export class Certd {
static use (providerClass) {
install(providerClass)
}
constructor (options) {
this.options = options
this.email = options.cert.email
@@ -87,16 +72,14 @@ export class Certd {
}
createDnsProvider (options) {
const accessProviders = options.accessProviders
const providerOptions = accessProviders[options.cert.dnsProvider]
return this.createProviderByType(providerOptions.providerType, providerOptions)
return this.createProviderByType(options.cert.dnsProvider, options.accessProviders)
}
async writeCert (cert) {
const newPath = await this.certStore.writeCert(cert)
return {
realPath: this.certStore.store.getActualKey(newPath),
currentPath: this.certStore.store.getActualKey(this.certStore.currentRootPath)
currentPath: this.certStore.store.getActualKey(this.certStore.currentMarkPath)
}
}
@@ -137,12 +120,12 @@ export class Certd {
}
}
createProviderByType (type, options) {
try {
const Provider = AccessProviderClasses[type]
return new Provider(options)
} catch (e) {
throw new Error('暂不支持此dnsProvider,请先use该provider' + type, e)
createProviderByType (props, accessProviders) {
const { type } = props
const Provider = dnsProviderRegistry.get(type)
if (Provider == null) {
throw new Error('暂不支持此dnsProvider,请先注册该provider' + type)
}
return new Provider({ accessProviders, props })
}
}

View File

@@ -1,5 +1,6 @@
import dayjs from 'dayjs'
import crypto from 'crypto'
// eslint-disable-next-line no-unused-vars
function md5 (content) {
return crypto.createHash('md5').update(content).digest('hex')
}
@@ -11,9 +12,10 @@ export class CertStore {
this.domain = this.getMainDomain(this.domains)
this.safetyDomain = this.getSafetyDomain(this.domain)
this.domainDir = this.safetyDomain + '-' + md5(this.getDomainStr(this.domains))
// this.domainDir = this.safetyDomain
this.certsRootPath = this.store.buildKey(this.email, 'certs')
this.currentRootPath = this.store.buildKey(this.certsRootPath, this.domainDir, 'current')
this.currentMarkPath = this.store.buildKey(this.certsRootPath, this.domainDir, 'current.json')
}
getMainDomain (domains) {
@@ -62,15 +64,19 @@ export class CertStore {
await this.store.set(priKey, this.formatCert(cert.key.toString()))
await this.store.set(csrKey, cert.csr.toString())
await this.store.link(newDir, this.currentRootPath)
await this.store.set(this.currentMarkPath, JSON.stringify({ latest: newDir }))
return newDir
}
async readCert (dir) {
if (dir == null) {
dir = this.currentRootPath
dir = await this.getCurrentDir()
}
if (dir == null) {
return
}
const crtKey = this.buildKey(dir, this.safetyDomain + '.crt')
const priKey = this.buildKey(dir, this.safetyDomain + '.key')
const csrKey = this.buildKey(dir, this.safetyDomain + '.csr')
@@ -99,13 +105,23 @@ export class CertStore {
return domain.replace(/\*/g, '_')
}
getCurrentFile (file) {
const key = this.buildKey(this.currentRootPath, file)
async getCurrentDir () {
const current = await this.store.get(this.currentMarkPath)
if (current == null) {
return null
}
return JSON.parse(current).latest
}
async getCurrentFile (file) {
const currentDir = await this.getCurrentDir()
const key = this.buildKey(currentDir, file)
return this.store.get(key)
}
setCurrentFile (file, value) {
const key = this.buildKey(this.currentRootPath, file)
async setCurrentFile (file, value) {
const currentDir = await this.getCurrentDir()
const key = this.buildKey(currentDir, file)
return this.store.set(key, value)
}
}

View File

@@ -1,6 +1,6 @@
import chai from 'chai'
import { Certd } from '../src/index.js'
import { createOptions } from '../../../test/options.js'
import { createOptions } from '../../../../test/options.js'
const { expect } = chai
const fakeCrt = `-----BEGIN CERTIFICATE-----
MIIFSTCCBDGgAwIBAgITAPoZZk/LhVIyXoic2NnJyxubezANBgkqhkiG9w0BAQsF
@@ -66,9 +66,9 @@ describe('Certd', function () {
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['*.docmirror.club']
const certd = new Certd(options)
const currentRootPath = certd.certStore.currentRootPath
const currentRootPath = certd.certStore.currentMarkPath
console.log('rootDir', currentRootPath)
expect(currentRootPath).match(/xiaojunnuo@qq.com\\certs\\_.docmirror.club-\w+\\current/)
expect(currentRootPath).match(/xiaojunnuo@qq.com\\certs\\_.docmirror.club-\w*\\current.json/)
})
it('#writeAndReadCert', async function () {
const options = createOptions()
@@ -83,6 +83,6 @@ describe('Certd', function () {
expect(cert.key).to.be.ok
expect(cert.detail).to.be.ok
expect(cert.expires).to.be.ok
console.log('expires:', cert.expires)
console.log('cert:', JSON.stringify(cert))
})
})

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/executor",
"version": "0.1.11",
"version": "0.1.18",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -35,11 +35,11 @@
}
},
"@babel/generator": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.11.tgz",
"integrity": "sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA==",
"version": "7.12.15",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.15.tgz",
"integrity": "sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ==",
"requires": {
"@babel/types": "^7.12.11",
"@babel/types": "^7.12.13",
"jsesc": "^2.5.1",
"source-map": "^0.5.0"
},
@@ -52,29 +52,29 @@
}
},
"@babel/helper-function-name": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz",
"integrity": "sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz",
"integrity": "sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA==",
"requires": {
"@babel/helper-get-function-arity": "^7.12.10",
"@babel/template": "^7.12.7",
"@babel/types": "^7.12.11"
"@babel/helper-get-function-arity": "^7.12.13",
"@babel/template": "^7.12.13",
"@babel/types": "^7.12.13"
}
},
"@babel/helper-get-function-arity": {
"version": "7.12.10",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz",
"integrity": "sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz",
"integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==",
"requires": {
"@babel/types": "^7.12.10"
"@babel/types": "^7.12.13"
}
},
"@babel/helper-split-export-declaration": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz",
"integrity": "sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz",
"integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==",
"requires": {
"@babel/types": "^7.12.11"
"@babel/types": "^7.12.13"
}
},
"@babel/helper-validator-identifier": {
@@ -105,36 +105,94 @@
}
},
"@babel/parser": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.11.tgz",
"integrity": "sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg=="
"version": "7.12.15",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.15.tgz",
"integrity": "sha512-AQBOU2Z9kWwSZMd6lNjCX0GUgFonL1wAM1db8L8PMk9UDaGsRCArBkU4Sc+UCM3AE4hjbXx+h58Lb3QT4oRmrA=="
},
"@babel/template": {
"version": "7.12.7",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz",
"integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz",
"integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==",
"requires": {
"@babel/code-frame": "^7.10.4",
"@babel/parser": "^7.12.7",
"@babel/types": "^7.12.7"
"@babel/code-frame": "^7.12.13",
"@babel/parser": "^7.12.13",
"@babel/types": "^7.12.13"
},
"dependencies": {
"@babel/code-frame": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"requires": {
"@babel/highlight": "^7.12.13"
}
},
"@babel/highlight": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
"integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
"requires": {
"@babel/helper-validator-identifier": "^7.12.11",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
}
}
},
"@babel/traverse": {
"version": "7.12.12",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz",
"integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.13.tgz",
"integrity": "sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA==",
"requires": {
"@babel/code-frame": "^7.12.11",
"@babel/generator": "^7.12.11",
"@babel/helper-function-name": "^7.12.11",
"@babel/helper-split-export-declaration": "^7.12.11",
"@babel/parser": "^7.12.11",
"@babel/types": "^7.12.12",
"@babel/code-frame": "^7.12.13",
"@babel/generator": "^7.12.13",
"@babel/helper-function-name": "^7.12.13",
"@babel/helper-split-export-declaration": "^7.12.13",
"@babel/parser": "^7.12.13",
"@babel/types": "^7.12.13",
"debug": "^4.1.0",
"globals": "^11.1.0",
"lodash": "^4.17.19"
},
"dependencies": {
"@babel/code-frame": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"requires": {
"@babel/highlight": "^7.12.13"
}
},
"@babel/highlight": {
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
"integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
"requires": {
"@babel/helper-validator-identifier": "^7.12.11",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"chalk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": {
"ansi-styles": "^3.2.1",
"escape-string-regexp": "^1.0.5",
"supports-color": "^5.3.0"
}
},
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
@@ -143,9 +201,9 @@
}
},
"@babel/types": {
"version": "7.12.12",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz",
"integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.13.tgz",
"integrity": "sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ==",
"requires": {
"@babel/helper-validator-identifier": "^7.12.11",
"lodash": "^4.17.19",
@@ -166,9 +224,9 @@
}
},
"@certd/api": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/@certd/api/-/api-0.1.7.tgz",
"integrity": "sha512-2spEdF9A6Tpe5KwkbWV1zE9Zwql04DrG5KlWRUsn8kLvwY6qfdDsdCsNoFf1+XDytn4OYH5nfrMGZBi8TpG84w==",
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/@certd/api/-/api-0.1.13.tgz",
"integrity": "sha512-klb4B5D+lu1SAtopCyU4sfe12Q9U4k5x+GTaSLLk1Dr3cX0Mpq7/fySQIW5yPH2ZJGQQAbKm/vciBnUGYWFy/A==",
"requires": {
"axios": "^0.21.1",
"dayjs": "^1.9.7",
@@ -178,26 +236,36 @@
}
},
"@certd/certd": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/@certd/certd/-/certd-0.1.7.tgz",
"integrity": "sha512-h+YWlcXzdQk3dbhK7u0guwyzotKRtsIA9zTaHdViWlMDlT9/oO9QflFoo8x8wA1Xx/Vd90APT6EEBnizgOXxsQ==",
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/@certd/certd/-/certd-0.1.13.tgz",
"integrity": "sha512-ng4iFJY23AhTM2VY/tX/3ywoIF96pUF6VP6iXRlhdap8o4xOEywfjeHefFMxdi85Aw3sklBm4U38QZjqA++tnA==",
"requires": {
"@certd/acme-client": "^0.1.6",
"@certd/api": "^0.1.7",
"@certd/providers": "^0.1.7",
"@certd/api": "^0.1.13",
"@certd/dns-providers": "^0.1.13",
"dayjs": "^1.9.7",
"lodash-es": "^4.17.20",
"node-forge": "^0.10.0"
}
},
"@certd/plugins": {
"version": "0.1.9",
"resolved": "https://registry.npmjs.org/@certd/plugins/-/plugins-0.1.9.tgz",
"integrity": "sha512-Gwalnoh8fHeoNoxEV9VSnEmAMtW0/Z7UrJR39eWKBtX/ZOVyPdiXbsLT6O8yueMIqG3Vx8jfRE1X42zYj6J/Og==",
"@certd/dns-providers": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/@certd/dns-providers/-/dns-providers-0.1.13.tgz",
"integrity": "sha512-a9eD61t6dnacTLJqEUWijhVf1OUmZmPyrm8asTxMAPt7zw60xNxFSJFGHGJYM0bMGPsqUP4WBsSZ5JU4SHy5bg==",
"requires": {
"@alicloud/pop-core": "^1.7.10",
"@certd/api": "^0.1.7",
"@certd/certd": "^0.1.7",
"@certd/api": "^0.1.13",
"lodash-es": "^4.17.20",
"tencentcloud-sdk-nodejs": "^4.0.44"
}
},
"@certd/plugins": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/@certd/plugins/-/plugins-0.1.13.tgz",
"integrity": "sha512-RFUxCPb70px0FAB54H3Iv1GP1+e2l/PgNfSRTRcfO8jmiCEW9lwWBQ1Yw20zZzxCTrcOXuUGDUHQjmXaQ9Vu/A==",
"requires": {
"@alicloud/pop-core": "^1.7.10",
"@certd/api": "^0.1.13",
"dayjs": "^1.9.7",
"kubernetes-client": "^9.0.0",
"lodash-es": "^4.17.20",
@@ -205,17 +273,6 @@
"tencentcloud-sdk-nodejs": "^4.0.44"
}
},
"@certd/providers": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/@certd/providers/-/providers-0.1.7.tgz",
"integrity": "sha512-ACiFNhRBVWB5Nyui3RTuAX0oTVkuWi0zopO1qMzbA/2iOrtFAoNs3I5DSLpZxS3d1erKcOq+Lx7Rm0rZxiL6wg==",
"requires": {
"@alicloud/pop-core": "^1.7.10",
"@certd/api": "^0.1.7",
"lodash-es": "^4.17.20",
"tencentcloud-sdk-nodejs": "^4.0.44"
}
},
"@eslint/eslintrc": {
"version": "0.2.2",
"resolved": "https://registry.npm.taobao.org/@eslint/eslintrc/download/@eslint/eslintrc-0.2.2.tgz?cache=0&sync_timestamp=1607145629875&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40eslint%2Feslintrc%2Fdownload%2F%40eslint%2Feslintrc-0.2.2.tgz",
@@ -273,9 +330,9 @@
},
"dependencies": {
"@types/node": {
"version": "10.17.50",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.50.tgz",
"integrity": "sha512-vwX+/ija9xKc/z9VqMCdbf4WYcMTGsI0I/L/6shIF3qXURxZOhPQlPRHtjTpiNhAwn0paMJzlOQqw6mAGEQnTA=="
"version": "10.17.51",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.51.tgz",
"integrity": "sha512-KANw+MkL626tq90l++hGelbl67irOJzGhUJk6a1Bt8QHOeh9tztJx+L0AqttraWKinmZn7Qi5lJZJzx45Gq0dg=="
},
"ws": {
"version": "6.2.1",
@@ -1616,9 +1673,9 @@
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA=="
},
"follow-redirects": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
"integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.2.tgz",
"integrity": "sha512-6mPTgLxYm3r6Bkkg0vNM0HTjfGrOEtsfbhagQvbxDEsEkpNhw582upBaoRZylzen6krEmxXJgt9Ju6HiI4O7BA=="
},
"forever-agent": {
"version": "0.6.1",
@@ -1902,31 +1959,23 @@
"integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w="
},
"internal-slot": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz",
"integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==",
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
"requires": {
"es-abstract": "^1.17.0-next.1",
"get-intrinsic": "^1.1.0",
"has": "^1.0.3",
"side-channel": "^1.0.2"
"side-channel": "^1.0.4"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"get-intrinsic": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
"has-symbols": "^1.0.1"
}
}
}
@@ -2642,9 +2691,9 @@
}
},
"oidc-token-hash": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.0.tgz",
"integrity": "sha512-8Yr4CZSv+Tn8ZkN3iN2i2w2G92mUKClp4z7EGUfdsERiYSbj7P4i/NHm72ft+aUdsiFx9UdIPSTwbyzQ6C4URg=="
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/oidc-token-hash/-/oidc-token-hash-5.0.1.tgz",
"integrity": "sha512-EvoOtz6FIEBzE+9q253HsLCVRiK/0doEJ2HCvvqMQb3dHZrP3WlJKYtJ55CRTw4jmYomzH4wkPuCj/I3ZvpKxQ=="
},
"once": {
"version": "1.4.0",
@@ -2930,30 +2979,21 @@
}
},
"regexp.prototype.flags": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
"integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz",
"integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==",
"requires": {
"define-properties": "^1.1.3",
"es-abstract": "^1.17.0-next.1"
"call-bind": "^1.0.2",
"define-properties": "^1.1.3"
},
"dependencies": {
"es-abstract": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz",
"integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==",
"call-bind": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"requires": {
"es-to-primitive": "^1.2.1",
"function-bind": "^1.1.1",
"has": "^1.0.3",
"has-symbols": "^1.0.1",
"is-callable": "^1.2.2",
"is-regex": "^1.1.1",
"object-inspect": "^1.8.0",
"object-keys": "^1.1.1",
"object.assign": "^4.1.1",
"string.prototype.trimend": "^1.0.1",
"string.prototype.trimstart": "^1.0.1"
"get-intrinsic": "^1.0.2"
}
}
}
@@ -3050,9 +3090,9 @@
}
},
"rfdc": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
"integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug=="
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.2.0.tgz",
"integrity": "sha512-ijLyszTMmUrXvjSooucVQwimGUk84eRcmCuLV8Xghe3UO85mjUtRAHRyoMM6XtyqbECaXuBWx18La3523sXINA=="
},
"rimraf": {
"version": "3.0.2",
@@ -3444,9 +3484,9 @@
}
},
"tencentcloud-sdk-nodejs": {
"version": "4.0.49",
"resolved": "https://registry.npmjs.org/tencentcloud-sdk-nodejs/-/tencentcloud-sdk-nodejs-4.0.49.tgz",
"integrity": "sha512-4mZIwIup5oTtmlXtyyqGIUdpurLFdU25ZLcgjElcKOep8HYnMKVXNCvV57WXEMJx+UBc+wYg21OBQd6neUSkxg==",
"version": "4.0.65",
"resolved": "https://registry.npmjs.org/tencentcloud-sdk-nodejs/-/tencentcloud-sdk-nodejs-4.0.65.tgz",
"integrity": "sha512-vhuFrGR/yGy9BSqOYNX4sENZYGyOfAiwM+ID3V9dMGvOOc7y/fXwvnAj+2bTRpKD8QgRLumss+ZyPy3H4FgJyQ==",
"requires": {
"babel-eslint": "^10.0.2",
"eslint-plugin-react": "^7.17.0",
@@ -3742,9 +3782,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"ws": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz",
"integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA=="
"version": "7.4.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz",
"integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA=="
},
"xml2js": {
"version": "0.4.23",

View File

@@ -1,22 +1,24 @@
{
"name": "@certd/executor",
"version": "0.1.11",
"version": "0.1.18",
"description": "",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"test": "echo \\\"Error: no test specified\\\" && exit 1",
"build": "webpack --config webpack.config.cjs ",
"rollup": "rollup --config rollup.config.js"
},
"type": "module",
"dependencies": {
"@certd/api": "^0.1.11",
"@certd/certd": "^0.1.11",
"@certd/plugins": "^0.1.11",
"@certd/api": "^0.1.17",
"@certd/certd": "^0.1.18",
"dayjs": "^1.9.7",
"lodash-es": "^4.17.20"
},
"devDependencies": {
"@certd/plugin-aliyun": "^0.1.18",
"@certd/plugin-host": "^0.1.18",
"@certd/plugin-tencent": "^0.1.18",
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^11.0.1",
@@ -32,5 +34,6 @@
},
"author": "Greper",
"license": "MIT",
"sideEffects": false
"sideEffects": false,
"gitHead": "4a421d5b142d453203c68ce6d1036e168ea2455b"
}

View File

@@ -1,6 +1,5 @@
import { Certd } from '@certd/certd'
import DefaultPlugins from '@certd/plugins'
import { util } from '@certd/api'
import { pluginRegistry, util } from '@certd/api'
import _ from 'lodash-es'
import dayjs from 'dayjs'
import { Trace } from './trace.js'
@@ -18,59 +17,38 @@ function createDefaultOptions () {
}
export class Executor {
constructor () {
this.usePlugins(DefaultPlugins)
this.trace = new Trace()
}
useProviders (providers) {
if (providers) {
_.forEach(item => {
Certd.use(item)
})
}
}
useProvider (provider) {
Certd.use(provider)
}
usePlugin (plugin) {
if (plugin == null) {
return
}
if (this.plugins == null) {
this.plugins = {}
}
this.plugins[plugin.name] = plugin
if (plugin.define) {
const define = plugin.define()
this.plugins[define.name] = plugin
}
}
usePlugins (plugins) {
if (plugins) {
_.forEach(plugins, item => {
this.usePlugin(item)
})
}
}
async run (options) {
logger.info('------------------- Cert-D ---------------------')
try {
this.transfer(options)
options = _.merge(createDefaultOptions(), options)
return await this.doRun(options)
} catch (e) {
logger.error('任务执行出错', e)
logger.error('任务执行出错', e)
throw e
}
}
transfer (options) {
const providers = options.accessProviders
if (_.isArray(providers)) {
const map = {}
for (const provider of providers) {
if (provider.key) {
map[provider.key] = provider
}
}
options.accessProviders = map
}
}
async doRun (options) {
// 申请证书
logger.info('任务开始')
const certd = new Certd(options, this.providers)
const certd = new Certd(options)
const cert = await this.runCertd(certd)
if (cert == null) {
throw new Error('申请证书失败')
@@ -85,6 +63,9 @@ export class Executor {
logger.info('证书无更新,无需重新部署')
logger.info('任务完成')
return { cert }
} else {
// 强制重新运行,清空保存的状态
await certd.certStore.setCurrentFile('context.json', '{}')
}
}
// 读取上次执行进度
@@ -140,6 +121,7 @@ export class Executor {
logger.info('此流程已被禁用,跳过')
logger.info('')
deployTrace.set({ value: { current: 'skip', status: 'disabled', remark: '流程禁用' } })
deployTrace.set({ tasks: null })
continue
}
try {
@@ -153,6 +135,7 @@ export class Executor {
}
deployTrace.set({ value: { status: 'success', remark: '执行成功' } })
trace.set({ type: 'result', value: { status: 'success', remark: '执行成功' } })
} catch (e) {
deployTrace.set({ value: { status: 'error', remark: '执行失败:' + e.message } })
trace.set({ type: 'result', value: { status: 'error', remark: deployName + '执行失败:' + e.message } })
@@ -165,7 +148,7 @@ export class Executor {
async runTask ({ options, task, cert, context, deploy, trace }) {
const taskType = task.type
const Plugin = this.plugins[taskType]
const Plugin = pluginRegistry.get(taskType)
const deployName = deploy.deployName
const taskName = task.taskName
if (Plugin == null) {

View File

@@ -1,8 +1,16 @@
import pkg from 'chai'
import { Executor } from '../src/index.js'
import { createOptions } from '../../../test/options.js'
import { createOptions } from '../../../../test/options.js'
import PluginAliyun from '@certd/plugin-aliyun'
import PluginTencent from '@certd/plugin-tencent'
import PluginHost from '@certd/plugin-host'
const { expect } = pkg
// 安装默认插件和授权提供者
PluginAliyun.install()
PluginTencent.install()
PluginHost.install()
describe('AutoDeploy', function () {
it('#run', async function () {
this.timeout(120000)

View File

@@ -0,0 +1,26 @@
{
"name": "@certd/plugin-aliyun",
"version": "0.1.18",
"description": "",
"main": "src/index.js",
"type": "module",
"dependencies": {
"@alicloud/pop-core": "^1.7.10",
"@certd/api": "^0.1.17",
"dayjs": "^1.9.7",
"lodash-es": "^4.17.20"
},
"devDependencies": {
"@certd/certd": "^0.1.18",
"chai": "^4.2.0",
"eslint": "^7.15.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"mocha": "^8.2.1"
},
"author": "Greper",
"license": "MIT",
"gitHead": "4a421d5b142d453203c68ce6d1036e168ea2455b"
}

View File

@@ -0,0 +1,30 @@
export class AliyunAccessProvider {
static define () {
return {
name: 'aliyun',
label: '阿里云',
desc: '',
input: {
accessKeyId: {
type: String,
component: {
placeholder: 'accessKeyId',
rules: [{ required: true, message: '必填项' }]
},
required: true
},
accessKeySecret: {
type: String,
component: {
placeholder: 'accessKeySecret',
rules: [{ required: true, message: '必填项' }]
}
}
},
output: {
}
}
}
}

View File

@@ -2,20 +2,41 @@ import { AbstractDnsProvider } from '@certd/api'
import Core from '@alicloud/pop-core'
import _ from 'lodash-es'
export class AliyunDnsProvider extends AbstractDnsProvider {
constructor (dnsProviderConfig) {
super()
static define () {
return {
name: 'aliyun',
label: '阿里云',
desc: '',
input: {
accessProvider: {
label: '授权',
type: [String, Object],
desc: '需要aliyun类型的授权',
component: {
name: 'access-provider-selector',
filter: 'aliyun'
},
required: true
}
},
output: {
}
}
}
constructor (args) {
super(args)
const { props } = args
const accessProvider = this.getAccessProvider(props.accessProvider)
this.client = new Core({
accessKeyId: dnsProviderConfig.accessKeyId,
accessKeySecret: dnsProviderConfig.accessKeySecret,
accessKeyId: accessProvider.accessKeyId,
accessKeySecret: accessProvider.accessKeySecret,
endpoint: 'https://alidns.aliyuncs.com',
apiVersion: '2015-01-09'
})
}
static name () {
return 'aliyun'
}
async getDomainList () {
const params = {
RegionId: 'cn-hangzhou'

View File

@@ -0,0 +1,24 @@
import _ from 'lodash-es'
import { AliyunDnsProvider } from './dns-providers/aliyun.js'
import { AliyunAccessProvider } from './access-providers/aliyun.js'
import { UploadCertToAliyun } from './plugins/upload-to-aliyun/index.js'
import { DeployCertToAliyunCDN } from './plugins/deploy-to-cdn/index.js'
import { pluginRegistry, accessProviderRegistry, dnsProviderRegistry } from '@certd/api'
export const Plugins = {
UploadCertToAliyun,
DeployCertToAliyunCDN
}
export default {
install () {
_.forEach(Plugins, item => {
pluginRegistry.install(item)
})
accessProviderRegistry.install(AliyunAccessProvider)
dnsProviderRegistry.install(AliyunDnsProvider)
}
}

View File

@@ -0,0 +1,107 @@
import { AbstractAliyunPlugin } from '../abstract-aliyun.js'
import Core from '@alicloud/pop-core'
import dayjs from 'dayjs'
const define = {
name: 'deployCertToAliyunCDN',
label: '部署到阿里云CDN',
input: {
domainName: {
label: 'cdn加速域名',
component: {
placeholder: 'cdn加速域名'
},
required: true
},
certName: {
label: '证书名称',
component: {
placeholder: '上传后将以此名称作为前缀'
}
},
from: {
default: 'upload',
label: '证书来源',
required: true,
component: {
required: true,
placeholder: '证书来源',
name: 'a-select',
options: [
{ value: 'upload', label: '直接上传' },
{ value: 'cas', label: '从证书库', title: '需要uploadCertToAliyun作为前置任务' }
]
},
desc: '如果选择‘从证书库’类型,则需要以《上传证书到阿里云》作为前置任务'
},
// serverCertificateStatus: {
// label: '启用https',
// options: [
// { value: 'on', label: '开启HTTPS并更新证书' },
// { value: 'auto', label: '若HTTPS开启则更新未开启不更新' }
// ],
// required:true
// },
accessProvider: {
label: 'Access提供者',
type: [String, Object],
desc: 'access授权',
component: {
name: 'access-provider-selector',
filter: 'aliyun'
},
required: true
}
},
output: {
}
}
export class DeployCertToAliyunCDN extends AbstractAliyunPlugin {
static define () {
return define
}
async execute ({ cert, props, context }) {
const accessProvider = this.getAccessProvider(props.accessProvider)
const client = this.getClient(accessProvider)
const params = this.buildParams(props, context, cert)
await this.doRequest(client, params)
}
getClient (aliyunProvider) {
return new Core({
accessKeyId: aliyunProvider.accessKeyId,
accessKeySecret: aliyunProvider.accessKeySecret,
endpoint: 'https://cdn.aliyuncs.com',
apiVersion: '2018-05-10'
})
}
buildParams (args, context, cert) {
const { certName, from, domainName } = args
const CertName = certName + '-' + dayjs().format('YYYYMMDDHHmmss')
const params = {
RegionId: 'cn-hangzhou',
DomainName: domainName,
ServerCertificateStatus: 'on',
CertName: CertName,
CertType: from,
ServerCertificate: cert.crt,
PrivateKey: cert.key
}
return params
}
async doRequest (client, params) {
const requestOption = {
method: 'POST'
}
const ret = await client.request('SetDomainServerCertificate', params, requestOption)
this.checkRet(ret)
this.logger.info('设置cdn证书成功:', ret.RequestId)
}
}

View File

@@ -1,38 +1,41 @@
import Core from '@alicloud/pop-core'
import { AbstractAliyunPlugin } from '../abstract-aliyun.js'
export class UploadCertToAliyun extends AbstractAliyunPlugin {
/**
* 插件定义
* 名称
* 入参
* 出参
*/
static define () {
return {
name: 'uploadCertToAliyun',
label: '上传证书到阿里云',
input: {
name: {
label: '证书名称'
},
regionId: {
label: '大区',
value: 'cn-hangzhou'
},
accessProvider: {
label: 'Access提供者',
type: [String, Object],
desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象',
options: 'accessProviders[type=aliyun]'
}
const define = {
name: 'uploadCertToAliyun',
label: '上传证书到阿里云',
input: {
name: {
label: '证书名称',
desc: '证书上传后将以此参数作为名称前缀'
},
regionId: {
label: '大区',
default: 'cn-hangzhou',
required: true
},
accessProvider: {
label: 'Access提供者',
type: [String, Object],
desc: 'access授权',
component: {
name: 'access-provider-selector',
filter: 'aliyun'
},
output: {
aliyunCertId: {
type: String,
desc: '上传成功后的阿里云CertId'
}
}
required: true
}
},
output: {
aliyunCertId: {
type: String,
desc: '上传成功后的阿里云CertId'
}
}
}
export class UploadCertToAliyun extends AbstractAliyunPlugin {
static define () {
return define
}
getClient (aliyunProvider) {

View File

@@ -1,6 +1,10 @@
import pkg from 'chai'
import { createOptions } from '../../../../test/options.js'
import { Certd } from '../../src/index.js'
import { createOptions } from '../../../../../test/options.js'
import { Certd } from '@certd/certd'
import PluginAliyun from '../../src/index.js'
// 安装默认插件和授权提供者
PluginAliyun.install()
const { expect } = pkg
describe('AliyunDnsProvider', function () {
it('#申请证书-aliyun', async function () {

View File

@@ -1,27 +1,33 @@
import pkg from 'chai'
import AliyunDnsProvider from '../../src/dns-provider/aliyun.js'
import { createOptions } from '../../../../test/options.js'
import { AliyunDnsProvider } from '../../src/dns-providers/aliyun.js'
import { createOptions } from '../../../../../test/options.js'
const { expect } = pkg
export function getPluginOptions () {
const options = createOptions()
return { accessProviders: options.accessProviders, props: options.cert.dnsProvider }
}
describe('AliyunDnsProvider', function () {
it('#getDomainList', async function () {
const options = createOptions()
const aliyunDnsProvider = new AliyunDnsProvider(options.accessProviders.aliyun)
const options = getPluginOptions()
const aliyunDnsProvider = new AliyunDnsProvider(options)
const domainList = await aliyunDnsProvider.getDomainList()
console.log('domainList', domainList)
expect(domainList.length).gt(0)
})
it('#getRecords', async function () {
const options = createOptions()
const aliyunDnsProvider = new AliyunDnsProvider(options.accessProviders.aliyun)
const options = getPluginOptions()
const aliyunDnsProvider = new AliyunDnsProvider(options)
const recordList = await aliyunDnsProvider.getRecords('docmirror.cn', '*')
console.log('recordList', recordList)
expect(recordList.length).gt(0)
})
it('#createAndRemoveRecord', async function () {
const options = createOptions()
const aliyunDnsProvider = new AliyunDnsProvider(options.accessProviders.aliyun)
const options = getPluginOptions()
const aliyunDnsProvider = new AliyunDnsProvider(options)
const record = await aliyunDnsProvider.createRecord({ fullRecord: '___certd___.__test__.docmirror.cn', type: 'TXT', value: 'aaaa' })
console.log('recordId', record)
expect(record != null).ok

View File

@@ -0,0 +1,42 @@
import _ from 'lodash-es'
import optionsPrivate from '../../../test/options.private.mjs'
const defaultOptions = {
version: '1.0.0',
args: {
directory: 'test',
dry: false
},
accessProviders: {
aliyun: {
providerType: 'aliyun',
accessKeyId: '',
accessKeySecret: ''
},
myLinux: {
providerType: 'SSH',
username: 'xxx',
password: 'xxx',
host: '1111.com',
port: 22,
publicKey: ''
}
},
cert: {
domains: ['*.docmirror.club', 'docmirror.club'],
email: 'xiaojunnuo@qq.com',
dnsProvider: { type: 'aliyun', accessProvider: 'aliyun' },
certProvider: 'letsencrypt',
csrInfo: {
country: 'CN',
state: 'GuangDong',
locality: 'ShengZhen',
organization: 'CertD Org.',
organizationUnit: 'IT Department',
emailAddress: 'xiaojunnuo@qq.com'
}
}
}
_.merge(defaultOptions, optionsPrivate)
export default defaultOptions

View File

@@ -1,20 +1,20 @@
import pkg from 'chai'
import { DeployCertToAliyunCDN } from '../../src/aliyun/deploy-to-cdn/index.js'
import { DeployCertToAliyunCDN } from '../../src/plugins/deploy-to-cdn/index.js'
import { Certd } from '@certd/certd'
import createOptions from '../../../../test/options.js'
import { createOptions } from '../../../../../test/options.js'
const { expect } = pkg
describe('DeployToAliyunCDN', function () {
it('#execute', async function () {
this.timeout(5000)
const options = createOptions()
const plugin = new DeployCertToAliyunCDN()
const plugin = new DeployCertToAliyunCDN(options)
options.cert.domains = ['*.docmirror.cn', 'docmirror.cn']
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const ret = await plugin.doExecute({
accessProviders: options.accessProviders,
cert,
props: { domainName: 'certd-cdn-upload.docmirror.cn', certName: 'certd部署测试', certType: 'cas', accessProvider: 'aliyun' }
props: { domainName: 'certd-cdn-upload.docmirror.cn', certName: 'certd部署测试', from: 'cas', accessProvider: 'aliyun' }
})
console.log('context:', context, ret)
})

View File

@@ -1,7 +1,7 @@
import pkg from 'chai'
import { UploadCertToAliyun } from '../../src/aliyun/upload-to-aliyun/index.js'
import { UploadCertToAliyun } from '../../src/plugins/upload-to-aliyun/index.js'
import { Certd } from '@certd/certd'
import { createOptions } from '../../../../test/options.js'
import { createOptions } from '../../../../../test/options.js'
const { expect } = pkg
describe('PluginUploadToAliyun', function () {
it('#execute', async function () {
@@ -9,12 +9,11 @@ describe('PluginUploadToAliyun', function () {
const options = createOptions()
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['_.docmirror.cn']
const plugin = new UploadCertToAliyun()
const plugin = new UploadCertToAliyun(options)
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const context = {}
const deployOpts = {
accessProviders: options.accessProviders,
cert,
props: { accessProvider: 'aliyun' },
context
@@ -22,7 +21,7 @@ describe('PluginUploadToAliyun', function () {
await plugin.doExecute(deployOpts)
console.log('context:', context)
// await plugin.sleep(1000)
// await plugin.sleep(1000)
// await plugin.rollback(deployOpts)
})
})

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
{
"name": "@certd/plugin-host",
"version": "0.1.18",
"description": "",
"main": "src/index.js",
"type": "module",
"dependencies": {
"@certd/api": "^0.1.17",
"dayjs": "^1.9.7",
"lodash-es": "^4.17.20",
"ssh2": "^0.8.9"
},
"devDependencies": {
"@certd/certd": "^0.1.18",
"chai": "^4.2.0",
"eslint": "^7.15.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"mocha": "^8.2.1"
},
"author": "Greper",
"license": "MIT",
"gitHead": "4a421d5b142d453203c68ce6d1036e168ea2455b"
}

View File

@@ -0,0 +1,26 @@
export class SSHAccessProvider {
static define () {
return {
name: 'ssh',
label: '主机',
desc: '',
input: {
host: { required: true },
port: {
label: '端口',
type: Number,
default: '22',
required: true
},
username: {
default: 'root',
required: true
},
password: { desc: '登录密码' },
publicKey: {
desc: '密钥,密码或此项必填一项'
}
}
}
}
}

View File

@@ -0,0 +1,22 @@
import _ from 'lodash-es'
import { SSHAccessProvider } from './access-providers/ssh.js'
import { UploadCertToHost } from './plugins/upload-to-host/index.js'
import { HostShellExecute } from './plugins/host-shell-execute/index.js'
import { pluginRegistry, accessProviderRegistry } from '@certd/api'
export const DefaultPlugins = {
UploadCertToHost,
HostShellExecute
}
export default {
install () {
_.forEach(DefaultPlugins, item => {
pluginRegistry.install(item)
})
accessProviderRegistry.install(SSHAccessProvider)
}
}

View File

@@ -12,14 +12,21 @@ export class HostShellExecute extends AbstractHostPlugin {
name: 'hostShellExecute',
label: '执行远程主机脚本命令',
input: {
script: {
label: 'shell脚本命令'
},
accessProvider: {
label: '主机登录配置',
type: [String, Object],
desc: 'AccessProviders的key 或 一个包含用户名密码的对象',
options: 'accessProviders[type=ssh]'
desc: '登录',
component: {
name: 'access-provider-selector',
filter: 'ssh'
},
required: true
},
script: {
label: 'shell脚本命令',
component: {
name: 'a-textarea'
}
}
},
output: {
@@ -32,7 +39,7 @@ export class HostShellExecute extends AbstractHostPlugin {
const { script, accessProvider } = props
const connectConf = this.getAccessProvider(accessProvider)
const sshClient = new SshClient()
const ret = await sshClient.shell({
const ret = await sshClient.exec({
connectConf,
script
})

View File

@@ -1,6 +1,8 @@
import ssh2 from 'ssh2'
import logger from '../utils/util.log.js'
import path from 'path'
import { util } from '@certd/api'
import _ from 'lodash-es'
const logger = util.logger
export class SshClient {
/**
*
@@ -13,7 +15,7 @@ export class SshClient {
}
* @param transports
*/
uploadFiles ({ connectConf, transports }) {
uploadFiles ({ connectConf, transports, sudo = false }) {
const conn = new ssh2.Client()
return new Promise((resolve, reject) => {
@@ -27,7 +29,8 @@ export class SshClient {
try {
for (const transport of transports) {
logger.info('上传文件:', JSON.stringify(transport))
await this.exec({ conn, cmd: 'mkdir ' + path.dirname(transport.remotePath) })
sudo = sudo ? 'sudo' : ''
await this.exec({ connectConf, script: `${sudo} mkdir -p ${path.dirname(transport.remotePath)} ` })
await this.fastPut({ sftp, ...transport })
}
resolve()
@@ -41,6 +44,43 @@ export class SshClient {
})
}
exec ({ connectConf, script }) {
if (_.isArray(script)) {
script = script.join('\n')
}
console.log('执行命令:', script)
return new Promise((resolve, reject) => {
this.connect({
connectConf,
onReady: (conn) => {
conn.exec(script, (err, stream) => {
if (err) {
reject(err)
return
}
let data = null
stream.on('close', (code, signal) => {
console.log(`[${connectConf.host}][close]:code:${code}`)
data = data ? data.toString() : null
if (code === 0) {
resolve(data)
} else {
reject(new Error(data))
}
conn.end()
}).on('data', (ret) => {
console.log(`[${connectConf.host}][info]: ` + ret)
data = ret
}).stderr.on('data', (err) => {
console.log(`[${connectConf.host}][error]: ` + err)
data = err
})
})
}
})
})
}
shell ({ connectConf, script }) {
return new Promise((resolve, reject) => {
this.connect({
@@ -87,24 +127,4 @@ export class SshClient {
})
})
}
exec ({ conn, cmd }) {
return new Promise((resolve, reject) => {
conn.exec(cmd, (err, stream) => {
if (err) {
logger.error('执行命令出错', err)
reject(err)
// return conn.end()
}
stream.on('close', (code, signal) => {
// logger.info('Stream :: close :: code: ' + code + ', signal: ' + signal)
// conn.end()
resolve()
}).on('data', (data) => {
logger.info('data', data.toString())
})
})
})
}
}

View File

@@ -13,16 +13,23 @@ export class UploadCertToHost extends AbstractHostPlugin {
label: '上传证书到主机',
input: {
crtPath: {
label: '证书路径'
label: '证书保存路径'
},
keyPath: {
label: '私钥路径'
label: '私钥保存路径'
},
accessProvider: {
label: '主机登录配置',
type: [String, Object],
desc: 'AccessProviders的key 或 一个包含用户名密码的对象',
options: 'accessProviders[type=ssh]'
desc: 'access授权',
component: {
name: 'access-provider-selector',
filter: 'ssh'
},
required: true
},
sudo: {
label: '是否sudo'
}
},
output: {

View File

@@ -0,0 +1,39 @@
import pkg from 'chai'
import { HostShellExecute } from '../../src/plugins/host-shell-execute/index.js'
import { Certd } from '@certd/certd'
import { createOptions } from '../../../../../test/options.js'
const { expect } = pkg
describe('HostShellExecute', function () {
it('#execute', async function () {
this.timeout(10000)
const options = createOptions()
options.args = { test: false }
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['*.docmirror.cn']
const plugin = new HostShellExecute(options)
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const context = {}
const uploadOpts = {
cert,
props: { script: ['ls ', 'ls '], accessProvider: 'aliyun-ssh' },
context
}
const ret = await plugin.doExecute(uploadOpts)
expect(ret).ok
console.log('-----' + JSON.stringify(ret))
})
it('#execute-hk-restart-docker', async function () {
this.timeout(10000)
const options = createOptions()
const plugin = new HostShellExecute(options)
const uploadOpts = {
props: { script: ['cd /home/ubuntu/deloy/nginx-proxy\nsudo docker-compose build\nsudo docker-compose up -d\n'], accessProvider: 'aliyun-ssh-hk' },
context: {}
}
const ret = await plugin.doExecute(uploadOpts)
expect(ret).ok
console.log('-----' + JSON.stringify(ret))
})
})

View File

@@ -0,0 +1,48 @@
import pkg from 'chai'
import { UploadCertToHost } from '../../src/plugins/upload-to-host/index.js'
import { Certd } from '@certd/certd'
import { createOptions } from '../../../../../test/options.js'
const { expect } = pkg
describe('PluginUploadToHost', function () {
it('#execute', async function () {
this.timeout(10000)
const options = createOptions()
options.args = { test: false }
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['*.docmirror.cn']
const plugin = new UploadCertToHost(options)
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const context = {}
const uploadOpts = {
cert,
props: { crtPath: '/root/certd/test/test.crt', keyPath: '/root/certd/test/test.key', accessProvider: 'aliyun-ssh' },
context
}
await plugin.doExecute(uploadOpts)
console.log('context:', context)
await plugin.doRollback(uploadOpts)
})
it('#execute-to-ubantu', async function () {
this.timeout(10000)
const options = createOptions()
options.args = { test: false }
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['*.docmirror.cn']
const plugin = new UploadCertToHost(options)
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const context = {}
const uploadOpts = {
cert,
props: { crtPath: '/home/ubuntu/deloy/nginx-proxy/ssl/test.crt', keyPath: '/home/ubuntu/deloy/nginx-proxy/ssl/test.key', accessProvider: 'aliyun-ssh-hk' },
context
}
await plugin.doExecute(uploadOpts)
console.log('context:', context)
await plugin.doRollback(uploadOpts)
})
})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@certd/plugins",
"version": "0.1.11",
"name": "@certd/plugin-tencent",
"version": "0.1.18",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -8,6 +8,7 @@
"version": "1.7.10",
"resolved": "https://registry.npm.taobao.org/@alicloud/pop-core/download/@alicloud/pop-core-1.7.10.tgz",
"integrity": "sha1-0OIhA227DM3kU90Jsc+r2DQbemk=",
"dev": true,
"requires": {
"debug": "^3.1.0",
"httpx": "^2.1.2",
@@ -131,10 +132,41 @@
"to-fast-properties": "^2.0.0"
}
},
"@certd/acme-client": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/@certd/acme-client/-/acme-client-0.1.6.tgz",
"integrity": "sha512-XffzB/QHRj61gUHXor1B8R2TVt7HnklJpjAbwQi8vHjBGloU8I3occJxIunoh1AShhc4wsxnc+h/D5yRIUp17A==",
"dev": true,
"requires": {
"axios": "0.21.1",
"backo2": "^1.0.0",
"bluebird": "^3.5.0",
"debug": "^4.1.1",
"log4js": "^6.3.0",
"node-forge": "^0.10.0"
},
"dependencies": {
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": {
"ms": "2.1.2"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}
}
},
"@certd/api": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/@certd/api/-/api-0.1.7.tgz",
"integrity": "sha512-2spEdF9A6Tpe5KwkbWV1zE9Zwql04DrG5KlWRUsn8kLvwY6qfdDsdCsNoFf1+XDytn4OYH5nfrMGZBi8TpG84w==",
"version": "0.1.13",
"resolved": "https://registry.npm.taobao.org/@certd/api/download/@certd/api-0.1.13.tgz",
"integrity": "sha1-ProCS1OfZAWzr3bIKHHfZA5hrOw=",
"requires": {
"axios": "^0.21.1",
"dayjs": "^1.9.7",
@@ -143,6 +175,32 @@
"qs": "^6.9.4"
}
},
"@certd/certd": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/@certd/certd/-/certd-0.1.13.tgz",
"integrity": "sha512-ng4iFJY23AhTM2VY/tX/3ywoIF96pUF6VP6iXRlhdap8o4xOEywfjeHefFMxdi85Aw3sklBm4U38QZjqA++tnA==",
"dev": true,
"requires": {
"@certd/acme-client": "^0.1.6",
"@certd/api": "^0.1.13",
"@certd/dns-providers": "^0.1.13",
"dayjs": "^1.9.7",
"lodash-es": "^4.17.20",
"node-forge": "^0.10.0"
}
},
"@certd/dns-providers": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/@certd/dns-providers/-/dns-providers-0.1.13.tgz",
"integrity": "sha512-a9eD61t6dnacTLJqEUWijhVf1OUmZmPyrm8asTxMAPt7zw60xNxFSJFGHGJYM0bMGPsqUP4WBsSZ5JU4SHy5bg==",
"dev": true,
"requires": {
"@alicloud/pop-core": "^1.7.10",
"@certd/api": "^0.1.13",
"lodash-es": "^4.17.20",
"tencentcloud-sdk-nodejs": "^4.0.44"
}
},
"@eslint/eslintrc": {
"version": "0.2.2",
"resolved": "https://registry.npm.taobao.org/@eslint/eslintrc/download/@eslint/eslintrc-0.2.2.tgz?cache=0&sync_timestamp=1607145629875&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40eslint%2Feslintrc%2Fdownload%2F%40eslint%2Feslintrc-0.2.2.tgz",
@@ -490,8 +548,8 @@
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"resolved": "https://registry.npm.taobao.org/axios/download/axios-0.21.1.tgz?cache=0&sync_timestamp=1608609215811&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Faxios%2Fdownload%2Faxios-0.21.1.tgz",
"integrity": "sha1-IlY0gZYvTWvemnbVFu8OXTwJsrg=",
"requires": {
"follow-redirects": "^1.10.0"
}
@@ -509,6 +567,12 @@
"resolve": "^1.12.0"
}
},
"backo2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
"dev": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz",
@@ -530,7 +594,8 @@
"bignumber.js": {
"version": "9.0.1",
"resolved": "https://registry.npm.taobao.org/bignumber.js/download/bignumber.js-9.0.1.tgz",
"integrity": "sha1-jXuhJMiCv9jkMmDGdHVRjQaJ5OU="
"integrity": "sha1-jXuhJMiCv9jkMmDGdHVRjQaJ5OU=",
"dev": true
},
"binary-extensions": {
"version": "2.1.0",
@@ -538,6 +603,12 @@
"integrity": "sha1-MPpAyef+B9vIlWeM0ocCTeokHdk=",
"dev": true
},
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz?cache=0&sync_timestamp=1601898189928&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fbrace-expansion%2Fdownload%2Fbrace-expansion-1.1.11.tgz",
@@ -784,8 +855,8 @@
},
"date-format": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz",
"integrity": "sha512-eyTcpKOcamdhWJXj56DpQMo1ylSQpcGtGKXcU0Tb97+K56/CF5amAqqqNj0+KvA0iw2ynxtHWFsPDSClCxe48w=="
"resolved": "https://registry.npm.taobao.org/date-format/download/date-format-3.0.0.tgz",
"integrity": "sha1-64eANlx9KxURB4+0keZHl4DzrZU="
},
"dayjs": {
"version": "1.10.2",
@@ -1433,13 +1504,13 @@
},
"flatted": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
"integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA=="
"resolved": "https://registry.npm.taobao.org/flatted/download/flatted-2.0.2.tgz?cache=0&sync_timestamp=1611061309017&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fflatted%2Fdownload%2Fflatted-2.0.2.tgz",
"integrity": "sha1-RXWyHivO50NKqb5mL0t7X5wrUTg="
},
"follow-redirects": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
"integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
"version": "1.13.2",
"resolved": "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.13.2.tgz?cache=0&sync_timestamp=1611606737937&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffollow-redirects%2Fdownload%2Ffollow-redirects-1.13.2.tgz",
"integrity": "sha1-3XPI7/wScoulz0JZ12DqX7g+MUc="
},
"forever-agent": {
"version": "0.6.1",
@@ -1458,8 +1529,8 @@
},
"fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"resolved": "https://registry.npm.taobao.org/fs-extra/download/fs-extra-8.1.0.tgz?cache=0&sync_timestamp=1611075469998&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffs-extra%2Fdownload%2Ffs-extra-8.1.0.tgz",
"integrity": "sha1-SdQ8RaiM2Wd2aMt74bRu/bjS4cA=",
"requires": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
@@ -1662,6 +1733,7 @@
"version": "2.2.7",
"resolved": "https://registry.npm.taobao.org/httpx/download/httpx-2.2.7.tgz?cache=0&sync_timestamp=1604908999113&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttpx%2Fdownload%2Fhttpx-2.2.7.tgz",
"integrity": "sha1-HjQZgUbjLKMwWmbBEglVnhy+ugk=",
"dev": true,
"requires": {
"@types/node": "^14",
"debug": "^4.1.1"
@@ -1671,6 +1743,7 @@
"version": "4.3.1",
"resolved": "https://registry.npm.taobao.org/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1607566533140&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz",
"integrity": "sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4=",
"dev": true,
"requires": {
"ms": "2.1.2"
}
@@ -1678,7 +1751,8 @@
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1607433842694&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
"integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
"integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=",
"dev": true
}
}
},
@@ -1923,6 +1997,7 @@
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/json-bigint/download/json-bigint-1.0.0.tgz",
"integrity": "sha1-rlR4I6wMrYOYZn+M2e9HMPWwH/E=",
"dev": true,
"requires": {
"bignumber.js": "^9.0.0"
}
@@ -1969,7 +2044,7 @@
},
"jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"resolved": "https://registry.npm.taobao.org/jsonfile/download/jsonfile-4.0.0.tgz?cache=0&sync_timestamp=1604161797011&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fjsonfile%2Fdownload%2Fjsonfile-4.0.0.tgz",
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
"requires": {
"graceful-fs": "^4.1.6"
@@ -2011,7 +2086,8 @@
"kitx": {
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/kitx/download/kitx-1.3.0.tgz",
"integrity": "sha1-qz7nxZjSsdYp/VVWj4aMREDCAOo="
"integrity": "sha1-qz7nxZjSsdYp/VVWj4aMREDCAOo=",
"dev": true
},
"kubernetes-client": {
"version": "9.0.0",
@@ -2137,8 +2213,8 @@
},
"log4js": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/log4js/-/log4js-6.3.0.tgz",
"integrity": "sha512-Mc8jNuSFImQUIateBFwdOQcmC6Q5maU0VVvdC2R6XMb66/VnT+7WS4D/0EeNMZu1YODmJe5NIn2XftCzEocUgw==",
"resolved": "https://registry.npm.taobao.org/log4js/download/log4js-6.3.0.tgz",
"integrity": "sha1-EN+vu0NDUaPjAnegC5h5RG9xW8s=",
"requires": {
"date-format": "^3.0.0",
"debug": "^4.1.1",
@@ -2149,16 +2225,16 @@
"dependencies": {
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"resolved": "https://registry.npm.taobao.org/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1607566533140&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz",
"integrity": "sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4=",
"requires": {
"ms": "2.1.2"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1607433842694&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
"integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
}
}
},
@@ -2366,6 +2442,12 @@
"resolved": "https://registry.npm.taobao.org/node-fetch/download/node-fetch-2.6.1.tgz?cache=0&sync_timestamp=1599309179354&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnode-fetch%2Fdownload%2Fnode-fetch-2.6.1.tgz",
"integrity": "sha1-BFvTI2Mfdu0uK1VXM5RBa2OaAFI="
},
"node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
"integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
"dev": true
},
"normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npm.taobao.org/normalize-package-data/download/normalize-package-data-2.5.0.tgz?cache=0&sync_timestamp=1602547447569&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fnormalize-package-data%2Fdownload%2Fnormalize-package-data-2.5.0.tgz",
@@ -2875,9 +2957,9 @@
}
},
"rfdc": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz",
"integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug=="
"version": "1.2.0",
"resolved": "https://registry.npm.taobao.org/rfdc/download/rfdc-1.2.0.tgz?cache=0&sync_timestamp=1610744108114&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frfdc%2Fdownload%2Frfdc-1.2.0.tgz",
"integrity": "sha1-npiUJY9I8oS0PDFDxoBwpPNzuUk="
},
"rimraf": {
"version": "3.0.2",
@@ -2901,7 +2983,8 @@
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz",
"integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk="
"integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=",
"dev": true
},
"semver": {
"version": "7.3.4",
@@ -3041,24 +3124,6 @@
"resolved": "https://registry.npm.taobao.org/sprintf-js/download/sprintf-js-1.0.3.tgz",
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
},
"ssh2": {
"version": "0.8.9",
"resolved": "https://registry.npm.taobao.org/ssh2/download/ssh2-0.8.9.tgz",
"integrity": "sha1-VNo6bEuj2vDYR3pTikgTJgkYFfM=",
"requires": {
"ssh2-streams": "~0.4.10"
}
},
"ssh2-streams": {
"version": "0.4.10",
"resolved": "https://registry.npm.taobao.org/ssh2-streams/download/ssh2-streams-0.4.10.tgz",
"integrity": "sha1-SO9+ig452PKSHDBSHVbayzHSOjQ=",
"requires": {
"asn1": "~0.2.0",
"bcrypt-pbkdf": "^1.0.2",
"streamsearch": "~0.1.2"
}
},
"sshpk": {
"version": "1.16.1",
"resolved": "https://registry.npm.taobao.org/sshpk/download/sshpk-1.16.1.tgz",
@@ -3077,8 +3142,8 @@
},
"streamroller": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/streamroller/-/streamroller-2.2.4.tgz",
"integrity": "sha512-OG79qm3AujAM9ImoqgWEY1xG4HX+Lw+yY6qZj9R1K2mhF5bEmQ849wvrb+4vt4jLMLzwXttJlQbOdPOQVRv7DQ==",
"resolved": "https://registry.npm.taobao.org/streamroller/download/streamroller-2.2.4.tgz",
"integrity": "sha1-wZjO1C25QIamGTYIGHzoCl8rDlM=",
"requires": {
"date-format": "^2.1.0",
"debug": "^4.1.1",
@@ -3087,29 +3152,24 @@
"dependencies": {
"date-format": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/date-format/-/date-format-2.1.0.tgz",
"integrity": "sha512-bYQuGLeFxhkxNOF3rcMtiZxvCBAquGzZm6oWA1oZ0g2THUzivaRhv8uOhdr19LmoobSOLoIAxeUK2RdbM8IFTA=="
"resolved": "https://registry.npm.taobao.org/date-format/download/date-format-2.1.0.tgz",
"integrity": "sha1-MdW16iEc9f12TNOLr50DPffhJc8="
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"resolved": "https://registry.npm.taobao.org/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1607566533140&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz",
"integrity": "sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4=",
"requires": {
"ms": "2.1.2"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1607433842694&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
"integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
}
}
},
"streamsearch": {
"version": "0.1.2",
"resolved": "https://registry.npm.taobao.org/streamsearch/download/streamsearch-0.1.2.tgz",
"integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo="
},
"string-width": {
"version": "4.2.0",
"resolved": "https://registry.npm.taobao.org/string-width/download/string-width-4.2.0.tgz",
@@ -3331,8 +3391,8 @@
},
"universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="
"resolved": "https://registry.npm.taobao.org/universalify/download/universalify-0.1.2.tgz?cache=0&sync_timestamp=1603179967633&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Funiversalify%2Fdownload%2Funiversalify-0.1.2.tgz",
"integrity": "sha1-tkb2m+OULavOzJ1mOcgNwQXvqmY="
},
"uri-js": {
"version": "4.4.0",
@@ -3520,6 +3580,7 @@
"version": "0.4.23",
"resolved": "https://registry.npm.taobao.org/xml2js/download/xml2js-0.4.23.tgz?cache=0&sync_timestamp=1599054229598&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fxml2js%2Fdownload%2Fxml2js-0.4.23.tgz",
"integrity": "sha1-oMaVFnUkIesqx1juTUzPWIQ+rGY=",
"dev": true,
"requires": {
"sax": ">=0.6.0",
"xmlbuilder": "~11.0.0"
@@ -3528,7 +3589,8 @@
"xmlbuilder": {
"version": "11.0.1",
"resolved": "https://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-11.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fxmlbuilder%2Fdownload%2Fxmlbuilder-11.0.1.tgz",
"integrity": "sha1-vpuuHIoEbnazESdyY0fQrXACvrM="
"integrity": "sha1-vpuuHIoEbnazESdyY0fQrXACvrM=",
"dev": true
},
"y18n": {
"version": "4.0.1",

View File

@@ -1,19 +1,18 @@
{
"name": "@certd/plugins",
"version": "0.1.11",
"name": "@certd/plugin-tencent",
"version": "0.1.18",
"description": "",
"main": "./src/index.js",
"main": "src/index.js",
"type": "module",
"dependencies": {
"@alicloud/pop-core": "^1.7.10",
"@certd/api": "^0.1.11",
"@certd/api": "^0.1.17",
"dayjs": "^1.9.7",
"kubernetes-client": "^9.0.0",
"lodash-es": "^4.17.20",
"ssh2": "^0.8.9",
"tencentcloud-sdk-nodejs": "^4.0.44"
},
"devDependencies": {
"@certd/certd": "^0.1.18",
"chai": "^4.2.0",
"eslint": "^7.15.0",
"eslint-config-standard": "^16.0.2",
@@ -23,5 +22,6 @@
"mocha": "^8.2.1"
},
"author": "Greper",
"license": "MIT"
"license": "MIT",
"gitHead": "4a421d5b142d453203c68ce6d1036e168ea2455b"
}

View File

@@ -0,0 +1,26 @@
export class DnspodAccessProvider {
static define () {
return {
name: 'dnspod',
label: 'dnspod',
desc: '腾讯云的域名解析接口已迁移到dnspod',
input: {
id: {
type: String,
component: {
placeholder: 'dnspod接口账户id',
rules: [{ required: true, message: '该项必填' }]
}
},
token: {
type: String,
label: 'token',
component: {
placeholder: '开放接口token',
rules: [{ required: true, message: '该项必填' }]
}
}
}
}
}
}

View File

@@ -0,0 +1,26 @@
export class TencentAccessProvider {
static define () {
return {
name: 'tencent',
label: '腾讯云',
input: {
secretId: {
type: String,
label: 'secretId',
component: {
placeholder: 'secretId',
rules: [{ required: true, message: '该项必填' }]
}
},
secretKey: {
type: String,
label: 'secretKey',
component: {
placeholder: 'secretKey',
rules: [{ required: true, message: '该项必填' }]
}
}
}
}
}
}

View File

@@ -2,16 +2,31 @@ import { AbstractDnsProvider, util } from '@certd/api'
import _ from 'lodash-es'
const request = util.request
export class DnspodDnsProvider extends AbstractDnsProvider {
static name () {
return 'dnspod'
static define () {
return {
name: 'dnspod',
label: 'dnspod(腾讯云)',
desc: '腾讯云的域名解析接口已迁移到dnspod',
input: {
accessProvider: {
label: '授权',
type: [String, Object],
desc: '需要dnspod类型的授权',
component: {
name: 'access-provider-selector',
filter: 'dnspod'
},
required: true
}
}
}
}
constructor (dnsProviderConfig) {
super()
if (!dnsProviderConfig.id || !dnsProviderConfig.token) {
throw new Error('请正确配置dnspod的 id 和 token')
}
this.loginToken = dnsProviderConfig.id + ',' + dnsProviderConfig.token
constructor (args) {
super(args)
const { props } = args
const accessProvider = this.getAccessProvider(props.accessProvider)
this.loginToken = accessProvider.id + ',' + accessProvider.token
}
async doRequest (options) {

View File

@@ -0,0 +1,34 @@
import _ from 'lodash-es'
import { TencentAccessProvider } from './access-providers/tencent.js'
import { DnspodAccessProvider } from './access-providers/dnspod.js'
import { DnspodDnsProvider } from './dns-providers/dnspod.js'
import { UploadCertToTencent } from './plugins/upload-to-tencent/index.js'
import { DeployCertToTencentCDN } from './plugins/deploy-to-cdn/index.js'
import { DeployCertToTencentCLB } from './plugins/deploy-to-clb/index.js'
import { DeployCertToTencentTKEIngress } from './plugins/deploy-to-tke-ingress/index.js'
import { pluginRegistry, accessProviderRegistry, dnsProviderRegistry } from '@certd/api'
export const DefaultPlugins = {
UploadCertToTencent,
DeployCertToTencentTKEIngress,
DeployCertToTencentCDN,
DeployCertToTencentCLB
}
export default {
install () {
_.forEach(DefaultPlugins, item => {
pluginRegistry.install(item)
})
accessProviderRegistry.install(TencentAccessProvider)
accessProviderRegistry.install(DnspodAccessProvider)
dnsProviderRegistry.install(DnspodDnsProvider)
}
}

View File

@@ -1,4 +1,4 @@
import { AbstractTencentPlugin } from '../../tencent/abstract-tencent.js'
import { AbstractTencentPlugin } from '../abstract-tencent.js'
import dayjs from 'dayjs'
import tencentcloud from 'tencentcloud-sdk-nodejs'
@@ -19,35 +19,35 @@ export class DeployCertToTencentCDN extends AbstractTencentPlugin {
required: true
},
certName: {
label: '证书名称'
label: '证书名称',
desc: '证书上传后将以此参数作为名称前缀'
},
certType: {
value: 'upload',
default: 'upload',
label: '证书来源',
options: [
{ value: 'upload', label: '直接上传' },
{ value: 'cloud', label: '从证书库', desc: '需要uploadCertToTencent作为前置任务' }
],
desc: '如果选择‘从证书库’类型,则需要以《上传证书到腾讯云》作为前置任务',
required: true
},
// serverCertificateStatus: {
// label: '启用https',
// options: [
// { value: 'on', label: '开启HTTPS并更新证书' },
// { value: 'auto', label: '若HTTPS开启则更新未开启不更新' }
// ],
// required:true
// },
accessProvider: {
label: 'Access提供者',
type: [String, Object],
desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象',
options: 'accessProviders[type=aliyun]',
desc: 'access 授权',
component: {
name: 'access-provider-selector',
filter: 'tencent'
},
required: true
}
},
output: {
tencentCertId: {
type: String,
desc: '证书来源选择上传时将返回此id'
}
}
}
}

View File

@@ -1,4 +1,4 @@
import { AbstractTencentPlugin } from '../../tencent/abstract-tencent.js'
import { AbstractTencentPlugin } from '../abstract-tencent.js'
import tencentcloud from 'tencentcloud-sdk-nodejs'
export class DeployCertToTencentCLB extends AbstractTencentPlugin {
/**
@@ -15,16 +15,19 @@ export class DeployCertToTencentCLB extends AbstractTencentPlugin {
input: {
region: {
label: '大区',
value: 'ap-guangzhou'
default: 'ap-guangzhou',
required: true
},
domain: {
label: '域名',
type: [String, Array],
required: true,
desc: '要更新的支持https的负载均衡的域名'
},
loadBalancerId: {
label: '负载均衡ID',
desc: '如果没有配置则根据域名匹配负载均衡下的监听器根据域名匹配时暂时只支持前100个'
desc: '如果没有配置则根据域名匹配负载均衡下的监听器根据域名匹配时暂时只支持前100个',
required: true
},
listenerId: {
label: '监听器ID',
@@ -37,8 +40,11 @@ export class DeployCertToTencentCLB extends AbstractTencentPlugin {
accessProvider: {
label: 'Access提供者',
type: [String, Object],
desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象',
options: 'accessProviders[type=tencent]',
desc: 'access授权',
component: {
name: 'access-provider-selector',
filter: 'tencent'
},
required: true
}
},

View File

@@ -1,4 +1,4 @@
import { AbstractTencentPlugin } from '../../tencent/abstract-tencent.js'
import { AbstractTencentPlugin } from '../abstract-tencent.js'
import tencentcloud from 'tencentcloud-sdk-nodejs'
import { K8sClient } from '../../utils/util.k8s.client.js'
export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
@@ -16,21 +16,25 @@ export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
input: {
region: {
label: '大区',
value: 'ap-guangzhou'
default: 'ap-guangzhou',
required: true
},
clusterId: {
label: '集群ID',
required: true,
desc: '例如cls-6lbj1vee'
desc: '例如cls-6lbj1vee',
request: true
},
namespace: {
label: '集群namespace',
value: 'default'
label: '集群namespace',
default: 'default',
required: true
},
secreteName: {
type: [String, Array],
label: '证书的secret名称',
desc: '支持多个(传入数组)'
desc: '支持多个(传入数组)',
required: true
},
ingressName: {
type: [String, Array],
@@ -44,20 +48,19 @@ export class DeployCertToTencentTKEIngress extends AbstractTencentPlugin {
},
clusterDomain: {
type: String,
label: '集群域名,可不填,默认为:[clusterId].ccs.tencent-cloud.com'
label: '集群域名',
desc: '可不填,默认为:[clusterId].ccs.tencent-cloud.com'
},
/**
* AccessProvider的key,或者一个包含access的具体的对象
*/
accessProvider: {
label: 'Access提供者',
label: 'Access授权',
type: [String, Object],
desc: '请选择access提供者',
desc: 'access授权',
component: {
name: 'accessProviderSelect',
props: {
filterType: 'tencent'
}
name: 'access-provider-selector',
filter: 'tencent'
},
required: true
}

View File

@@ -1,4 +1,3 @@
import dayjs from 'dayjs'
import tencentcloud from 'tencentcloud-sdk-nodejs'
import { AbstractTencentPlugin } from '../abstract-tencent.js'
@@ -18,10 +17,14 @@ export class UploadCertToTencent extends AbstractTencentPlugin {
label: '证书名称'
},
accessProvider: {
label: 'Access提供者',
label: 'Access授权',
type: [String, Object],
desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象',
options: 'accessProviders[type=tencent]'
desc: 'access授权',
component: {
name: 'access-provider-selector',
filter: 'tencent'
},
required: true
}
},
output: {

View File

@@ -45,7 +45,7 @@ export class K8sClient {
* @param opts = {namespace:default}
* @returns secretsList
*/
async getSecret (opts) {
async getSecret (opts = {}) {
const namespace = opts.namespace || 'default'
const secrets = await this.client.api.v1.namespaces(namespace).secrets.get()
return secrets

View File

@@ -1,13 +1,20 @@
import pkg from 'chai'
import { Certd } from '../../src/index.js'
import { createOptions } from '../../../../test/options.js'
import PluginTencent from '../../src/index.js'
import { createOptions } from '../../../../../test/options.js'
import { Certd } from '@certd/certd'
const { expect } = pkg
// 安装默认插件和授权提供者
PluginTencent.install()
describe('DnspodDnsProvider', function () {
it('#申请证书', async function () {
this.timeout(300000)
const options = createOptions()
options.cert.domains = ['*.certd.xyz', '*.test.certd.xyz', '*.base.certd.xyz', 'certd.xyz']
options.cert.dnsProvider = 'dnspod'
options.cert.dnsProvider = {
type: 'dnspod',
accessProvider: 'dnspod'
}
options.args = { forceCert: true }
const certd = new Certd(options)
const cert = await certd.certApply()

View File

@@ -1,20 +1,31 @@
import pkg from 'chai'
import DnspodDnsProvider from '../../src/dns-provider/dnspod.js'
import { Certd } from '../../src/index.js'
import { createOptions } from '../../../../test/options.js'
import { DnspodDnsProvider } from '../../src/dns-providers/dnspod.js'
import { createOptions, getDnsProviderOptions } from '../../../../../test/options.js'
const { expect } = pkg
describe('DnspodDnsProvider', function () {
it('#getDomainList', async function () {
const options = createOptions()
const dnsProvider = new DnspodDnsProvider(options.accessProviders.dnspod)
let options = createOptions()
options.cert.dnsProvider = {
type: 'dnspod',
accessProvider: 'dnspod'
}
options = getDnsProviderOptions(options)
const dnsProvider = new DnspodDnsProvider(options)
const domainList = await dnsProvider.getDomainList()
console.log('domainList', domainList)
expect(domainList.length).gt(0)
})
it('#createRecord&removeRecord', async function () {
const options = createOptions()
const dnsProvider = new DnspodDnsProvider(options.accessProviders.dnspod)
let options = createOptions()
options.cert.dnsProvider = {
type: 'dnspod',
accessProvider: 'dnspod'
}
options = getDnsProviderOptions(options)
const dnsProvider = new DnspodDnsProvider(options)
const record = await dnsProvider.createRecord({ fullRecord: '___certd___.__test__.certd.xyz', type: 'TXT', value: 'aaaa' })
console.log('recordId', record.id)
expect(record.id != null).ok

View File

@@ -1,35 +1,33 @@
import pkg from 'chai'
import { DeployCertToTencentCDN } from '../../src/tencent/deploy-to-cdn/index.js'
import { DeployCertToTencentCDN } from '../../src/plugins/deploy-to-cdn/index.js'
import { Certd } from '@certd/certd'
import { UploadCertToTencent } from '../../src/tencent/upload-to-tencent/index.js'
import { createOptions } from '../../../../test/options.js'
import { UploadCertToTencent } from '../../src/plugins/upload-to-tencent/index.js'
import { createOptions } from '../../../../../test/options.js'
const { expect } = pkg
describe('DeployToTencentCDN', function () {
it('#execute-from-store', async function () {
const options = createOptions()
options.args.test = false
const certd = new Certd(options)
const cert = certd.readCurrentCert('xiaojunnuo@qq.com', ['*.docmirror.cn'])
const cert = await certd.readCurrentCert('xiaojunnuo@qq.com', ['*.docmirror.cn'])
const context = {}
const uploadPlugin = new UploadCertToTencent()
const uploadPlugin = new UploadCertToTencent(options)
const uploadOptions = {
accessProviders: options.accessProviders,
cert,
props: { name: 'certd部署测试', accessProvider: 'tencent' },
context
}
await uploadPlugin.doExecute(uploadOptions)
const deployPlugin = new DeployCertToTencentCDN()
const deployPlugin = new DeployCertToTencentCDN(options)
const deployOpts = {
accessProviders: options.accessProviders,
cert,
props: { domainName: 'tentcent-certd.docmirror.cn', certName: 'certd部署测试', accessProvider: 'tencent' },
context
}
const ret = await deployPlugin.doExecute(deployOpts)
expect(ret).ok
await deployPlugin.doExecute(deployOpts)
console.log('context:', context)
expect(context.tencentCertId).ok
await uploadPlugin.doRollback(uploadOptions)
})
@@ -38,17 +36,17 @@ describe('DeployToTencentCDN', function () {
options.args.test = false
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['*.docmirror.cn']
const plugin = new DeployCertToTencentCDN()
const plugin = new DeployCertToTencentCDN(options)
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const context = {}
const deployOpts = {
accessProviders: options.accessProviders,
cert,
props: { domainName: 'tentcent-certd.docmirror.cn', accessProvider: 'tencent' },
context
}
const ret = await plugin.doExecute(deployOpts)
console.log('context:', context, ret)
expect(context).be.empty
})
})

View File

@@ -1,23 +1,22 @@
import pkg from 'chai'
import { DeployCertToTencentCLB } from '../../src/tencent/deploy-to-clb/index.js'
import { DeployCertToTencentCLB } from '../../src/plugins/deploy-to-clb/index.js'
import { Certd } from '@certd/certd'
// eslint-disable-next-line no-unused-vars
import { createOptions } from '../../../../test/options.js'
import { UploadCertToTencent } from '../../src/tencent/upload-to-tencent/index.js'
import { createOptions } from '../../../../../test/options.js'
import { UploadCertToTencent } from '../../src/plugins/upload-to-tencent/index.js'
const { expect } = pkg
describe('DeployToTencentCLB', function () {
it('#execute-getClbList', async function () {
const options = createOptions()
options.args.test = false
options.cert.dnsProvider = 'tencent-yonsz'
const deployPlugin = new DeployCertToTencentCLB()
const deployPlugin = new DeployCertToTencentCLB(options)
const props = {
region: 'ap-guangzhou',
domain: 'certd-test-no-sni.base.yonsz.net',
accessProvider: 'tencent-yonsz'
}
const accessProviders = options.accessProviders
const accessProvider = deployPlugin.getAccessProvider(props.accessProvider, accessProviders)
const accessProvider = deployPlugin.getAccessProvider(props.accessProvider)
const { region } = props
const client = deployPlugin.getClient(accessProvider, region)
@@ -34,13 +33,14 @@ describe('DeployToTencentCLB', function () {
region: 'ap-guangzhou',
domain: 'certd-test-no-sni.base.yonsz.net',
accessProvider: 'tencent-yonsz',
loadBalancerId: 'lb-59yhe5xo'
loadBalancerId: 'lb-59yhe5xo',
listenerId: 'lbl-1vfwx8dq'
}
const accessProvider = deployPlugin.getAccessProvider(props.accessProvider)
const { region } = props
const client = deployPlugin.getClient(accessProvider, region)
const ret = await deployPlugin.getListenerList(client, props.loadBalancerId, props)
const ret = await deployPlugin.getListenerList(client, props.loadBalancerId, [props.listenerId])
expect(ret.length > 0).ok
console.log('clb count:', ret.length, ret)
})
@@ -54,10 +54,9 @@ describe('DeployToTencentCLB', function () {
options.cert.domains = ['*.docmirror.cn']
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const deployPlugin = new DeployCertToTencentCLB()
const deployPlugin = new DeployCertToTencentCLB(options)
const context = {}
const deployOpts = {
accessProviders: options.accessProviders,
cert,
props: {
region: 'ap-guangzhou',
@@ -72,7 +71,7 @@ describe('DeployToTencentCLB', function () {
console.log('ret:', ret)
// 删除测试证书
const uploadPlugin = new UploadCertToTencent()
const uploadPlugin = new UploadCertToTencent(options)
await uploadPlugin.doRollback(deployOpts)
})
@@ -83,10 +82,9 @@ describe('DeployToTencentCLB', function () {
options.cert.dnsProvider = 'tencent-yonsz'
const certd = new Certd(options)
const cert = certd.readCurrentCert('xiaojunnuo@qq.com', ['*.docmirror.cn'])
const deployPlugin = new DeployCertToTencentCLB()
const deployPlugin = new DeployCertToTencentCLB(options)
const context = {}
const deployOpts = {
accessProviders: options.accessProviders,
cert,
props: {
region: 'ap-guangzhou',
@@ -98,10 +96,10 @@ describe('DeployToTencentCLB', function () {
context
}
const ret = await deployPlugin.doExecute(deployOpts)
expect(ret).ok
console.log('ret:', ret)
expect(ret).ok
// 删除测试证书
const uploadPlugin = new UploadCertToTencent()
const uploadPlugin = new UploadCertToTencent(options)
await uploadPlugin.doRollback(deployOpts)
})
})

View File

@@ -0,0 +1,57 @@
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('DeployCertToTencentTKEIngress', 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: 'default' })
console.log('secrets:', secrets)
})
it('#execute', async function () {
this.timeout(5000)
const { options, deployOpts } = await getOptions()
deployOpts.props.ingressName = 'ingress-base'
deployOpts.props.secretName = 'cert---docmirror-cn'
deployOpts.context.tencentCertId = 'hNUZJrZf'
const plugin = new DeployCertToTencentTKEIngress(options)
const ret = await plugin.doExecute(deployOpts)
console.log('sucess', ret)
})
})

View File

@@ -1,12 +1,12 @@
import pkg from 'chai'
import { UploadCertToTencent } from '../../src/tencent/upload-to-tencent/index.js'
import { UploadCertToTencent } from '../../src/plugins/upload-to-tencent/index.js'
import { Certd } from '@certd/certd'
import { createOptions } from '../../../../test/options.js'
import { createOptions } from '../../../../../test/options.js'
const { expect } = pkg
describe('PluginUploadToTencent', function () {
it('#execute', async function () {
const options = createOptions()
const plugin = new UploadCertToTencent()
const plugin = new UploadCertToTencent(options)
options.args = { test: false }
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['*.docmirror.cn']

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,94 +0,0 @@
import { AbstractAliyunPlugin } from '../../aliyun/abstract-aliyun.js'
import Core from '@alicloud/pop-core'
import dayjs from 'dayjs'
export class DeployCertToAliyunCDN extends AbstractAliyunPlugin {
/**
* 插件定义
* 名称
* 入参
* 出参
*/
static define () {
return {
name: 'deployCertToAliyunCDN',
label: '部署到阿里云CDN',
input: {
domainName: {
label: 'cdn加速域名',
required: true
},
certName: {
label: '证书名称'
},
from: {
value: 'upload',
label: '证书来源',
options: [
{ value: 'upload', label: '直接上传' },
{ value: 'cas', label: '从证书库', desc: '需要uploadCertToAliyun作为前置任务' }
],
required: true
},
// serverCertificateStatus: {
// label: '启用https',
// options: [
// { value: 'on', label: '开启HTTPS并更新证书' },
// { value: 'auto', label: '若HTTPS开启则更新未开启不更新' }
// ],
// required:true
// },
accessProvider: {
label: 'Access提供者',
type: [String, Object],
desc: 'AccessProviders的key 或 一个包含accessKeyId与accessKeySecret的对象',
options: 'accessProviders[type=aliyun]',
required: true
}
},
output: {
}
}
}
async execute ({ cert, props, context }) {
const accessProvider = this.getAccessProvider(props.accessProvider)
const client = this.getClient(accessProvider)
const params = this.buildParams(props, context, cert)
await this.doRequest(client, params)
}
getClient (aliyunProvider) {
return new Core({
accessKeyId: aliyunProvider.accessKeyId,
accessKeySecret: aliyunProvider.accessKeySecret,
endpoint: 'https://cdn.aliyuncs.com',
apiVersion: '2018-05-10'
})
}
buildParams (args, context, cert) {
const { certName, from, domainName } = args
const CertName = certName + '-' + dayjs().format('YYYYMMDDHHmmss')
const params = {
RegionId: 'cn-hangzhou',
DomainName: domainName,
ServerCertificateStatus: 'on',
CertName: CertName,
CertType: from,
ServerCertificate: cert.crt,
PrivateKey: cert.key
}
return params
}
async doRequest (client, params) {
const requestOption = {
method: 'POST'
}
const ret = await client.request('SetDomainServerCertificate', params, requestOption)
this.checkRet(ret)
this.logger.info('设置cdn证书成功:', ret.RequestId)
}
}

View File

@@ -1,19 +0,0 @@
import { UploadCertToAliyun } from './aliyun/upload-to-aliyun/index.js'
import { DeployCertToAliyunCDN } from './aliyun/deploy-to-cdn/index.js'
import { UploadCertToTencent } from './tencent/upload-to-tencent/index.js'
import { DeployCertToTencentCDN } from './tencent/deploy-to-cdn/index.js'
import { DeployCertToTencentCLB } from './tencent/deploy-to-clb/index.js'
import { DeployCertToTencentTKEIngress } from './tencent/deploy-to-tke-ingress/index.js'
export default {
UploadCertToAliyun,
DeployCertToAliyunCDN,
UploadCertToTencent,
DeployCertToTencentTKEIngress,
DeployCertToTencentCDN,
DeployCertToTencentCLB
}

View File

@@ -1,29 +0,0 @@
import pkg from 'chai'
import { HostShellExecute } from '../../src/host/host-shell-execute/index.js'
import { Certd } from '@certd/certd'
import { createOptions } from '../../../../test/options.js'
const { expect } = pkg
describe('HostShellExecute', function () {
it('#execute', async function () {
this.timeout(10000)
const options = createOptions()
options.args = { test: false }
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['*.docmirror.cn']
const plugin = new HostShellExecute(options)
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const context = {}
const uploadOpts = {
cert,
props: { script: 'ls ', accessProvider: 'aliyun-ssh' },
context
}
const ret = await plugin.doExecute(uploadOpts)
for (const retElement of ret) {
console.log('-----' + retElement)
}
await plugin.doRollback(uploadOpts)
})
})

View File

@@ -1,27 +0,0 @@
import pkg from 'chai'
import { UploadCertToHost } from '../../src/host/upload-to-host/index.js'
import { Certd } from '@certd/certd'
import { createOptions } from '../../../../test/options.js'
const { expect } = pkg
describe('PluginUploadToHost', function () {
it('#execute', async function () {
this.timeout(10000)
const options = createOptions()
options.args = { test: false }
options.cert.email = 'xiaojunnuo@qq.com'
options.cert.domains = ['*.docmirror.cn']
const plugin = new UploadCertToHost(options)
const certd = new Certd(options)
const cert = await certd.readCurrentCert()
const context = {}
const uploadOpts = {
cert,
props: { crtPath: '/root/certd/test/test.crt', keyPath: '/root/certd/test/test.key', accessProvider: 'aliyun-ssh' },
context
}
await plugin.doExecute(uploadOpts)
console.log('context:', context)
await plugin.doRollback(uploadOpts)
})
})

View File

@@ -1,114 +0,0 @@
import pkg from 'chai'
import { DeployCertToTencentTKEIngress } from '../../src/tencent/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('DeployCertToTencentTKEIngress', function () {
// it('#getTkeKubeConfig', async function () {
// const { options, deployOpts } = await getOptions()
// const plugin = new DeployCertToTencentTKEIngress()
// const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
// const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props)
// console.log('kubeConfig:', kubeConfig)
// })
//
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()
console.log('secrets:', secrets)
})
//
// it('#patchTKECertSecrets', async function () {
// this.timeout(5000)
//
// const { options, deployOpts } = await getOptions()
// const plugin = new DeployCertToTencentTKEIngress()
// const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
// const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props)
// const k8sClient = new K8sClient(kubeConfig)
//
// deployOpts.k8sClient = k8sClient
// deployOpts.context.tencentCertId = 'hNVD3Z45'
// const newCecret = await plugin.patchCertSecret(deployOpts)
// console.log('newCecret', newCecret)
// })
// it('#GetTkeIngress', async function () {
// this.timeout(5000)
//
// const { options, deployOpts } = await getOptions()
// deployOpts.props.ingressName = 'ingress-base'
// deployOpts.props.secretName = 'cert---docmirror-cn'
// const plugin = new DeployCertToTencentTKEIngress()
// const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
// const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props)
//
// const k8sClient = new K8sClient(kubeConfig)
// const ingress = await k8sClient.getIngress({
// ingressName: 'ingress-base'
// })
// console.log('ingress:', ingress)
// })
// it('#RestartTKEIngress', async function () {
// this.timeout(5000)
//
// const { options, deployOpts } = await getOptions()
// deployOpts.props.ingressName = 'ingress-base'
// deployOpts.props.secretName = 'cert---docmirror-cn'
// const plugin = new DeployCertToTencentTKEIngress()
// const tkeClient = plugin.getTkeClient(options.accessProviders[deployOpts.props.accessProvider], deployOpts.props.region)
// const kubeConfig = await plugin.getTkeKubeConfig(tkeClient, deployOpts.props)
//
// const k8sClient = new K8sClient(kubeConfig)
//
// deployOpts.k8sClient = k8sClient
// deployOpts.context.tencentCertId = 'hNVD3Z45'
// const newCecret = await plugin.restartIngress(deployOpts)
// console.log('newCecret', newCecret)
// })
it('#execute', async function () {
this.timeout(5000)
const { deployOpts } = await getOptions()
deployOpts.props.ingressName = 'ingress-base'
deployOpts.props.secretName = 'cert---docmirror-cn'
deployOpts.context.tencentCertId = 'hNUZJrZf'
const plugin = new DeployCertToTencentTKEIngress()
const ret = await plugin.doExecute(deployOpts)
console.log('sucess', ret)
})
})

Some files were not shown because too many files have changed in this diff Show More