fix: poll order status, not finalize status

This commit is contained in:
AJ ONeal 2024-05-13 12:23:36 -06:00
parent 005b496054
commit 61a435d6c2
Signed by: coolaj86
GPG Key ID: F1D692A76F70CF98
1 changed files with 129 additions and 97 deletions

226
index.js
View File

@ -900,118 +900,127 @@ ACME._finalizeOrder = function (me, options, validatedDomains) {
var csr = me.RSA.generateCsrWeb64(options.domainKeypair, validatedDomains); var csr = me.RSA.generateCsrWeb64(options.domainKeypair, validatedDomains);
var body = { csr: csr }; var body = { csr: csr };
var payload = JSON.stringify(body); var payload = JSON.stringify(body);
var tried = false;
var orderUrl = '';
function pollCert() { function pollCert() {
var jws = me.RSA.signJws( var certReq;
options.accountKeypair, var jws;
undefined, if (!tried) {
{ tried = true;
nonce: me._nonce, jws = me.RSA.signJws(
alg: me._alg || 'RS256', options.accountKeypair,
undefined,
{
nonce: me._nonce,
alg: me._alg || 'RS256',
url: me._finalize,
kid: me._kid
},
Buffer.from(payload)
);
certReq = {
method: 'POST',
url: me._finalize, url: me._finalize,
kid: me._kid headers: { 'Content-Type': 'application/jose+json' },
}, json: jws
Buffer.from(payload) };
); } else {
jws = me.RSA.signJws(
options.accountKeypair,
undefined,
{
nonce: me._nonce,
alg: me._alg || 'RS256',
url: orderUrl,
kid: me._kid
},
''
);
certReq = {
method: 'POST',
url: orderUrl,
headers: { 'Content-Type': 'application/jose+json' },
json: jws
};
}
if (me.debug) { if (me.debug) {
console.debug('finalize:', me._finalize); console.debug('finalize:', me._finalize);
} }
me._nonce = null; me._nonce = null;
return me
._request({
method: 'POST',
url: me._finalize,
headers: { 'Content-Type': 'application/jose+json' },
json: jws
})
.then(function (resp) {
// https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.3
// Possible values are: "pending" => ("invalid" || "ready") => "processing" => "valid"
me._nonce = resp.toJSON().headers['replay-nonce'];
if (me.debug) { return me._request(certReq).then(function (resp) {
console.debug('order finalized: resp.body:'); // https://tools.ietf.org/html/draft-ietf-acme-acme-12#section-7.1.3
} // Possible values are: "pending" => ("invalid" || "ready") => "processing" => "valid"
if (me.debug) { me._nonce = resp.toJSON().headers['replay-nonce'];
console.debug(resp.body); if (resp.headers.location) {
} orderUrl = resp.headers.location;
}
if ('valid' === resp.body.status) { if (me.debug) {
me._expires = resp.body.expires; console.debug('order finalized: resp.body:');
me._certificate = resp.body.certificate; }
if (me.debug) {
console.debug(resp.body);
}
return resp.body; // return order if ('valid' === resp.body.status) {
} me._expires = resp.body.expires;
me._certificate = resp.body.certificate;
if ('processing' === resp.body.status) { return resp.body; // return order
return ACME._wait().then(pollCert); }
}
if (me.debug) { if ('processing' === resp.body.status) {
console.debug( return ACME._wait().then(pollCert);
'Error: bad status:\n' + JSON.stringify(resp.body, null, 2) }
);
}
if ('pending' === resp.body.status) { if (me.debug) {
return Promise.reject( console.debug(
new Error( 'Error: bad status:\n' + JSON.stringify(resp.body, null, 2)
"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: '" +
validatedDomains.join(', ') +
"'\n" +
JSON.stringify(resp.body, null, 2)
)
);
}
if ('invalid' === resp.body.status) {
return Promise.reject(
new Error(
"Did not finalize order: status 'invalid'." +
' Best guess: One or more of the domain challenges could not be verified' +
' (or the order was canceled).\n' +
"Requested: '" +
options.domains.join(', ') +
"'\n" +
"Validated: '" +
validatedDomains.join(', ') +
"'\n" +
JSON.stringify(resp.body, null, 2)
)
);
}
if ('ready' === resp.body.status) {
return Promise.reject(
new Error(
"Did not finalize order: status 'ready'." +
" Hmmm... this state shouldn't be possible here. That was the last state." +
" This one should at least be 'processing'.\n" +
"Requested: '" +
options.domains.join(', ') +
"'\n" +
"Validated: '" +
validatedDomains.join(', ') +
"'\n" +
JSON.stringify(resp.body, null, 2) +
'\n\n' +
'Please open an issue at https://git.coolaj86.com/coolaj86/acme-v2.js'
)
);
}
if ('pending' === resp.body.status) {
return Promise.reject( return Promise.reject(
new Error( new Error(
"Didn't finalize order: Unhandled status '" + "Did not finalize order: status 'pending'." +
resp.body.status + ' Best guess: You have not accepted at least one challenge for each domain:\n' +
"'." + "Requested: '" +
' This is not one of the known statuses...\n' + options.domains.join(', ') +
"'\n" +
"Validated: '" +
validatedDomains.join(', ') +
"'\n" +
JSON.stringify(resp.body, null, 2)
)
);
}
if ('invalid' === resp.body.status) {
return Promise.reject(
new Error(
"Did not finalize order: status 'invalid'." +
' Best guess: One or more of the domain challenges could not be verified' +
' (or the order was canceled).\n' +
"Requested: '" +
options.domains.join(', ') +
"'\n" +
"Validated: '" +
validatedDomains.join(', ') +
"'\n" +
JSON.stringify(resp.body, null, 2)
)
);
}
if ('ready' === resp.body.status) {
return Promise.reject(
new Error(
"Did not finalize order: status 'ready'." +
" Hmmm... this state shouldn't be possible here. That was the last state." +
" This one should at least be 'processing'.\n" +
"Requested: '" + "Requested: '" +
options.domains.join(', ') + options.domains.join(', ') +
"'\n" + "'\n" +
@ -1023,7 +1032,26 @@ ACME._finalizeOrder = function (me, options, validatedDomains) {
'Please open an issue at https://git.coolaj86.com/coolaj86/acme-v2.js' 'Please open an issue at https://git.coolaj86.com/coolaj86/acme-v2.js'
) )
); );
}); }
return Promise.reject(
new Error(
"Didn't finalize order: Unhandled status '" +
resp.body.status +
"'." +
' This is not one of the known statuses...\n' +
"Requested: '" +
options.domains.join(', ') +
"'\n" +
"Validated: '" +
validatedDomains.join(', ') +
"'\n" +
JSON.stringify(resp.body, null, 2) +
'\n\n' +
'Please open an issue at https://git.coolaj86.com/coolaj86/acme-v2.js'
)
);
});
} }
return pollCert(); return pollCert();
@ -1177,7 +1205,11 @@ ACME._getCertificate = function (me, options) {
me._authorizations = resp.body.authorizations; me._authorizations = resp.body.authorizations;
me._order = location; me._order = location;
me._finalize = resp.body.finalize; me._finalize = resp.body.finalize;
//if (me.debug) console.debug('[DEBUG] finalize:', me._finalize); return; if (me.debug)
console.debug('[DEBUG] pre-finalize:', resp.headers);
if (me.debug) console.debug('[DEBUG] pre-finalize:', resp.body);
if (me.debug)
console.debug('[DEBUG] pre-finalize:', me._finalize);
if (!me._authorizations) { if (!me._authorizations) {
return Promise.reject( return Promise.reject(