forked from root/acme.js
Bug fix: Polling status using POST-as-GET wherever possible
Avoid repeating finalize POST request and challenge POST requests by using POST-as-GET requests instead. Allows for testing with Pebble, and more correctly follows the spec.
This commit is contained in:
parent
bef931f28f
commit
0aa939a227
144
acme.js
144
acme.js
|
@ -756,12 +756,8 @@ ACME._postChallenge = function (me, options, kid, auth) {
|
||||||
altname: altname
|
altname: altname
|
||||||
});
|
});
|
||||||
|
|
||||||
if ('processing' === resp.body.status) {
|
// State can be pending while waiting ACME server to transition to
|
||||||
//#console.debug('poll: again', auth.url);
|
// processing
|
||||||
return ACME._wait(RETRY_INTERVAL).then(pollStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This state should never occur
|
|
||||||
if ('pending' === resp.body.status) {
|
if ('pending' === resp.body.status) {
|
||||||
if (count >= MAX_PEND) {
|
if (count >= MAX_PEND) {
|
||||||
return ACME._wait(RETRY_INTERVAL)
|
return ACME._wait(RETRY_INTERVAL)
|
||||||
|
@ -769,7 +765,12 @@ ACME._postChallenge = function (me, options, kid, auth) {
|
||||||
.then(respondToChallenge);
|
.then(respondToChallenge);
|
||||||
}
|
}
|
||||||
//#console.debug('poll: again', auth.url);
|
//#console.debug('poll: again', auth.url);
|
||||||
return ACME._wait(RETRY_INTERVAL).then(respondToChallenge);
|
return ACME._wait(RETRY_INTERVAL).then(pollStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('processing' === resp.body.status) {
|
||||||
|
//#console.debug('poll: again', auth.url);
|
||||||
|
return ACME._wait(RETRY_INTERVAL).then(pollStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
// REMOVE DNS records as soon as the state is non-processing
|
// REMOVE DNS records as soon as the state is non-processing
|
||||||
|
@ -1012,73 +1013,84 @@ ACME._pollOrderStatus = function (me, options, kid, order, verifieds) {
|
||||||
var body = { csr: csr64 };
|
var body = { csr: csr64 };
|
||||||
var payload = JSON.stringify(body);
|
var payload = JSON.stringify(body);
|
||||||
|
|
||||||
function pollCert() {
|
function processResponse(resp) {
|
||||||
|
ACME._notify(me, options, 'certificate_status', {
|
||||||
|
subject: options.domains[0],
|
||||||
|
status: resp.body.status
|
||||||
|
});
|
||||||
|
|
||||||
|
// https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.3
|
||||||
|
// Possible values are: "pending" => ("invalid" || "ready") => "processing" => "valid"
|
||||||
|
if ('valid' === resp.body.status) {
|
||||||
|
var voucher = resp.body;
|
||||||
|
voucher._certificateUrl = resp.body.certificate;
|
||||||
|
|
||||||
|
return voucher;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('processing' === resp.body.status) {
|
||||||
|
return ACME._wait().then(pollStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (me.debug) {
|
||||||
|
console.debug(
|
||||||
|
'Error: bad status:\n' + JSON.stringify(resp.body, null, 2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('pending' === resp.body.status) {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(
|
||||||
|
"Did not finalize order: status 'pending'." +
|
||||||
|
' Best guess: You have not accepted at least one challenge for each domain:\n' +
|
||||||
|
"Requested: '" +
|
||||||
|
options.domains.join(', ') +
|
||||||
|
"'\n" +
|
||||||
|
"Validated: '" +
|
||||||
|
verifieds.join(', ') +
|
||||||
|
"'\n" +
|
||||||
|
JSON.stringify(resp.body, null, 2)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('invalid' === resp.body.status) {
|
||||||
|
return Promise.reject(
|
||||||
|
E.ORDER_INVALID(options, verifieds, resp)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('ready' === resp.body.status) {
|
||||||
|
return Promise.reject(
|
||||||
|
E.DOUBLE_READY_ORDER(options, verifieds, resp)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.reject(
|
||||||
|
E.UNHANDLED_ORDER_STATUS(options, verifieds, resp)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pollStatus() {
|
||||||
|
return U._jwsRequest(me, {
|
||||||
|
accountKey: options.accountKey,
|
||||||
|
url: order._orderUrl,
|
||||||
|
protected: { kid: kid },
|
||||||
|
payload: Enc.binToBuf('')
|
||||||
|
}).then(processResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
function finalizeOrder() {
|
||||||
//#console.debug('[ACME.js] pollCert:', order._finalizeUrl);
|
//#console.debug('[ACME.js] pollCert:', order._finalizeUrl);
|
||||||
return U._jwsRequest(me, {
|
return U._jwsRequest(me, {
|
||||||
accountKey: options.accountKey,
|
accountKey: options.accountKey,
|
||||||
url: order._finalizeUrl,
|
url: order._finalizeUrl,
|
||||||
protected: { kid: kid },
|
protected: { kid: kid },
|
||||||
payload: Enc.strToBuf(payload)
|
payload: Enc.strToBuf(payload)
|
||||||
}).then(function (resp) {
|
}).then(processResponse);
|
||||||
ACME._notify(me, options, 'certificate_status', {
|
|
||||||
subject: options.domains[0],
|
|
||||||
status: resp.body.status
|
|
||||||
});
|
|
||||||
|
|
||||||
// https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.3
|
|
||||||
// Possible values are: "pending" => ("invalid" || "ready") => "processing" => "valid"
|
|
||||||
if ('valid' === resp.body.status) {
|
|
||||||
var voucher = resp.body;
|
|
||||||
voucher._certificateUrl = resp.body.certificate;
|
|
||||||
|
|
||||||
return voucher;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('processing' === resp.body.status) {
|
|
||||||
return ACME._wait().then(pollCert);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (me.debug) {
|
|
||||||
console.debug(
|
|
||||||
'Error: bad status:\n' + JSON.stringify(resp.body, null, 2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('pending' === resp.body.status) {
|
|
||||||
return Promise.reject(
|
|
||||||
new Error(
|
|
||||||
"Did not finalize order: status 'pending'." +
|
|
||||||
' Best guess: You have not accepted at least one challenge for each domain:\n' +
|
|
||||||
"Requested: '" +
|
|
||||||
options.domains.join(', ') +
|
|
||||||
"'\n" +
|
|
||||||
"Validated: '" +
|
|
||||||
verifieds.join(', ') +
|
|
||||||
"'\n" +
|
|
||||||
JSON.stringify(resp.body, null, 2)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('invalid' === resp.body.status) {
|
|
||||||
return Promise.reject(
|
|
||||||
E.ORDER_INVALID(options, verifieds, resp)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('ready' === resp.body.status) {
|
|
||||||
return Promise.reject(
|
|
||||||
E.DOUBLE_READY_ORDER(options, verifieds, resp)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject(
|
|
||||||
E.UNHANDLED_ORDER_STATUS(options, verifieds, resp)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pollCert();
|
return finalizeOrder();
|
||||||
};
|
};
|
||||||
|
|
||||||
ACME._redeemCert = function (me, options, kid, voucher) {
|
ACME._redeemCert = function (me, options, kid, voucher) {
|
||||||
|
|
Loading…
Reference in New Issue