add zerossl acme (#6084)

Signed-off-by: si458 <simonsmith5521@gmail.com>

Simon Smith committed May 12, 2024 at 15:45 UTC bf7957ebffd2f74ca7d867e40b4975e9f9a6bd99
3 files changed +50 -12
letsencrypt.js
+23 -10
@@ -28,6 +28,8 @@ module.exports.CreateLetsEncrypt = function (parent) {
28 obj.challenges = {};
29 obj.runAsProduction = false;
30 obj.redirWebServerHooked = false;
31 + obj.zerossl = false;
32 + obj.csr = null;
33 obj.configErr = null;
34 obj.configOk = false;
35 obj.pendingRequest = false;
@@ -57,6 +59,7 @@ module.exports.CreateLetsEncrypt = function (parent) {
59 // Get the current certificate
60 obj.getCertificate = function(certs, func) {
61 obj.runAsProduction = (obj.parent.config.letsencrypt.production === true);
62 + obj.zerossl = ((typeof obj.parent.config.letsencrypt.zerossl == 'object') ? obj.parent.config.letsencrypt.zerossl : false);
63 obj.log("Getting certs from local store (" + (obj.runAsProduction ? "Production" : "Staging") + ")");
64 if (certs.CommonName.indexOf('.') == -1) { obj.configErr = "Add \"cert\" value to settings in config.json before using Let's Encrypt."; parent.addServerWarning(obj.configErr); obj.log("WARNING: " + obj.configErr); func(certs); return; }
65 if (obj.parent.config.letsencrypt == null) { obj.configErr = "No Let's Encrypt configuration"; parent.addServerWarning(obj.configErr); obj.log("WARNING: " + obj.configErr); func(certs); return; }
@@ -164,26 +167,36 @@ module.exports.CreateLetsEncrypt = function (parent) {
167 obj.log("Generating private key...");
168 acme.forge.createPrivateKey().then(function (accountKey) {
169
167 - // TODO: ZeroSSL
168 - // https://acme.zerossl.com/v2/DV90
169 -
170 // Create the ACME client
171 obj.log("Setting up ACME client...");
172 - obj.client = new acme.Client({
173 - directoryUrl: obj.runAsProduction ? acme.directory.letsencrypt.production : acme.directory.letsencrypt.staging,
174 - accountKey: accountKey
175 - });
172 + if (obj.zerossl) {
173 + if (obj.zerossl.kid == "") { obj.log("EAB KID hasn't been set, invalid configuration."); return; }
174 + if (obj.zerossl.hmackey == "") { obj.log("EAB HMAC KEY hasn't been set, invalid configuration."); return; }
175 + obj.client = new acme.Client({
176 + directoryUrl: acme.directory.zerossl.production,
177 + accountKey: accountKey,
178 + externalAccountBinding: {
179 + kid: obj.zerossl.kid,
180 + hmacKey: obj.zerossl.hmackey
181 + }
182 + });
183 + } else {
184 + obj.client = new acme.Client({
185 + directoryUrl: obj.runAsProduction ? acme.directory.letsencrypt.production : acme.directory.letsencrypt.staging,
186 + accountKey: accountKey
187 + });
188 + }
189
190 // Create Certificate Request (CSR)
191 obj.log("Creating certificate request...");
192 var certRequest = { commonName: obj.leDomains[0] };
193 if (obj.leDomains.length > 1) { certRequest.altNames = obj.leDomains; }
194 acme.forge.createCsr(certRequest).then(function (r) {
182 - var csr = r[1];
195 + obj.csr = r[1];
196 obj.tempPrivateKey = r[0];
184 - obj.log("Requesting certificate from Let's Encrypt...");
197 + if(obj.zerossl) { obj.log("Requesting certificate from ZeroSSL..."); } else { obj.log("Requesting certificate from Let's Encrypt..."); }
198 obj.client.auto({
186 - csr,
199 + csr: obj.csr,
200 email: obj.parent.config.letsencrypt.email,
201 termsOfServiceAgreed: true,
202 skipChallengeVerification: (obj.parent.config.letsencrypt.skipchallengeverification === true),
meshcentral-config-schema.json
+22 -1
@@ -3504,12 +3504,33 @@
3504 "production": {
3505 "type": "boolean",
3506 "default": false,
3507 - "description": "By default a test certificate will be obtained from Let's Encrypt. Always start by getting a test certificate and make sure that works before setting this to true and obtaining a production certificate. Making too many bad requests for a production certificate will get you banned for a long period of time."
3507 + "description": "By default a test certificate will be obtained from Let's Encrypt. Setting \"zerossl\", will ignore this setting. Always start by getting a test certificate and make sure that works before setting this to true and obtaining a production certificate. Making too many bad requests for a production certificate will get you banned for a long period of time."
3508 },
3509 "nochecks": {
3510 "type": "boolean",
3511 "default": false,
3512 "description": "If you choose \"true\", MeshCentral won't verify if \"email\" is valid, has a valid MX record, AND if \"names\" doesn't contain a wildcard, can be resolved by DNS A/AAAA record."
3513 + },
3514 + "zerossl": {
3515 + "type": "object",
3516 + "description": "If this object is set, we will use ZeroSSL for SSL creation instead of Let's Encrypt",
3517 + "required": [
3518 + "kid",
3519 + "hmacKey"
3520 + ],
3521 + "properties": {
3522 + "kid": {
3523 + "type": "string",
3524 + "description": "EAB KID",
3525 + "default": ""
3526 + },
3527 + "hmackey": {
3528 + "type": "string",
3529 + "description": "EAB HMAC KEY",
3530 + "default": ""
3531 + }
3532 + },
3533 + "additionalProperties": false
3534 }
3535 },
3536 "required": [
sample-config-advanced.json
+5 -1
@@ -565,7 +565,11 @@
565 "email": "myemail@myserver.com",
566 "names": "myserver.com,customer1.myserver.com",
567 "skipChallengeVerification": false,
568 - "production": false
568 + "production": false,
569 + "zerossl": {
570 + "kid": "a1b2c3d4e5",
571 + "hmacKey": "a1b2c3d4e5"
572 + }
573 },
574 "_peers": {
575 "serverId": "server1",