perf: http校验方式,支持七牛云oss、阿里云oss、腾讯云cos

This commit is contained in:
xiaojunnuo
2025-01-04 01:45:24 +08:00
parent 297d09c5ad
commit 3f74d4d9e5
23 changed files with 385 additions and 73 deletions

View File

@@ -186,11 +186,12 @@ export class AcmeService {
const filePath = `.well-known/acme-challenge/${challenge.token}`;
const fileContents = keyAuthorization;
this.logger.info(`校验 ${fullDomain} ,准备上传文件:${filePath}`);
await httpUploader.upload(filePath, fileContents);
await httpUploader.upload(filePath, Buffer.from(fileContents));
this.logger.info(`上传文件【${filePath}】成功`);
return {
challenge,
keyAuthorization,
httpUploader,
};
};
@@ -248,7 +249,8 @@ export class AcmeService {
const httpVerifyPlan = domainVerifyPlan.httpVerifyPlan;
if (httpVerifyPlan) {
const httpChallenge = getChallenge("http-01");
return await doHttpVerify(httpChallenge, httpVerifyPlan[fullDomain].httpUploader);
const plan = httpVerifyPlan[fullDomain];
return await doHttpVerify(httpChallenge, plan.httpUploader);
} else {
throw new Error("未找到域名【" + fullDomain + "】的http校验配置");
}

View File

@@ -416,9 +416,14 @@ HTTP文件验证不支持泛域名需要配置网站文件上传`,
for (const key in domainVerifyPlan.httpVerifyPlan) {
const httpRecord = domainVerifyPlan.httpVerifyPlan[key];
const access = await this.ctx.accessService.getById(httpRecord.httpUploaderAccess);
let rootDir = httpRecord.httpUploadRootDir;
if (!rootDir.endsWith("/") && !rootDir.endsWith("\\")) {
rootDir = rootDir + "/";
}
this.logger.info("上传方式", httpRecord.httpUploaderType);
const httpUploader = await httpChallengeUploaderFactory.createUploaderByType(httpRecord.httpUploaderType, {
access,
rootDir: httpRecord.httpUploadRootDir,
rootDir: rootDir,
ctx: httpUploaderContext,
});
httpVerifyPlan[key] = {

View File

@@ -2,7 +2,7 @@ import { IAccessService } from "@certd/pipeline";
import { ILogger, utils } from "@certd/basic";
export type HttpChallengeUploader = {
upload: (fileName: string, fileContent: string) => Promise<void>;
upload: (fileName: string, fileContent: Buffer) => Promise<void>;
remove: (fileName: string) => Promise<void>;
};
@@ -31,5 +31,5 @@ export abstract class BaseHttpChallengeUploader<A> implements HttpChallengeUploa
}
abstract remove(fileName: string): Promise<void>;
abstract upload(fileName: string, fileContent: string): Promise<void>;
abstract upload(fileName: string, fileContent: Buffer): Promise<void>;
}

View File

@@ -3,7 +3,7 @@ import { AliossAccess, AliyunAccess } from "@certd/plugin-lib";
import { AliossClient } from "@certd/plugin-lib";
export class AliossHttpChallengeUploader extends BaseHttpChallengeUploader<AliossAccess> {
async upload(filePath: string, fileContent: string) {
async upload(filePath: string, fileContent: Buffer) {
const aliyunAccess = await this.ctx.accessService.getById<AliyunAccess>(this.access.accessId);
const client = new AliossClient({
access: aliyunAccess,
@@ -11,16 +11,19 @@ export class AliossHttpChallengeUploader extends BaseHttpChallengeUploader<Alios
region: this.access.region,
});
await client.uploadFile(filePath, Buffer.from(fileContent));
const key = this.rootDir + filePath;
this.logger.info(`开始上传文件: ${key}`);
await client.uploadFile(key, fileContent);
this.logger.info(`校验文件上传成功: ${filePath}`);
}
async remove(filePath: string) {
const key = this.rootDir + filePath;
// remove file from alioss
const client = await this.getAliossClient();
await client.removeFile(filePath);
this.logger.info(`文件删除成功: ${filePath}`);
await client.removeFile(key);
this.logger.info(`文件删除成功: ${key}`);
}
private async getAliossClient() {

View File

@@ -1,24 +1,41 @@
import { BaseHttpChallengeUploader } from "../api.js";
import { FtpAccess, FtpClient } from "@certd/plugin-lib";
import path from "path";
import os from "os";
import fs from "fs";
export class FtpHttpChallengeUploader extends BaseHttpChallengeUploader<FtpAccess> {
async upload(fileName: string, fileContent: string) {
async upload(filePath: string, fileContent: Buffer) {
const client = new FtpClient({
access: this.access,
logger: this.logger,
});
await client.connect(async (client) => {
await client.upload(fileName, fileContent);
const tmpFilePath = path.join(os.tmpdir(), "cert", "http", filePath);
const dir = path.dirname(tmpFilePath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.writeFileSync(tmpFilePath, fileContent);
try {
// Write file to temp path
const path = this.rootDir + filePath;
await client.upload(path, tmpFilePath);
} finally {
// Remove temp file
fs.unlinkSync(tmpFilePath);
}
});
}
async remove(fileName: string) {
async remove(filePath: string) {
const client = new FtpClient({
access: this.access,
logger: this.logger,
});
await client.connect(async (client) => {
await client.client.remove(fileName);
const path = this.rootDir + filePath;
await client.client.remove(path);
});
}
}

View File

@@ -1,10 +1,31 @@
import { BaseHttpChallengeUploader } from "../api.js";
import { QiniuOssAccess } from "@certd/plugin-lib/dist/qiniu/access-oss";
import { QiniuOssAccess, QiniuClient, QiniuAccess } from "@certd/plugin-lib";
export class QiniuOssHttpChallengeUploader extends BaseHttpChallengeUploader<QiniuOssAccess> {
async upload(fileName: string, fileContent: string) {
return null;
async upload(filePath: string, fileContent: Buffer) {
const qiniuAccess = await this.ctx.accessService.getById<QiniuAccess>(this.access.accessId);
const client = new QiniuClient({
access: qiniuAccess,
logger: this.logger,
http: this.ctx.utils.http,
});
if (this.rootDir.endsWith("/")) {
this.rootDir = this.rootDir.slice(0, -1);
}
await client.uploadFile(this.access.bucket, this.rootDir + filePath, fileContent);
}
async remove(fileName: string) {}
async remove(filePath: string) {
const qiniuAccess = await this.ctx.accessService.getById<QiniuAccess>(this.access.accessId);
const client = new QiniuClient({
access: qiniuAccess,
logger: this.logger,
http: this.ctx.utils.http,
});
if (this.rootDir.endsWith("/")) {
this.rootDir = this.rootDir.slice(0, -1);
}
await client.removeFile(this.access.bucket, this.rootDir + filePath);
}
}

View File

@@ -5,11 +5,17 @@ import os from "os";
import fs from "fs";
export class SshHttpChallengeUploader extends BaseHttpChallengeUploader<SshAccess> {
async upload(fileName: string, fileContent: string) {
const tmpFilePath = path.join(os.tmpdir(), "cert", "http", fileName);
async upload(filePath: string, fileContent: Buffer) {
const tmpFilePath = path.join(os.tmpdir(), "cert", "http", filePath);
// Write file to temp path
const dir = path.dirname(tmpFilePath);
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir, { recursive: true });
}
fs.writeFileSync(tmpFilePath, fileContent);
const key = this.rootDir + filePath;
try {
const client = new SshClient(this.logger);
await client.uploadFiles({
@@ -17,8 +23,8 @@ export class SshHttpChallengeUploader extends BaseHttpChallengeUploader<SshAcces
mkdirs: true,
transports: [
{
localPath: fileName,
remotePath: fileName,
localPath: tmpFilePath,
remotePath: key,
},
],
});
@@ -30,9 +36,10 @@ export class SshHttpChallengeUploader extends BaseHttpChallengeUploader<SshAcces
async remove(filePath: string) {
const client = new SshClient(this.logger);
const key = this.rootDir + filePath;
await client.removeFiles({
connectConf: this.access,
files: [filePath],
files: [key],
});
}
}

View File

@@ -1,10 +1,28 @@
import { BaseHttpChallengeUploader } from "../api.js";
import { TencentCosAccess } from "@certd/plugin-lib/dist/tencent/access-cos";
import { TencentAccess, TencentCosAccess, TencentCosClient } from "@certd/plugin-lib";
export class TencentCosHttpChallengeUploader extends BaseHttpChallengeUploader<TencentCosAccess> {
async upload(fileName: string, fileContent: string) {
return null;
async upload(filePath: string, fileContent: Buffer) {
const access = await this.ctx.accessService.getById<TencentAccess>(this.access.accessId);
const client = new TencentCosClient({
access: access,
logger: this.logger,
region: this.access.region,
bucket: this.access.bucket,
});
const key = this.rootDir + filePath;
await client.uploadFile(key, fileContent);
}
async remove(fileName: string) {}
async remove(filePath: string) {
const access = await this.ctx.accessService.getById<TencentAccess>(this.access.accessId);
const client = new TencentCosClient({
access: access,
logger: this.logger,
region: this.access.region,
bucket: this.access.bucket,
});
const key = this.rootDir + filePath;
await client.removeFile(key);
}
}