Skip to content

Commit

Permalink
Add replaces option to client.auto() for ARI renewal
Browse files Browse the repository at this point in the history
  • Loading branch information
nmorsman committed Jul 17, 2024
1 parent 468f8ef commit 18158e7
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/auto.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const defaultOpts = {
email: null,
preferredChain: null,
termsOfServiceAgreed: false,
replacesCertificateId: null,
skipChallengeVerification: false,
challengePriority: ['http-01', 'dns-01'],
challengeCreateFn: async () => { throw new Error('Missing challengeCreateFn()'); },
Expand Down Expand Up @@ -67,6 +68,12 @@ module.exports = async (client, userOpts) => {

log('[auto] Placing new certificate order with ACME provider');
const orderPayload = { identifiers: uniqueDomains.map((d) => ({ type: 'dns', value: d })) };

if (opts.replacesCertificateId) {
log(`[auto] Replacing certificate with ID ${opts.replacesCertificateId}`);
orderPayload.replaces = opts.replacesCertificateId;
}

const order = await client.createOrder(orderPayload);
const authorizations = await client.getAuthorizations(order);

Expand Down
23 changes: 23 additions & 0 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ class AcmeClient {
* @param {function} opts.challengeRemoveFn Function returning Promise triggered after completing ACME challenge
* @param {string} [opts.email] Account email address
* @param {boolean} [opts.termsOfServiceAgreed] Agree to Terms of Service, default: `false`
* @param {string} [opts.replacesCertificateId] Certificate ID to replace when renewing using ARI
* @param {boolean} [opts.skipChallengeVerification] Skip internal challenge verification before notifying ACME provider, default: `false`
* @param {string[]} [opts.challengePriority] Array defining challenge type priority, default: `['http-01', 'dns-01']`
* @param {string} [opts.preferredChain] Indicate which certificate chain is preferred if a CA offers multiple, by exact issuer common name, default: `null`
Expand Down Expand Up @@ -777,6 +778,28 @@ class AcmeClient {
* challengeRemoveFn: async () => {},
* });
* ```
*
* @example Renew an existing certificate using ARI (ACME Renewal Information)
* ```js
* const certificate = { ... }; // Previously issued certificate
* const ariCertId = acme.crypto.getAriCertificateId(certificate);
* const waitSeconds = await client.getSecondsUntilCertificateRenewable(certId);
*
* if (waitSeconds === 0) {
* const [certificateKey, certificateRequest] = await acme.crypto.createCsr({
* altNames: ['test.example.com'],
* });
*
* const renewedCertificate = await client.auto({
* csr: certificateRequest,
* email: 'test@example.com',
* termsOfServiceAgreed: true,
* replacesCertificateId: ariCertId,
* challengeCreateFn: async () => {},
* challengeRemoveFn: async () => {},
* });
* }
* ```
*/

auto(opts) {
Expand Down
25 changes: 25 additions & 0 deletions test/70-auto.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ describe('client.auto', () => {
assert.isString(cert);
});

/**
* Alternate certificate chains
*/

it('should order alternate certificate chain [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function () {
if (!capAlternateCertRoots) {
this.skip();
Expand Down Expand Up @@ -385,6 +389,27 @@ describe('client.auto', () => {
assert.strictEqual(testIssuers[0], info.issuer.commonName);
});

/**
* Renew certificate using ACME Renewal Information (ARI)
*/

it('should renew certificate using ari', async () => {
const [, csr] = await acme.crypto.createCsr({
commonName: testDomain,
}, await createKeyFn());

const cert = await testClient.auto({
csr,
termsOfServiceAgreed: true,
replacesCertificateId: acme.crypto.getAriCertificateId(testCertificate),
challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn,
});

assert.isString(cert);
assert.notStrictEqual(cert, testCertificate);
});

/**
* Order certificate with alternate key sizes
*/
Expand Down

0 comments on commit 18158e7

Please sign in to comment.