"use strict"; var request = require("@root/request"); // For most tests var siteSubject = "xx.com"; var siteAltname = "www.foo.xx.com"; var siteWildname = "*.xx.com"; var siteMatch = "foo.xx.com"; var domains = [siteSubject, siteAltname, siteWildname]; // Similar, but non-matching subjects var noExistWild = "*.foo.xx.com"; var noExistAlt = "bar.xx.com"; // For wildcard-as-subject test var siteWildnameNet = "*.xx.net"; var siteMatchNet = "foo.xx.net"; module.exports.test = async function(pkg, config) { if ("function" !== typeof pkg.create) { throw new Error( "must have a create function that accepts a single options object" ); } var features = { altnames: false, wildcard: false, renewal: false }; var manager = pkg.create(config); var initVal; if (manager.init) { initVal = await manager.init({ request: request }); if (!initVal && initVal !== null) { console.warn( "WARN: `init()` returned `undefined`, but should return `null`" ); } } console.info("PASS: init(deps)"); await manager.set({ subject: siteSubject, altnames: domains }); var site = await manager.get({ servername: siteSubject // *.com is an invalid wildname }); if (!site || site.subject !== siteSubject) { throw new Error( "set({ subject: '" + siteSubject + "'}), but could not `get()` or `find()` it" ); } // // Test for altname support // site = await get({ servername: siteAltname, wildname: untame(siteAltname) }); if (site) { if (site.subject !== siteSubject) { throw new Error("found incorrect site"); } features.altnames = true; } else { console.warn("WARN: Does not support altnames."); console.warn( " (searched for %s but did not find site '%s')", siteAltname, domains.join(" ") ); } // // Test for wildcard support // if (features.altnames) { // Set the wildcard as an altname site = await get({ servername: siteMatch, wildname: siteWildname }); if (site) { if (site.subject !== siteSubject) { throw new Error( "found %s when looking for %s", site.subject, siteSubject ); } features.wildcard = true; } else { console.warn("WARN: Does not support wildcard domains."); console.warn( " (searched for %s but did not find site %s)", siteMatch, siteSubject ); } } // Set the wildcard as the subject await manager.set({ subject: siteWildnameNet, altnames: [siteWildnameNet] }); site = await get({ servername: siteMatchNet, wildname: siteWildnameNet }); if (site) { if (site.subject !== siteWildnameNet) { throw new Error("found incorrect site"); } features.wildcard = true; } else { if (features.wildcard) { throw new Error( "searched for wildcard subject " + siteWildnameNet + " but did not find it" ); } if (!features.altnames) { console.warn( "WARN: Does not support wildcard domains as certificate subjects." ); console.warn( " (searched for %s as %s but did not find site %s)", siteMatchNet, siteWildnameNet, siteWildnameNet ); } } await remove({ subject: siteWildnameNet }); var wasSet = false; if (manager.find) { await manager.find({}).then(function(results) { if (!results.length) { //console.error(results); throw new Error("should have found all managed sites"); } wasSet = results.some(function(site) { return site.subject === siteSubject; }); if (!wasSet) { throw new Error("should have found " + siteSubject); } }); } if (manager.get) { await manager.get({ servername: siteSubject }).then(function(site) { if (!site || site.subject !== siteSubject) { throw new Error("should have found " + siteSubject); } wasSet = true; }); if (features.altnames) { wasSet = false; await manager.get({ servername: siteAltname }).then(function(site) { if (!site || site.subject !== siteSubject) { throw new Error("should have found " + siteAltname); } }); await manager .get({ servername: siteMatch, wildname: siteWildname }) .then(function(site) { if (!site || site.subject !== siteSubject) { throw new Error( "did not find " + siteMatch + ", which matches " + siteWildname ); } wasSet = true; }); } console.info("PASS: get({ servername, wildname })"); } else { console.info("[skip] get({ servername, wildname }) not implemented"); } if (wasSet) { console.info("PASS: set({ subject })"); } else { throw new Error("neither `get()` nor `find()` was implemented"); } if (manager.find) { await manager.find({ subject: siteAltname }).then(function(results) { if (results.length) { console.error(results); throw new Error( "shouldn't find what doesn't exist, exactly, by subject" ); } }); await manager .find({ servernames: [siteAltname], altnames: [siteAltname] }) .then(function(results) { if (!results.length) { console.error(results); throw new Error("should have found sites matching altname"); } }); console.info("PASS: find({ servernames, renewBefore })"); } else { console.info( "[skip] find({ servernames, renewBefore }) not implemented" ); } await remove({ subject: noExistWild }).then(function(result) { if (result) { console.error(siteWildname, result); throw new Error( "should not return prior object when deleting non-existing wildcard domain: " + noExistWild ); } }); await remove({ subject: noExistAlt }).then(function(result) { if (result) { throw new Error( "should not return prior object when deleting non-existing site: " + noExistAlt ); } }); await remove({ subject: siteWildname }).then(function(result) { if (result) { throw new Error("should not delete by wildname: " + siteWildname); } }); await remove({ subject: siteAltname }).then(function(result) { if (result) { throw new Error("should not delete by altname: " + siteAltname); } }); await remove({ subject: siteSubject }).then(function(result) { if (!result || !result.subject || !result.altnames) { throw new Error("should return prior object when deleting site"); } }); if (!manager.remove) { console.info( "[skip] remove() not implemented - using set({ deletedAt }) instead" ); } await manager.set({ subject: siteSubject, altnames: domains.slice(0, 2) }); if (manager.find) { await manager .find({ servernames: [noExistWild], altnames: [noExistWild] }) .then(function(results) { if (results.length) { console.error(results); throw new Error( "should only find an exact (literal) wildcard match" ); } }); } await remove({ subject: siteSubject }).then(function(result) { if (!result || !result.subject || !result.altnames) { console.error( "Could not find", siteSubject, "to delete it:", result ); throw new Error("should return prior object when deleting site"); } }); if (manager.find) { await manager .find({ servernames: domains, altnames: domains }) .then(function(results) { if (results.length) { console.error(results); throw new Error("should not find() deleted sites"); } }); } else { await get({ servername: siteAltname }).then(function(result) { if (result) { console.error(result); throw new Error("should not get() deleted sites"); } }); } console.info("PASS: remove({ subject })"); var originalInput = { serverKeyType: "RSA-2048", accountKeyType: "P-256", subscriberEmail: "jon@example.com", agreeToTerms: true, store: { module: "/path/to/store-module", foo: "foo" }, challenges: { "http-01": { module: "/path/to/http-01-module", bar: "bar" }, "dns-01": { module: "/path/to/dns-01-module", baz: "baz" }, "tls-alpn-01": { module: "/path/to/tls-alpn-01-module", qux: "quux" } }, customerEmail: "jane@example.com" }; //var backup = JSON.parse(JSON.stringify(originalInput)); var configUpdate = { renewOffset: "45d", renewStagger: "12h", subscriberEmail: "pat@example.com" }; var internalConfig; if (manager.defaults) { await manager.defaults().then(function(result) { internalConfig = result; if (!result) { throw new Error( "should at least return an empty object, perhaps one with some defaults set" ); } }); await manager.defaults(originalInput).then(function(result) { // can't say much... what _should_ this return? // probably nothing? or maybe the full config object? if (internalConfig === result) { console.warn( "WARN: should return a new copy, not the same internal object" ); } if (originalInput === result) { console.warn( "WARN: should probably return a copy, not the original input" ); } }); await manager.defaults().then(function(result) { if (originalInput === result) { console.warn( "WARN: should probably return a copy, not the prior input" ); } }); await manager.defaults(configUpdate).then(function() { if (originalInput.renewOffset) { console.warn("WARN: should probably modify the prior input"); } }); console.info("PASS: defaults(conf)"); await manager.defaults().then(function(result) { if (!result.subscriberEmail || !result.renewOffset) { throw new Error("should merge config values together"); } }); console.info("PASS: defaults()"); } else { console.info( "[skip] defaults({ store, challenges, ... }) not implemented" ); } features.renewal = !!manager.find; var featureNames = { altnames: "Multiple Domains per Certificate", wildcard: "Wildcard Certificates" + (features.altnames ? "" : " (subject only)"), renewal: "Fully Automatic Renewal" }; return Object.keys(features).map(function(k) { return { name: k, description: featureNames[k], supported: features[k] }; }); function get(opts) { if (manager.get) { opts.servername = opts.servername || opts.subject; delete opts.subject; return manager.get(opts); } else { return manager.find(opts); } } function remove(opts) { if (manager.remove) { return manager.remove(opts); } else { return get(opts).then(function(site) { // get matches servername, but remove should only match subject if (site && site.subject === opts.servername) { site.deletedAt = Date.now(); return manager.set(site).then(function() { return site; }); } return null; }); } } function untame(str) { return ( "*." + str .split(".") .slice(1) .join(".") ); } };