mirror of https://github.com/certd/certd
				
				
				
			Merge branch 'v2' into v2-dev
						commit
						7c5166c8bb
					
				| 
						 | 
				
			
			@ -10,3 +10,5 @@ export * from './plugin-west/index.js';
 | 
			
		|||
export * from './plugin-doge/index.js';
 | 
			
		||||
export * from './plugin-qiniu/index.js';
 | 
			
		||||
export * from './plugin-woai/index.js';
 | 
			
		||||
export * from './plugin-cachefly/index.js';
 | 
			
		||||
export * from './plugin-gcore/index.js';
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline';
 | 
			
		||||
 | 
			
		||||
@IsAccess({
 | 
			
		||||
  name: 'CacheFly',
 | 
			
		||||
  title: 'CacheFly',
 | 
			
		||||
  desc: 'CacheFly',
 | 
			
		||||
})
 | 
			
		||||
export class CacheflyAccess extends BaseAccess {
 | 
			
		||||
  @AccessInput({
 | 
			
		||||
    title: 'username',
 | 
			
		||||
    component: {
 | 
			
		||||
      placeholder: 'username',
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
  })
 | 
			
		||||
  username = '';
 | 
			
		||||
  @AccessInput({
 | 
			
		||||
    title: 'password',
 | 
			
		||||
    component: {
 | 
			
		||||
      placeholder: 'password',
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
    encrypt: true,
 | 
			
		||||
  })
 | 
			
		||||
  password = '';
 | 
			
		||||
  @AccessInput({
 | 
			
		||||
    title: 'totp key',
 | 
			
		||||
    component: {
 | 
			
		||||
      placeholder: 'totp key',
 | 
			
		||||
    },
 | 
			
		||||
    encrypt: true,
 | 
			
		||||
  })
 | 
			
		||||
  otpkey = '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
new CacheflyAccess();
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
export * from './plugins/index.js';
 | 
			
		||||
export * from './access.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
export * from './plugin-deploy-to-cdn.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,93 @@
 | 
			
		|||
import { AbstractTaskPlugin, HttpClient, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
 | 
			
		||||
import { CertInfo } from '@certd/plugin-cert';
 | 
			
		||||
import { CacheflyAccess } from '../access.js';
 | 
			
		||||
 | 
			
		||||
@IsTaskPlugin({
 | 
			
		||||
  name: 'CacheFly',
 | 
			
		||||
  title: '部署证书到 CacheFly',
 | 
			
		||||
  desc: '部署证书到 CacheFly',
 | 
			
		||||
  icon: 'clarity:plugin-line',
 | 
			
		||||
  group: pluginGroups.cdn.key,
 | 
			
		||||
  default: {
 | 
			
		||||
    strategy: {
 | 
			
		||||
      runStrategy: RunStrategy.SkipWhenSucceed,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
export class CacheFlyPlugin extends AbstractTaskPlugin {
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: '域名证书',
 | 
			
		||||
    helper: '请选择前置任务输出的域名证书',
 | 
			
		||||
    component: {
 | 
			
		||||
      name: 'output-selector',
 | 
			
		||||
      from: ['CertApply', 'CertApplyLego'],
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
  })
 | 
			
		||||
  cert!: CertInfo;
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: 'Access授权',
 | 
			
		||||
    helper: 'CacheFly 的授权',
 | 
			
		||||
    component: {
 | 
			
		||||
      name: 'access-selector',
 | 
			
		||||
      type: 'CacheFly',
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
  })
 | 
			
		||||
  accessId!: string;
 | 
			
		||||
  http!: HttpClient;
 | 
			
		||||
  private readonly baseApi = 'https://api.cachefly.com';
 | 
			
		||||
 | 
			
		||||
  async onInstance() {
 | 
			
		||||
    this.http = this.ctx.http;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) {
 | 
			
		||||
    const headers = {
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
      ...(token ? { 'x-cf-authorization': `Bearer ${token}` } : {}),
 | 
			
		||||
    };
 | 
			
		||||
    const res = await this.http.request<any, any>({
 | 
			
		||||
      url,
 | 
			
		||||
      method,
 | 
			
		||||
      data,
 | 
			
		||||
      headers,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async execute(): Promise<void> {
 | 
			
		||||
    const { cert, accessId } = this;
 | 
			
		||||
    const access = (await this.accessService.getById(accessId)) as CacheflyAccess;
 | 
			
		||||
    let otp = null;
 | 
			
		||||
    if (access.otpkey) {
 | 
			
		||||
      const response = await this.http.request<any, any>({
 | 
			
		||||
        url: `https://cn-api.my-api.cn/api/totp/?key=${access.otpkey}`,
 | 
			
		||||
        method: 'get',
 | 
			
		||||
      });
 | 
			
		||||
      otp = response;
 | 
			
		||||
      this.logger.info('获取到otp:', otp);
 | 
			
		||||
    }
 | 
			
		||||
    const loginResponse = await this.doRequestApi(`${this.baseApi}/api/2.6/auth/login`, {
 | 
			
		||||
      username: access.username,
 | 
			
		||||
      password: access.password,
 | 
			
		||||
      ...(otp && { otp }),
 | 
			
		||||
    });
 | 
			
		||||
    const token = loginResponse.token;
 | 
			
		||||
    this.logger.info('Token 获取成功');
 | 
			
		||||
    // 更新证书
 | 
			
		||||
    await this.doRequestApi(
 | 
			
		||||
      `${this.baseApi}/api/2.6/certificates`,
 | 
			
		||||
      {
 | 
			
		||||
        certificate: cert.crt,
 | 
			
		||||
        certificateKey: cert.key,
 | 
			
		||||
      },
 | 
			
		||||
      'post',
 | 
			
		||||
      token
 | 
			
		||||
    );
 | 
			
		||||
    this.logger.info('证书更新成功');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
new CacheFlyPlugin();
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
import { AccessInput, BaseAccess, IsAccess } from '@certd/pipeline';
 | 
			
		||||
 | 
			
		||||
@IsAccess({
 | 
			
		||||
  name: 'Gcore',
 | 
			
		||||
  title: 'Gcore',
 | 
			
		||||
  desc: 'Gcore',
 | 
			
		||||
})
 | 
			
		||||
export class GcoreAccess extends BaseAccess {
 | 
			
		||||
  @AccessInput({
 | 
			
		||||
    title: 'username',
 | 
			
		||||
    component: {
 | 
			
		||||
      placeholder: 'username',
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
  })
 | 
			
		||||
  username = '';
 | 
			
		||||
  @AccessInput({
 | 
			
		||||
    title: 'password',
 | 
			
		||||
    component: {
 | 
			
		||||
      placeholder: 'password',
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
    encrypt: true,
 | 
			
		||||
  })
 | 
			
		||||
  password = '';
 | 
			
		||||
  @AccessInput({
 | 
			
		||||
    title: 'totp key',
 | 
			
		||||
    component: {
 | 
			
		||||
      placeholder: 'totp key',
 | 
			
		||||
    },
 | 
			
		||||
    encrypt: true,
 | 
			
		||||
  })
 | 
			
		||||
  otpkey = '';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
new GcoreAccess();
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
export * from './plugins/index.js';
 | 
			
		||||
export * from './access.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
export * from './plugin-upload.js';
 | 
			
		||||
export * from './plugin-flush.js';
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,105 @@
 | 
			
		|||
import { AbstractTaskPlugin, HttpClient, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
 | 
			
		||||
import { CertInfo } from '@certd/plugin-cert';
 | 
			
		||||
import { GcoreAccess } from '../access.js';
 | 
			
		||||
 | 
			
		||||
@IsTaskPlugin({
 | 
			
		||||
  name: 'Gcoreflush',
 | 
			
		||||
  title: '刷新证书 Gcore',
 | 
			
		||||
  desc: '刷新现有的证书',
 | 
			
		||||
  icon: 'clarity:plugin-line',
 | 
			
		||||
  group: pluginGroups.cdn.key,
 | 
			
		||||
  default: {
 | 
			
		||||
    strategy: {
 | 
			
		||||
      runStrategy: RunStrategy.SkipWhenSucceed,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
export class GcoreflushPlugin extends AbstractTaskPlugin {
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: '证书名称',
 | 
			
		||||
    helper: '可以修改也可以和现在的保留一致',
 | 
			
		||||
  })
 | 
			
		||||
  certName!: string;
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: '证书ID',
 | 
			
		||||
  })
 | 
			
		||||
  ssl_id!: string;
 | 
			
		||||
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: '域名证书',
 | 
			
		||||
    helper: '请选择前置任务输出的域名证书',
 | 
			
		||||
    component: {
 | 
			
		||||
      name: 'output-selector',
 | 
			
		||||
      from: ['CertApply', 'CertApplyLego'],
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
  })
 | 
			
		||||
  cert!: CertInfo;
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: 'Access授权',
 | 
			
		||||
    helper: 'Gcore',
 | 
			
		||||
    component: {
 | 
			
		||||
      name: 'access-selector',
 | 
			
		||||
      type: 'Gcore',
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
  })
 | 
			
		||||
  accessId!: string;
 | 
			
		||||
  http!: HttpClient;
 | 
			
		||||
  private readonly baseApi = 'https://api.gcore.com';
 | 
			
		||||
 | 
			
		||||
  async onInstance() {
 | 
			
		||||
    this.http = this.ctx.http;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) {
 | 
			
		||||
    const headers = {
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
      ...(token ? { 'authorization': `Bearer ${token}` } : {}),
 | 
			
		||||
    };
 | 
			
		||||
    const res = await this.http.request<any, any>({
 | 
			
		||||
      url,
 | 
			
		||||
      method,
 | 
			
		||||
      data,
 | 
			
		||||
      headers,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async execute(): Promise<void> {
 | 
			
		||||
    const { cert,accessId } = this;
 | 
			
		||||
    const access = (await this.accessService.getById(accessId)) as GcoreAccess;
 | 
			
		||||
    let otp = null;
 | 
			
		||||
    if (access.otpkey) {
 | 
			
		||||
      const response = await this.http.request<any, any>({
 | 
			
		||||
        url: `https://cn-api.my-api.cn/api/totp/?key=${access.otpkey}`,
 | 
			
		||||
        method: 'get',
 | 
			
		||||
      });
 | 
			
		||||
      otp = response;
 | 
			
		||||
      this.logger.info('获取到otp:', otp);
 | 
			
		||||
    }
 | 
			
		||||
    const loginResponse = await this.doRequestApi(`${this.baseApi}/iam/auth/jwt/login`, {
 | 
			
		||||
      username: access.username,
 | 
			
		||||
      password: access.password,
 | 
			
		||||
      ...(otp && { otp }),
 | 
			
		||||
    });
 | 
			
		||||
    const token = loginResponse.access;
 | 
			
		||||
    this.logger.info('Token 获取成功');
 | 
			
		||||
    this.logger.info('开始上传证书');
 | 
			
		||||
    await this.doRequestApi(
 | 
			
		||||
      `${this.baseApi}/cdn/sslData/${this.ssl_id}`,
 | 
			
		||||
      {
 | 
			
		||||
        name: this.certName,
 | 
			
		||||
        sslCertificate: cert.crt,
 | 
			
		||||
        sslPrivateKey: cert.key,
 | 
			
		||||
        validate_root_ca: true,
 | 
			
		||||
      },
 | 
			
		||||
      'put',
 | 
			
		||||
      token
 | 
			
		||||
    );
 | 
			
		||||
    this.logger.info('证书部署成功');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
new GcoreflushPlugin();
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,101 @@
 | 
			
		|||
import { AbstractTaskPlugin, HttpClient, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
 | 
			
		||||
import { CertInfo } from '@certd/plugin-cert';
 | 
			
		||||
import { GcoreAccess } from '../access.js';
 | 
			
		||||
 | 
			
		||||
@IsTaskPlugin({
 | 
			
		||||
  name: 'Gcoreupload',
 | 
			
		||||
  title: '部署证书到 Gcore',
 | 
			
		||||
  desc: '仅上传 并不会部署到cdn',
 | 
			
		||||
  icon: 'clarity:plugin-line',
 | 
			
		||||
  group: pluginGroups.cdn.key,
 | 
			
		||||
  default: {
 | 
			
		||||
    strategy: {
 | 
			
		||||
      runStrategy: RunStrategy.SkipWhenSucceed,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
export class GcoreuploadPlugin extends AbstractTaskPlugin {
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: '证书名称',
 | 
			
		||||
    helper: '作为备注',
 | 
			
		||||
  })
 | 
			
		||||
  certName!: string;
 | 
			
		||||
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: '域名证书',
 | 
			
		||||
    helper: '请选择前置任务输出的域名证书',
 | 
			
		||||
    component: {
 | 
			
		||||
      name: 'output-selector',
 | 
			
		||||
      from: ['CertApply', 'CertApplyLego'],
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
  })
 | 
			
		||||
  cert!: CertInfo;
 | 
			
		||||
  @TaskInput({
 | 
			
		||||
    title: 'Access授权',
 | 
			
		||||
    helper: 'Gcore',
 | 
			
		||||
    component: {
 | 
			
		||||
      name: 'access-selector',
 | 
			
		||||
      type: 'Gcore',
 | 
			
		||||
    },
 | 
			
		||||
    required: true,
 | 
			
		||||
  })
 | 
			
		||||
  accessId!: string;
 | 
			
		||||
  http!: HttpClient;
 | 
			
		||||
  private readonly baseApi = 'https://api.gcore.com';
 | 
			
		||||
 | 
			
		||||
  async onInstance() {
 | 
			
		||||
    this.http = this.ctx.http;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async doRequestApi(url: string, data: any = null, method = 'post', token: string | null = null) {
 | 
			
		||||
    const headers = {
 | 
			
		||||
      'Content-Type': 'application/json',
 | 
			
		||||
      ...(token ? { 'authorization': `Bearer ${token}` } : {}),
 | 
			
		||||
    };
 | 
			
		||||
    const res = await this.http.request<any, any>({
 | 
			
		||||
      url,
 | 
			
		||||
      method,
 | 
			
		||||
      data,
 | 
			
		||||
      headers,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async execute(): Promise<void> {
 | 
			
		||||
    const { cert,accessId } = this;
 | 
			
		||||
    const access = (await this.accessService.getById(accessId)) as GcoreAccess;
 | 
			
		||||
    let otp = null;
 | 
			
		||||
    if (access.otpkey) {
 | 
			
		||||
      const response = await this.http.request<any, any>({
 | 
			
		||||
        url: `https://cn-api.my-api.cn/api/totp/?key=${access.otpkey}`,
 | 
			
		||||
        method: 'get',
 | 
			
		||||
      });
 | 
			
		||||
      otp = response;
 | 
			
		||||
      this.logger.info('获取到otp:', otp);
 | 
			
		||||
    }
 | 
			
		||||
    const loginResponse = await this.doRequestApi(`${this.baseApi}/iam/auth/jwt/login`, {
 | 
			
		||||
      username: access.username,
 | 
			
		||||
      password: access.password,
 | 
			
		||||
      ...(otp && { otp }),
 | 
			
		||||
    });
 | 
			
		||||
    const token = loginResponse.access;
 | 
			
		||||
    this.logger.info('Token 获取成功');
 | 
			
		||||
    this.logger.info('开始上传证书');
 | 
			
		||||
    await this.doRequestApi(
 | 
			
		||||
      `${this.baseApi}/cdn/sslData`,
 | 
			
		||||
      {
 | 
			
		||||
        name: this.certName,
 | 
			
		||||
        sslCertificate: cert.crt,
 | 
			
		||||
        sslPrivateKey: cert.key,
 | 
			
		||||
        validate_root_ca: true,
 | 
			
		||||
      },
 | 
			
		||||
      'post',
 | 
			
		||||
      token
 | 
			
		||||
    );
 | 
			
		||||
    this.logger.info('证书上传成功');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
new GcoreuploadPlugin();
 | 
			
		||||
		Loading…
	
		Reference in New Issue