mirror of https://github.com/certd/certd
fix: 修复并发情况下证书申请日志混乱的bug
parent
54c42b1fc2
commit
bb2714ff24
|
|
@ -28,7 +28,6 @@ class AcmeApi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(locationUrl, mapping);
|
|
||||||
return locationUrl;
|
return locationUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
* ACME auto helper
|
* ACME auto helper
|
||||||
*/
|
*/
|
||||||
import { readCsrDomains } from "./crypto/index.js";
|
import { readCsrDomains } from "./crypto/index.js";
|
||||||
import { log } from "./logger.js";
|
|
||||||
import { wait } from "./wait.js";
|
import { wait } from "./wait.js";
|
||||||
import { CancelError } from "./error.js";
|
import { CancelError } from "./error.js";
|
||||||
|
|
||||||
|
|
@ -45,6 +44,9 @@ export default async (client, userOpts) => {
|
||||||
accountPayload.externalAccountBinding = opts.externalAccountBinding;
|
accountPayload.externalAccountBinding = opts.externalAccountBinding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const log = (...args)=>{
|
||||||
|
return client.logger.info(...args);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Register account
|
* Register account
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@
|
||||||
*/
|
*/
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { parseRetryAfterHeader } from './util.js';
|
import { parseRetryAfterHeader } from './util.js';
|
||||||
import { log } from './logger.js';
|
|
||||||
const { AxiosError } = axios;
|
const { AxiosError } = axios;
|
||||||
import {getGlobalAgents, HttpError} from '@certd/basic'
|
import {getGlobalAgents, HttpError} from '@certd/basic'
|
||||||
|
import { log } from './logger.js';
|
||||||
/**
|
/**
|
||||||
* Defaults
|
* Defaults
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
*/
|
*/
|
||||||
import { createHash } from 'crypto';
|
import { createHash } from 'crypto';
|
||||||
import { getPemBodyAsB64u } from './crypto/index.js';
|
import { getPemBodyAsB64u } from './crypto/index.js';
|
||||||
import { log } from './logger.js';
|
|
||||||
import HttpClient from './http.js';
|
import HttpClient from './http.js';
|
||||||
import AcmeApi from './api.js';
|
import AcmeApi from './api.js';
|
||||||
import verify from './verify.js';
|
import verify from './verify.js';
|
||||||
|
|
@ -104,8 +103,13 @@ class AcmeClient {
|
||||||
max: this.opts.backoffMax,
|
max: this.opts.backoffMax,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding, this.opts.urlMapping);
|
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding, this.opts.urlMapping, opts.logger);
|
||||||
this.api = new AcmeApi(this.http, this.opts.accountUrl);
|
this.api = new AcmeApi(this.http, this.opts.accountUrl);
|
||||||
|
this.logger = opts.logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
log(...args) {
|
||||||
|
this.logger.info(...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -177,7 +181,7 @@ class AcmeClient {
|
||||||
this.getAccountUrl();
|
this.getAccountUrl();
|
||||||
|
|
||||||
/* Account URL exists */
|
/* Account URL exists */
|
||||||
log('Account URL exists, returning updateAccount()');
|
this.log('Account URL exists, returning updateAccount()');
|
||||||
return this.updateAccount(data);
|
return this.updateAccount(data);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
|
@ -185,7 +189,7 @@ class AcmeClient {
|
||||||
|
|
||||||
/* HTTP 200: Account exists */
|
/* HTTP 200: Account exists */
|
||||||
if (resp.status === 200) {
|
if (resp.status === 200) {
|
||||||
log('Account already exists (HTTP 200), returning updateAccount()');
|
this.log('Account already exists (HTTP 200), returning updateAccount()');
|
||||||
return this.updateAccount(data);
|
return this.updateAccount(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,7 +218,7 @@ class AcmeClient {
|
||||||
this.api.getAccountUrl();
|
this.api.getAccountUrl();
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
log('No account URL found, returning createAccount()');
|
this.log('No account URL found, returning createAccount()');
|
||||||
return this.createAccount(data);
|
return this.createAccount(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -502,7 +506,7 @@ class AcmeClient {
|
||||||
await verify[challenge.type](authz, challenge, keyAuthorization);
|
await verify[challenge.type](authz, challenge, keyAuthorization);
|
||||||
};
|
};
|
||||||
|
|
||||||
log('Waiting for ACME challenge verification(等待ACME检查验证)');
|
this.log('Waiting for ACME challenge verification(等待ACME检查验证)');
|
||||||
return util.retry(verifyFn, this.backoffOpts);
|
return util.retry(verifyFn, this.backoffOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -570,7 +574,7 @@ class AcmeClient {
|
||||||
const resp = await this.api.apiRequest(item.url, null, [200]);
|
const resp = await this.api.apiRequest(item.url, null, [200]);
|
||||||
|
|
||||||
/* Verify status */
|
/* Verify status */
|
||||||
log(`[${d}] Item has status(检查状态): ${resp.data.status}`);
|
this.log(`[${d}] Item has status(检查状态): ${resp.data.status}`);
|
||||||
|
|
||||||
if (invalidStates.includes(resp.data.status)) {
|
if (invalidStates.includes(resp.data.status)) {
|
||||||
abort();
|
abort();
|
||||||
|
|
@ -586,7 +590,7 @@ class AcmeClient {
|
||||||
throw new Error(`[${d}] Unexpected item status: ${resp.data.status}`);
|
throw new Error(`[${d}] Unexpected item status: ${resp.data.status}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
log(`[${d}] Waiting for valid status (等待valid状态): ${item.url}`, this.backoffOpts);
|
this.log(`[${d}] Waiting for valid status (等待valid状态): ${item.url}`, this.backoffOpts);
|
||||||
return util.retry(verifyFn, this.backoffOpts);
|
return util.retry(verifyFn, this.backoffOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import { getJwk } from './crypto/index.js';
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class HttpClient {
|
class HttpClient {
|
||||||
constructor(directoryUrl, accountKey, externalAccountBinding = {}, urlMapping = {}) {
|
constructor(directoryUrl, accountKey, externalAccountBinding = {}, urlMapping = {},logger) {
|
||||||
this.directoryUrl = directoryUrl;
|
this.directoryUrl = directoryUrl;
|
||||||
this.accountKey = accountKey;
|
this.accountKey = accountKey;
|
||||||
this.externalAccountBinding = externalAccountBinding;
|
this.externalAccountBinding = externalAccountBinding;
|
||||||
|
|
@ -31,6 +31,7 @@ class HttpClient {
|
||||||
this.directoryMaxAge = 86400;
|
this.directoryMaxAge = 86400;
|
||||||
this.directoryTimestamp = 0;
|
this.directoryTimestamp = 0;
|
||||||
this.urlMapping = urlMapping;
|
this.urlMapping = urlMapping;
|
||||||
|
this.log = logger? logger.info.bind(logger) : log;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -48,7 +49,7 @@ class HttpClient {
|
||||||
for (const key in this.urlMapping.mappings) {
|
for (const key in this.urlMapping.mappings) {
|
||||||
if (url.includes(key)) {
|
if (url.includes(key)) {
|
||||||
const newUrl = url.replace(key, this.urlMapping.mappings[key]);
|
const newUrl = url.replace(key, this.urlMapping.mappings[key]);
|
||||||
log(`use reverse proxy: ${newUrl}`);
|
this.log(`use reverse proxy: ${newUrl}`);
|
||||||
url = newUrl;
|
url = newUrl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -65,10 +66,10 @@ class HttpClient {
|
||||||
opts.headers['Content-Type'] = 'application/jose+json';
|
opts.headers['Content-Type'] = 'application/jose+json';
|
||||||
|
|
||||||
/* Request */
|
/* Request */
|
||||||
log(`HTTP request: ${method} ${url}`);
|
this.log(`HTTP request: ${method} ${url}`);
|
||||||
const resp = await axios.request(opts);
|
const resp = await axios.request(opts);
|
||||||
|
|
||||||
log(`RESP ${resp.status} ${method} ${url}`);
|
this.log(`RESP ${resp.status} ${method} ${url}`);
|
||||||
return resp;
|
return resp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,7 +86,7 @@ class HttpClient {
|
||||||
const age = (now - this.directoryTimestamp);
|
const age = (now - this.directoryTimestamp);
|
||||||
|
|
||||||
if (!this.directoryCache || (age > this.directoryMaxAge)) {
|
if (!this.directoryCache || (age > this.directoryMaxAge)) {
|
||||||
log(`Refreshing ACME directory, age: ${age}`);
|
this.log(`Refreshing ACME directory, age: ${age}`);
|
||||||
const resp = await this.request(this.directoryUrl, 'get');
|
const resp = await this.request(this.directoryUrl, 'get');
|
||||||
|
|
||||||
if (resp.status >= 400) {
|
if (resp.status >= 400) {
|
||||||
|
|
@ -187,7 +188,7 @@ class HttpClient {
|
||||||
|
|
||||||
/* Nonce */
|
/* Nonce */
|
||||||
if (nonce) {
|
if (nonce) {
|
||||||
log(`Using nonce: ${nonce}`);
|
this.log(`Using nonce: ${nonce}`);
|
||||||
header.nonce = nonce;
|
header.nonce = nonce;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,7 +315,7 @@ class HttpClient {
|
||||||
nonce = resp.headers['replay-nonce'] || null;
|
nonce = resp.headers['replay-nonce'] || null;
|
||||||
attempts += 1;
|
attempts += 1;
|
||||||
|
|
||||||
log(`Caught invalid nonce error, retrying (${attempts}/${this.maxBadNonceRetries}) signed request to: ${url}`);
|
this.log(`Caught invalid nonce error, retrying (${attempts}/${this.maxBadNonceRetries}) signed request to: ${url}`);
|
||||||
return this.signedRequest(url, payload, { kid, nonce, includeExternalAccountBinding }, attempts);
|
return this.signedRequest(url, payload, { kid, nonce, includeExternalAccountBinding }, attempts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ export interface ClientOptions {
|
||||||
backoffMax?: number;
|
backoffMax?: number;
|
||||||
urlMapping?: UrlMapping;
|
urlMapping?: UrlMapping;
|
||||||
signal?: AbortSignal;
|
signal?: AbortSignal;
|
||||||
|
logger?:any
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientExternalAccountBindingOptions {
|
export interface ClientExternalAccountBindingOptions {
|
||||||
|
|
|
||||||
|
|
@ -82,9 +82,9 @@ export class AcmeService {
|
||||||
this.sslProvider = options.sslProvider || "letsencrypt";
|
this.sslProvider = options.sslProvider || "letsencrypt";
|
||||||
this.eab = options.eab;
|
this.eab = options.eab;
|
||||||
this.skipLocalVerify = options.skipLocalVerify ?? false;
|
this.skipLocalVerify = options.skipLocalVerify ?? false;
|
||||||
acme.setLogger((message: any, ...args: any[]) => {
|
// acme.setLogger((message: any, ...args: any[]) => {
|
||||||
this.logger.info(message, ...args);
|
// this.logger.info(message, ...args);
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAccountConfig(email: string, urlMapping: UrlMapping): Promise<any> {
|
async getAccountConfig(email: string, urlMapping: UrlMapping): Promise<any> {
|
||||||
|
|
@ -155,6 +155,7 @@ export class AcmeService {
|
||||||
backoffMax: 10000,
|
backoffMax: 10000,
|
||||||
urlMapping,
|
urlMapping,
|
||||||
signal: this.options.signal,
|
signal: this.options.signal,
|
||||||
|
logger: this.logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (conf.accountUrl == null) {
|
if (conf.accountUrl == null) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue