🔱: [acme] sync upgrade with 3 commits [trident-sync]

Clean up eslintrc, style refactor and formatting fixes
Update auto.js

see https://github.com/publishlab/node-acme-client/issues/88#issuecomment-2105255828
pull/53/head
GitHub Actions Bot 2024-05-22 19:24:07 +00:00
parent c9d5cda953
commit 0f1ae6ccd9
34 changed files with 175 additions and 422 deletions

View File

@ -9,15 +9,8 @@ env:
rules: rules:
indent: [2, 4, { SwitchCase: 1, VariableDeclarator: 1 }] indent: [2, 4, { SwitchCase: 1, VariableDeclarator: 1 }]
brace-style: [2, 'stroustrup', { allowSingleLine: true }] brace-style: [2, 'stroustrup', { allowSingleLine: true }]
space-before-function-paren: [2, { anonymous: 'never', named: 'never' }]
func-names: 0 func-names: 0
prefer-destructuring: 0
object-curly-newline: 0
class-methods-use-this: 0 class-methods-use-this: 0
wrap-iife: [2, 'inside']
no-param-reassign: 0 no-param-reassign: 0
comma-dangle: [2, 'never']
max-len: [1, 200, 2, { ignoreUrls: true, ignoreComments: false }] max-len: [1, 200, 2, { ignoreUrls: true, ignoreComments: false }]
no-multiple-empty-lines: [2, { max: 2, maxBOF: 0, maxEOF: 0 }]
prefer-object-spread: 0
import/no-useless-path-segments: 0 import/no-useless-path-segments: 0

View File

@ -1,4 +1,3 @@
---
name: test name: test
on: [push, pull_request] on: [push, pull_request]
@ -12,7 +11,6 @@ jobs:
node: [16, 18, 20, 22] node: [16, 18, 20, 22]
eab: [0, 1] eab: [0, 1]
# #
# Environment # Environment
# #
@ -41,7 +39,6 @@ jobs:
ACME_HTTP_PORT: 5002 ACME_HTTP_PORT: 5002
ACME_HTTPS_PORT: 5003 ACME_HTTPS_PORT: 5003
# #
# Pipeline # Pipeline
# #

View File

@ -37,7 +37,7 @@
* `fixed` Upgrade `axios@0.26.1` * `fixed` Upgrade `axios@0.26.1`
* `fixed` Upgrade `node-forge@1.3.0` - [CVE-2022-24771](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24771), [CVE-2022-24772](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24772), [CVE-2022-24773](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24773) * `fixed` Upgrade `node-forge@1.3.0` - [CVE-2022-24771](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24771), [CVE-2022-24772](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24772), [CVE-2022-24773](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-24773)
## 4.2.4 (2022-03-19) ## v4.2.4 (2022-03-19)
* `fixed` Use SHA-256 when signing CSRs * `fixed` Use SHA-256 when signing CSRs

View File

@ -8,7 +8,6 @@ function log(m) {
process.stdout.write(`${m}\n`); process.stdout.write(`${m}\n`);
} }
/** /**
* Function used to satisfy an ACME challenge * Function used to satisfy an ACME challenge
* *
@ -25,7 +24,6 @@ async function challengeCreateFn(authz, challenge, keyAuthorization) {
log(keyAuthorization); log(keyAuthorization);
} }
/** /**
* Function used to remove an ACME challenge response * Function used to remove an ACME challenge response
* *
@ -41,30 +39,29 @@ async function challengeRemoveFn(authz, challenge, keyAuthorization) {
log(keyAuthorization); log(keyAuthorization);
} }
/** /**
* Main * Main
*/ */
module.exports = async function() { module.exports = async () => {
/* Init client */ /* Init client */
const client = new acme.Client({ const client = new acme.Client({
directoryUrl: acme.directory.letsencrypt.staging, directoryUrl: acme.directory.letsencrypt.staging,
accountKey: await acme.crypto.createPrivateKey() accountKey: await acme.crypto.createPrivateKey(),
}); });
/* Register account */ /* Register account */
await client.createAccount({ await client.createAccount({
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
contact: ['mailto:test@example.com'] contact: ['mailto:test@example.com'],
}); });
/* Place new order */ /* Place new order */
const order = await client.createOrder({ const order = await client.createOrder({
identifiers: [ identifiers: [
{ type: 'dns', value: 'example.com' }, { type: 'dns', value: 'example.com' },
{ type: 'dns', value: '*.example.com' } { type: 'dns', value: '*.example.com' },
] ],
}); });
/** /**
@ -139,7 +136,7 @@ module.exports = async function() {
/* Finalize order */ /* Finalize order */
const [key, csr] = await acme.crypto.createCsr({ const [key, csr] = await acme.crypto.createCsr({
commonName: '*.example.com', commonName: '*.example.com',
altNames: ['example.com'] altNames: ['example.com'],
}); });
const finalized = await client.finalizeOrder(order, csr); const finalized = await client.finalizeOrder(order, csr);

View File

@ -9,7 +9,6 @@ function log(m) {
process.stdout.write(`${m}\n`); process.stdout.write(`${m}\n`);
} }
/** /**
* Function used to satisfy an ACME challenge * Function used to satisfy an ACME challenge
* *
@ -47,7 +46,6 @@ async function challengeCreateFn(authz, challenge, keyAuthorization) {
} }
} }
/** /**
* Function used to remove an ACME challenge response * Function used to remove an ACME challenge response
* *
@ -80,25 +78,24 @@ async function challengeRemoveFn(authz, challenge, keyAuthorization) {
/* Replace this */ /* Replace this */
log(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`); log(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`);
// await dnsProvider.removeRecord(dnsRecord, 'TXT'); // await dnsProvider.removeRecord(dnsRecord, 'TXT', recordValue);
} }
} }
/** /**
* Main * Main
*/ */
module.exports = async function() { module.exports = async () => {
/* Init client */ /* Init client */
const client = new acme.Client({ const client = new acme.Client({
directoryUrl: acme.directory.letsencrypt.staging, directoryUrl: acme.directory.letsencrypt.staging,
accountKey: await acme.crypto.createPrivateKey() accountKey: await acme.crypto.createPrivateKey(),
}); });
/* Create CSR */ /* Create CSR */
const [key, csr] = await acme.crypto.createCsr({ const [key, csr] = await acme.crypto.createCsr({
commonName: 'example.com' commonName: 'example.com',
}); });
/* Certificate */ /* Certificate */
@ -107,7 +104,7 @@ module.exports = async function() {
email: 'test@example.com', email: 'test@example.com',
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn, challengeCreateFn,
challengeRemoveFn challengeRemoveFn,
}); });
/* Done */ /* Done */

View File

@ -19,7 +19,6 @@ function log(m) {
process.stdout.write(`${(new Date()).toISOString()} ${m}\n`); process.stdout.write(`${(new Date()).toISOString()} ${m}\n`);
} }
/** /**
* Main * Main
*/ */
@ -33,10 +32,9 @@ function log(m) {
log('Initializing ACME client'); log('Initializing ACME client');
const client = new acme.Client({ const client = new acme.Client({
directoryUrl: acme.directory.letsencrypt.staging, directoryUrl: acme.directory.letsencrypt.staging,
accountKey: await acme.crypto.createPrivateKey() accountKey: await acme.crypto.createPrivateKey(),
}); });
/** /**
* Order wildcard certificate * Order wildcard certificate
*/ */
@ -44,7 +42,7 @@ function log(m) {
log(`Creating CSR for ${WILDCARD_DOMAIN}`); log(`Creating CSR for ${WILDCARD_DOMAIN}`);
const [key, csr] = await acme.crypto.createCsr({ const [key, csr] = await acme.crypto.createCsr({
commonName: WILDCARD_DOMAIN, commonName: WILDCARD_DOMAIN,
altNames: [`*.${WILDCARD_DOMAIN}`] altNames: [`*.${WILDCARD_DOMAIN}`],
}); });
log(`Ordering certificate for ${WILDCARD_DOMAIN}`); log(`Ordering certificate for ${WILDCARD_DOMAIN}`);
@ -60,12 +58,11 @@ function log(m) {
challengeRemoveFn: (authz, challenge, keyAuthorization) => { challengeRemoveFn: (authz, challenge, keyAuthorization) => {
/* TODO: Implement this */ /* TODO: Implement this */
log(`[TODO] Remove TXT record key=_acme-challenge.${authz.identifier.value} value=${keyAuthorization}`); log(`[TODO] Remove TXT record key=_acme-challenge.${authz.identifier.value} value=${keyAuthorization}`);
} },
}); });
log(`Certificate for ${WILDCARD_DOMAIN} created successfully`); log(`Certificate for ${WILDCARD_DOMAIN} created successfully`);
/** /**
* HTTPS server * HTTPS server
*/ */
@ -78,7 +75,7 @@ function log(m) {
const httpsServer = https.createServer({ const httpsServer = https.createServer({
key, key,
cert cert,
}, requestListener); }, requestListener);
httpsServer.listen(HTTPS_SERVER_PORT, () => { httpsServer.listen(HTTPS_SERVER_PORT, () => {

View File

@ -23,7 +23,6 @@ function log(m) {
process.stdout.write(`${(new Date()).toISOString()} ${m}\n`); process.stdout.write(`${(new Date()).toISOString()} ${m}\n`);
} }
/** /**
* On-demand certificate generation using http-01 * On-demand certificate generation using http-01
*/ */
@ -52,7 +51,7 @@ async function getCertOnDemand(client, servername, attempt = 0) {
/* Create CSR */ /* Create CSR */
log(`Creating CSR for ${servername}`); log(`Creating CSR for ${servername}`);
const [key, csr] = await acme.crypto.createCsr({ const [key, csr] = await acme.crypto.createCsr({
commonName: servername commonName: servername,
}); });
/* Order certificate */ /* Order certificate */
@ -67,7 +66,7 @@ async function getCertOnDemand(client, servername, attempt = 0) {
}, },
challengeRemoveFn: (authz, challenge) => { challengeRemoveFn: (authz, challenge) => {
delete challengeResponses[challenge.token]; delete challengeResponses[challenge.token];
} },
}); });
/* Done, store certificate */ /* Done, store certificate */
@ -77,7 +76,6 @@ async function getCertOnDemand(client, servername, attempt = 0) {
return certificateStore[servername]; return certificateStore[servername];
} }
/** /**
* Main * Main
*/ */
@ -91,10 +89,9 @@ async function getCertOnDemand(client, servername, attempt = 0) {
log('Initializing ACME client'); log('Initializing ACME client');
const client = new acme.Client({ const client = new acme.Client({
directoryUrl: acme.directory.letsencrypt.staging, directoryUrl: acme.directory.letsencrypt.staging,
accountKey: await acme.crypto.createPrivateKey() accountKey: await acme.crypto.createPrivateKey(),
}); });
/** /**
* HTTP server * HTTP server
*/ */
@ -129,7 +126,6 @@ async function getCertOnDemand(client, servername, attempt = 0) {
log(`HTTP server listening on port ${HTTP_SERVER_PORT}`); log(`HTTP server listening on port ${HTTP_SERVER_PORT}`);
}); });
/** /**
* HTTPS server * HTTPS server
*/ */
@ -158,7 +154,7 @@ async function getCertOnDemand(client, servername, attempt = 0) {
log(`[ERROR] ${e.message}`); log(`[ERROR] ${e.message}`);
cb(e.message); cb(e.message);
} }
} },
}, requestListener); }, requestListener);
httpsServer.listen(HTTPS_SERVER_PORT, () => { httpsServer.listen(HTTPS_SERVER_PORT, () => {

View File

@ -22,7 +22,6 @@ function log(m) {
process.stdout.write(`${(new Date()).toISOString()} ${m}\n`); process.stdout.write(`${(new Date()).toISOString()} ${m}\n`);
} }
/** /**
* On-demand certificate generation using tls-alpn-01 * On-demand certificate generation using tls-alpn-01
*/ */
@ -51,7 +50,7 @@ async function getCertOnDemand(client, servername, attempt = 0) {
/* Create CSR */ /* Create CSR */
log(`Creating CSR for ${servername}`); log(`Creating CSR for ${servername}`);
const [key, csr] = await acme.crypto.createCsr({ const [key, csr] = await acme.crypto.createCsr({
commonName: servername commonName: servername,
}); });
/* Order certificate */ /* Order certificate */
@ -66,7 +65,7 @@ async function getCertOnDemand(client, servername, attempt = 0) {
}, },
challengeRemoveFn: (authz) => { challengeRemoveFn: (authz) => {
delete alpnResponses[authz.identifier.value]; delete alpnResponses[authz.identifier.value];
} },
}); });
/* Done, store certificate */ /* Done, store certificate */
@ -76,7 +75,6 @@ async function getCertOnDemand(client, servername, attempt = 0) {
return certificateStore[servername]; return certificateStore[servername];
} }
/** /**
* Main * Main
*/ */
@ -90,10 +88,9 @@ async function getCertOnDemand(client, servername, attempt = 0) {
log('Initializing ACME client'); log('Initializing ACME client');
const client = new acme.Client({ const client = new acme.Client({
directoryUrl: acme.directory.letsencrypt.staging, directoryUrl: acme.directory.letsencrypt.staging,
accountKey: await acme.crypto.createPrivateKey() accountKey: await acme.crypto.createPrivateKey(),
}); });
/** /**
* ALPN responder * ALPN responder
*/ */
@ -118,14 +115,14 @@ async function getCertOnDemand(client, servername, attempt = 0) {
log(`Found ALPN certificate for ${servername}, serving secure context`); log(`Found ALPN certificate for ${servername}, serving secure context`);
cb(null, tls.createSecureContext({ cb(null, tls.createSecureContext({
key: alpnResponses[servername][0], key: alpnResponses[servername][0],
cert: alpnResponses[servername][1] cert: alpnResponses[servername][1],
})); }));
} }
catch (e) { catch (e) {
log(`[ERROR] ${e.message}`); log(`[ERROR] ${e.message}`);
cb(e.message); cb(e.message);
} }
} },
}); });
/* Terminate once TLS handshake has been established */ /* Terminate once TLS handshake has been established */
@ -137,7 +134,6 @@ async function getCertOnDemand(client, servername, attempt = 0) {
log(`ALPN responder listening on port ${ALPN_RESPONDER_PORT}`); log(`ALPN responder listening on port ${ALPN_RESPONDER_PORT}`);
}); });
/** /**
* HTTPS server * HTTPS server
*/ */
@ -166,7 +162,7 @@ async function getCertOnDemand(client, servername, attempt = 0) {
log(`[ERROR] ${e.message}`); log(`[ERROR] ${e.message}`);
cb(e.message); cb(e.message);
} }
} },
}, requestListener); }, requestListener);
httpsServer.listen(HTTPS_SERVER_PORT, () => { httpsServer.listen(HTTPS_SERVER_PORT, () => {

View File

@ -4,7 +4,6 @@
const util = require('./util'); const util = require('./util');
/** /**
* AcmeApi * AcmeApi
* *
@ -18,7 +17,6 @@ class AcmeApi {
this.accountUrl = accountUrl; this.accountUrl = accountUrl;
} }
/** /**
* Get account URL * Get account URL
* *
@ -34,7 +32,6 @@ class AcmeApi {
return this.accountUrl; return this.accountUrl;
} }
/** /**
* ACME API request * ACME API request
* *
@ -59,7 +56,6 @@ class AcmeApi {
return resp; return resp;
} }
/** /**
* ACME API request by resource name helper * ACME API request by resource name helper
* *
@ -78,7 +74,6 @@ class AcmeApi {
return this.apiRequest(resourceUrl, payload, validStatusCodes, { includeJwsKid, includeExternalAccountBinding }); return this.apiRequest(resourceUrl, payload, validStatusCodes, { includeJwsKid, includeExternalAccountBinding });
} }
/** /**
* Get Terms of Service URL if available * Get Terms of Service URL if available
* *
@ -91,7 +86,6 @@ class AcmeApi {
return this.http.getMetaField('termsOfService'); return this.http.getMetaField('termsOfService');
} }
/** /**
* Create new account * Create new account
* *
@ -104,7 +98,7 @@ class AcmeApi {
async createAccount(data) { async createAccount(data) {
const resp = await this.apiResourceRequest('newAccount', data, [200, 201], { const resp = await this.apiResourceRequest('newAccount', data, [200, 201], {
includeJwsKid: false, includeJwsKid: false,
includeExternalAccountBinding: (data.onlyReturnExisting !== true) includeExternalAccountBinding: (data.onlyReturnExisting !== true),
}); });
/* Set account URL */ /* Set account URL */
@ -115,7 +109,6 @@ class AcmeApi {
return resp; return resp;
} }
/** /**
* Update account * Update account
* *
@ -129,7 +122,6 @@ class AcmeApi {
return this.apiRequest(this.getAccountUrl(), data, [200, 202]); return this.apiRequest(this.getAccountUrl(), data, [200, 202]);
} }
/** /**
* Update account key * Update account key
* *
@ -143,7 +135,6 @@ class AcmeApi {
return this.apiResourceRequest('keyChange', data, [200]); return this.apiResourceRequest('keyChange', data, [200]);
} }
/** /**
* Create new order * Create new order
* *
@ -157,7 +148,6 @@ class AcmeApi {
return this.apiResourceRequest('newOrder', data, [201]); return this.apiResourceRequest('newOrder', data, [201]);
} }
/** /**
* Get order * Get order
* *
@ -171,7 +161,6 @@ class AcmeApi {
return this.apiRequest(url, null, [200]); return this.apiRequest(url, null, [200]);
} }
/** /**
* Finalize order * Finalize order
* *
@ -186,7 +175,6 @@ class AcmeApi {
return this.apiRequest(url, data, [200]); return this.apiRequest(url, data, [200]);
} }
/** /**
* Get identifier authorization * Get identifier authorization
* *
@ -200,7 +188,6 @@ class AcmeApi {
return this.apiRequest(url, null, [200]); return this.apiRequest(url, null, [200]);
} }
/** /**
* Update identifier authorization * Update identifier authorization
* *
@ -215,7 +202,6 @@ class AcmeApi {
return this.apiRequest(url, data, [200]); return this.apiRequest(url, data, [200]);
} }
/** /**
* Complete challenge * Complete challenge
* *
@ -230,7 +216,6 @@ class AcmeApi {
return this.apiRequest(url, data, [200]); return this.apiRequest(url, data, [200]);
} }
/** /**
* Revoke certificate * Revoke certificate
* *
@ -245,6 +230,5 @@ class AcmeApi {
} }
} }
/* Export API */ /* Export API */
module.exports = AcmeApi; module.exports = AcmeApi;

View File

@ -13,10 +13,9 @@ const defaultOpts = {
skipChallengeVerification: false, skipChallengeVerification: false,
challengePriority: ['http-01', 'dns-01'], challengePriority: ['http-01', 'dns-01'],
challengeCreateFn: async () => { throw new Error('Missing challengeCreateFn()'); }, challengeCreateFn: async () => { throw new Error('Missing challengeCreateFn()'); },
challengeRemoveFn: async () => { throw new Error('Missing challengeRemoveFn()'); } challengeRemoveFn: async () => { throw new Error('Missing challengeRemoveFn()'); },
}; };
/** /**
* ACME client auto mode * ACME client auto mode
* *
@ -25,8 +24,8 @@ const defaultOpts = {
* @returns {Promise<buffer>} Certificate * @returns {Promise<buffer>} Certificate
*/ */
module.exports = async function(client, userOpts) { module.exports = async (client, userOpts) => {
const opts = Object.assign({}, defaultOpts, userOpts); const opts = { ...defaultOpts, ...userOpts };
const accountPayload = { termsOfServiceAgreed: opts.termsOfServiceAgreed }; const accountPayload = { termsOfServiceAgreed: opts.termsOfServiceAgreed };
if (!Buffer.isBuffer(opts.csr)) { if (!Buffer.isBuffer(opts.csr)) {
@ -37,7 +36,6 @@ module.exports = async function(client, userOpts) {
accountPayload.contact = [`mailto:${opts.email}`]; accountPayload.contact = [`mailto:${opts.email}`];
} }
/** /**
* Register account * Register account
*/ */
@ -53,7 +51,6 @@ module.exports = async function(client, userOpts) {
await client.createAccount(accountPayload); await client.createAccount(accountPayload);
} }
/** /**
* Parse domains from CSR * Parse domains from CSR
*/ */
@ -64,7 +61,6 @@ module.exports = async function(client, userOpts) {
log(`[auto] Resolved ${uniqueDomains.length} unique domains from parsing the Certificate Signing Request`); log(`[auto] Resolved ${uniqueDomains.length} unique domains from parsing the Certificate Signing Request`);
/** /**
* Place order * Place order
*/ */
@ -76,7 +72,6 @@ module.exports = async function(client, userOpts) {
log(`[auto] Placed certificate order successfully, received ${authorizations.length} identity authorizations`); log(`[auto] Placed certificate order successfully, received ${authorizations.length} identity authorizations`);
/** /**
* Resolve and satisfy challenges * Resolve and satisfy challenges
*/ */
@ -164,7 +159,6 @@ module.exports = async function(client, userOpts) {
} }
}); });
/** /**
* Wait for all challenge promises to settle * Wait for all challenge promises to settle
*/ */
@ -178,7 +172,6 @@ module.exports = async function(client, userOpts) {
throw e; throw e;
} }
/** /**
* Finalize order and download certificate * Finalize order and download certificate
*/ */

View File

@ -5,7 +5,6 @@
const axios = require('axios'); const axios = require('axios');
const pkg = require('./../package.json'); const pkg = require('./../package.json');
/** /**
* Instance * Instance
*/ */
@ -19,10 +18,9 @@ instance.defaults.headers.common['User-Agent'] = `node-${pkg.name}/${pkg.version
instance.defaults.acmeSettings = { instance.defaults.acmeSettings = {
httpChallengePort: 80, httpChallengePort: 80,
httpsChallengePort: 443, httpsChallengePort: 443,
tlsAlpnChallengePort: 443 tlsAlpnChallengePort: 443,
}; };
/** /**
* Explicitly set Node as default HTTP adapter * Explicitly set Node as default HTTP adapter
* *
@ -32,7 +30,6 @@ instance.defaults.acmeSettings = {
instance.defaults.adapter = 'http'; instance.defaults.adapter = 'http';
/** /**
* Export instance * Export instance
*/ */

View File

@ -13,7 +13,6 @@ const verify = require('./verify');
const util = require('./util'); const util = require('./util');
const auto = require('./auto'); const auto = require('./auto');
/** /**
* ACME states * ACME states
* *
@ -24,7 +23,6 @@ const validStates = ['ready', 'valid'];
const pendingStates = ['pending', 'processing']; const pendingStates = ['pending', 'processing'];
const invalidStates = ['invalid']; const invalidStates = ['invalid'];
/** /**
* Default options * Default options
* *
@ -38,10 +36,9 @@ const defaultOpts = {
externalAccountBinding: {}, externalAccountBinding: {},
backoffAttempts: 10, backoffAttempts: 10,
backoffMin: 5000, backoffMin: 5000,
backoffMax: 30000 backoffMax: 30000,
}; };
/** /**
* AcmeClient * AcmeClient
* *
@ -96,19 +93,17 @@ class AcmeClient {
opts.accountKey = Buffer.from(opts.accountKey); opts.accountKey = Buffer.from(opts.accountKey);
} }
this.opts = Object.assign({}, defaultOpts, opts); this.opts = { ...defaultOpts, ...opts };
this.backoffOpts = { this.backoffOpts = {
attempts: this.opts.backoffAttempts, attempts: this.opts.backoffAttempts,
min: this.opts.backoffMin, min: this.opts.backoffMin,
max: this.opts.backoffMax max: this.opts.backoffMax,
}; };
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding); this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding);
this.api = new AcmeApi(this.http, this.opts.accountUrl); this.api = new AcmeApi(this.http, this.opts.accountUrl);
} }
/** /**
* Get Terms of Service URL if available * Get Terms of Service URL if available
* *
@ -128,7 +123,6 @@ class AcmeClient {
return this.api.getTermsOfServiceUrl(); return this.api.getTermsOfServiceUrl();
} }
/** /**
* Get current account URL * Get current account URL
* *
@ -150,7 +144,6 @@ class AcmeClient {
return this.api.getAccountUrl(); return this.api.getAccountUrl();
} }
/** /**
* Create a new account * Create a new account
* *
@ -196,7 +189,6 @@ class AcmeClient {
} }
} }
/** /**
* Update existing account * Update existing account
* *
@ -236,7 +228,6 @@ class AcmeClient {
return resp.data; return resp.data;
} }
/** /**
* Update account private key * Update account private key
* *
@ -282,7 +273,6 @@ class AcmeClient {
return resp.data; return resp.data;
} }
/** /**
* Create a new order * Create a new order
* *
@ -314,7 +304,6 @@ class AcmeClient {
return resp.data; return resp.data;
} }
/** /**
* Refresh order object from CA * Refresh order object from CA
* *
@ -376,7 +365,6 @@ class AcmeClient {
return resp.data; return resp.data;
} }
/** /**
* Get identifier authorizations from order * Get identifier authorizations from order
* *
@ -406,7 +394,6 @@ class AcmeClient {
})); }));
} }
/** /**
* Deactivate identifier authorization * Deactivate identifier authorization
* *
@ -427,10 +414,7 @@ class AcmeClient {
throw new Error('Unable to deactivate identifier authorization, URL not found'); throw new Error('Unable to deactivate identifier authorization, URL not found');
} }
const data = { const data = { status: 'deactivated' };
status: 'deactivated'
};
const resp = await this.api.updateAuthorization(authz.url, data); const resp = await this.api.updateAuthorization(authz.url, data);
/* Add URL to response */ /* Add URL to response */
@ -438,7 +422,6 @@ class AcmeClient {
return resp.data; return resp.data;
} }
/** /**
* Get key authorization for ACME challenge * Get key authorization for ACME challenge
* *
@ -480,7 +463,6 @@ class AcmeClient {
throw new Error(`Unable to produce key authorization, unknown challenge type: ${challenge.type}`); throw new Error(`Unable to produce key authorization, unknown challenge type: ${challenge.type}`);
} }
/** /**
* Verify that ACME challenge is satisfied * Verify that ACME challenge is satisfied
* *
@ -515,7 +497,6 @@ class AcmeClient {
return util.retry(verifyFn, this.backoffOpts); return util.retry(verifyFn, this.backoffOpts);
} }
/** /**
* Notify CA that challenge has been completed * Notify CA that challenge has been completed
* *
@ -536,7 +517,6 @@ class AcmeClient {
return resp.data; return resp.data;
} }
/** /**
* Wait for ACME provider to verify status on a order, authorization or challenge * Wait for ACME provider to verify status on a order, authorization or challenge
* *
@ -593,7 +573,6 @@ class AcmeClient {
return util.retry(verifyFn, this.backoffOpts); return util.retry(verifyFn, this.backoffOpts);
} }
/** /**
* Get certificate from ACME order * Get certificate from ACME order
* *
@ -640,7 +619,6 @@ class AcmeClient {
return resp.data; return resp.data;
} }
/** /**
* Revoke certificate * Revoke certificate
* *
@ -671,7 +649,6 @@ class AcmeClient {
return resp.data; return resp.data;
} }
/** /**
* Auto mode * Auto mode
* *
@ -727,6 +704,5 @@ class AcmeClient {
} }
} }
/* Export client */ /* Export client */
module.exports = AcmeClient; module.exports = AcmeClient;

View File

@ -13,7 +13,6 @@ const forge = require('node-forge');
const generateKeyPair = promisify(forge.pki.rsa.generateKeyPair); const generateKeyPair = promisify(forge.pki.rsa.generateKeyPair);
/** /**
* Attempt to parse forge object from PEM encoded string * Attempt to parse forge object from PEM encoded string
* *
@ -54,7 +53,6 @@ function forgeObjectFromPem(input) {
return result; return result;
} }
/** /**
* Parse domain names from a certificate or CSR * Parse domain names from a certificate or CSR
* *
@ -93,11 +91,10 @@ function parseDomains(obj) {
return { return {
commonName, commonName,
altNames altNames,
}; };
} }
/** /**
* Generate a private RSA key * Generate a private RSA key
* *
@ -123,7 +120,6 @@ async function createPrivateKey(size = 2048) {
exports.createPrivateKey = createPrivateKey; exports.createPrivateKey = createPrivateKey;
/** /**
* Create public key from a private RSA key * Create public key from a private RSA key
* *
@ -136,14 +132,13 @@ exports.createPrivateKey = createPrivateKey;
* ``` * ```
*/ */
exports.createPublicKey = async function(key) { exports.createPublicKey = async (key) => {
const privateKey = forge.pki.privateKeyFromPem(key); const privateKey = forge.pki.privateKeyFromPem(key);
const publicKey = forge.pki.rsa.setPublicKey(privateKey.n, privateKey.e); const publicKey = forge.pki.rsa.setPublicKey(privateKey.n, privateKey.e);
const pemKey = forge.pki.publicKeyToPem(publicKey); const pemKey = forge.pki.publicKeyToPem(publicKey);
return Buffer.from(pemKey); return Buffer.from(pemKey);
}; };
/** /**
* Parse body of PEM encoded object from buffer or string * Parse body of PEM encoded object from buffer or string
* If multiple objects are chained, the first body will be returned * If multiple objects are chained, the first body will be returned
@ -157,7 +152,6 @@ exports.getPemBody = (str) => {
return forge.util.encode64(msg.body); return forge.util.encode64(msg.body);
}; };
/** /**
* Split chain of PEM encoded objects from buffer or string into array * Split chain of PEM encoded objects from buffer or string into array
* *
@ -167,7 +161,6 @@ exports.getPemBody = (str) => {
exports.splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode); exports.splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode);
/** /**
* Get modulus * Get modulus
* *
@ -182,7 +175,7 @@ exports.splitPemChain = (str) => forge.pem.decode(str).map(forge.pem.encode);
* ``` * ```
*/ */
exports.getModulus = async function(input) { exports.getModulus = async (input) => {
if (!Buffer.isBuffer(input)) { if (!Buffer.isBuffer(input)) {
input = Buffer.from(input); input = Buffer.from(input);
} }
@ -191,7 +184,6 @@ exports.getModulus = async function(input) {
return Buffer.from(forge.util.hexToBytes(obj.n.toString(16)), 'binary'); return Buffer.from(forge.util.hexToBytes(obj.n.toString(16)), 'binary');
}; };
/** /**
* Get public exponent * Get public exponent
* *
@ -206,7 +198,7 @@ exports.getModulus = async function(input) {
* ``` * ```
*/ */
exports.getPublicExponent = async function(input) { exports.getPublicExponent = async (input) => {
if (!Buffer.isBuffer(input)) { if (!Buffer.isBuffer(input)) {
input = Buffer.from(input); input = Buffer.from(input);
} }
@ -215,7 +207,6 @@ exports.getPublicExponent = async function(input) {
return Buffer.from(forge.util.hexToBytes(obj.e.toString(16)), 'binary'); return Buffer.from(forge.util.hexToBytes(obj.e.toString(16)), 'binary');
}; };
/** /**
* Read domains from a Certificate Signing Request * Read domains from a Certificate Signing Request
* *
@ -231,7 +222,7 @@ exports.getPublicExponent = async function(input) {
* ``` * ```
*/ */
exports.readCsrDomains = async function(csr) { exports.readCsrDomains = async (csr) => {
if (!Buffer.isBuffer(csr)) { if (!Buffer.isBuffer(csr)) {
csr = Buffer.from(csr); csr = Buffer.from(csr);
} }
@ -240,7 +231,6 @@ exports.readCsrDomains = async function(csr) {
return parseDomains(obj); return parseDomains(obj);
}; };
/** /**
* Read information from a certificate * Read information from a certificate
* *
@ -260,7 +250,7 @@ exports.readCsrDomains = async function(csr) {
* ``` * ```
*/ */
exports.readCertificateInfo = async function(cert) { exports.readCertificateInfo = async (cert) => {
if (!Buffer.isBuffer(cert)) { if (!Buffer.isBuffer(cert)) {
cert = Buffer.from(cert); cert = Buffer.from(cert);
} }
@ -270,15 +260,14 @@ exports.readCertificateInfo = async function(cert) {
return { return {
issuer: { issuer: {
commonName: issuerCn ? issuerCn.value : null commonName: issuerCn ? issuerCn.value : null,
}, },
domains: parseDomains(obj), domains: parseDomains(obj),
notAfter: obj.validity.notAfter, notAfter: obj.validity.notAfter,
notBefore: obj.validity.notBefore notBefore: obj.validity.notBefore,
}; };
}; };
/** /**
* Determine ASN.1 type for CSR subject short name * Determine ASN.1 type for CSR subject short name
* Note: https://datatracker.ietf.org/doc/html/rfc5280 * Note: https://datatracker.ietf.org/doc/html/rfc5280
@ -299,7 +288,6 @@ function getCsrValueTagClass(shortName) {
} }
} }
/** /**
* Create array of short names and values for Certificate Signing Request subjects * Create array of short names and values for Certificate Signing Request subjects
* *
@ -319,7 +307,6 @@ function createCsrSubject(subjectObj) {
}, []); }, []);
} }
/** /**
* Create array of alt names for Certificate Signing Requests * Create array of alt names for Certificate Signing Requests
* Note: https://github.com/digitalbazaar/forge/blob/dfdde475677a8a25c851e33e8f81dca60d90cfb9/lib/x509.js#L1444-L1454 * Note: https://github.com/digitalbazaar/forge/blob/dfdde475677a8a25c851e33e8f81dca60d90cfb9/lib/x509.js#L1444-L1454
@ -336,7 +323,6 @@ function formatCsrAltNames(altNames) {
}); });
} }
/** /**
* Create a Certificate Signing Request * Create a Certificate Signing Request
* *
@ -391,7 +377,7 @@ function formatCsrAltNames(altNames) {
* }, certificateKey); * }, certificateKey);
*/ */
exports.createCsr = async function(data, key = null) { exports.createCsr = async (data, key = null) => {
if (!key) { if (!key) {
key = await createPrivateKey(data.keySize); key = await createPrivateKey(data.keySize);
} }
@ -423,7 +409,7 @@ exports.createCsr = async function(data, key = null) {
L: data.locality, L: data.locality,
O: data.organization, O: data.organization,
OU: data.organizationUnit, OU: data.organizationUnit,
E: data.emailAddress E: data.emailAddress,
}); });
csr.setSubject(subject); csr.setSubject(subject);
@ -434,8 +420,8 @@ exports.createCsr = async function(data, key = null) {
name: 'extensionRequest', name: 'extensionRequest',
extensions: [{ extensions: [{
name: 'subjectAltName', name: 'subjectAltName',
altNames: formatCsrAltNames(data.altNames) altNames: formatCsrAltNames(data.altNames),
}] }],
}]); }]);
} }

View File

@ -22,7 +22,6 @@ const subjectAltNameOID = '2.5.29.17';
/* id-pe-acmeIdentifier - https://datatracker.ietf.org/doc/html/rfc8737#section-6.1 */ /* id-pe-acmeIdentifier - https://datatracker.ietf.org/doc/html/rfc8737#section-6.1 */
const alpnAcmeIdentifierOID = '1.3.6.1.5.5.7.1.31'; const alpnAcmeIdentifierOID = '1.3.6.1.5.5.7.1.31';
/** /**
* Determine key type and info by attempting to derive public key * Determine key type and info by attempting to derive public key
* *
@ -35,7 +34,7 @@ function getKeyInfo(keyPem) {
const result = { const result = {
isRSA: false, isRSA: false,
isECDSA: false, isECDSA: false,
publicKey: crypto.createPublicKey(keyPem) publicKey: crypto.createPublicKey(keyPem),
}; };
if (result.publicKey.asymmetricKeyType === 'rsa') { if (result.publicKey.asymmetricKeyType === 'rsa') {
@ -51,7 +50,6 @@ function getKeyInfo(keyPem) {
return result; return result;
} }
/** /**
* Generate a private RSA key * Generate a private RSA key
* *
@ -74,8 +72,8 @@ async function createPrivateRsaKey(modulusLength = 2048) {
modulusLength, modulusLength,
privateKeyEncoding: { privateKeyEncoding: {
type: 'pkcs8', type: 'pkcs8',
format: 'pem' format: 'pem',
} },
}); });
return Buffer.from(pair.privateKey); return Buffer.from(pair.privateKey);
@ -83,7 +81,6 @@ async function createPrivateRsaKey(modulusLength = 2048) {
exports.createPrivateRsaKey = createPrivateRsaKey; exports.createPrivateRsaKey = createPrivateRsaKey;
/** /**
* Alias of `createPrivateRsaKey()` * Alias of `createPrivateRsaKey()`
* *
@ -92,7 +89,6 @@ exports.createPrivateRsaKey = createPrivateRsaKey;
exports.createPrivateKey = createPrivateRsaKey; exports.createPrivateKey = createPrivateRsaKey;
/** /**
* Generate a private ECDSA key * Generate a private ECDSA key
* *
@ -115,14 +111,13 @@ exports.createPrivateEcdsaKey = async (namedCurve = 'P-256') => {
namedCurve, namedCurve,
privateKeyEncoding: { privateKeyEncoding: {
type: 'pkcs8', type: 'pkcs8',
format: 'pem' format: 'pem',
} },
}); });
return Buffer.from(pair.privateKey); return Buffer.from(pair.privateKey);
}; };
/** /**
* Get a public key derived from a RSA or ECDSA key * Get a public key derived from a RSA or ECDSA key
* *
@ -140,13 +135,12 @@ exports.getPublicKey = (keyPem) => {
const publicKey = info.publicKey.export({ const publicKey = info.publicKey.export({
type: info.isECDSA ? 'spki' : 'pkcs1', type: info.isECDSA ? 'spki' : 'pkcs1',
format: 'pem' format: 'pem',
}); });
return Buffer.from(publicKey); return Buffer.from(publicKey);
}; };
/** /**
* Get a JSON Web Key derived from a RSA or ECDSA key * Get a JSON Web Key derived from a RSA or ECDSA key
* *
@ -163,7 +157,7 @@ exports.getPublicKey = (keyPem) => {
function getJwk(keyPem) { function getJwk(keyPem) {
const jwk = crypto.createPublicKey(keyPem).export({ const jwk = crypto.createPublicKey(keyPem).export({
format: 'jwk' format: 'jwk',
}); });
/* Sort keys */ /* Sort keys */
@ -175,7 +169,6 @@ function getJwk(keyPem) {
exports.getJwk = getJwk; exports.getJwk = getJwk;
/** /**
* Produce CryptoKeyPair and signing algorithm from a PEM encoded private key * Produce CryptoKeyPair and signing algorithm from a PEM encoded private key
* *
@ -191,7 +184,7 @@ async function getWebCryptoKeyPair(keyPem) {
/* Signing algorithm */ /* Signing algorithm */
const sigalg = { const sigalg = {
name: 'RSASSA-PKCS1-v1_5', name: 'RSASSA-PKCS1-v1_5',
hash: { name: 'SHA-256' } hash: { name: 'SHA-256' },
}; };
if (info.isECDSA) { if (info.isECDSA) {
@ -215,7 +208,6 @@ async function getWebCryptoKeyPair(keyPem) {
return [{ privateKey, publicKey }, sigalg]; return [{ privateKey, publicKey }, sigalg];
} }
/** /**
* Split chain of PEM encoded objects from string into array * Split chain of PEM encoded objects from string into array
* *
@ -235,7 +227,6 @@ function splitPemChain(chainPem) {
exports.splitPemChain = splitPemChain; exports.splitPemChain = splitPemChain;
/** /**
* Parse body of PEM encoded object and return a Base64URL string * Parse body of PEM encoded object and return a Base64URL string
* If multiple objects are chained, the first body will be returned * If multiple objects are chained, the first body will be returned
@ -256,7 +247,6 @@ exports.getPemBodyAsB64u = (pem) => {
return Buffer.from(dec).toString('base64url'); return Buffer.from(dec).toString('base64url');
}; };
/** /**
* Parse domains from a certificate or CSR * Parse domains from a certificate or CSR
* *
@ -277,11 +267,10 @@ function parseDomains(input) {
return { return {
commonName, commonName,
altNames altNames,
}; };
} }
/** /**
* Read domains from a Certificate Signing Request * Read domains from a Certificate Signing Request
* *
@ -307,7 +296,6 @@ exports.readCsrDomains = (csrPem) => {
return parseDomains(csr); return parseDomains(csr);
}; };
/** /**
* Read information from a certificate * Read information from a certificate
* If multiple certificates are chained, the first will be read * If multiple certificates are chained, the first will be read
@ -338,15 +326,14 @@ exports.readCertificateInfo = (certPem) => {
return { return {
issuer: { issuer: {
commonName: cert.issuerName.getField('CN').pop() || null commonName: cert.issuerName.getField('CN').pop() || null,
}, },
domains: parseDomains(cert), domains: parseDomains(cert),
notBefore: cert.notBefore, notBefore: cert.notBefore,
notAfter: cert.notAfter notAfter: cert.notAfter,
}; };
}; };
/** /**
* Determine ASN.1 character string type for CSR subject field name * Determine ASN.1 character string type for CSR subject field name
* *
@ -369,7 +356,6 @@ function getCsrAsn1CharStringType(field) {
} }
} }
/** /**
* Create array of subject fields for a Certificate Signing Request * Create array of subject fields for a Certificate Signing Request
* *
@ -391,7 +377,6 @@ function createCsrSubject(input) {
}, []); }, []);
} }
/** /**
* Create x509 subject alternate name extension * Create x509 subject alternate name extension
* *
@ -409,7 +394,6 @@ function createSubjectAltNameExtension(altNames) {
})); }));
} }
/** /**
* Create a Certificate Signing Request * Create a Certificate Signing Request
* *
@ -489,7 +473,7 @@ exports.createCsr = async (data, keyPem = null) => {
new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature | x509.KeyUsageFlags.keyEncipherment), // eslint-disable-line no-bitwise new x509.KeyUsagesExtension(x509.KeyUsageFlags.digitalSignature | x509.KeyUsageFlags.keyEncipherment), // eslint-disable-line no-bitwise
/* https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 */ /* https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 */
createSubjectAltNameExtension(data.altNames) createSubjectAltNameExtension(data.altNames),
]; ];
/* Create CSR */ /* Create CSR */
@ -504,8 +488,8 @@ exports.createCsr = async (data, keyPem = null) => {
L: data.locality, L: data.locality,
O: data.organization, O: data.organization,
OU: data.organizationUnit, OU: data.organizationUnit,
E: data.emailAddress E: data.emailAddress,
}) }),
}); });
/* Done */ /* Done */
@ -513,7 +497,6 @@ exports.createCsr = async (data, keyPem = null) => {
return [keyPem, Buffer.from(pem)]; return [keyPem, Buffer.from(pem)];
}; };
/** /**
* Create a self-signed ALPN certificate for TLS-ALPN-01 challenges * Create a self-signed ALPN certificate for TLS-ALPN-01 challenges
* *
@ -564,7 +547,7 @@ exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) =
await x509.SubjectKeyIdentifierExtension.create(keys.publicKey), await x509.SubjectKeyIdentifierExtension.create(keys.publicKey),
/* https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 */ /* https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.6 */
createSubjectAltNameExtension([commonName]) createSubjectAltNameExtension([commonName]),
]; ];
/* ALPN extension */ /* ALPN extension */
@ -581,8 +564,8 @@ exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) =
notBefore: now, notBefore: now,
notAfter: now, notAfter: now,
name: createCsrSubject({ name: createCsrSubject({
CN: commonName CN: commonName,
}) }),
}); });
/* Done */ /* Done */
@ -590,7 +573,6 @@ exports.createAlpnCertificate = async (authz, keyAuthorization, keyPem = null) =
return [keyPem, Buffer.from(pem)]; return [keyPem, Buffer.from(pem)];
}; };
/** /**
* Validate that a ALPN certificate contains the expected key authorization * Validate that a ALPN certificate contains the expected key authorization
* *

View File

@ -7,7 +7,6 @@ const { getJwk } = require('./crypto');
const { log } = require('./logger'); const { log } = require('./logger');
const axios = require('./axios'); const axios = require('./axios');
/** /**
* ACME HTTP client * ACME HTTP client
* *
@ -30,7 +29,6 @@ class HttpClient {
this.jwk = null; this.jwk = null;
} }
/** /**
* HTTP request * HTTP request
* *
@ -60,7 +58,6 @@ class HttpClient {
return resp; return resp;
} }
/** /**
* Ensure provider directory exists * Ensure provider directory exists
* *
@ -85,7 +82,6 @@ class HttpClient {
} }
} }
/** /**
* Get JSON Web Key * Get JSON Web Key
* *
@ -100,7 +96,6 @@ class HttpClient {
return this.jwk; return this.jwk;
} }
/** /**
* Get nonce from directory API endpoint * Get nonce from directory API endpoint
* *
@ -120,7 +115,6 @@ class HttpClient {
return resp.headers['replay-nonce']; return resp.headers['replay-nonce'];
} }
/** /**
* Get URL for a directory resource * Get URL for a directory resource
* *
@ -138,7 +132,6 @@ class HttpClient {
return this.directory[resource]; return this.directory[resource];
} }
/** /**
* Get directory meta field * Get directory meta field
* *
@ -156,7 +149,6 @@ class HttpClient {
return null; return null;
} }
/** /**
* Prepare HTTP request body for signature * Prepare HTTP request body for signature
* *
@ -189,11 +181,10 @@ class HttpClient {
/* Body */ /* Body */
return { return {
payload: payload ? Buffer.from(JSON.stringify(payload)).toString('base64url') : '', payload: payload ? Buffer.from(JSON.stringify(payload)).toString('base64url') : '',
protected: Buffer.from(JSON.stringify(header)).toString('base64url') protected: Buffer.from(JSON.stringify(header)).toString('base64url'),
}; };
} }
/** /**
* Create JWS HTTP request body using HMAC * Create JWS HTTP request body using HMAC
* *
@ -216,7 +207,6 @@ class HttpClient {
return result; return result;
} }
/** /**
* Create JWS HTTP request body using RSA or ECC * Create JWS HTTP request body using RSA or ECC
* *
@ -257,13 +247,12 @@ class HttpClient {
result.signature = signer.sign({ result.signature = signer.sign({
key: this.accountKey, key: this.accountKey,
padding: RSA_PKCS1_PADDING, padding: RSA_PKCS1_PADDING,
dsaEncoding: 'ieee-p1363' dsaEncoding: 'ieee-p1363',
}, 'base64url'); }, 'base64url');
return result; return result;
} }
/** /**
* Signed HTTP request * Signed HTTP request
* *
@ -299,7 +288,7 @@ class HttpClient {
const data = this.createSignedBody(url, payload, { nonce, kid }); const data = this.createSignedBody(url, payload, { nonce, kid });
const resp = await this.request(url, 'post', { data }); const resp = await this.request(url, 'post', { data });
/* Retry on bad nonce - https://datatracker.ietf.org/doc/html/draft-ietf-acme-acme-10#section-6.4 */ /* Retry on bad nonce - https://datatracker.ietf.org/doc/html/rfc8555#section-6.5 */
if (resp.data && resp.data.type && (resp.status === 400) && (resp.data.type === 'urn:ietf:params:acme:error:badNonce') && (attempts < this.maxBadNonceRetries)) { if (resp.data && resp.data.type && (resp.status === 400) && (resp.data.type === 'urn:ietf:params:acme:error:badNonce') && (attempts < this.maxBadNonceRetries)) {
nonce = resp.headers['replay-nonce'] || null; nonce = resp.headers['replay-nonce'] || null;
attempts += 1; attempts += 1;
@ -313,6 +302,5 @@ class HttpClient {
} }
} }
/* Export client */ /* Export client */
module.exports = HttpClient; module.exports = HttpClient;

View File

@ -4,7 +4,6 @@
exports.Client = require('./client'); exports.Client = require('./client');
/** /**
* Directory URLs * Directory URLs
*/ */
@ -12,18 +11,17 @@ exports.Client = require('./client');
exports.directory = { exports.directory = {
buypass: { buypass: {
staging: 'https://api.test4.buypass.no/acme/directory', staging: 'https://api.test4.buypass.no/acme/directory',
production: 'https://api.buypass.com/acme/directory' production: 'https://api.buypass.com/acme/directory',
}, },
letsencrypt: { letsencrypt: {
staging: 'https://acme-staging-v02.api.letsencrypt.org/directory', staging: 'https://acme-staging-v02.api.letsencrypt.org/directory',
production: 'https://acme-v02.api.letsencrypt.org/directory' production: 'https://acme-v02.api.letsencrypt.org/directory',
}, },
zerossl: { zerossl: {
production: 'https://acme.zerossl.com/v2/DV90' production: 'https://acme.zerossl.com/v2/DV90',
} },
}; };
/** /**
* Crypto * Crypto
*/ */
@ -31,14 +29,12 @@ exports.directory = {
exports.crypto = require('./crypto'); exports.crypto = require('./crypto');
exports.forge = require('./crypto/forge'); exports.forge = require('./crypto/forge');
/** /**
* Axios * Axios
*/ */
exports.axios = require('./axios'); exports.axios = require('./axios');
/** /**
* Logger * Logger
*/ */

View File

@ -6,7 +6,6 @@ const debug = require('debug')('acme-client');
let logger = () => {}; let logger = () => {};
/** /**
* Set logger function * Set logger function
* *
@ -17,11 +16,10 @@ exports.setLogger = (fn) => {
logger = fn; logger = fn;
}; };
/** /**
* Log message * Log message
* *
* @param {string} Message * @param {string} msg Message
*/ */
exports.log = (msg) => { exports.log = (msg) => {

View File

@ -7,7 +7,6 @@ const dns = require('dns').promises;
const { readCertificateInfo, splitPemChain } = require('./crypto'); const { readCertificateInfo, splitPemChain } = require('./crypto');
const { log } = require('./logger'); const { log } = require('./logger');
/** /**
* Exponential backoff * Exponential backoff
* *
@ -26,7 +25,6 @@ class Backoff {
this.attempts = 0; this.attempts = 0;
} }
/** /**
* Get backoff duration * Get backoff duration
* *
@ -40,7 +38,6 @@ class Backoff {
} }
} }
/** /**
* Retry promise * Retry promise
* *
@ -70,7 +67,6 @@ async function retryPromise(fn, attempts, backoff) {
} }
} }
/** /**
* Retry promise * Retry promise
* *
@ -87,7 +83,6 @@ function retry(fn, { attempts = 5, min = 5000, max = 30000 } = {}) {
return retryPromise(fn, attempts, backoff); return retryPromise(fn, attempts, backoff);
} }
/** /**
* Parse URLs from link header * Parse URLs from link header
* *
@ -107,7 +102,6 @@ function parseLinkHeader(header, rel = 'alternate') {
return results.filter((r) => r); return results.filter((r) => r);
} }
/** /**
* Find certificate chain with preferred issuer common name * Find certificate chain with preferred issuer common name
* - If issuer is found in multiple chains, the closest to root wins * - If issuer is found in multiple chains, the closest to root wins
@ -157,7 +151,6 @@ function findCertificateChainForIssuer(chains, issuer) {
return chains[0]; return chains[0];
} }
/** /**
* Find and format error in response object * Find and format error in response object
* *
@ -178,7 +171,6 @@ function formatResponseError(resp) {
return result.replace(/\n/g, ''); return result.replace(/\n/g, '');
} }
/** /**
* Resolve root domain name by looking for SOA record * Resolve root domain name by looking for SOA record
* *
@ -204,7 +196,6 @@ async function resolveDomainBySoaRecord(recordName) {
} }
} }
/** /**
* Get DNS resolver using domains authoritative NS records * Get DNS resolver using domains authoritative NS records
* *
@ -245,7 +236,6 @@ async function getAuthoritativeDnsResolver(recordName) {
return resolver; return resolver;
} }
/** /**
* Attempt to retrieve TLS ALPN certificate from peer * Attempt to retrieve TLS ALPN certificate from peer
* *
@ -267,7 +257,7 @@ async function retrieveTlsAlpnCertificate(host, port, timeout = 30000) {
port, port,
servername: host, servername: host,
rejectUnauthorized: false, rejectUnauthorized: false,
ALPNProtocols: ['acme-tls/1'] ALPNProtocols: ['acme-tls/1'],
}); });
socket.setTimeout(timeout); socket.setTimeout(timeout);
@ -299,7 +289,6 @@ async function retrieveTlsAlpnCertificate(host, port, timeout = 30000) {
}); });
} }
/** /**
* Export utils * Export utils
*/ */
@ -310,5 +299,5 @@ module.exports = {
findCertificateChainForIssuer, findCertificateChainForIssuer,
formatResponseError, formatResponseError,
getAuthoritativeDnsResolver, getAuthoritativeDnsResolver,
retrieveTlsAlpnCertificate retrieveTlsAlpnCertificate,
}; };

View File

@ -9,7 +9,6 @@ const axios = require('./axios');
const util = require('./util'); const util = require('./util');
const { isAlpnCertificateAuthorizationValid } = require('./crypto'); const { isAlpnCertificateAuthorizationValid } = require('./crypto');
/** /**
* Verify ACME HTTP challenge * Verify ACME HTTP challenge
* *
@ -43,7 +42,6 @@ async function verifyHttpChallenge(authz, challenge, keyAuthorization, suffix =
return true; return true;
} }
/** /**
* Walk DNS until TXT records are found * Walk DNS until TXT records are found
*/ */
@ -81,7 +79,6 @@ async function walkDnsChallengeRecord(recordName, resolver = dns) {
throw new Error(`No TXT records found for name: ${recordName}`); throw new Error(`No TXT records found for name: ${recordName}`);
} }
/** /**
* Verify ACME DNS challenge * Verify ACME DNS challenge
* *
@ -121,7 +118,6 @@ async function verifyDnsChallenge(authz, challenge, keyAuthorization, prefix = '
return true; return true;
} }
/** /**
* Verify ACME TLS ALPN challenge * Verify ACME TLS ALPN challenge
* *
@ -149,7 +145,6 @@ async function verifyTlsAlpnChallenge(authz, challenge, keyAuthorization) {
return true; return true;
} }
/** /**
* Export API * Export API
*/ */
@ -157,5 +152,5 @@ async function verifyTlsAlpnChallenge(authz, challenge, keyAuthorization) {
module.exports = { module.exports = {
'http-01': verifyHttpChallenge, 'http-01': verifyHttpChallenge,
'dns-01': verifyDnsChallenge, 'dns-01': verifyDnsChallenge,
'tls-alpn-01': verifyTlsAlpnChallenge 'tls-alpn-01': verifyTlsAlpnChallenge,
}; };

View File

@ -16,7 +16,6 @@ const httpPort = axios.defaults.acmeSettings.httpChallengePort || 80;
const httpsPort = axios.defaults.acmeSettings.httpsChallengePort || 443; const httpsPort = axios.defaults.acmeSettings.httpsChallengePort || 443;
const tlsAlpnPort = axios.defaults.acmeSettings.tlsAlpnChallengePort || 443; const tlsAlpnPort = axios.defaults.acmeSettings.tlsAlpnChallengePort || 443;
describe('pebble', () => { describe('pebble', () => {
const httpsAgent = new https.Agent({ rejectUnauthorized: false }); const httpsAgent = new https.Agent({ rejectUnauthorized: false });
@ -39,18 +38,16 @@ describe('pebble', () => {
const testTlsAlpn01ChallengeHost = `${uuid()}.${domainName}`; const testTlsAlpn01ChallengeHost = `${uuid()}.${domainName}`;
const testTlsAlpn01ChallengeValue = uuid(); const testTlsAlpn01ChallengeValue = uuid();
/** /**
* Pebble CTS required * Pebble CTS required
*/ */
before(function() { before(function () {
if (!cts.isEnabled()) { if (!cts.isEnabled()) {
this.skip(); this.skip();
} }
}); });
/** /**
* DNS mocking * DNS mocking
*/ */
@ -92,7 +89,6 @@ describe('pebble', () => {
}); });
}); });
/** /**
* HTTP-01 challenge response * HTTP-01 challenge response
*/ */
@ -118,7 +114,6 @@ describe('pebble', () => {
}); });
}); });
/** /**
* HTTPS-01 challenge response * HTTPS-01 challenge response
*/ */
@ -143,7 +138,7 @@ describe('pebble', () => {
/* Assert HTTP 302 */ /* Assert HTTP 302 */
const resp = await axios.get(`http://${testHttps01ChallengeHost}:${httpPort}/.well-known/acme-challenge/${testHttps01ChallengeToken}`, { const resp = await axios.get(`http://${testHttps01ChallengeHost}:${httpPort}/.well-known/acme-challenge/${testHttps01ChallengeToken}`, {
maxRedirects: 0, maxRedirects: 0,
validateStatus: null validateStatus: null,
}); });
assert.strictEqual(resp.status, 302); assert.strictEqual(resp.status, 302);
@ -165,7 +160,6 @@ describe('pebble', () => {
}); });
}); });
/** /**
* DNS-01 challenge response * DNS-01 challenge response
*/ */
@ -188,7 +182,6 @@ describe('pebble', () => {
}); });
}); });
/** /**
* TLS-ALPN-01 challenge response * TLS-ALPN-01 challenge response
*/ */

View File

@ -9,7 +9,6 @@ const axios = require('./../src/axios');
const HttpClient = require('./../src/http'); const HttpClient = require('./../src/http');
const pkg = require('./../package.json'); const pkg = require('./../package.json');
describe('http', () => { describe('http', () => {
let testClient; let testClient;
@ -20,7 +19,6 @@ describe('http', () => {
const defaultUaEndpoint = `http://${uuid()}.example.com`; const defaultUaEndpoint = `http://${uuid()}.example.com`;
const customUaEndpoint = `http://${uuid()}.example.com`; const customUaEndpoint = `http://${uuid()}.example.com`;
/** /**
* HTTP mocking * HTTP mocking
*/ */
@ -43,7 +41,6 @@ describe('http', () => {
axios.defaults.headers.common['User-Agent'] = defaultUserAgent; axios.defaults.headers.common['User-Agent'] = defaultUserAgent;
}); });
/** /**
* Initialize * Initialize
*/ */
@ -52,7 +49,6 @@ describe('http', () => {
testClient = new HttpClient(); testClient = new HttpClient();
}); });
/** /**
* HTTP verbs * HTTP verbs
*/ */
@ -65,7 +61,6 @@ describe('http', () => {
assert.strictEqual(resp.data, 'ok'); assert.strictEqual(resp.data, 'ok');
}); });
/** /**
* User-Agent * User-Agent
*/ */

View File

@ -5,7 +5,6 @@
const { assert } = require('chai'); const { assert } = require('chai');
const logger = require('./../src/logger'); const logger = require('./../src/logger');
describe('logger', () => { describe('logger', () => {
let lastLogMessage = null; let lastLogMessage = null;
@ -13,7 +12,6 @@ describe('logger', () => {
lastLogMessage = msg; lastLogMessage = msg;
} }
/** /**
* Logger * Logger
*/ */
@ -23,7 +21,6 @@ describe('logger', () => {
assert.isNull(lastLogMessage); assert.isNull(lastLogMessage);
}); });
it('should log with custom logger', () => { it('should log with custom logger', () => {
logger.setLogger(customLoggerFn); logger.setLogger(customLoggerFn);

View File

@ -9,7 +9,6 @@ const verify = require('./../src/verify');
const domainName = process.env.ACME_DOMAIN_NAME || 'example.com'; const domainName = process.env.ACME_DOMAIN_NAME || 'example.com';
describe('verify', () => { describe('verify', () => {
const challengeTypes = ['http-01', 'dns-01']; const challengeTypes = ['http-01', 'dns-01'];
@ -30,18 +29,16 @@ describe('verify', () => {
const testTlsAlpn01Challenge = { type: 'dns-01', status: 'pending', token: uuid() }; const testTlsAlpn01Challenge = { type: 'dns-01', status: 'pending', token: uuid() };
const testTlsAlpn01Key = uuid(); const testTlsAlpn01Key = uuid();
/** /**
* Pebble CTS required * Pebble CTS required
*/ */
before(function() { before(function () {
if (!cts.isEnabled()) { if (!cts.isEnabled()) {
this.skip(); this.skip();
} }
}); });
/** /**
* API * API
*/ */
@ -50,7 +47,6 @@ describe('verify', () => {
assert.containsAllKeys(verify, challengeTypes); assert.containsAllKeys(verify, challengeTypes);
}); });
/** /**
* http-01 * http-01
*/ */
@ -81,7 +77,6 @@ describe('verify', () => {
}); });
}); });
/** /**
* https-01 * https-01
*/ */
@ -102,7 +97,6 @@ describe('verify', () => {
}); });
}); });
/** /**
* dns-01 * dns-01
*/ */
@ -133,7 +127,6 @@ describe('verify', () => {
}); });
}); });
/** /**
* tls-alpn-01 * tls-alpn-01
*/ */

View File

@ -9,10 +9,9 @@ const spec = require('./spec');
const forge = require('./../src/crypto/forge'); const forge = require('./../src/crypto/forge');
const cryptoEngines = { const cryptoEngines = {
forge forge,
}; };
describe('crypto-legacy', () => { describe('crypto-legacy', () => {
let testPemKey; let testPemKey;
let testCert; let testCert;
@ -28,7 +27,6 @@ describe('crypto-legacy', () => {
const testCertPath = path.join(__dirname, 'fixtures', 'certificate.crt'); const testCertPath = path.join(__dirname, 'fixtures', 'certificate.crt');
const testSanCertPath = path.join(__dirname, 'fixtures', 'san-certificate.crt'); const testSanCertPath = path.join(__dirname, 'fixtures', 'san-certificate.crt');
/** /**
* Fixtures * Fixtures
*/ */
@ -50,7 +48,6 @@ describe('crypto-legacy', () => {
}); });
}); });
/** /**
* Engines * Engines
*/ */
@ -62,7 +59,6 @@ describe('crypto-legacy', () => {
let testNonCnCsr; let testNonCnCsr;
let testNonAsciiCsr; let testNonAsciiCsr;
/** /**
* Key generation * Key generation
*/ */
@ -83,14 +79,13 @@ describe('crypto-legacy', () => {
publicKeyStore.push(key.toString().replace(/[\r\n]/gm, '')); publicKeyStore.push(key.toString().replace(/[\r\n]/gm, ''));
}); });
/** /**
* Certificate Signing Request * Certificate Signing Request
*/ */
it('should generate a csr', async () => { it('should generate a csr', async () => {
const [key, csr] = await engine.createCsr({ const [key, csr] = await engine.createCsr({
commonName: testCsrDomain commonName: testCsrDomain,
}); });
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -102,7 +97,7 @@ describe('crypto-legacy', () => {
it('should generate a san csr', async () => { it('should generate a san csr', async () => {
const [key, csr] = await engine.createCsr({ const [key, csr] = await engine.createCsr({
commonName: testSanCsrDomains[0], commonName: testSanCsrDomains[0],
altNames: testSanCsrDomains.slice(1, testSanCsrDomains.length) altNames: testSanCsrDomains.slice(1, testSanCsrDomains.length),
}); });
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -113,7 +108,7 @@ describe('crypto-legacy', () => {
it('should generate a csr without common name', async () => { it('should generate a csr without common name', async () => {
const [key, csr] = await engine.createCsr({ const [key, csr] = await engine.createCsr({
altNames: testSanCsrDomains altNames: testSanCsrDomains,
}); });
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -126,7 +121,7 @@ describe('crypto-legacy', () => {
const [key, csr] = await engine.createCsr({ const [key, csr] = await engine.createCsr({
commonName: testCsrDomain, commonName: testCsrDomain,
organization: '大安區', organization: '大安區',
organizationUnit: '中文部門' organizationUnit: '中文部門',
}); });
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -167,7 +162,6 @@ describe('crypto-legacy', () => {
assert.deepStrictEqual(result.altNames, [testCsrDomain]); assert.deepStrictEqual(result.altNames, [testCsrDomain]);
}); });
/** /**
* Certificate * Certificate
*/ */
@ -188,7 +182,6 @@ describe('crypto-legacy', () => {
assert.deepEqual(info.domains.altNames, testSanCsrDomains.slice(1, testSanCsrDomains.length)); assert.deepEqual(info.domains.altNames, testSanCsrDomains.slice(1, testSanCsrDomains.length));
}); });
/** /**
* PEM utils * PEM utils
*/ */
@ -214,7 +207,6 @@ describe('crypto-legacy', () => {
}); });
}); });
/** /**
* Modulus and exponent * Modulus and exponent
*/ */
@ -246,7 +238,6 @@ describe('crypto-legacy', () => {
}); });
}); });
/** /**
* Verify identical results * Verify identical results
*/ */

View File

@ -50,7 +50,6 @@ dGVzdGluZ3Rlc3Rpbmd0ZXN0aW5ndGVzdGluZ3Rlc3Rpbmd0ZXN0aW5ndGVzdGluZ3Rlc3Rpbmd0ZXN0
-----END TEST----- -----END TEST-----
`; `;
describe('crypto', () => { describe('crypto', () => {
const testCsrDomain = 'example.com'; const testCsrDomain = 'example.com';
const testSanCsrDomains = ['example.com', 'test.example.com', 'abc.example.com']; const testSanCsrDomains = ['example.com', 'test.example.com', 'abc.example.com'];
@ -58,7 +57,6 @@ describe('crypto', () => {
const testCertPath = path.join(__dirname, 'fixtures', 'certificate.crt'); const testCertPath = path.join(__dirname, 'fixtures', 'certificate.crt');
const testSanCertPath = path.join(__dirname, 'fixtures', 'san-certificate.crt'); const testSanCertPath = path.join(__dirname, 'fixtures', 'san-certificate.crt');
/** /**
* Key types * Key types
*/ */
@ -68,24 +66,23 @@ describe('crypto', () => {
createKeyFns: { createKeyFns: {
s1024: () => crypto.createPrivateRsaKey(1024), s1024: () => crypto.createPrivateRsaKey(1024),
s2048: () => crypto.createPrivateRsaKey(), s2048: () => crypto.createPrivateRsaKey(),
s4096: () => crypto.createPrivateRsaKey(4096) s4096: () => crypto.createPrivateRsaKey(4096),
}, },
jwkSpecFn: spec.jwk.rsa jwkSpecFn: spec.jwk.rsa,
}, },
ecdsa: { ecdsa: {
createKeyFns: { createKeyFns: {
p256: () => crypto.createPrivateEcdsaKey(), p256: () => crypto.createPrivateEcdsaKey(),
p384: () => crypto.createPrivateEcdsaKey('P-384'), p384: () => crypto.createPrivateEcdsaKey('P-384'),
p521: () => crypto.createPrivateEcdsaKey('P-521') p521: () => crypto.createPrivateEcdsaKey('P-521'),
}, },
jwkSpecFn: spec.jwk.ecdsa jwkSpecFn: spec.jwk.ecdsa,
} },
}).forEach(([name, { createKeyFns, jwkSpecFn }]) => { }).forEach(([name, { createKeyFns, jwkSpecFn }]) => {
describe(name, () => { describe(name, () => {
const testPrivateKeys = {}; const testPrivateKeys = {};
const testPublicKeys = {}; const testPublicKeys = {};
/** /**
* Iterate through all generator variations * Iterate through all generator variations
*/ */
@ -97,7 +94,6 @@ describe('crypto', () => {
let testNonAsciiCsr; let testNonAsciiCsr;
let testAlpnCertificate; let testAlpnCertificate;
/** /**
* Keys and JWK * Keys and JWK
*/ */
@ -132,14 +128,13 @@ describe('crypto', () => {
jwkSpecFn(jwk); jwkSpecFn(jwk);
}); });
/** /**
* Certificate Signing Request * Certificate Signing Request
*/ */
it(`${n}/should generate a csr`, async () => { it(`${n}/should generate a csr`, async () => {
const [key, csr] = await crypto.createCsr({ const [key, csr] = await crypto.createCsr({
commonName: testCsrDomain commonName: testCsrDomain,
}, testPrivateKeys[n]); }, testPrivateKeys[n]);
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -151,7 +146,7 @@ describe('crypto', () => {
it(`${n}/should generate a san csr`, async () => { it(`${n}/should generate a san csr`, async () => {
const [key, csr] = await crypto.createCsr({ const [key, csr] = await crypto.createCsr({
commonName: testSanCsrDomains[0], commonName: testSanCsrDomains[0],
altNames: testSanCsrDomains.slice(1, testSanCsrDomains.length) altNames: testSanCsrDomains.slice(1, testSanCsrDomains.length),
}, testPrivateKeys[n]); }, testPrivateKeys[n]);
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -162,7 +157,7 @@ describe('crypto', () => {
it(`${n}/should generate a csr without common name`, async () => { it(`${n}/should generate a csr without common name`, async () => {
const [key, csr] = await crypto.createCsr({ const [key, csr] = await crypto.createCsr({
altNames: testSanCsrDomains altNames: testSanCsrDomains,
}, testPrivateKeys[n]); }, testPrivateKeys[n]);
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -175,7 +170,7 @@ describe('crypto', () => {
const [key, csr] = await crypto.createCsr({ const [key, csr] = await crypto.createCsr({
commonName: testCsrDomain, commonName: testCsrDomain,
organization: '大安區', organization: '大安區',
organizationUnit: '中文部門' organizationUnit: '中文部門',
}, testPrivateKeys[n]); }, testPrivateKeys[n]);
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -186,7 +181,7 @@ describe('crypto', () => {
it(`${n}/should generate a csr with key as string`, async () => { it(`${n}/should generate a csr with key as string`, async () => {
const [key, csr] = await crypto.createCsr({ const [key, csr] = await crypto.createCsr({
commonName: testCsrDomain commonName: testCsrDomain,
}, testPrivateKeys[n].toString()); }, testPrivateKeys[n].toString());
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
@ -195,11 +190,10 @@ describe('crypto', () => {
it(`${n}/should throw with invalid key`, async () => { it(`${n}/should throw with invalid key`, async () => {
await assert.isRejected(crypto.createCsr({ await assert.isRejected(crypto.createCsr({
commonName: testCsrDomain commonName: testCsrDomain,
}, testPublicKeys[n])); }, testPublicKeys[n]));
}); });
/** /**
* Domain and info resolver * Domain and info resolver
*/ */
@ -243,7 +237,6 @@ describe('crypto', () => {
}); });
}); });
/** /**
* ALPN * ALPN
*/ */
@ -284,7 +277,6 @@ describe('crypto', () => {
}); });
}); });
/** /**
* Common functionality * Common functionality
*/ */
@ -294,7 +286,6 @@ describe('crypto', () => {
let testCert; let testCert;
let testSanCert; let testSanCert;
it('should read private key fixture', async () => { it('should read private key fixture', async () => {
testPemKey = await fs.readFile(testKeyPath); testPemKey = await fs.readFile(testKeyPath);
assert.isTrue(Buffer.isBuffer(testPemKey)); assert.isTrue(Buffer.isBuffer(testPemKey));
@ -310,21 +301,19 @@ describe('crypto', () => {
assert.isTrue(Buffer.isBuffer(testSanCert)); assert.isTrue(Buffer.isBuffer(testSanCert));
}); });
/** /**
* CSR with auto-generated key * CSR with auto-generated key
*/ */
it('should generate a csr with default key', async () => { it('should generate a csr with default key', async () => {
const [key, csr] = await crypto.createCsr({ const [key, csr] = await crypto.createCsr({
commonName: testCsrDomain commonName: testCsrDomain,
}); });
assert.isTrue(Buffer.isBuffer(key)); assert.isTrue(Buffer.isBuffer(key));
assert.isTrue(Buffer.isBuffer(csr)); assert.isTrue(Buffer.isBuffer(csr));
}); });
/** /**
* Certificate * Certificate
*/ */
@ -352,7 +341,6 @@ describe('crypto', () => {
}); });
}); });
/** /**
* ALPN * ALPN
*/ */
@ -365,7 +353,6 @@ describe('crypto', () => {
assert.isTrue(Buffer.isBuffer(cert)); assert.isTrue(Buffer.isBuffer(cert));
}); });
/** /**
* PEM utils * PEM utils
*/ */

View File

@ -20,35 +20,32 @@ const clientOpts = {
directoryUrl, directoryUrl,
backoffAttempts: 5, backoffAttempts: 5,
backoffMin: 1000, backoffMin: 1000,
backoffMax: 5000 backoffMax: 5000,
}; };
if (capEabEnabled && process.env.ACME_EAB_KID && process.env.ACME_EAB_HMAC_KEY) { if (capEabEnabled && process.env.ACME_EAB_KID && process.env.ACME_EAB_HMAC_KEY) {
clientOpts.externalAccountBinding = { clientOpts.externalAccountBinding = {
kid: process.env.ACME_EAB_KID, kid: process.env.ACME_EAB_KID,
hmacKey: process.env.ACME_EAB_HMAC_KEY hmacKey: process.env.ACME_EAB_HMAC_KEY,
}; };
} }
describe('client', () => { describe('client', () => {
const testDomain = `${uuid()}.${domainName}`; const testDomain = `${uuid()}.${domainName}`;
const testDomainAlpn = `${uuid()}.${domainName}`; const testDomainAlpn = `${uuid()}.${domainName}`;
const testDomainWildcard = `*.${testDomain}`; const testDomainWildcard = `*.${testDomain}`;
const testContact = `mailto:test-${uuid()}@nope.com`; const testContact = `mailto:test-${uuid()}@nope.com`;
/** /**
* Pebble CTS required * Pebble CTS required
*/ */
before(function() { before(function () {
if (!cts.isEnabled()) { if (!cts.isEnabled()) {
this.skip(); this.skip();
} }
}); });
/** /**
* Key types * Key types
*/ */
@ -58,18 +55,18 @@ describe('client', () => {
createKeyFn: () => acme.crypto.createPrivateRsaKey(), createKeyFn: () => acme.crypto.createPrivateRsaKey(),
createKeyAltFns: { createKeyAltFns: {
s1024: () => acme.crypto.createPrivateRsaKey(1024), s1024: () => acme.crypto.createPrivateRsaKey(1024),
s4096: () => acme.crypto.createPrivateRsaKey(4096) s4096: () => acme.crypto.createPrivateRsaKey(4096),
}, },
jwkSpecFn: spec.jwk.rsa jwkSpecFn: spec.jwk.rsa,
}, },
ecdsa: { ecdsa: {
createKeyFn: () => acme.crypto.createPrivateEcdsaKey(), createKeyFn: () => acme.crypto.createPrivateEcdsaKey(),
createKeyAltFns: { createKeyAltFns: {
p384: () => acme.crypto.createPrivateEcdsaKey('P-384'), p384: () => acme.crypto.createPrivateEcdsaKey('P-384'),
p521: () => acme.crypto.createPrivateEcdsaKey('P-521') p521: () => acme.crypto.createPrivateEcdsaKey('P-521'),
}, },
jwkSpecFn: spec.jwk.ecdsa jwkSpecFn: spec.jwk.ecdsa,
} },
}).forEach(([name, { createKeyFn, createKeyAltFns, jwkSpecFn }]) => { }).forEach(([name, { createKeyFn, createKeyAltFns, jwkSpecFn }]) => {
describe(name, () => { describe(name, () => {
let testIssuers; let testIssuers;
@ -97,7 +94,6 @@ describe('client', () => {
let testCertificateAlpn; let testCertificateAlpn;
let testCertificateWildcard; let testCertificateWildcard;
/** /**
* Fixtures * Fixtures
*/ */
@ -118,7 +114,7 @@ describe('client', () => {
[, testCsrWildcard] = await acme.crypto.createCsr({ commonName: testDomainWildcard }, await createKeyFn()); [, testCsrWildcard] = await acme.crypto.createCsr({ commonName: testDomainWildcard }, await createKeyFn());
}); });
it('should resolve certificate issuers [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function() { it('should resolve certificate issuers [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function () {
if (!capAlternateCertRoots) { if (!capAlternateCertRoots) {
this.skip(); this.skip();
} }
@ -134,7 +130,6 @@ describe('client', () => {
}); });
}); });
/** /**
* Initialize clients * Initialize clients
*/ */
@ -142,7 +137,7 @@ describe('client', () => {
it('should initialize client', () => { it('should initialize client', () => {
testClient = new acme.Client({ testClient = new acme.Client({
...clientOpts, ...clientOpts,
accountKey: testAccountKey accountKey: testAccountKey,
}); });
}); });
@ -151,12 +146,11 @@ describe('client', () => {
jwkSpecFn(jwk); jwkSpecFn(jwk);
}); });
/** /**
* Terms of Service * Terms of Service
*/ */
it('should produce tos url [ACME_CAP_META_TOS_FIELD]', async function() { it('should produce tos url [ACME_CAP_META_TOS_FIELD]', async function () {
if (!capMetaTosField) { if (!capMetaTosField) {
this.skip(); this.skip();
} }
@ -165,7 +159,7 @@ describe('client', () => {
assert.isString(tos); assert.isString(tos);
}); });
it('should not produce tos url [!ACME_CAP_META_TOS_FIELD]', async function() { it('should not produce tos url [!ACME_CAP_META_TOS_FIELD]', async function () {
if (capMetaTosField) { if (capMetaTosField) {
this.skip(); this.skip();
} }
@ -174,12 +168,11 @@ describe('client', () => {
assert.isNull(tos); assert.isNull(tos);
}); });
/** /**
* Create account * Create account
*/ */
it('should refuse account creation without tos [ACME_CAP_META_TOS_FIELD]', async function() { it('should refuse account creation without tos [ACME_CAP_META_TOS_FIELD]', async function () {
if (!capMetaTosField) { if (!capMetaTosField) {
this.skip(); this.skip();
} }
@ -187,7 +180,7 @@ describe('client', () => {
await assert.isRejected(testClient.createAccount()); await assert.isRejected(testClient.createAccount());
}); });
it('should refuse account creation without eab [ACME_CAP_EAB_ENABLED]', async function() { it('should refuse account creation without eab [ACME_CAP_EAB_ENABLED]', async function () {
if (!capEabEnabled) { if (!capEabEnabled) {
this.skip(); this.skip();
} }
@ -195,17 +188,17 @@ describe('client', () => {
const client = new acme.Client({ const client = new acme.Client({
...clientOpts, ...clientOpts,
accountKey: testAccountKey, accountKey: testAccountKey,
externalAccountBinding: null externalAccountBinding: null,
}); });
await assert.isRejected(client.createAccount({ await assert.isRejected(client.createAccount({
termsOfServiceAgreed: true termsOfServiceAgreed: true,
})); }));
}); });
it('should create an account', async () => { it('should create an account', async () => {
testAccount = await testClient.createAccount({ testAccount = await testClient.createAccount({
termsOfServiceAgreed: true termsOfServiceAgreed: true,
}); });
spec.rfc8555.account(testAccount); spec.rfc8555.account(testAccount);
@ -217,7 +210,6 @@ describe('client', () => {
assert.isString(testAccountUrl); assert.isString(testAccountUrl);
}); });
/** /**
* Create account with alternate key sizes * Create account with alternate key sizes
*/ */
@ -226,11 +218,11 @@ describe('client', () => {
it(`should create account with key=${k}`, async () => { it(`should create account with key=${k}`, async () => {
const client = new acme.Client({ const client = new acme.Client({
...clientOpts, ...clientOpts,
accountKey: await altKeyFn() accountKey: await altKeyFn(),
}); });
const account = await client.createAccount({ const account = await client.createAccount({
termsOfServiceAgreed: true termsOfServiceAgreed: true,
}); });
spec.rfc8555.account(account); spec.rfc8555.account(account);
@ -238,7 +230,6 @@ describe('client', () => {
}); });
}); });
/** /**
* Find existing account using secondary client * Find existing account using secondary client
*/ */
@ -246,22 +237,22 @@ describe('client', () => {
it('should throw when trying to find account using invalid account key', async () => { it('should throw when trying to find account using invalid account key', async () => {
const client = new acme.Client({ const client = new acme.Client({
...clientOpts, ...clientOpts,
accountKey: testAccountSecondaryKey accountKey: testAccountSecondaryKey,
}); });
await assert.isRejected(client.createAccount({ await assert.isRejected(client.createAccount({
onlyReturnExisting: true onlyReturnExisting: true,
})); }));
}); });
it('should find existing account using account key', async () => { it('should find existing account using account key', async () => {
const client = new acme.Client({ const client = new acme.Client({
...clientOpts, ...clientOpts,
accountKey: testAccountKey accountKey: testAccountKey,
}); });
const account = await client.createAccount({ const account = await client.createAccount({
onlyReturnExisting: true onlyReturnExisting: true,
}); });
spec.rfc8555.account(account); spec.rfc8555.account(account);
@ -269,7 +260,6 @@ describe('client', () => {
assert.deepStrictEqual(account.key, testAccount.key); assert.deepStrictEqual(account.key, testAccount.key);
}); });
/** /**
* Account URL * Account URL
*/ */
@ -278,7 +268,7 @@ describe('client', () => {
const client = new acme.Client({ const client = new acme.Client({
...clientOpts, ...clientOpts,
accountKey: testAccountKey, accountKey: testAccountKey,
accountUrl: 'https://acme-staging-v02.api.letsencrypt.org/acme/acct/1' accountUrl: 'https://acme-staging-v02.api.letsencrypt.org/acme/acct/1',
}); });
await assert.isRejected(client.updateAccount()); await assert.isRejected(client.updateAccount());
@ -288,11 +278,11 @@ describe('client', () => {
const client = new acme.Client({ const client = new acme.Client({
...clientOpts, ...clientOpts,
accountKey: testAccountKey, accountKey: testAccountKey,
accountUrl: testAccountUrl accountUrl: testAccountUrl,
}); });
const account = await client.createAccount({ const account = await client.createAccount({
onlyReturnExisting: true onlyReturnExisting: true,
}); });
spec.rfc8555.account(account); spec.rfc8555.account(account);
@ -300,7 +290,6 @@ describe('client', () => {
assert.deepStrictEqual(account.key, testAccount.key); assert.deepStrictEqual(account.key, testAccount.key);
}); });
/** /**
* Update account contact info * Update account contact info
*/ */
@ -316,12 +305,11 @@ describe('client', () => {
assert.include(account.contact, testContact); assert.include(account.contact, testContact);
}); });
/** /**
* Change account private key * Change account private key
*/ */
it('should change account private key [ACME_CAP_UPDATE_ACCOUNT_KEY]', async function() { it('should change account private key [ACME_CAP_UPDATE_ACCOUNT_KEY]', async function () {
if (!capUpdateAccountKey) { if (!capUpdateAccountKey) {
this.skip(); this.skip();
} }
@ -329,7 +317,7 @@ describe('client', () => {
await testClient.updateAccountKey(testAccountSecondaryKey); await testClient.updateAccountKey(testAccountSecondaryKey);
const account = await testClient.createAccount({ const account = await testClient.createAccount({
onlyReturnExisting: true onlyReturnExisting: true,
}); });
spec.rfc8555.account(account); spec.rfc8555.account(account);
@ -337,7 +325,6 @@ describe('client', () => {
assert.notDeepEqual(account.key, testAccount.key); assert.notDeepEqual(account.key, testAccount.key);
}); });
/** /**
* Create new certificate order * Create new certificate order
*/ */
@ -357,7 +344,6 @@ describe('client', () => {
}); });
}); });
/** /**
* Get status of existing certificate order * Get status of existing certificate order
*/ */
@ -371,7 +357,6 @@ describe('client', () => {
})); }));
}); });
/** /**
* Get identifier authorization * Get identifier authorization
*/ */
@ -401,7 +386,6 @@ describe('client', () => {
}); });
}); });
/** /**
* Generate challenge key authorization * Generate challenge key authorization
*/ */
@ -418,7 +402,6 @@ describe('client', () => {
[testKeyAuthorization, testKeyAuthorizationAlpn, testKeyAuthorizationWildcard].forEach((k) => assert.isString(k)); [testKeyAuthorization, testKeyAuthorizationAlpn, testKeyAuthorizationWildcard].forEach((k) => assert.isString(k));
}); });
/** /**
* Deactivate identifier authorization * Deactivate identifier authorization
*/ */
@ -427,8 +410,8 @@ describe('client', () => {
const order = await testClient.createOrder({ const order = await testClient.createOrder({
identifiers: [ identifiers: [
{ type: 'dns', value: `${uuid()}.${domainName}` }, { type: 'dns', value: `${uuid()}.${domainName}` },
{ type: 'dns', value: `${uuid()}.${domainName}` } { type: 'dns', value: `${uuid()}.${domainName}` },
] ],
}); });
const authzCollection = await testClient.getAuthorizations(order); const authzCollection = await testClient.getAuthorizations(order);
@ -445,7 +428,6 @@ describe('client', () => {
}); });
}); });
/** /**
* Verify satisfied challenge * Verify satisfied challenge
*/ */
@ -460,7 +442,6 @@ describe('client', () => {
await testClient.verifyChallenge(testAuthzWildcard, testChallengeWildcard); await testClient.verifyChallenge(testAuthzWildcard, testChallengeWildcard);
}); });
/** /**
* Complete challenge * Complete challenge
*/ */
@ -474,7 +455,6 @@ describe('client', () => {
})); }));
}); });
/** /**
* Wait for valid challenge * Wait for valid challenge
*/ */
@ -483,7 +463,6 @@ describe('client', () => {
await Promise.all([testChallenge, testChallengeAlpn, testChallengeWildcard].map(async (c) => testClient.waitForValidStatus(c))); await Promise.all([testChallenge, testChallengeAlpn, testChallengeWildcard].map(async (c) => testClient.waitForValidStatus(c)));
}); });
/** /**
* Finalize order * Finalize order
*/ */
@ -500,7 +479,6 @@ describe('client', () => {
assert.strictEqual(testOrderWildcard.url, finalizeWildcard.url); assert.strictEqual(testOrderWildcard.url, finalizeWildcard.url);
}); });
/** /**
* Wait for valid order * Wait for valid order
*/ */
@ -509,7 +487,6 @@ describe('client', () => {
await Promise.all([testOrder, testOrderAlpn, testOrderWildcard].map(async (o) => testClient.waitForValidStatus(o))); await Promise.all([testOrder, testOrderAlpn, testOrderWildcard].map(async (o) => testClient.waitForValidStatus(o)));
}); });
/** /**
* Get certificate * Get certificate
*/ */
@ -525,7 +502,7 @@ describe('client', () => {
}); });
}); });
it('should get alternate certificate chain [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function() { it('should get alternate certificate chain [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function () {
if (!capAlternateCertRoots) { if (!capAlternateCertRoots) {
this.skip(); this.skip();
} }
@ -539,7 +516,7 @@ describe('client', () => {
})); }));
}); });
it('should get default chain with invalid preference [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function() { it('should get default chain with invalid preference [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function () {
if (!capAlternateCertRoots) { if (!capAlternateCertRoots) {
this.skip(); this.skip();
} }
@ -551,7 +528,6 @@ describe('client', () => {
assert.strictEqual(testIssuers[0], info.issuer.commonName); assert.strictEqual(testIssuers[0], info.issuer.commonName);
}); });
/** /**
* Revoke certificate * Revoke certificate
*/ */
@ -568,7 +544,6 @@ describe('client', () => {
await assert.isRejected(testClient.getCertificate(testOrderWildcard)); await assert.isRejected(testClient.getCertificate(testOrderWildcard));
}); });
/** /**
* Deactivate account * Deactivate account
*/ */
@ -581,7 +556,6 @@ describe('client', () => {
assert.strictEqual(account.status, 'deactivated'); assert.strictEqual(account.status, 'deactivated');
}); });
/** /**
* Verify that no new orders can be made * Verify that no new orders can be made
*/ */

