diff --git a/src/acme2.js b/src/acme2.js index 1a2f28c5b..538a058fa 100644 --- a/src/acme2.js +++ b/src/acme2.js @@ -88,10 +88,10 @@ Acme2.prototype.sendSignedRequest = async function (url, payload) { let [error, response] = await safe(superagent.get(this.directory.newNonce).timeout(30000).ok(() => true)); if (error) throw new BoxError(BoxError.NETWORK_ERROR, `Network error sending signed request: ${error.message}`); - if (response.status !== 204) throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid response code when fetching nonce : ${response.status}`); + if (response.status !== 204) throw new BoxError(BoxError.ACME_ERROR, `Invalid response code when fetching nonce : ${response.status}`); const nonce = response.headers['Replay-Nonce'.toLowerCase()]; - if (!nonce) throw new BoxError(BoxError.EXTERNAL_ERROR, 'No nonce in response'); + if (!nonce) throw new BoxError(BoxError.ACME_ERROR, 'No nonce in response'); debug('sendSignedRequest: using nonce %s for url %s', nonce, url); @@ -129,7 +129,7 @@ Acme2.prototype.updateContact = async function (registrationUri) { }; const result = await this.sendSignedRequest(registrationUri, JSON.stringify(payload)); - if (result.status !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, `Failed to update contact. Expecting 200, got ${result.status} ${JSON.stringify(result.body)}`); + if (result.status !== 200) throw new BoxError(BoxError.ACME_ERROR, `Failed to update contact. Expecting 200, got ${result.status} ${JSON.stringify(result.body)}`); debug(`updateContact: contact of user updated to ${this.email}`); }; @@ -163,7 +163,7 @@ Acme2.prototype.ensureAccount = async function () { } // 200 if already exists. 201 for new accounts - if (result.status !== 200 && result.status !== 201) throw new BoxError(BoxError.EXTERNAL_ERROR, `Failed to register new account. Expecting 200 or 201, got ${result.status} ${JSON.stringify(result.body)}`); + if (result.status !== 200 && result.status !== 201) throw new BoxError(BoxError.ACME_ERROR, `Failed to register new account. Expecting 200 or 201, got ${result.status} ${JSON.stringify(result.body)}`); debug(`ensureAccount: user registered keyid: ${result.headers.location}`); @@ -186,15 +186,15 @@ Acme2.prototype.newOrder = async function (domain) { const result = await this.sendSignedRequest(this.directory.newOrder, JSON.stringify(payload)); if (result.status === 403) throw new BoxError(BoxError.ACCESS_DENIED, `Forbidden sending new order: ${result.body.detail}`); - if (result.status !== 201) throw new BoxError(BoxError.EXTERNAL_ERROR, `Failed to send new order. Expecting 201, got ${result.statusCode} ${JSON.stringify(result.body)}`); + if (result.status !== 201) throw new BoxError(BoxError.ACME_ERROR, `Failed to send new order. Expecting 201, got ${result.statusCode} ${JSON.stringify(result.body)}`); debug('newOrder: created order %s %j', domain, result.body); const order = result.body, orderUrl = result.headers.location; - if (!Array.isArray(order.authorizations)) throw new BoxError(BoxError.EXTERNAL_ERROR, 'invalid authorizations in order'); - if (typeof order.finalize !== 'string') throw new BoxError(BoxError.EXTERNAL_ERROR, 'invalid finalize in order'); - if (typeof orderUrl !== 'string') throw new BoxError(BoxError.EXTERNAL_ERROR, 'invalid order location in order header'); + if (!Array.isArray(order.authorizations)) throw new BoxError(BoxError.ACME_ERROR, 'invalid authorizations in order'); + if (typeof order.finalize !== 'string') throw new BoxError(BoxError.ACME_ERROR, 'invalid finalize in order'); + if (typeof orderUrl !== 'string') throw new BoxError(BoxError.ACME_ERROR, 'invalid order location in order header'); return { order, orderUrl }; }; @@ -210,14 +210,14 @@ Acme2.prototype.waitForOrder = async function (orderUrl) { const result = await this.postAsGet(orderUrl); if (result.status !== 200) { debug(`waitForOrder: invalid response code getting uri ${result.status}`); - throw new BoxError(BoxError.EXTERNAL_ERROR, `Bad response code: ${result.status}`); + throw new BoxError(BoxError.ACME_ERROR, `Bad response when waiting for order. code: ${result.status}`); } debug('waitForOrder: status is "%s %j', result.body.status, result.body); - if (result.body.status === 'pending' || result.body.status === 'processing') throw new BoxError(BoxError.TRY_AGAIN, `Request is in ${result.body.status} state`); + if (result.body.status === 'pending' || result.body.status === 'processing') throw new BoxError(BoxError.ACME_ERROR, `Request is in ${result.body.status} state`); else if (result.body.status === 'valid' && result.body.certificate) return result.body.certificate; - else throw new BoxError(BoxError.EXTERNAL_ERROR, `Unexpected status or invalid response: ${JSON.stringify(result.body)}`); + else throw new BoxError(BoxError.ACME_ERROR, `Unexpected status or invalid response when waiting for order: ${JSON.stringify(result.body)}`); }); }; @@ -249,7 +249,7 @@ Acme2.prototype.notifyChallengeReady = async function (challenge) { }; const result = await this.sendSignedRequest(challenge.url, JSON.stringify(payload)); - if (result.status !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, `Failed to notify challenge. Expecting 200, got ${result.statusCode} ${JSON.stringify(result.body)}`); + if (result.status !== 200) throw new BoxError(BoxError.ACME_ERROR, `Failed to notify challenge. Expecting 200, got ${result.statusCode} ${JSON.stringify(result.body)}`); }; Acme2.prototype.waitForChallenge = async function (challenge) { @@ -263,14 +263,14 @@ Acme2.prototype.waitForChallenge = async function (challenge) { const result = await this.postAsGet(challenge.url); if (result.status !== 200) { debug(`waitForChallenge: invalid response code getting uri ${result.status}`); - throw new BoxError(BoxError.EXTERNAL_ERROR, 'Bad response code:' + result.statusCode); + throw new BoxError(BoxError.ACME_ERROR, `Bad response code when waiting for challenge : ${result.status}`); } debug(`waitForChallenge: status is "${result.body.status}" "${JSON.stringify(result.body)}"`); - if (result.body.status === 'pending') throw new BoxError(BoxError.TRY_AGAIN); + if (result.body.status === 'pending') throw new BoxError(BoxError.ACME_ERROR, 'Challenge is in pending state'); else if (result.body.status === 'valid') return; - else throw new BoxError(BoxError.EXTERNAL_ERROR, `Unexpected status: ${result.body.status}`); + else throw new BoxError(BoxError.ACME_ERROR, `Unexpected status when waiting for challenge: ${result.body.status}`); }); }; @@ -288,7 +288,7 @@ Acme2.prototype.signCertificate = async function (domain, finalizationUrl, csrDe const result = await this.sendSignedRequest(finalizationUrl, JSON.stringify(payload)); // 429 means we reached the cert limit for this domain - if (result.status !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, `Failed to sign certificate. Expecting 200, got ${result.status} ${JSON.stringify(result.body)}`); + if (result.status !== 200) throw new BoxError(BoxError.ACME_ERROR, `Failed to sign certificate. Expecting 200, got ${result.status} ${JSON.stringify(result.body)}`); }; Acme2.prototype.createKeyAndCsr = async function (hostname, keyFilePath, csrFilePath) { @@ -339,8 +339,8 @@ Acme2.prototype.downloadCertificate = async function (hostname, certUrl, certFil debug('downloadCertificate: downloading certificate'); const result = await this.postAsGet(certUrl); - if (result.statusCode === 202) throw new BoxError(BoxError.TRY_AGAIN, 'Retry downloading certificate'); - if (result.statusCode !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, `Failed to get cert. Expecting 200, got ${result.statusCode} ${JSON.stringify(result.body)}`); + if (result.statusCode === 202) throw new BoxError(BoxError.ACME_ERROR, 'Retry downloading certificate'); + if (result.statusCode !== 200) throw new BoxError(BoxError.ACME_ERROR, `Failed to get cert. Expecting 200, got ${result.statusCode} ${JSON.stringify(result.body)}`); const fullChainPem = result.body; // buffer @@ -358,7 +358,7 @@ Acme2.prototype.prepareHttpChallenge = async function (hostname, domain, authori debug('prepareHttpChallenge: challenges: %j', authorization); let httpChallenges = authorization.challenges.filter(function(x) { return x.type === 'http-01'; }); - if (httpChallenges.length === 0) throw new BoxError(BoxError.EXTERNAL_ERROR, 'no http challenges'); + if (httpChallenges.length === 0) throw new BoxError(BoxError.ACME_ERROR, 'no http challenges'); let challenge = httpChallenges[0]; debug('prepareHttpChallenge: preparing for challenge %j', challenge); @@ -407,7 +407,7 @@ Acme2.prototype.prepareDnsChallenge = async function (hostname, domain, authoriz debug('prepareDnsChallenge: challenges: %j', authorization); const dnsChallenges = authorization.challenges.filter(function(x) { return x.type === 'dns-01'; }); - if (dnsChallenges.length === 0) throw new BoxError(BoxError.EXTERNAL_ERROR, 'no dns challenges'); + if (dnsChallenges.length === 0) throw new BoxError(BoxError.ACME_ERROR, 'no dns challenges'); const challenge = dnsChallenges[0]; const keyAuthorization = this.getKeyAuthorization(challenge.token); @@ -452,7 +452,7 @@ Acme2.prototype.prepareChallenge = async function (hostname, domain, authorizati debug(`prepareChallenge: http: ${this.performHttpAuthorization}`); const response = await this.postAsGet(authorizationUrl); - if (response.status !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid response code getting authorization : ${response.status}`); + if (response.status !== 200) throw new BoxError(BoxError.ACME_ERROR, `Invalid response code getting authorization : ${response.status}`); const authorization = response.body; @@ -512,11 +512,11 @@ Acme2.prototype.loadDirectory = async function () { await promiseRetry({ times: 3, interval: 20000 }, async () => { const response = await superagent.get(this.caDirectory).timeout(30000).ok(() => true); - if (response.status !== 200) throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid response code when fetching directory : ${response.status}`); + if (response.status !== 200) throw new BoxError(BoxError.ACME_ERROR, `Invalid response code when fetching directory : ${response.status}`); if (typeof response.body.newNonce !== 'string' || typeof response.body.newOrder !== 'string' || - typeof response.body.newAccount !== 'string') throw new BoxError(BoxError.EXTERNAL_ERROR, `Invalid response body : ${response.body}`); + typeof response.body.newAccount !== 'string') throw new BoxError(BoxError.ACME_ERROR, `Invalid response body : ${response.body}`); this.directory = response.body; }); diff --git a/src/boxerror.js b/src/boxerror.js index e6bebb58e..a7721fdeb 100644 --- a/src/boxerror.js +++ b/src/boxerror.js @@ -33,6 +33,7 @@ function BoxError(reason, errorOrMessage, override) { } util.inherits(BoxError, Error); BoxError.ACCESS_DENIED = 'Access Denied'; +BoxError.ACME_ERROR = 'Acme Error'; BoxError.ADDONS_ERROR = 'Addons Error'; BoxError.ALREADY_EXISTS = 'Already Exists'; BoxError.BAD_FIELD = 'Bad Field'; @@ -91,6 +92,7 @@ BoxError.toHttpError = function (error) { case BoxError.INVALID_CREDENTIALS: return new HttpError(412, error); case BoxError.EXTERNAL_ERROR: + case BoxError.ACME_ERROR: case BoxError.NETWORK_ERROR: case BoxError.FS_ERROR: case BoxError.MOUNT_ERROR: