mirror of
https://github.com/certd/certd.git
synced 2026-04-23 19:57:27 +08:00
feat: 升级midway,支持esm
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
export * from '@certd/plugin-cert';
|
||||
export * from './plugin-aliyun';
|
||||
export * from './plugin-tencent';
|
||||
export * from './plugin-host';
|
||||
export * from './plugin-huawei';
|
||||
export * from './plugin-demo';
|
||||
export * from './plugin-aliyun/index.js';
|
||||
export * from './plugin-tencent/index.js';
|
||||
export * from './plugin-host/index.js';
|
||||
export * from './plugin-huawei/index.js';
|
||||
export * from './plugin-demo/index.js';
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from './aliyun-access';
|
||||
export * from './aliyun-access.js';
|
||||
|
||||
+12
-7
@@ -1,7 +1,12 @@
|
||||
import Core from "@alicloud/pop-core";
|
||||
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||
import { Autowire, ILogger } from "@certd/pipeline";
|
||||
import { AliyunAccess } from "../access";
|
||||
import Core from '@alicloud/pop-core';
|
||||
import {
|
||||
AbstractDnsProvider,
|
||||
CreateRecordOptions,
|
||||
IsDnsProvider,
|
||||
RemoveRecordOptions,
|
||||
} from '@certd/plugin-cert';
|
||||
import { Autowire, ILogger } from '@certd/pipeline';
|
||||
import { AliyunAccess } from '../access/index.js';
|
||||
|
||||
@IsDnsProvider({
|
||||
name: 'aliyun',
|
||||
@@ -9,7 +14,7 @@ import { AliyunAccess } from "../access";
|
||||
desc: '阿里云DNS解析提供商',
|
||||
accessType: 'aliyun',
|
||||
})
|
||||
export class AliyunDnsProvider extends AbstractDnsProvider{
|
||||
export class AliyunDnsProvider extends AbstractDnsProvider {
|
||||
client: any;
|
||||
@Autowire()
|
||||
access!: AliyunAccess;
|
||||
@@ -86,8 +91,8 @@ export class AliyunDnsProvider extends AbstractDnsProvider{
|
||||
// }
|
||||
|
||||
async createRecord(options: CreateRecordOptions): Promise<any> {
|
||||
const { fullRecord, value, type,domain } = options;
|
||||
this.logger.info('添加域名解析:', fullRecord, value,domain);
|
||||
const { fullRecord, value, type, domain } = options;
|
||||
this.logger.info('添加域名解析:', fullRecord, value, domain);
|
||||
// const domain = await this.matchDomain(fullRecord);
|
||||
const rr = fullRecord.replace('.' + domain, '');
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
import './aliyun-dns-provider';
|
||||
import './aliyun-dns-provider.js';
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './access/index';
|
||||
export * from './dns-provider/index';
|
||||
export * from './plugin/index';
|
||||
export * from './access/index.js';
|
||||
export * from './dns-provider/index.js';
|
||||
export * from './plugin/index.js';
|
||||
|
||||
+3
-3
@@ -9,9 +9,9 @@ import {
|
||||
} from '@certd/pipeline';
|
||||
// @ts-ignore
|
||||
import { ROAClient } from '@alicloud/pop-core';
|
||||
import { AliyunAccess } from '../../access';
|
||||
import { K8sClient } from '@certd/plugin-util';
|
||||
import { appendTimeSuffix } from '../../utils';
|
||||
import { AliyunAccess } from '../../access/index.js';
|
||||
import { K8sClient } from '@certd/lib-k8s';
|
||||
import { appendTimeSuffix } from '../../utils/index.js';
|
||||
import { CertInfo } from '@certd/plugin-cert';
|
||||
|
||||
@IsTaskPlugin({
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import dayjs from 'dayjs';
|
||||
import Core from '@alicloud/pop-core';
|
||||
import RPCClient from '@alicloud/pop-core';
|
||||
import { AliyunAccess } from '../../access';
|
||||
import { AliyunAccess } from '../../access/index.js';
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: 'DeployCertToAliyunCDN',
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './deploy-to-cdn/index';
|
||||
export * from './deploy-to-ack-ingress/index';
|
||||
export * from './upload-to-aliyun/index';
|
||||
export * from './deploy-to-cdn/index.js';
|
||||
export * from './deploy-to-ack-ingress/index.js';
|
||||
export * from './upload-to-aliyun/index.js';
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
TaskOutput,
|
||||
} from '@certd/pipeline';
|
||||
import Core from '@alicloud/pop-core';
|
||||
import { AliyunAccess } from '../../access';
|
||||
import { appendTimeSuffix, checkRet, ZoneOptions } from '../../utils';
|
||||
import { AliyunAccess } from '../../access/index.js';
|
||||
import { appendTimeSuffix, checkRet, ZoneOptions } from '../../utils/index.js';
|
||||
import { Logger } from 'log4js';
|
||||
|
||||
@IsTaskPlugin({
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||
import { Autowire, HttpClient, ILogger } from "@certd/pipeline";
|
||||
import { CloudflareAccess } from "./access";
|
||||
import {
|
||||
AbstractDnsProvider,
|
||||
CreateRecordOptions,
|
||||
IsDnsProvider,
|
||||
RemoveRecordOptions,
|
||||
} from '@certd/plugin-cert';
|
||||
import { Autowire, HttpClient, ILogger } from '@certd/pipeline';
|
||||
import { CloudflareAccess } from './access.js';
|
||||
|
||||
export type CloudflareRecord = {
|
||||
id: string;
|
||||
@@ -15,7 +20,6 @@ export type CloudflareRecord = {
|
||||
modified_on: string;
|
||||
};
|
||||
|
||||
|
||||
// 这里通过IsDnsProvider注册一个dnsProvider
|
||||
@IsDnsProvider({
|
||||
name: 'cloudflare',
|
||||
@@ -24,94 +28,96 @@ export type CloudflareRecord = {
|
||||
// 这里是对应的 cloudflare的access类型名称
|
||||
accessType: 'cloudflare',
|
||||
})
|
||||
export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>{
|
||||
export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord> {
|
||||
// 通过Autowire传递context
|
||||
@Autowire()
|
||||
logger! : ILogger;
|
||||
logger!: ILogger;
|
||||
access!: CloudflareAccess;
|
||||
http!: HttpClient;
|
||||
async onInstance() {
|
||||
//一些初始化的操作
|
||||
// 也可以通过ctx成员变量传递context, 与Autowire效果一样
|
||||
this.access = this.ctx.access as CloudflareAccess;
|
||||
this.http = this.ctx.http
|
||||
this.http = this.ctx.http;
|
||||
}
|
||||
|
||||
|
||||
async getZoneId(domain:string){
|
||||
async getZoneId(domain: string) {
|
||||
const url = `https://api.cloudflare.com/client/v4/zones?name=${domain}`;
|
||||
const res = await this.doRequestApi(url,null,"get");
|
||||
return res.result[0].id
|
||||
const res = await this.doRequestApi(url, null, 'get');
|
||||
return res.result[0].id;
|
||||
}
|
||||
|
||||
|
||||
private async doRequestApi(url: string,data:any = null,method:string="post") {
|
||||
const res = await this.http.request<any,any>({
|
||||
url,
|
||||
method,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${this.access.apiToken}`,
|
||||
},
|
||||
data
|
||||
});
|
||||
if (!res.success) {
|
||||
throw new Error(`${JSON.stringify(res.errors)}`);
|
||||
}
|
||||
return res
|
||||
private async doRequestApi(url: string, data: any = null, method = 'post') {
|
||||
const res = await this.http.request<any, any>({
|
||||
url,
|
||||
method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${this.access.apiToken}`,
|
||||
},
|
||||
data,
|
||||
});
|
||||
if (!res.success) {
|
||||
throw new Error(`${JSON.stringify(res.errors)}`);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建dns解析记录,用于验证域名所有权
|
||||
* 创建dns解析记录,用于验证域名所有权
|
||||
*/
|
||||
async createRecord(options: CreateRecordOptions): Promise<CloudflareRecord> {
|
||||
|
||||
/**
|
||||
* fullRecord: '_acme-challenge.test.example.com',
|
||||
* value: 一串uuid
|
||||
* type: 'TXT',
|
||||
* domain: 'example.com'
|
||||
*/
|
||||
const { fullRecord, value, type,domain } = options;
|
||||
this.logger.info('添加域名解析:', fullRecord, value, type,domain);
|
||||
const { fullRecord, value, type, domain } = options;
|
||||
this.logger.info('添加域名解析:', fullRecord, value, type, domain);
|
||||
|
||||
const zoneId = await this.getZoneId(domain);
|
||||
this.logger.info('获取zoneId成功:',zoneId)
|
||||
this.logger.info('获取zoneId成功:', zoneId);
|
||||
|
||||
// 给domain下创建txt类型的dns解析记录,fullRecord
|
||||
let url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`;
|
||||
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records`;
|
||||
const res = await this.doRequestApi(url, {
|
||||
content: value,
|
||||
name: fullRecord,
|
||||
type: type,
|
||||
ttl: 60,
|
||||
})
|
||||
content: value,
|
||||
name: fullRecord,
|
||||
type: type,
|
||||
ttl: 60,
|
||||
});
|
||||
const record = res.result as CloudflareRecord;
|
||||
this.logger.info(`添加域名解析成功:fullRecord=${fullRecord},value=${value}`);
|
||||
this.logger.info(`dns解析记录:${JSON.stringify(record)}`,)
|
||||
this.logger.info(
|
||||
`添加域名解析成功:fullRecord=${fullRecord},value=${value}`
|
||||
);
|
||||
this.logger.info(`dns解析记录:${JSON.stringify(record)}`);
|
||||
|
||||
//本接口需要返回本次创建的dns解析记录,这个记录会在删除的时候用到
|
||||
return record
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除dns解析记录,清理申请痕迹
|
||||
* @param options
|
||||
*/
|
||||
async removeRecord(options: RemoveRecordOptions<CloudflareRecord>): Promise<void> {
|
||||
async removeRecord(
|
||||
options: RemoveRecordOptions<CloudflareRecord>
|
||||
): Promise<void> {
|
||||
const { fullRecord, value, record } = options;
|
||||
this.logger.info('删除域名解析:', fullRecord, value);
|
||||
if(!record){
|
||||
if (!record) {
|
||||
this.logger.info('record不存在');
|
||||
return
|
||||
return;
|
||||
}
|
||||
//这里调用删除txt dns解析记录接口
|
||||
const zoneId = record.zone_id;
|
||||
const recordId = record.id;
|
||||
let url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`;
|
||||
await this.doRequestApi(url,null,"delete")
|
||||
this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},value=${value}`);
|
||||
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`;
|
||||
await this.doRequestApi(url, null, 'delete');
|
||||
this.logger.info(
|
||||
`删除域名解析成功:fullRecord=${fullRecord},value=${value}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './dns-provider';
|
||||
export * from './plugins';
|
||||
export * from './access';
|
||||
export * from './dns-provider.js';
|
||||
export * from './plugins/index.js';
|
||||
export * from './access.js';
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from './plugin-deploy-to-cdn';
|
||||
export * from './plugin-deploy-to-cdn.js';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { IsAccess, AccessInput, IAccess } from "@certd/pipeline";
|
||||
import { IsAccess, AccessInput, IAccess } from '@certd/pipeline';
|
||||
|
||||
/**
|
||||
* 这个注解将注册一个授权配置
|
||||
@@ -9,7 +9,7 @@ import { IsAccess, AccessInput, IAccess } from "@certd/pipeline";
|
||||
title: '授权插件示例',
|
||||
desc: '',
|
||||
})
|
||||
export class DemoAccess implements IAccess{
|
||||
export class DemoAccess implements IAccess {
|
||||
/**
|
||||
* 授权属性配置
|
||||
*/
|
||||
|
||||
@@ -1,20 +1,24 @@
|
||||
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||
import { Autowire, HttpClient, ILogger } from "@certd/pipeline";
|
||||
import { DemoAccess } from "./access";
|
||||
|
||||
import {
|
||||
AbstractDnsProvider,
|
||||
CreateRecordOptions,
|
||||
IsDnsProvider,
|
||||
RemoveRecordOptions,
|
||||
} from '@certd/plugin-cert';
|
||||
import { Autowire, HttpClient, ILogger } from '@certd/pipeline';
|
||||
import { DemoAccess } from './access.js';
|
||||
|
||||
type DemoRecord = {
|
||||
// 这里定义Record记录的数据结构,跟对应云平台接口返回值一样即可,一般是拿到id就行,用于删除txt解析记录,清理申请痕迹
|
||||
// id:string
|
||||
}
|
||||
};
|
||||
|
||||
// 这里通过IsDnsProvider注册一个dnsProvider
|
||||
@IsDnsProvider({
|
||||
name: "demo",
|
||||
title: "Dns提供商Demo",
|
||||
desc: "dns provider示例",
|
||||
name: 'demo',
|
||||
title: 'Dns提供商Demo',
|
||||
desc: 'dns provider示例',
|
||||
// 这里是对应的云平台的access类型名称
|
||||
accessType: "demo"
|
||||
accessType: 'demo',
|
||||
})
|
||||
export class DemoDnsProvider extends AbstractDnsProvider<DemoRecord> {
|
||||
// 通过Autowire注入工具对象
|
||||
@@ -27,12 +31,11 @@ export class DemoDnsProvider extends AbstractDnsProvider<DemoRecord> {
|
||||
async onInstance() {
|
||||
// 也可以通过ctx成员变量传递context, 与Autowire效果一样
|
||||
this.http = this.ctx.http;
|
||||
this.logger.debug("access", this.access);
|
||||
this.logger.debug('access', this.access);
|
||||
//初始化的操作
|
||||
//...
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建dns解析记录,用于验证域名所有权
|
||||
*/
|
||||
@@ -45,7 +48,7 @@ export class DemoDnsProvider extends AbstractDnsProvider<DemoRecord> {
|
||||
* domain: 'example.com'
|
||||
*/
|
||||
const { fullRecord, value, type, domain } = options;
|
||||
this.logger.info("添加域名解析:", fullRecord, value, type, domain);
|
||||
this.logger.info('添加域名解析:', fullRecord, value, type, domain);
|
||||
|
||||
// 调用创建dns解析记录的对应的云端接口,创建txt类型的dns解析记录
|
||||
// 请根据实际接口情况调用,例如:
|
||||
@@ -64,7 +67,7 @@ export class DemoDnsProvider extends AbstractDnsProvider<DemoRecord> {
|
||||
*/
|
||||
async removeRecord(options: RemoveRecordOptions<DemoRecord>): Promise<void> {
|
||||
const { fullRecord, value, record } = options;
|
||||
this.logger.info("删除域名解析:", fullRecord, value, record);
|
||||
this.logger.info('删除域名解析:', fullRecord, value, record);
|
||||
//这里调用删除txt dns解析记录接口
|
||||
//请根据实际接口情况调用,例如:
|
||||
|
||||
@@ -75,7 +78,7 @@ export class DemoDnsProvider extends AbstractDnsProvider<DemoRecord> {
|
||||
// })
|
||||
//
|
||||
|
||||
this.logger.info("删除域名解析成功:", fullRecord, value);
|
||||
this.logger.info('删除域名解析成功:', fullRecord, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './dns-provider';
|
||||
export * from './plugins';
|
||||
export * from './access';
|
||||
export * from './dns-provider.js';
|
||||
export * from './plugins/index.js';
|
||||
export * from './access.js';
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from './plugin-test';
|
||||
export * from './plugin-test.js';
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from './ssh-access';
|
||||
export * from './ssh-access.js';
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './access';
|
||||
export * from './lib/ssh';
|
||||
export * from './plugin';
|
||||
export * from './access/index.js';
|
||||
export * from './lib/ssh.js';
|
||||
export * from './plugin/index.js';
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
// @ts-ignore
|
||||
import ssh2, { ConnectConfig } from 'ssh2';
|
||||
import path from 'path';
|
||||
import _ from 'lodash';
|
||||
import * as _ from 'lodash-es';
|
||||
import { ILogger } from '@certd/pipeline';
|
||||
import iconv from 'iconv-lite';
|
||||
import {SshAccess} from "../access";
|
||||
import { SshAccess } from '../access/index.js';
|
||||
export class AsyncSsh2Client {
|
||||
conn: ssh2.Client;
|
||||
logger: ILogger;
|
||||
connConf: ssh2.ConnectConfig;
|
||||
windows:boolean = false;
|
||||
encoding:string;
|
||||
windows = false;
|
||||
encoding: string;
|
||||
constructor(connConf: SshAccess, logger: ILogger) {
|
||||
this.connConf = connConf;
|
||||
this.logger = logger;
|
||||
@@ -19,7 +19,7 @@ export class AsyncSsh2Client {
|
||||
}
|
||||
|
||||
convert(buffer: Buffer) {
|
||||
if(this.encoding){
|
||||
if (this.encoding) {
|
||||
return iconv.decode(buffer, this.encoding);
|
||||
}
|
||||
return buffer.toString();
|
||||
@@ -31,6 +31,7 @@ export class AsyncSsh2Client {
|
||||
const conn = new ssh2.Client();
|
||||
conn
|
||||
.on('error', (err: any) => {
|
||||
this.logger.error('连接失败', err);
|
||||
reject(err);
|
||||
})
|
||||
.on('ready', () => {
|
||||
@@ -77,7 +78,7 @@ export class AsyncSsh2Client {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
let data: string = '';
|
||||
let data = '';
|
||||
stream
|
||||
.on('close', (code: any, signal: any) => {
|
||||
this.logger.info(`[${this.connConf.host}][close]:code:${code}`);
|
||||
@@ -88,13 +89,13 @@ export class AsyncSsh2Client {
|
||||
}
|
||||
})
|
||||
.on('data', (ret: Buffer) => {
|
||||
const out = this.convert(ret)
|
||||
data += out
|
||||
const out = this.convert(ret);
|
||||
data += out;
|
||||
this.logger.info(`[${this.connConf.host}][info]: ` + out.trimEnd());
|
||||
})
|
||||
.stderr.on('data', (ret:Buffer) => {
|
||||
const err = this.convert(ret)
|
||||
data += err
|
||||
.stderr.on('data', (ret: Buffer) => {
|
||||
const err = this.convert(ret);
|
||||
data += err;
|
||||
this.logger.info(`[${this.connConf.host}][error]: ` + err.trimEnd());
|
||||
});
|
||||
});
|
||||
@@ -103,9 +104,7 @@ export class AsyncSsh2Client {
|
||||
|
||||
async shell(script: string | string[]): Promise<string[]> {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this.logger.info(
|
||||
`执行shell脚本:[${this.connConf.host}][shell]: ` + script
|
||||
);
|
||||
this.logger.info(`执行shell脚本:[${this.connConf.host}][shell]: ` + script);
|
||||
this.conn.shell((err: Error, stream: any) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
@@ -118,15 +117,15 @@ export class AsyncSsh2Client {
|
||||
resolve(output);
|
||||
})
|
||||
.on('data', (ret: Buffer) => {
|
||||
const data = this.convert(ret)
|
||||
const data = this.convert(ret);
|
||||
this.logger.info('' + data);
|
||||
output.push(data);
|
||||
})
|
||||
.stderr.on('data', (ret:Buffer) => {
|
||||
const data = this.convert(ret)
|
||||
.stderr.on('data', (ret: Buffer) => {
|
||||
const data = this.convert(ret);
|
||||
output.push(data);
|
||||
this.logger.info(`[${this.connConf.host}][error]: ` + data);
|
||||
});
|
||||
});
|
||||
stream.end(script + '\nexit\n');
|
||||
});
|
||||
});
|
||||
@@ -161,15 +160,15 @@ export class SshClient {
|
||||
const sftp = await conn.getSftp();
|
||||
this.logger.info('开始上传');
|
||||
for (const transport of transports) {
|
||||
let filePath = path.dirname(transport.remotePath);
|
||||
const filePath = path.dirname(transport.remotePath);
|
||||
let mkdirCmd = `mkdir -p ${filePath} `;
|
||||
if(conn.windows){
|
||||
if(filePath.indexOf("/") > -1){
|
||||
this.logger.info("--------------------------")
|
||||
this.logger.info("请注意:windows下,文件目录分隔应该写成\\而不是/")
|
||||
this.logger.info("--------------------------")
|
||||
if (conn.windows) {
|
||||
if (filePath.indexOf('/') > -1) {
|
||||
this.logger.info('--------------------------');
|
||||
this.logger.info('请注意:windows下,文件目录分隔应该写成\\而不是/');
|
||||
this.logger.info('--------------------------');
|
||||
}
|
||||
const spec = await conn.exec(`echo %COMSPEC%`);
|
||||
const spec = await conn.exec('echo %COMSPEC%');
|
||||
if (spec.toString().trim() === '%COMSPEC%') {
|
||||
mkdirCmd = `New-Item -ItemType Directory -Path "${filePath}" -Force`;
|
||||
} else {
|
||||
@@ -184,10 +183,7 @@ export class SshClient {
|
||||
});
|
||||
}
|
||||
|
||||
async exec(options: {
|
||||
connectConf: SshAccess;
|
||||
script: string | Array<string>;
|
||||
}) {
|
||||
async exec(options: { connectConf: SshAccess; script: string | Array<string> }) {
|
||||
let { script } = options;
|
||||
const { connectConf } = options;
|
||||
if (_.isArray(script)) {
|
||||
@@ -203,10 +199,7 @@ export class SshClient {
|
||||
});
|
||||
}
|
||||
|
||||
async shell(options: {
|
||||
connectConf: SshAccess;
|
||||
script: string;
|
||||
}): Promise<string[]> {
|
||||
async shell(options: { connectConf: SshAccess; script: string }): Promise<string[]> {
|
||||
const { connectConf, script } = options;
|
||||
return await this._call({
|
||||
connectConf,
|
||||
@@ -216,10 +209,7 @@ export class SshClient {
|
||||
});
|
||||
}
|
||||
|
||||
async _call(options: {
|
||||
connectConf: SshAccess;
|
||||
callable: any;
|
||||
}): Promise<string[]> {
|
||||
async _call(options: { connectConf: SshAccess; callable: any }): Promise<string[]> {
|
||||
const { connectConf, callable } = options;
|
||||
const conn = new AsyncSsh2Client(connectConf, this.logger);
|
||||
await conn.connect();
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
RunStrategy,
|
||||
TaskInput,
|
||||
} from '@certd/pipeline';
|
||||
import { SshClient } from '../../lib/ssh';
|
||||
import { SshClient } from '../../lib/ssh.js';
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: 'hostShellExecute',
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './host-shell-execute';
|
||||
export * from './upload-to-host';
|
||||
export * from './host-shell-execute/index.js';
|
||||
export * from './upload-to-host/index.js';
|
||||
|
||||
@@ -7,10 +7,10 @@ import {
|
||||
TaskInput,
|
||||
TaskOutput,
|
||||
} from '@certd/pipeline';
|
||||
import { SshClient } from '../../lib/ssh';
|
||||
import { SshClient } from '../../lib/ssh.js';
|
||||
import { CertInfo, CertReader } from '@certd/plugin-cert';
|
||||
import * as fs from 'fs';
|
||||
import {SshAccess} from "../../access";
|
||||
import { SshAccess } from '../../access/index.js';
|
||||
|
||||
@IsTaskPlugin({
|
||||
name: 'uploadCertToHost',
|
||||
@@ -113,7 +113,7 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
|
||||
throw new Error('主机登录授权配置不能为空');
|
||||
}
|
||||
this.logger.info('准备上传到服务器');
|
||||
const connectConf:SshAccess = await this.accessService.getById(accessId);
|
||||
const connectConf: SshAccess = await this.accessService.getById(accessId);
|
||||
const sshClient = new SshClient(this.logger);
|
||||
await sshClient.uploadFiles({
|
||||
connectConf,
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from './huawei-access';
|
||||
export * from './huawei-access.js';
|
||||
|
||||
+6
-6
@@ -1,8 +1,8 @@
|
||||
import _ from "lodash";
|
||||
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||
import { Autowire, ILogger } from "@certd/pipeline";
|
||||
import { HuaweiAccess } from "../access";
|
||||
import { ApiRequestOptions, HuaweiYunClient } from "../lib/client";
|
||||
import * as _ from 'lodash-es';
|
||||
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||
import { Autowire, ILogger } from '@certd/pipeline';
|
||||
import { HuaweiAccess } from '../access/index.js';
|
||||
import { ApiRequestOptions, HuaweiYunClient } from '@certd/lib-huawei';
|
||||
|
||||
export type SearchRecordOptions = {
|
||||
zoneId: string;
|
||||
@@ -14,7 +14,7 @@ export type SearchRecordOptions = {
|
||||
desc: '华为云DNS解析提供商',
|
||||
accessType: 'huawei',
|
||||
})
|
||||
export class HuaweiDnsProvider extends AbstractDnsProvider{
|
||||
export class HuaweiDnsProvider extends AbstractDnsProvider {
|
||||
client!: HuaweiYunClient;
|
||||
@Autowire()
|
||||
access!: HuaweiAccess;
|
||||
|
||||
@@ -1 +1 @@
|
||||
import './huawei-dns-provider';
|
||||
import './huawei-dns-provider.js';
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './access';
|
||||
export * from './dns-provider';
|
||||
export * from './access/index.js';
|
||||
export * from './dns-provider/index.js';
|
||||
|
||||
-24
@@ -1,24 +0,0 @@
|
||||
# License
|
||||
|
||||
[The MIT License (MIT)](http://opensource.org/licenses/MIT)
|
||||
|
||||
Copyright (c) 2009-2013 Jeff Mott
|
||||
Copyright (c) 2013-2016 Evan Vosberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
Vendored
-35
@@ -1,35 +0,0 @@
|
||||
var signer = require("./signer");
|
||||
var https = require("https");
|
||||
var sig = new signer.Signer();
|
||||
//Set the AK/SK to sign and authenticate the request.
|
||||
sig.Key = "QTWAOYTTINDUT2QVKYUC";
|
||||
sig.Secret = "MFyfvK41ba2giqM7**********KGpownRZlmVmHc";
|
||||
|
||||
//The following example shows how to set the request URL and parameters to query a VPC list.
|
||||
//Specify a request method, such as GET, PUT, POST, DELETE, HEAD, and PATCH.
|
||||
//Set request host.
|
||||
//Set request URI.
|
||||
//Set parameters for the request URL.
|
||||
var r = new signer.HttpRequest("GET", "endpoint.example.com/v1/77b6a44cba5143ab91d13ab9a8ff44fd/vpcs?limie=1");
|
||||
//Add header parameters, for example, x-domain-id for invoking a global service and x-project-id for invoking a project-level service.
|
||||
r.headers = { "Content-Type": "application/json" };
|
||||
//Add a body if you have specified the PUT or POST method. Special characters, such as the double quotation mark ("), contained in the body must be escaped.
|
||||
r.body = "";
|
||||
|
||||
var opt = sig.Sign(r);
|
||||
console.log(opt.headers["X-Sdk-Date"]);
|
||||
console.log(opt.headers["Authorization"]);
|
||||
|
||||
var req = https.request(opt, function (res) {
|
||||
console.log(res.statusCode);
|
||||
console.log("headers:", JSON.stringify(res.headers));
|
||||
res.on("data", function (chunk) {
|
||||
console.log(chunk.toString());
|
||||
});
|
||||
});
|
||||
|
||||
req.on("error", function (err) {
|
||||
console.log(err.message);
|
||||
});
|
||||
req.write(r.body);
|
||||
req.end();
|
||||
Vendored
-501
@@ -1,501 +0,0 @@
|
||||
// HWS API Gateway Signature
|
||||
(function (root, factory) {
|
||||
"use strict";
|
||||
|
||||
/*global define*/
|
||||
if (typeof define === "function" && define.amd) {
|
||||
// AMD
|
||||
define(["CryptoJS"], function (CryptoJS) {
|
||||
var crypto_wrapper = {
|
||||
hmacsha256: function (keyByte, message) {
|
||||
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
HexEncodeSHA256Hash: function (body) {
|
||||
return CryptoJS.SHA256(body);
|
||||
},
|
||||
};
|
||||
return factory(crypto_wrapper);
|
||||
});
|
||||
} else if (typeof wx === "object") {
|
||||
// wechat
|
||||
var CryptoJS = require("./js/hmac-sha256.js");
|
||||
var crypto_wrapper = {
|
||||
hmacsha256: function (keyByte, message) {
|
||||
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
HexEncodeSHA256Hash: function (body) {
|
||||
return CryptoJS.SHA256(body);
|
||||
},
|
||||
};
|
||||
module.exports = factory(crypto_wrapper);
|
||||
} else if (typeof module === "object" && module.exports) {
|
||||
// Node
|
||||
var crypto = require("crypto");
|
||||
var crypto_wrapper = {
|
||||
hmacsha256: function (keyByte, message) {
|
||||
return crypto.createHmac("SHA256", keyByte).update(message).digest().toString("hex");
|
||||
},
|
||||
HexEncodeSHA256Hash: function (body) {
|
||||
return crypto.createHash("SHA256").update(body).digest().toString("hex");
|
||||
},
|
||||
};
|
||||
module.exports = factory(crypto_wrapper);
|
||||
} else {
|
||||
// Browser
|
||||
var CryptoJS = root.CryptoJS;
|
||||
var crypto_wrapper = {
|
||||
hmacsha256: function (keyByte, message) {
|
||||
return CryptoJS.HmacSHA256(message, keyByte).toString(CryptoJS.enc.Hex);
|
||||
},
|
||||
HexEncodeSHA256Hash: function (body) {
|
||||
return CryptoJS.SHA256(body);
|
||||
},
|
||||
};
|
||||
root.signer = factory(crypto_wrapper);
|
||||
}
|
||||
})(this, function (crypto_wrapper) {
|
||||
"use strict";
|
||||
|
||||
var Algorithm = "SDK-HMAC-SHA256";
|
||||
var HeaderXDate = "X-Sdk-Date";
|
||||
var HeaderAuthorization = "Authorization";
|
||||
var HeaderContentSha256 = "x-sdk-content-sha256";
|
||||
|
||||
const hexTable = new Array(256);
|
||||
for (var i = 0; i < 256; ++i) hexTable[i] = "%" + ((i < 16 ? "0" : "") + i.toString(16)).toUpperCase();
|
||||
|
||||
const noEscape = [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 0 - 15
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 16 - 31
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0, // 32 - 47
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 48 - 63
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 64 - 79
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1, // 80 - 95
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 96 - 111
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0, // 112 - 127
|
||||
];
|
||||
|
||||
// function urlEncode is based on https://github.com/nodejs/node/blob/master/lib/querystring.js
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
function urlEncode(str) {
|
||||
if (typeof str !== "string") {
|
||||
if (typeof str === "object") str = String(str);
|
||||
else str += "";
|
||||
}
|
||||
var out = "";
|
||||
var lastPos = 0;
|
||||
|
||||
for (var i = 0; i < str.length; ++i) {
|
||||
var c = str.charCodeAt(i);
|
||||
|
||||
// ASCII
|
||||
if (c < 0x80) {
|
||||
if (noEscape[c] === 1) continue;
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
out += hexTable[c];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
|
||||
// Multi-byte characters ...
|
||||
if (c < 0x800) {
|
||||
lastPos = i + 1;
|
||||
out += hexTable[0xc0 | (c >> 6)] + hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
if (c < 0xd800 || c >= 0xe000) {
|
||||
lastPos = i + 1;
|
||||
out += hexTable[0xe0 | (c >> 12)] + hexTable[0x80 | ((c >> 6) & 0x3f)] + hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
// Surrogate pair
|
||||
++i;
|
||||
|
||||
if (i >= str.length) throw new errors.URIError("ERR_INVALID_URI");
|
||||
|
||||
var c2 = str.charCodeAt(i) & 0x3ff;
|
||||
|
||||
lastPos = i + 1;
|
||||
c = 0x10000 + (((c & 0x3ff) << 10) | c2);
|
||||
out += hexTable[0xf0 | (c >> 18)] + hexTable[0x80 | ((c >> 12) & 0x3f)] + hexTable[0x80 | ((c >> 6) & 0x3f)] + hexTable[0x80 | (c & 0x3f)];
|
||||
}
|
||||
if (lastPos === 0) return str;
|
||||
if (lastPos < str.length) return out + str.slice(lastPos);
|
||||
return out;
|
||||
}
|
||||
|
||||
function HttpRequest(method, url, headers, body) {
|
||||
if (method === undefined) {
|
||||
this.method = "";
|
||||
} else {
|
||||
this.method = method;
|
||||
}
|
||||
if (url === undefined) {
|
||||
this.host = "";
|
||||
this.uri = "";
|
||||
this.query = {};
|
||||
} else {
|
||||
this.query = {};
|
||||
var host, path;
|
||||
var i = url.indexOf("://");
|
||||
if (i !== -1) {
|
||||
url = url.substr(i + 3);
|
||||
}
|
||||
var i = url.indexOf("?");
|
||||
if (i !== -1) {
|
||||
var query_str = url.substr(i + 1);
|
||||
url = url.substr(0, i);
|
||||
var spl = query_str.split("&");
|
||||
for (var i in spl) {
|
||||
var kv = spl[i];
|
||||
var index = kv.indexOf("=");
|
||||
var key, value;
|
||||
if (index >= 0) {
|
||||
key = kv.substr(0, index);
|
||||
value = kv.substr(index + 1);
|
||||
} else {
|
||||
key = kv;
|
||||
value = "";
|
||||
}
|
||||
if (key !== "") {
|
||||
key = decodeURI(key);
|
||||
value = decodeURI(value);
|
||||
if (this.query[key] === undefined) {
|
||||
this.query[key] = [value];
|
||||
} else {
|
||||
this.query[key].push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var i = url.indexOf("/");
|
||||
if (i === -1) {
|
||||
host = url;
|
||||
path = "/";
|
||||
} else {
|
||||
host = url.substr(0, i);
|
||||
path = url.substr(i);
|
||||
}
|
||||
this.host = host;
|
||||
this.uri = decodeURI(path);
|
||||
}
|
||||
if (headers === undefined) {
|
||||
this.headers = {};
|
||||
} else {
|
||||
this.headers = headers;
|
||||
}
|
||||
if (body === undefined) {
|
||||
this.body = "";
|
||||
} else {
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
|
||||
function findHeader(r, header) {
|
||||
for (var k in r.headers) {
|
||||
if (k.toLowerCase() === header.toLowerCase()) {
|
||||
return r.headers[k];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Build a CanonicalRequest from a regular request string
|
||||
//
|
||||
// CanonicalRequest =
|
||||
// HTTPRequestMethod + '\n' +
|
||||
// CanonicalURI + '\n' +
|
||||
// CanonicalQueryString + '\n' +
|
||||
// CanonicalHeaders + '\n' +
|
||||
// SignedHeaders + '\n' +
|
||||
// HexEncode(Hash(RequestPayload))
|
||||
function CanonicalRequest(r, signedHeaders) {
|
||||
var hexencode = findHeader(r, HeaderContentSha256);
|
||||
if (hexencode === null) {
|
||||
var data = RequestPayload(r);
|
||||
hexencode = crypto_wrapper.HexEncodeSHA256Hash(data);
|
||||
}
|
||||
return (
|
||||
r.method +
|
||||
"\n" +
|
||||
CanonicalURI(r) +
|
||||
"\n" +
|
||||
CanonicalQueryString(r) +
|
||||
"\n" +
|
||||
CanonicalHeaders(r, signedHeaders) +
|
||||
"\n" +
|
||||
signedHeaders.join(";") +
|
||||
"\n" +
|
||||
hexencode
|
||||
);
|
||||
}
|
||||
|
||||
function CanonicalURI(r) {
|
||||
var pattens = r.uri.split("/");
|
||||
var uri = [];
|
||||
for (var k in pattens) {
|
||||
var v = pattens[k];
|
||||
uri.push(urlEncode(v));
|
||||
}
|
||||
var urlpath = uri.join("/");
|
||||
if (urlpath[urlpath.length - 1] !== "/") {
|
||||
urlpath = urlpath + "/";
|
||||
}
|
||||
//r.uri = urlpath
|
||||
return urlpath;
|
||||
}
|
||||
|
||||
function CanonicalQueryString(r) {
|
||||
var keys = [];
|
||||
for (var key in r.query) {
|
||||
keys.push(key);
|
||||
}
|
||||
keys.sort();
|
||||
var a = [];
|
||||
for (var i in keys) {
|
||||
var key = urlEncode(keys[i]);
|
||||
var value = r.query[keys[i]];
|
||||
if (Array.isArray(value)) {
|
||||
value.sort();
|
||||
for (var iv in value) {
|
||||
a.push(key + "=" + urlEncode(value[iv]));
|
||||
}
|
||||
} else {
|
||||
a.push(key + "=" + urlEncode(value));
|
||||
}
|
||||
}
|
||||
return a.join("&");
|
||||
}
|
||||
|
||||
function CanonicalHeaders(r, signedHeaders) {
|
||||
var headers = {};
|
||||
for (var key in r.headers) {
|
||||
headers[key.toLowerCase()] = r.headers[key];
|
||||
}
|
||||
var a = [];
|
||||
for (var i in signedHeaders) {
|
||||
var value = headers[signedHeaders[i]];
|
||||
a.push(signedHeaders[i] + ":" + value.trim());
|
||||
}
|
||||
return a.join("\n") + "\n";
|
||||
}
|
||||
|
||||
function SignedHeaders(r) {
|
||||
var a = [];
|
||||
for (var key in r.headers) {
|
||||
a.push(key.toLowerCase());
|
||||
}
|
||||
a.sort();
|
||||
return a;
|
||||
}
|
||||
|
||||
function RequestPayload(r) {
|
||||
return r.body;
|
||||
}
|
||||
|
||||
// Create a "String to Sign".
|
||||
function StringToSign(canonicalRequest, t) {
|
||||
var bytes = crypto_wrapper.HexEncodeSHA256Hash(canonicalRequest);
|
||||
return Algorithm + "\n" + t + "\n" + bytes;
|
||||
}
|
||||
|
||||
// Create the HWS Signature.
|
||||
function SignStringToSign(stringToSign, signingKey) {
|
||||
return crypto_wrapper.hmacsha256(signingKey, stringToSign);
|
||||
}
|
||||
|
||||
// Get the finalized value for the "Authorization" header. The signature
|
||||
// parameter is the output from SignStringToSign
|
||||
function AuthHeaderValue(signature, Key, signedHeaders) {
|
||||
return Algorithm + " Access=" + Key + ", SignedHeaders=" + signedHeaders.join(";") + ", Signature=" + signature;
|
||||
}
|
||||
|
||||
function twoChar(s) {
|
||||
if (s >= 10) {
|
||||
return "" + s;
|
||||
} else {
|
||||
return "0" + s;
|
||||
}
|
||||
}
|
||||
|
||||
function getTime() {
|
||||
var date = new Date();
|
||||
return (
|
||||
"" +
|
||||
date.getUTCFullYear() +
|
||||
twoChar(date.getUTCMonth() + 1) +
|
||||
twoChar(date.getUTCDate()) +
|
||||
"T" +
|
||||
twoChar(date.getUTCHours()) +
|
||||
twoChar(date.getUTCMinutes()) +
|
||||
twoChar(date.getUTCSeconds()) +
|
||||
"Z"
|
||||
);
|
||||
}
|
||||
|
||||
function Signer() {
|
||||
this.Key = "";
|
||||
this.Secret = "";
|
||||
}
|
||||
|
||||
Signer.prototype.Sign = function (r) {
|
||||
var headerTime = findHeader(r, HeaderXDate);
|
||||
if (headerTime === null) {
|
||||
headerTime = getTime();
|
||||
r.headers[HeaderXDate] = headerTime;
|
||||
}
|
||||
if (r.method !== "PUT" && r.method !== "PATCH" && r.method !== "POST") {
|
||||
r.body = "";
|
||||
}
|
||||
var queryString = CanonicalQueryString(r);
|
||||
if (queryString !== "") {
|
||||
queryString = "?" + queryString;
|
||||
}
|
||||
var options = {
|
||||
hostname: r.host,
|
||||
path: encodeURI(r.uri) + queryString,
|
||||
method: r.method,
|
||||
headers: r.headers,
|
||||
};
|
||||
if (findHeader(r, "host") === null) {
|
||||
r.headers.host = r.host;
|
||||
}
|
||||
var signedHeaders = SignedHeaders(r);
|
||||
var canonicalRequest = CanonicalRequest(r, signedHeaders);
|
||||
var stringToSign = StringToSign(canonicalRequest, headerTime);
|
||||
var signature = SignStringToSign(stringToSign, this.Secret);
|
||||
options.headers[HeaderAuthorization] = AuthHeaderValue(signature, this.Key, signedHeaders);
|
||||
return options;
|
||||
};
|
||||
return {
|
||||
HttpRequest: HttpRequest,
|
||||
Signer: Signer,
|
||||
urlEncode: urlEncode,
|
||||
findHeader: findHeader,
|
||||
SignedHeaders: SignedHeaders,
|
||||
CanonicalRequest: CanonicalRequest,
|
||||
StringToSign: StringToSign,
|
||||
};
|
||||
});
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
var assert = require("assert");
|
||||
var signer = require('./signer')
|
||||
|
||||
var s = ""
|
||||
for (i = 0; i < 0x80; i++) {
|
||||
s = s + signer.urlEncode(String.fromCharCode(i))
|
||||
}
|
||||
console.log(s)
|
||||
assert.equal(s, "%00%01%02%03%04%05%06%07%08%09%0A%0B%0C%0D%0E%0F%10%11%12%13%14%15%16%17%18%19%1A%1B%1C%1D%1E%1F%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%7F")
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import { Signer, SigHttpRequest } from './signer';
|
||||
import { HuaweiAccess } from '../access';
|
||||
import axios from 'axios';
|
||||
import { logger } from '@certd/pipeline';
|
||||
|
||||
export type ApiRequestOptions = {
|
||||
method: string;
|
||||
url: string;
|
||||
headers?: any;
|
||||
data?: any;
|
||||
};
|
||||
export class HuaweiYunClient {
|
||||
access: HuaweiAccess;
|
||||
constructor(access: HuaweiAccess) {
|
||||
this.access = access;
|
||||
}
|
||||
async request(options: ApiRequestOptions) {
|
||||
const sig = new Signer(
|
||||
this.access.accessKeyId,
|
||||
this.access.accessKeySecret
|
||||
);
|
||||
|
||||
//The following example shows how to set the request URL and parameters to query a VPC list.
|
||||
//Specify a request method, such as GET, PUT, POST, DELETE, HEAD, and PATCH.
|
||||
//Set request host.
|
||||
//Set request URI.
|
||||
//Set parameters for the request URL.
|
||||
let body = undefined;
|
||||
if (options.data) {
|
||||
body = JSON.stringify(options.data);
|
||||
}
|
||||
const r = new SigHttpRequest(
|
||||
options.method,
|
||||
options.url,
|
||||
options.headers,
|
||||
body
|
||||
);
|
||||
//Add header parameters, for example, x-domain-id for invoking a global service and x-project-id for invoking a project-level service.
|
||||
r.headers = { 'Content-Type': 'application/json' };
|
||||
//Add a body if you have specified the PUT or POST method. Special characters, such as the double quotation mark ("), contained in the body must be escaped.
|
||||
// r.body = option;
|
||||
const opt = sig.Sign(r);
|
||||
try {
|
||||
const res = await axios.request({
|
||||
url: options.url,
|
||||
method: options.method,
|
||||
headers: opt.headers,
|
||||
data: body,
|
||||
});
|
||||
return res.data;
|
||||
} catch (e: any) {
|
||||
logger.error('华为云接口请求出错:', e?.response?.data);
|
||||
const error: any = new Error(e?.response?.data.message);
|
||||
error.code = e?.response?.code;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,476 +0,0 @@
|
||||
import crypto from 'crypto';
|
||||
function hmacsha256(keyByte: any, message: any) {
|
||||
return crypto
|
||||
.createHmac('SHA256', keyByte)
|
||||
.update(message)
|
||||
.digest()
|
||||
.toString('hex');
|
||||
}
|
||||
function HexEncodeSHA256Hash(body: any) {
|
||||
return crypto.createHash('SHA256').update(body).digest().toString('hex');
|
||||
}
|
||||
const Algorithm = 'SDK-HMAC-SHA256';
|
||||
const HeaderXDate = 'X-Sdk-Date';
|
||||
const HeaderAuthorization = 'Authorization';
|
||||
const HeaderContentSha256 = 'x-sdk-content-sha256';
|
||||
|
||||
const hexTable = new Array(256);
|
||||
for (let i = 0; i < 256; ++i)
|
||||
hexTable[i] = '%' + ((i < 16 ? '0' : '') + i.toString(16)).toUpperCase();
|
||||
|
||||
const noEscape = [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 0 - 15
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 16 - 31
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0, // 32 - 47
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, // 48 - 63
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 64 - 79
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1, // 80 - 95
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1, // 96 - 111
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0, // 112 - 127
|
||||
];
|
||||
|
||||
// function urlEncode is based on https://github.com/nodejs/node/blob/master/lib/querystring.js
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
function urlEncode(str: any) {
|
||||
if (typeof str !== 'string') {
|
||||
if (typeof str === 'object') str = String(str);
|
||||
else str += '';
|
||||
}
|
||||
let out = '';
|
||||
let lastPos = 0;
|
||||
|
||||
for (let i = 0; i < str.length; ++i) {
|
||||
let c = str.charCodeAt(i);
|
||||
|
||||
// ASCII
|
||||
if (c < 0x80) {
|
||||
if (noEscape[c] === 1) continue;
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
lastPos = i + 1;
|
||||
out += hexTable[c];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lastPos < i) out += str.slice(lastPos, i);
|
||||
|
||||
// Multi-byte characters ...
|
||||
if (c < 0x800) {
|
||||
lastPos = i + 1;
|
||||
out += hexTable[0xc0 | (c >> 6)] + hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
if (c < 0xd800 || c >= 0xe000) {
|
||||
lastPos = i + 1;
|
||||
out +=
|
||||
hexTable[0xe0 | (c >> 12)] +
|
||||
hexTable[0x80 | ((c >> 6) & 0x3f)] +
|
||||
hexTable[0x80 | (c & 0x3f)];
|
||||
continue;
|
||||
}
|
||||
// Surrogate pair
|
||||
++i;
|
||||
|
||||
if (i >= str.length) throw new Error('ERR_INVALID_URI');
|
||||
|
||||
const c2 = str.charCodeAt(i) & 0x3ff;
|
||||
|
||||
lastPos = i + 1;
|
||||
c = 0x10000 + (((c & 0x3ff) << 10) | c2);
|
||||
out +=
|
||||
hexTable[0xf0 | (c >> 18)] +
|
||||
hexTable[0x80 | ((c >> 12) & 0x3f)] +
|
||||
hexTable[0x80 | ((c >> 6) & 0x3f)] +
|
||||
hexTable[0x80 | (c & 0x3f)];
|
||||
}
|
||||
if (lastPos === 0) return str;
|
||||
if (lastPos < str.length) return out + str.slice(lastPos);
|
||||
return out;
|
||||
}
|
||||
|
||||
function findHeader(r: any, header: any) {
|
||||
for (const k in r.headers) {
|
||||
if (k.toLowerCase() === header.toLowerCase()) {
|
||||
return r.headers[k];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Build a CanonicalRequest from a regular request string
|
||||
//
|
||||
// CanonicalRequest =
|
||||
// HTTPRequestMethod + '\n' +
|
||||
// CanonicalURI + '\n' +
|
||||
// CanonicalQueryString + '\n' +
|
||||
// CanonicalHeaders + '\n' +
|
||||
// SignedHeaders + '\n' +
|
||||
// HexEncode(Hash(RequestPayload))
|
||||
function CanonicalRequest(r: any, signedHeaders: any) {
|
||||
let hexencode = findHeader(r, HeaderContentSha256);
|
||||
if (hexencode === null) {
|
||||
const data = RequestPayload(r);
|
||||
hexencode = HexEncodeSHA256Hash(data);
|
||||
}
|
||||
return (
|
||||
r.method +
|
||||
'\n' +
|
||||
CanonicalURI(r) +
|
||||
'\n' +
|
||||
CanonicalQueryString(r) +
|
||||
'\n' +
|
||||
CanonicalHeaders(r, signedHeaders) +
|
||||
'\n' +
|
||||
signedHeaders.join(';') +
|
||||
'\n' +
|
||||
hexencode
|
||||
);
|
||||
}
|
||||
|
||||
function CanonicalURI(r: any) {
|
||||
const pattens = r.uri.split('/');
|
||||
const uri = [];
|
||||
for (const k in pattens) {
|
||||
const v = pattens[k];
|
||||
uri.push(urlEncode(v));
|
||||
}
|
||||
let urlpath = uri.join('/');
|
||||
if (urlpath[urlpath.length - 1] !== '/') {
|
||||
urlpath = urlpath + '/';
|
||||
}
|
||||
//r.uri = urlpath
|
||||
return urlpath;
|
||||
}
|
||||
|
||||
function CanonicalQueryString(r: any) {
|
||||
const keys = [];
|
||||
for (const key in r.query) {
|
||||
keys.push(key);
|
||||
}
|
||||
keys.sort();
|
||||
const a = [];
|
||||
for (const i in keys) {
|
||||
const key = urlEncode(keys[i]);
|
||||
const value = r.query[keys[i]];
|
||||
if (Array.isArray(value)) {
|
||||
value.sort();
|
||||
for (const iv in value) {
|
||||
a.push(key + '=' + urlEncode(value[iv]));
|
||||
}
|
||||
} else {
|
||||
a.push(key + '=' + urlEncode(value));
|
||||
}
|
||||
}
|
||||
return a.join('&');
|
||||
}
|
||||
|
||||
function CanonicalHeaders(r: any, signedHeaders: any) {
|
||||
const headers: any = {};
|
||||
for (const key in r.headers) {
|
||||
headers[key.toLowerCase()] = r.headers[key];
|
||||
}
|
||||
const a = [];
|
||||
for (const i in signedHeaders) {
|
||||
const value = headers[signedHeaders[i]];
|
||||
a.push(signedHeaders[i] + ':' + value.trim());
|
||||
}
|
||||
return a.join('\n') + '\n';
|
||||
}
|
||||
|
||||
function SignedHeaders(r: any) {
|
||||
const a = [];
|
||||
for (const key in r.headers) {
|
||||
a.push(key.toLowerCase());
|
||||
}
|
||||
a.sort();
|
||||
return a;
|
||||
}
|
||||
|
||||
function RequestPayload(r: any) {
|
||||
return r.body;
|
||||
}
|
||||
|
||||
// Create a "String to Sign".
|
||||
function StringToSign(canonicalRequest: any, t: any) {
|
||||
const bytes = HexEncodeSHA256Hash(canonicalRequest);
|
||||
return Algorithm + '\n' + t + '\n' + bytes;
|
||||
}
|
||||
|
||||
// Create the HWS Signature.
|
||||
function SignStringToSign(stringToSign: any, signingKey: any) {
|
||||
return hmacsha256(signingKey, stringToSign);
|
||||
}
|
||||
|
||||
// Get the finalized value for the "Authorization" header. The signature
|
||||
// parameter is the output from SignStringToSign
|
||||
function AuthHeaderValue(signature: any, Key: any, signedHeaders: any) {
|
||||
return (
|
||||
Algorithm +
|
||||
' Access=' +
|
||||
Key +
|
||||
', SignedHeaders=' +
|
||||
signedHeaders.join(';') +
|
||||
', Signature=' +
|
||||
signature
|
||||
);
|
||||
}
|
||||
|
||||
function twoChar(s: any) {
|
||||
if (s >= 10) {
|
||||
return '' + s;
|
||||
} else {
|
||||
return '0' + s;
|
||||
}
|
||||
}
|
||||
|
||||
function getTime() {
|
||||
const date = new Date();
|
||||
return (
|
||||
'' +
|
||||
date.getUTCFullYear() +
|
||||
twoChar(date.getUTCMonth() + 1) +
|
||||
twoChar(date.getUTCDate()) +
|
||||
'T' +
|
||||
twoChar(date.getUTCHours()) +
|
||||
twoChar(date.getUTCMinutes()) +
|
||||
twoChar(date.getUTCSeconds()) +
|
||||
'Z'
|
||||
);
|
||||
}
|
||||
|
||||
export class SigHttpRequest {
|
||||
method = '';
|
||||
host = '';
|
||||
uri = '';
|
||||
query: any = {};
|
||||
headers: any = {};
|
||||
body = '';
|
||||
|
||||
constructor(method: any, url: any, headers: any, body: any) {
|
||||
if (method === undefined) {
|
||||
this.method = '';
|
||||
} else {
|
||||
this.method = method;
|
||||
}
|
||||
if (url === undefined) {
|
||||
this.host = '';
|
||||
this.uri = '';
|
||||
this.query = {};
|
||||
} else {
|
||||
this.query = {};
|
||||
let host, path;
|
||||
let i = url.indexOf('://');
|
||||
if (i !== -1) {
|
||||
url = url.substr(i + 3);
|
||||
}
|
||||
i = url.indexOf('?');
|
||||
if (i !== -1) {
|
||||
const query_str = url.substr(i + 1);
|
||||
url = url.substr(0, i);
|
||||
const spl = query_str.split('&');
|
||||
for (const i in spl) {
|
||||
const kv = spl[i];
|
||||
const index = kv.indexOf('=');
|
||||
let key, value;
|
||||
if (index >= 0) {
|
||||
key = kv.substr(0, index);
|
||||
value = kv.substr(index + 1);
|
||||
} else {
|
||||
key = kv;
|
||||
value = '';
|
||||
}
|
||||
if (key !== '') {
|
||||
key = decodeURI(key);
|
||||
value = decodeURI(value);
|
||||
if (this.query[key] === undefined) {
|
||||
this.query[key] = [value];
|
||||
} else {
|
||||
this.query[key].push(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i = url.indexOf('/');
|
||||
if (i === -1) {
|
||||
host = url;
|
||||
path = '/';
|
||||
} else {
|
||||
host = url.substr(0, i);
|
||||
path = url.substr(i);
|
||||
}
|
||||
this.host = host;
|
||||
this.uri = decodeURI(path);
|
||||
}
|
||||
if (headers === undefined) {
|
||||
this.headers = {};
|
||||
} else {
|
||||
this.headers = headers;
|
||||
}
|
||||
if (body === undefined) {
|
||||
this.body = '';
|
||||
} else {
|
||||
this.body = body;
|
||||
}
|
||||
}
|
||||
}
|
||||
export class Signer {
|
||||
Key = '';
|
||||
Secret = '';
|
||||
constructor(Key: any, Secret: any) {
|
||||
this.Key = Key;
|
||||
this.Secret = Secret;
|
||||
}
|
||||
|
||||
Sign(r: any) {
|
||||
let headerTime = findHeader(r, HeaderXDate);
|
||||
if (headerTime === null) {
|
||||
headerTime = getTime();
|
||||
r.headers[HeaderXDate] = headerTime;
|
||||
}
|
||||
if (r.method !== 'PUT' && r.method !== 'PATCH' && r.method !== 'POST') {
|
||||
r.body = '';
|
||||
}
|
||||
let queryString = CanonicalQueryString(r);
|
||||
if (queryString !== '') {
|
||||
queryString = '?' + queryString;
|
||||
}
|
||||
const options = {
|
||||
hostname: r.host,
|
||||
path: encodeURI(r.uri) + queryString,
|
||||
method: r.method,
|
||||
headers: r.headers,
|
||||
};
|
||||
if (findHeader(r, 'host') === null) {
|
||||
r.headers.host = r.host;
|
||||
}
|
||||
const signedHeaders = SignedHeaders(r);
|
||||
const canonicalRequest = CanonicalRequest(r, signedHeaders);
|
||||
const stringToSign = StringToSign(canonicalRequest, headerTime);
|
||||
const signature = SignStringToSign(stringToSign, this.Secret);
|
||||
options.headers[HeaderAuthorization] = AuthHeaderValue(
|
||||
signature,
|
||||
this.Key,
|
||||
signedHeaders
|
||||
);
|
||||
return options;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
export * from './dnspod-access';
|
||||
export * from './tencent-access';
|
||||
export * from './dnspod-access.js';
|
||||
export * from './tencent-access.js';
|
||||
|
||||
+2
-2
@@ -5,8 +5,8 @@ import {
|
||||
IsDnsProvider,
|
||||
RemoveRecordOptions,
|
||||
} from '@certd/plugin-cert';
|
||||
import _ from 'lodash';
|
||||
import { DnspodAccess } from '../access';
|
||||
import * as _ from 'lodash-es';
|
||||
import { DnspodAccess } from '../access/index.js';
|
||||
|
||||
@IsDnsProvider({
|
||||
name: 'dnspod',
|
||||
|
||||
@@ -1 +1 @@
|
||||
import './dnspod-dns-provider';
|
||||
import './dnspod-dns-provider.js';
|
||||
|
||||
+5
-8
@@ -5,9 +5,8 @@ import {
|
||||
IsDnsProvider,
|
||||
RemoveRecordOptions,
|
||||
} from '@certd/plugin-cert';
|
||||
import { TencentAccess } from '../access';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs/index';
|
||||
import TencentCloudSDKHttpException from 'tencentcloud-sdk-nodejs/tencentcloud/common/exception/tencent_cloud_sdk_exception';
|
||||
import { TencentAccess } from '../access/index.js';
|
||||
import * as tencentcloud from 'tencentcloud-sdk-nodejs';
|
||||
|
||||
const DnspodClient = tencentcloud.dnspod.v20210323.Client;
|
||||
@IsDnsProvider({
|
||||
@@ -73,11 +72,9 @@ export class TencentDnsProvider extends AbstractDnsProvider {
|
||||
*/
|
||||
return ret;
|
||||
} catch (e: any) {
|
||||
if (e instanceof TencentCloudSDKHttpException) {
|
||||
if (e.code === 'InvalidParameter.DomainRecordExist') {
|
||||
this.logger.info('域名解析已存在,无需重复添加:', fullRecord, value);
|
||||
return {};
|
||||
}
|
||||
if (e?.code === 'InvalidParameter.DomainRecordExist') {
|
||||
this.logger.info('域名解析已存在,无需重复添加:', fullRecord, value);
|
||||
return {};
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export * from './access';
|
||||
export * from './plugin';
|
||||
export * from './dns-provider';
|
||||
export * from './access/index.js';
|
||||
export * from './plugin/index.js';
|
||||
export * from './dns-provider/index.js';
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
RunStrategy,
|
||||
TaskInput,
|
||||
} from '@certd/pipeline';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs/index';
|
||||
import { TencentAccess } from '../../access';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs';
|
||||
import { TencentAccess } from '../../access/index.js';
|
||||
import { CertInfo } from '@certd/plugin-cert';
|
||||
|
||||
@IsTaskPlugin({
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
TaskInput,
|
||||
utils,
|
||||
} from '@certd/pipeline';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs/index';
|
||||
import { TencentAccess } from '../../access';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs';
|
||||
import { TencentAccess } from '../../access/index.js';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
@IsTaskPlugin({
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ import {
|
||||
TaskInput,
|
||||
utils,
|
||||
} from '@certd/pipeline';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs/index';
|
||||
import { K8sClient } from '@certd/plugin-util';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs';
|
||||
import { K8sClient } from '@certd/lib-k8s';
|
||||
import dayjs from 'dayjs';
|
||||
import { Logger } from 'log4js';
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from './deploy-to-clb';
|
||||
export * from './deploy-to-tke-ingress';
|
||||
export * from './deploy-to-cdn';
|
||||
export * from './upload-to-tencent';
|
||||
export * from './deploy-to-clb/index.js';
|
||||
export * from './deploy-to-tke-ingress/index.js';
|
||||
export * from './deploy-to-cdn/index.js';
|
||||
export * from './upload-to-tencent/index.js';
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import {
|
||||
TaskInput,
|
||||
TaskOutput,
|
||||
} from '@certd/pipeline';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs/index';
|
||||
import tencentcloud from 'tencentcloud-sdk-nodejs';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
@IsTaskPlugin({
|
||||
|
||||
Reference in New Issue
Block a user