View File

@ -18,17 +18,16 @@ const clientOpts = {
directoryUrl, directoryUrl,
backoffAttempts: 5, backoffAttempts: 5,
backoffMin: 1000, backoffMin: 1000,
backoffMax: 5000 backoffMax: 5000,
}; };
if (capEabEnabled && process.env.ACME_EAB_KID && process.env.ACME_EAB_HMAC_KEY) { if (capEabEnabled && process.env.ACME_EAB_KID && process.env.ACME_EAB_HMAC_KEY) {
clientOpts.externalAccountBinding = { clientOpts.externalAccountBinding = {
kid: process.env.ACME_EAB_KID, kid: process.env.ACME_EAB_KID,
hmacKey: process.env.ACME_EAB_HMAC_KEY hmacKey: process.env.ACME_EAB_HMAC_KEY,
}; };
} }
describe('client.auto', () => { describe('client.auto', () => {
const testDomain = `${uuid()}.${domainName}`; const testDomain = `${uuid()}.${domainName}`;
const testHttpDomain = `${uuid()}.${domainName}`; const testHttpDomain = `${uuid()}.${domainName}`;
@ -40,21 +39,19 @@ describe('client.auto', () => {
const testSanDomains = [ const testSanDomains = [
`${uuid()}.${domainName}`, `${uuid()}.${domainName}`,
`${uuid()}.${domainName}`, `${uuid()}.${domainName}`,
`${uuid()}.${domainName}` `${uuid()}.${domainName}`,
]; ];
/** /**
* Pebble CTS required * Pebble CTS required
*/ */
before(function() { before(function () {
if (!cts.isEnabled()) { if (!cts.isEnabled()) {
this.skip(); this.skip();
} }
}); });
/** /**
* Key types * Key types
*/ */
@ -64,16 +61,16 @@ describe('client.auto', () => {
createKeyFn: () => acme.crypto.createPrivateRsaKey(), createKeyFn: () => acme.crypto.createPrivateRsaKey(),
createKeyAltFns: { createKeyAltFns: {
s1024: () => acme.crypto.createPrivateRsaKey(1024), s1024: () => acme.crypto.createPrivateRsaKey(1024),
s4096: () => acme.crypto.createPrivateRsaKey(4096) s4096: () => acme.crypto.createPrivateRsaKey(4096),
} },
}, },
ecdsa: { ecdsa: {
createKeyFn: () => acme.crypto.createPrivateEcdsaKey(), createKeyFn: () => acme.crypto.createPrivateEcdsaKey(),
createKeyAltFns: { createKeyAltFns: {
p384: () => acme.crypto.createPrivateEcdsaKey('P-384'), p384: () => acme.crypto.createPrivateEcdsaKey('P-384'),
p521: () => acme.crypto.createPrivateEcdsaKey('P-521') p521: () => acme.crypto.createPrivateEcdsaKey('P-521'),
} },
} },
}).forEach(([name, { createKeyFn, createKeyAltFns }]) => { }).forEach(([name, { createKeyFn, createKeyAltFns }]) => {
describe(name, () => { describe(name, () => {
let testIssuers; let testIssuers;
@ -82,12 +79,11 @@ describe('client.auto', () => {
let testSanCertificate; let testSanCertificate;
let testWildcardCertificate; let testWildcardCertificate;
/** /**
* Fixtures * Fixtures
*/ */
it('should resolve certificate issuers [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function() { it('should resolve certificate issuers [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function () {
if (!capAlternateCertRoots) { if (!capAlternateCertRoots) {
this.skip(); this.skip();
} }
@ -103,7 +99,6 @@ describe('client.auto', () => {
}); });
}); });
/** /**
* Initialize client * Initialize client
*/ */
@ -111,31 +106,30 @@ describe('client.auto', () => {
it('should initialize client', async () => { it('should initialize client', async () => {
testClient = new acme.Client({ testClient = new acme.Client({
...clientOpts, ...clientOpts,
accountKey: await createKeyFn() accountKey: await createKeyFn(),
}); });
}); });
/** /**
* Invalid challenge response * Invalid challenge response
*/ */
it('should throw on invalid challenge response', async () => { it('should throw on invalid challenge response', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: `${uuid()}.${domainName}` commonName: `${uuid()}.${domainName}`,
}, await createKeyFn()); }, await createKeyFn());
await assert.isRejected(testClient.auto({ await assert.isRejected(testClient.auto({
csr, csr,
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.challengeNoopFn, challengeCreateFn: cts.challengeNoopFn,
challengeRemoveFn: cts.challengeNoopFn challengeRemoveFn: cts.challengeNoopFn,
}), /^authorization not found/i); }), /^authorization not found/i);
}); });
it('should throw on invalid challenge response with opts.skipChallengeVerification=true', async () => { it('should throw on invalid challenge response with opts.skipChallengeVerification=true', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: `${uuid()}.${domainName}` commonName: `${uuid()}.${domainName}`,
}, await createKeyFn()); }, await createKeyFn());
await assert.isRejected(testClient.auto({ await assert.isRejected(testClient.auto({
@ -143,38 +137,37 @@ describe('client.auto', () => {
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
skipChallengeVerification: true, skipChallengeVerification: true,
challengeCreateFn: cts.challengeNoopFn, challengeCreateFn: cts.challengeNoopFn,
challengeRemoveFn: cts.challengeNoopFn challengeRemoveFn: cts.challengeNoopFn,
})); }));
}); });
/** /**
* Challenge function exceptions * Challenge function exceptions
*/ */
it('should throw on challengeCreate exception', async () => { it('should throw on challengeCreate exception', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: `${uuid()}.${domainName}` commonName: `${uuid()}.${domainName}`,
}, await createKeyFn()); }, await createKeyFn());
await assert.isRejected(testClient.auto({ await assert.isRejected(testClient.auto({
csr, csr,
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.challengeThrowFn, challengeCreateFn: cts.challengeThrowFn,
challengeRemoveFn: cts.challengeNoopFn challengeRemoveFn: cts.challengeNoopFn,
}), /^oops$/); }), /^oops$/);
}); });
it('should not throw on challengeRemove exception', async () => { it('should not throw on challengeRemove exception', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: `${uuid()}.${domainName}` commonName: `${uuid()}.${domainName}`,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
csr, csr,
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.challengeCreateFn, challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeThrowFn challengeRemoveFn: cts.challengeThrowFn,
}); });
assert.isString(cert); assert.isString(cert);
@ -188,8 +181,8 @@ describe('client.auto', () => {
`${uuid()}.${domainName}`, `${uuid()}.${domainName}`,
`${uuid()}.${domainName}`, `${uuid()}.${domainName}`,
`${uuid()}.${domainName}`, `${uuid()}.${domainName}`,
`${uuid()}.${domainName}` `${uuid()}.${domainName}`,
] ],
}, await createKeyFn()); }, await createKeyFn());
await assert.isRejected(testClient.auto({ await assert.isRejected(testClient.auto({
@ -205,28 +198,27 @@ describe('client.auto', () => {
results.push(true); results.push(true);
return cts.challengeCreateFn(...args); return cts.challengeCreateFn(...args);
}, },
challengeRemoveFn: cts.challengeRemoveFn challengeRemoveFn: cts.challengeRemoveFn,
})); }));
assert.strictEqual(results.length, 5); assert.strictEqual(results.length, 5);
assert.deepStrictEqual(results, [false, false, false, true, true]); assert.deepStrictEqual(results, [false, false, false, true, true]);
}); });
/** /**
* Order certificates * Order certificates
*/ */
it('should order certificate', async () => { it('should order certificate', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: testDomain commonName: testDomain,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
csr, csr,
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.challengeCreateFn, challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn challengeRemoveFn: cts.challengeRemoveFn,
}); });
assert.isString(cert); assert.isString(cert);
@ -235,7 +227,7 @@ describe('client.auto', () => {
it('should order certificate using http-01', async () => { it('should order certificate using http-01', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: testHttpDomain commonName: testHttpDomain,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
@ -243,7 +235,7 @@ describe('client.auto', () => {
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.assertHttpChallengeCreateFn, challengeCreateFn: cts.assertHttpChallengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn, challengeRemoveFn: cts.challengeRemoveFn,
challengePriority: ['http-01'] challengePriority: ['http-01'],
}); });
assert.isString(cert); assert.isString(cert);
@ -251,7 +243,7 @@ describe('client.auto', () => {
it('should order certificate using https-01', async () => { it('should order certificate using https-01', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: testHttpsDomain commonName: testHttpsDomain,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
@ -259,7 +251,7 @@ describe('client.auto', () => {
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.assertHttpsChallengeCreateFn, challengeCreateFn: cts.assertHttpsChallengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn, challengeRemoveFn: cts.challengeRemoveFn,
challengePriority: ['http-01'] challengePriority: ['http-01'],
}); });
assert.isString(cert); assert.isString(cert);
@ -267,7 +259,7 @@ describe('client.auto', () => {
it('should order certificate using dns-01', async () => { it('should order certificate using dns-01', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: testDnsDomain commonName: testDnsDomain,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
@ -275,7 +267,7 @@ describe('client.auto', () => {
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.assertDnsChallengeCreateFn, challengeCreateFn: cts.assertDnsChallengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn, challengeRemoveFn: cts.challengeRemoveFn,
challengePriority: ['dns-01'] challengePriority: ['dns-01'],
}); });
assert.isString(cert); assert.isString(cert);
@ -283,7 +275,7 @@ describe('client.auto', () => {
it('should order certificate using tls-alpn-01', async () => { it('should order certificate using tls-alpn-01', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: testAlpnDomain commonName: testAlpnDomain,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
@ -291,7 +283,7 @@ describe('client.auto', () => {
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.assertTlsAlpnChallengeCreateFn, challengeCreateFn: cts.assertTlsAlpnChallengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn, challengeRemoveFn: cts.challengeRemoveFn,
challengePriority: ['tls-alpn-01'] challengePriority: ['tls-alpn-01'],
}); });
assert.isString(cert); assert.isString(cert);
@ -299,14 +291,14 @@ describe('client.auto', () => {
it('should order san certificate', async () => { it('should order san certificate', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
altNames: testSanDomains altNames: testSanDomains,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
csr, csr,
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.challengeCreateFn, challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn challengeRemoveFn: cts.challengeRemoveFn,
}); });
assert.isString(cert); assert.isString(cert);
@ -316,14 +308,14 @@ describe('client.auto', () => {
it('should order wildcard certificate', async () => { it('should order wildcard certificate', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: testWildcardDomain, commonName: testWildcardDomain,
altNames: [`*.${testWildcardDomain}`] altNames: [`*.${testWildcardDomain}`],
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
csr, csr,
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.challengeCreateFn, challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn challengeRemoveFn: cts.challengeRemoveFn,
}); });
assert.isString(cert); assert.isString(cert);
@ -332,7 +324,7 @@ describe('client.auto', () => {
it('should order certificate with opts.skipChallengeVerification=true', async () => { it('should order certificate with opts.skipChallengeVerification=true', async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: `${uuid()}.${domainName}` commonName: `${uuid()}.${domainName}`,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
@ -340,20 +332,20 @@ describe('client.auto', () => {
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
skipChallengeVerification: true, skipChallengeVerification: true,
challengeCreateFn: cts.challengeCreateFn, challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn challengeRemoveFn: cts.challengeRemoveFn,
}); });
assert.isString(cert); assert.isString(cert);
}); });
it('should order alternate certificate chain [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function() { it('should order alternate certificate chain [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function () {
if (!capAlternateCertRoots) { if (!capAlternateCertRoots) {
this.skip(); this.skip();
} }
await Promise.all(testIssuers.map(async (issuer) => { await Promise.all(testIssuers.map(async (issuer) => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: `${uuid()}.${domainName}` commonName: `${uuid()}.${domainName}`,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
@ -361,7 +353,7 @@ describe('client.auto', () => {
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
preferredChain: issuer, preferredChain: issuer,
challengeCreateFn: cts.challengeCreateFn, challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn challengeRemoveFn: cts.challengeRemoveFn,
}); });
const rootCert = acme.crypto.splitPemChain(cert).pop(); const rootCert = acme.crypto.splitPemChain(cert).pop();
@ -371,13 +363,13 @@ describe('client.auto', () => {
})); }));
}); });
it('should get default chain with invalid preference [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function() { it('should get default chain with invalid preference [ACME_CAP_ALTERNATE_CERT_ROOTS]', async function () {
if (!capAlternateCertRoots) { if (!capAlternateCertRoots) {
this.skip(); this.skip();
} }
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: `${uuid()}.${domainName}` commonName: `${uuid()}.${domainName}`,
}, await createKeyFn()); }, await createKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
@ -385,7 +377,7 @@ describe('client.auto', () => {
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
preferredChain: uuid(), preferredChain: uuid(),
challengeCreateFn: cts.challengeCreateFn, challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn challengeRemoveFn: cts.challengeRemoveFn,
}); });
const rootCert = acme.crypto.splitPemChain(cert).pop(); const rootCert = acme.crypto.splitPemChain(cert).pop();
@ -394,7 +386,6 @@ describe('client.auto', () => {
assert.strictEqual(testIssuers[0], info.issuer.commonName); assert.strictEqual(testIssuers[0], info.issuer.commonName);
}); });
/** /**
* Order certificate with alternate key sizes * Order certificate with alternate key sizes
*/ */
@ -402,21 +393,20 @@ describe('client.auto', () => {
Object.entries(createKeyAltFns).forEach(([k, altKeyFn]) => { Object.entries(createKeyAltFns).forEach(([k, altKeyFn]) => {
it(`should order certificate with key=${k}`, async () => { it(`should order certificate with key=${k}`, async () => {
const [, csr] = await acme.crypto.createCsr({ const [, csr] = await acme.crypto.createCsr({
commonName: testDomain commonName: testDomain,
}, await altKeyFn()); }, await altKeyFn());
const cert = await testClient.auto({ const cert = await testClient.auto({
csr, csr,
termsOfServiceAgreed: true, termsOfServiceAgreed: true,
challengeCreateFn: cts.challengeCreateFn, challengeCreateFn: cts.challengeCreateFn,
challengeRemoveFn: cts.challengeRemoveFn challengeRemoveFn: cts.challengeRemoveFn,
}); });
assert.isString(cert); assert.isString(cert);
}); });
}); });
/** /**
* Read certificates * Read certificates
*/ */

View File

@ -8,7 +8,6 @@ const axios = require('./../src/axios');
const apiBaseUrl = process.env.ACME_CHALLTESTSRV_URL || null; const apiBaseUrl = process.env.ACME_CHALLTESTSRV_URL || null;
const httpsPort = axios.defaults.acmeSettings.httpsChallengePort || 443; const httpsPort = axios.defaults.acmeSettings.httpsChallengePort || 443;
/** /**
* Send request * Send request
*/ */
@ -21,20 +20,18 @@ async function request(apiPath, data = {}) {
await axios.request({ await axios.request({
url: `${apiBaseUrl}/${apiPath}`, url: `${apiBaseUrl}/${apiPath}`,
method: 'post', method: 'post',
data data,
}); });
return true; return true;
} }
/** /**
* State * State
*/ */
exports.isEnabled = () => !!apiBaseUrl; exports.isEnabled = () => !!apiBaseUrl;
/** /**
* DNS * DNS
*/ */
@ -42,7 +39,6 @@ exports.isEnabled = () => !!apiBaseUrl;
exports.addDnsARecord = async (host, addresses) => request('add-a', { host, addresses }); exports.addDnsARecord = async (host, addresses) => request('add-a', { host, addresses });
exports.setDnsCnameRecord = async (host, target) => request('set-cname', { host, target }); exports.setDnsCnameRecord = async (host, target) => request('set-cname', { host, target });
/** /**
* Challenge response * Challenge response
*/ */
@ -55,7 +51,7 @@ async function addHttps01ChallengeResponse(token, content, targetHostname) {
await addHttp01ChallengeResponse(token, content); await addHttp01ChallengeResponse(token, content);
return request('add-redirect', { return request('add-redirect', {
path: `/.well-known/acme-challenge/${token}`, path: `/.well-known/acme-challenge/${token}`,
targetURL: `https://${targetHostname}:${httpsPort}/.well-known/acme-challenge/${token}` targetURL: `https://${targetHostname}:${httpsPort}/.well-known/acme-challenge/${token}`,
}); });
} }
@ -72,7 +68,6 @@ exports.addHttps01ChallengeResponse = addHttps01ChallengeResponse;
exports.addDns01ChallengeResponse = addDns01ChallengeResponse; exports.addDns01ChallengeResponse = addDns01ChallengeResponse;
exports.addTlsAlpn01ChallengeResponse = addTlsAlpn01ChallengeResponse; exports.addTlsAlpn01ChallengeResponse = addTlsAlpn01ChallengeResponse;
/** /**
* Challenge response mock functions * Challenge response mock functions
*/ */

View File

@ -7,7 +7,6 @@ const util = require('./../src/util');
const pebbleManagementUrl = process.env.ACME_PEBBLE_MANAGEMENT_URL || null; const pebbleManagementUrl = process.env.ACME_PEBBLE_MANAGEMENT_URL || null;
/** /**
* Pebble * Pebble
*/ */
@ -26,7 +25,6 @@ async function getPebbleCertIssuers() {
return info.map((i) => i.issuer.commonName); return info.map((i) => i.issuer.commonName);
} }
/** /**
* Get certificate issuers * Get certificate issuers
*/ */

View File

@ -7,14 +7,12 @@ const chai = require('chai');
const chaiAsPromised = require('chai-as-promised'); const chaiAsPromised = require('chai-as-promised');
const axios = require('./../src/axios'); const axios = require('./../src/axios');
/** /**
* Add promise support to Chai * Add promise support to Chai
*/ */
chai.use(chaiAsPromised); chai.use(chaiAsPromised);
/** /**
* Challenge test server ports * Challenge test server ports
*/ */
@ -31,7 +29,6 @@ if (process.env.ACME_TLSALPN_PORT) {
axios.defaults.acmeSettings.tlsAlpnChallengePort = process.env.ACME_TLSALPN_PORT; axios.defaults.acmeSettings.tlsAlpnChallengePort = process.env.ACME_TLSALPN_PORT;
} }
/** /**
* External account binding * External account binding
*/ */

View File

@ -7,7 +7,6 @@ const { assert } = require('chai');
const spec = {}; const spec = {};
module.exports = spec; module.exports = spec;
/** /**
* ACME * ACME
*/ */
@ -120,7 +119,6 @@ spec.rfc8555.challenge = (obj) => {
} }
}; };
/** /**
* Crypto * Crypto
*/ */
@ -150,7 +148,6 @@ spec.crypto.certificateInfo = (obj) => {
assert.strictEqual(Object.prototype.toString.call(obj.notAfter), '[object Date]'); assert.strictEqual(Object.prototype.toString.call(obj.notAfter), '[object Date]');
}; };
/** /**
* JWK * JWK
*/ */

View File

@ -15,7 +15,6 @@ export type PublicKeyString = string;
export type CertificateString = string; export type CertificateString = string;
export type CsrString = string; export type CsrString = string;
/** /**
* Augmented ACME interfaces * Augmented ACME interfaces
*/ */
@ -28,7 +27,6 @@ export interface Authorization extends rfc8555.Authorization {
url: string; url: string;
} }
/** /**
* Client * Client
*/ */
@ -80,7 +78,6 @@ export class Client {
auto(opts: ClientAutoOptions): Promise<string>; auto(opts: ClientAutoOptions): Promise<string>;
} }
/** /**
* Directory URLs * Directory URLs
*/ */
@ -99,7 +96,6 @@ export const directory: {
} }
}; };
/** /**
* Crypto * Crypto
*/ */
@ -177,14 +173,12 @@ export interface CryptoLegacyInterface {
export const forge: CryptoLegacyInterface; export const forge: CryptoLegacyInterface;
/** /**
* Axios * Axios
*/ */
export const axios: AxiosInstance; export const axios: AxiosInstance;
/** /**
* Logger * Logger
*/ */

View File

@ -4,7 +4,6 @@
import * as acme from 'acme-client'; import * as acme from 'acme-client';
(async () => { (async () => {
/* Client */ /* Client */
const accountKey = await acme.crypto.createPrivateKey(); const accountKey = await acme.crypto.createPrivateKey();

View File

@ -27,7 +27,6 @@ export interface AccountUpdateRequest {
termsOfServiceAgreed?: boolean; termsOfServiceAgreed?: boolean;
} }
/** /**
* Order * Order
* *
@ -53,7 +52,6 @@ export interface OrderCreateRequest {
notAfter?: string; notAfter?: string;
} }
/** /**
* Authorization * Authorization
* *
@ -73,7 +71,6 @@ export interface Identifier {
value: string; value: string;
} }
/** /**
* Challenge * Challenge
* *
@ -102,7 +99,6 @@ export interface DnsChallenge extends ChallengeAbstract {
export type Challenge = HttpChallenge | DnsChallenge; export type Challenge = HttpChallenge | DnsChallenge;
/** /**
* Certificate * Certificate
* *