|
|
@ -4,18 +4,18 @@ |
|
|
|
/*global URLSearchParams,Headers*/ |
|
|
|
var PromiseA = window.Promise; |
|
|
|
var VERSION = '2'; |
|
|
|
// ACME recommends ECDSA P-256, but RSA 2048 is still required by some old servers (like what replicated.io uses )
|
|
|
|
// ECDSA P-384, P-521, and RSA 3072, 4096 are NOT recommend standards (and not properly supported)
|
|
|
|
var BROWSER_SUPPORTS_RSA; |
|
|
|
var ECDSA_OPTS = { kty: 'EC', namedCurve: 'P-256' }; |
|
|
|
var RSA_OPTS = { kty: 'RSA', modulusLength: 2048 }; |
|
|
|
// ACME recommends ECDSA P-256, but RSA 2048 is still required by some old servers (like what replicated.io uses )
|
|
|
|
// ECDSA P-384, P-521, and RSA 3072, 4096 are NOT recommend standards (and not properly supported)
|
|
|
|
var BROWSER_SUPPORTS_RSA = false; |
|
|
|
var ECDSA_OPTS = { kty: 'EC', namedCurve: 'P-256' }; |
|
|
|
var RSA_OPTS = { kty: 'RSA', modulusLength: 2048 }; |
|
|
|
var Promise = window.Promise; |
|
|
|
var Keypairs = window.Keypairs; |
|
|
|
var ACME = window.ACME; |
|
|
|
var CSR = window.CSR; |
|
|
|
var $qs = function (s) { return window.document.querySelector(s); }; |
|
|
|
var $qsa = function (s) { return window.document.querySelectorAll(s); }; |
|
|
|
var acme; |
|
|
|
var acme; |
|
|
|
var info = {}; |
|
|
|
var steps = {}; |
|
|
|
var i = 1; |
|
|
@ -29,36 +29,12 @@ |
|
|
|
} |
|
|
|
localStorage.setItem('version', VERSION); |
|
|
|
|
|
|
|
var challenges = { |
|
|
|
'http-01': { |
|
|
|
set: function (auth) { |
|
|
|
console.log('Chose http-01 for', auth.altname, auth); |
|
|
|
return Promise.resolve(); |
|
|
|
} |
|
|
|
, remove: function (auth) { |
|
|
|
console.log('Can remove http-01 for', auth.altname, auth); |
|
|
|
return Promise.resolve(); |
|
|
|
} |
|
|
|
} |
|
|
|
, 'dns-01': { |
|
|
|
set: function (auth) { |
|
|
|
console.log('Chose dns-01 for', auth.altname, auth); |
|
|
|
return Promise.resolve(); |
|
|
|
} |
|
|
|
, remove: function (auth) { |
|
|
|
console.log('Can remove dns-01 for', auth.altname, auth); |
|
|
|
return Promise.resolve(); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
function updateApiType() { |
|
|
|
console.log("type updated"); |
|
|
|
/*jshint validthis: true */ |
|
|
|
var input = this || Array.prototype.filter.call( |
|
|
|
$qsa('.js-acme-api-type'), function ($el) { return $el.checked; } |
|
|
|
)[0]; |
|
|
|
console.log('ACME api type radio:', input.value); |
|
|
|
//#console.log('ACME api type radio:', input.value);
|
|
|
|
$qs('.js-acme-directory-url').value = apiUrl.replace(/{{env}}/g, input.value); |
|
|
|
} |
|
|
|
|
|
|
@ -70,7 +46,7 @@ |
|
|
|
|
|
|
|
function updateProgress(currentStep) { |
|
|
|
var progressSteps = $qs("#js-progress-bar").children; |
|
|
|
var j; |
|
|
|
var j; |
|
|
|
for (j = 0; j < progressSteps.length; j += 1) { |
|
|
|
if (j < currentStep) { |
|
|
|
progressSteps[j].classList.add("js-progress-step-complete"); |
|
|
@ -116,28 +92,18 @@ |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
function testEcdsaSupport() { |
|
|
|
/* |
|
|
|
var opts = { |
|
|
|
kty: $('input[name="kty"]:checked').value |
|
|
|
, namedCurve: $('input[name="ec-crv"]:checked').value |
|
|
|
, modulusLength: $('input[name="rsa-len"]:checked').value |
|
|
|
}; |
|
|
|
*/ |
|
|
|
} |
|
|
|
function testRsaSupport() { |
|
|
|
return Keypairs.generate(RSA_OPTS); |
|
|
|
} |
|
|
|
function testKeypairSupport() { |
|
|
|
|
|
|
|
return testRsaSupport().then(function () { |
|
|
|
return Keypairs.generate(RSA_OPTS).then(function () { |
|
|
|
console.info("[crypto] RSA is supported"); |
|
|
|
BROWSER_SUPPORTS_RSA = true; |
|
|
|
return BROWSER_SUPPORTS_RSA; |
|
|
|
}).catch(function () { |
|
|
|
console.warn("[crypto] RSA is NOT fully supported"); |
|
|
|
BROWSER_SUPPORTS_RSA = false; |
|
|
|
return BROWSER_SUPPORTS_RSA; |
|
|
|
console.warn("[crypto] RSA is NOT supported"); |
|
|
|
return Keypairs.generate(ECDSA_OPTS).then(function () { |
|
|
|
console.info('[crypto] ECDSA is supported'); |
|
|
|
}).catch(function (e) { |
|
|
|
console.warn("[crypto] EC is NOT supported"); |
|
|
|
throw e; |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
@ -159,36 +125,35 @@ |
|
|
|
return Keypairs.generate(RSA_OPTS).catch(function (err) { |
|
|
|
console.error("[Error] Keypairs.generate(" + JSON.stringify(RSA_OPTS) + "):"); |
|
|
|
throw err; |
|
|
|
}).then(function (pair) { |
|
|
|
localStorage.setItem('server:'+sortedAltnames, JSON.stringify(pair.private)); |
|
|
|
return pair.private; |
|
|
|
}); |
|
|
|
}).then(function (pair) { |
|
|
|
localStorage.setItem('server:'+sortedAltnames, JSON.stringify(pair.private)); |
|
|
|
return pair.private; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
function getAccountKeypair(email) { |
|
|
|
var json = localStorage.getItem('account:'+email); |
|
|
|
if (json) { |
|
|
|
return Promise.resolve(JSON.parse(json)); |
|
|
|
} |
|
|
|
|
|
|
|
return Keypairs.generate(ECDSA_OPTS).catch(function (err) { |
|
|
|
console.warn("[Error] Keypairs.generate(" + JSON.stringify(ECDSA_OPTS) + "):\n", err); |
|
|
|
return Keypairs.generate(RSA_OPTS).catch(function (err) { |
|
|
|
console.error("[Error] Keypairs.generate(" + JSON.stringify(RSA_OPTS) + "):"); |
|
|
|
throw err; |
|
|
|
}); |
|
|
|
}).then(function (pair) { |
|
|
|
localStorage.setItem('account:'+email, JSON.stringify(pair.private)); |
|
|
|
return pair.private; |
|
|
|
}); |
|
|
|
} |
|
|
|
function getAccountKeypair(email) { |
|
|
|
var json = localStorage.getItem('account:'+email); |
|
|
|
if (json) { |
|
|
|
return Promise.resolve(JSON.parse(json)); |
|
|
|
} |
|
|
|
|
|
|
|
return Keypairs.generate(ECDSA_OPTS).catch(function (err) { |
|
|
|
console.warn("[Error] Keypairs.generate(" + JSON.stringify(ECDSA_OPTS) + "):\n", err); |
|
|
|
return Keypairs.generate(RSA_OPTS).catch(function (err) { |
|
|
|
console.error("[Error] Keypairs.generate(" + JSON.stringify(RSA_OPTS) + "):"); |
|
|
|
throw err; |
|
|
|
}); |
|
|
|
}).then(function (pair) { |
|
|
|
localStorage.setItem('account:'+email, JSON.stringify(pair.private)); |
|
|
|
return pair.private; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
function updateChallengeType() { |
|
|
|
/*jshint validthis: true*/ |
|
|
|
var input = this || Array.prototype.filter.call( |
|
|
|
$qsa('.js-acme-challenge-type'), function ($el) { return $el.checked; } |
|
|
|
)[0]; |
|
|
|
console.log('ch type radio:', input.value); |
|
|
|
$qs('.js-acme-verification-wildcard').hidden = true; |
|
|
|
$qs('.js-acme-verification-http-01').hidden = true; |
|
|
|
$qs('.js-acme-verification-dns-01').hidden = true; |
|
|
@ -209,7 +174,7 @@ |
|
|
|
, body: JSON.stringify({ |
|
|
|
address: email |
|
|
|
, project: 'greenlock-domains@rootprojects.org' |
|
|
|
, timezone: new Intl.DateTimeFormat().resolvedOptions().timeZone |
|
|
|
, timezone: new Intl.DateTimeFormat().resolvedOptions().timeZone |
|
|
|
, domain: domains.join(',') |
|
|
|
}) |
|
|
|
}).catch(function (err) { |
|
|
@ -218,12 +183,17 @@ |
|
|
|
} |
|
|
|
|
|
|
|
steps[1] = function () { |
|
|
|
console.info("1. Show domains form"); |
|
|
|
updateProgress(0); |
|
|
|
hideForms(); |
|
|
|
$qs('.js-acme-form-domains').hidden = false; |
|
|
|
}; |
|
|
|
steps[1].submit = function () { |
|
|
|
info.domains = $qs('.js-acme-domains').value.replace(/https?:\/\//g, ' ').replace(/[,+]/g, ' ').trim().split(/\s+/g); |
|
|
|
console.info("[submit] 1. Process domains, create ACME client", info.domains); |
|
|
|
info.domains = $qs('.js-acme-domains').value |
|
|
|
.replace(/https?:\/\//g, ' ').replace(/[,+]/g, ' ').trim().split(/\s+/g); |
|
|
|
console.info("[domains]", info.domains.join(' ')); |
|
|
|
|
|
|
|
info.identifiers = info.domains.map(function (hostname) { |
|
|
|
return { type: 'dns', value: hostname.toLowerCase().trim() }; |
|
|
|
}); |
|
|
@ -233,90 +203,77 @@ |
|
|
|
if (a > b) { return -1; } |
|
|
|
}); |
|
|
|
|
|
|
|
var acmeDirectoryUrl = $qs('.js-acme-directory-url').value; |
|
|
|
acme = ACME.create({ Keypairs: Keypairs, CSR: CSR }); |
|
|
|
return acme.init(acmeDirectoryUrl).then(function (directory) { |
|
|
|
var acmeDirectoryUrl = $qs('.js-acme-directory-url').value; |
|
|
|
acme = ACME.create({ Keypairs: Keypairs, CSR: CSR }); |
|
|
|
return acme.init(acmeDirectoryUrl).then(function (directory) { |
|
|
|
$qs('.js-acme-tos-url').href = directory.meta.termsOfService; |
|
|
|
console.log("MAGIC STEP NUMBER in 1 is:", i); |
|
|
|
steps[i](); |
|
|
|
steps[i](); |
|
|
|
}); |
|
|
|
}; |
|
|
|
|
|
|
|
steps[2] = function () { |
|
|
|
console.info("2. Show account (email, ToS) form"); |
|
|
|
|
|
|
|
updateProgress(0); |
|
|
|
hideForms(); |
|
|
|
$qs('.js-acme-form-account').hidden = false; |
|
|
|
}; |
|
|
|
steps[2].submit = function () { |
|
|
|
var email = $qs('.js-acme-account-email').value.toLowerCase().trim(); |
|
|
|
console.info("[submit] 2. Create ACME account (get Key ID)"); |
|
|
|
|
|
|
|
var email = $qs('.js-acme-account-email').value.toLowerCase().trim(); |
|
|
|
info.email = email; |
|
|
|
info.contact = [ 'mailto:' + email ]; |
|
|
|
info.agree = $qs('.js-acme-account-tos').checked; |
|
|
|
//info.greenlockAgree = $qs('.js-gl-tos').checked;
|
|
|
|
info.domains = info.identifiers.map(function (ident) { return ident.value; }); |
|
|
|
console.log("domains:"); |
|
|
|
console.log(info.domains); |
|
|
|
|
|
|
|
// TODO ping with version and account creation
|
|
|
|
setTimeout(saveContact, 100, email, info.domains); |
|
|
|
|
|
|
|
function checkTos(tos) { |
|
|
|
if (info.agree) { |
|
|
|
return tos; |
|
|
|
} else { |
|
|
|
return ''; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
$qs('.js-account-next').disabled = true; |
|
|
|
|
|
|
|
return getAccountKeypair(email).then(function (jwk) { |
|
|
|
// TODO save account id rather than always retrieving it?
|
|
|
|
return acme.accounts.create({ |
|
|
|
email: email |
|
|
|
, agreeToTerms: checkTos |
|
|
|
, accountKeypair: { privateKeyJwk: jwk } |
|
|
|
}).then(function (account) { |
|
|
|
console.log("account created result:", account); |
|
|
|
info.account = account; |
|
|
|
info.privateJwk = jwk; |
|
|
|
info.email = email; |
|
|
|
info.acme = acme; // TODO XXX remove
|
|
|
|
}).catch(function (err) { |
|
|
|
console.error("A bad thing happened:"); |
|
|
|
console.error(err); |
|
|
|
window.alert(err.message || JSON.stringify(err, null, 2)); |
|
|
|
return new Promise(function () { |
|
|
|
// stop the process cold
|
|
|
|
console.warn('TODO: resume at ask email?'); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}).then(function () { |
|
|
|
return info.cryptoCheck.then(function () { |
|
|
|
return getAccountKeypair(email).then(function (jwk) { |
|
|
|
// TODO save account id rather than always retrieving it?
|
|
|
|
console.info("[accounts] upsert for", email); |
|
|
|
return acme.accounts.create({ |
|
|
|
email: email |
|
|
|
, agreeToTerms: info.agree && true |
|
|
|
, accountKeypair: { privateKeyJwk: jwk } |
|
|
|
}).then(function (account) { |
|
|
|
console.info("[accounts] result:", account); |
|
|
|
info.account = account; |
|
|
|
info.privateJwk = jwk; |
|
|
|
info.email = email; |
|
|
|
}).catch(function (err) { |
|
|
|
console.error("[accounts] failed to upsert account:"); |
|
|
|
console.error(err); |
|
|
|
window.alert(err.message || JSON.stringify(err, null, 2)); |
|
|
|
return new Promise(function () { |
|
|
|
if (window.confirm("Start over?")) { |
|
|
|
document.location.reload(); |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}).then(function () { |
|
|
|
var jwk = info.privateJwk; |
|
|
|
var account = info.account; |
|
|
|
|
|
|
|
return acme.orders.request({ |
|
|
|
account: account |
|
|
|
, accountKeypair: { privateKeyJwk: jwk } |
|
|
|
, domains: info.domains |
|
|
|
, challenges: challenges |
|
|
|
}).then(function (order) { |
|
|
|
console.info("[orders] requesting"); |
|
|
|
return acme.orders.request({ |
|
|
|
account: account |
|
|
|
, accountKeypair: { privateKeyJwk: jwk } |
|
|
|
, domains: info.domains |
|
|
|
}).then(function (order) { |
|
|
|
info.order = order; |
|
|
|
console.info("[orders] created ", order); |
|
|
|
|
|
|
|
var claims = order.claims; |
|
|
|
console.log('claims:'); |
|
|
|
console.log(claims); |
|
|
|
|
|
|
|
var obj = { 'dns-01': [], 'http-01': [], 'wildcard': [] }; |
|
|
|
info.challenges = obj; |
|
|
|
/* |
|
|
|
var map = { |
|
|
|
'http-01': '.js-acme-verification-http-01' |
|
|
|
, 'dns-01': '.js-acme-verification-dns-01' |
|
|
|
, 'wildcard': '.js-acme-verification-wildcard' |
|
|
|
}; |
|
|
|
*/ |
|
|
|
|
|
|
|
var $httpList = $qs('.js-acme-http'); |
|
|
|
var $dnsList = $qs('.js-acme-dns'); |
|
|
|
var $wildList = $qs('.js-acme-wildcard'); |
|
|
@ -328,8 +285,7 @@ |
|
|
|
$wildList.innerHTML = ''; |
|
|
|
|
|
|
|
claims.forEach(function (claim) { |
|
|
|
console.log("Challenge (claim):"); |
|
|
|
console.log(claim); |
|
|
|
//#console.log("claims[i]", claim);
|
|
|
|
var hostname = claim.identifier.value; |
|
|
|
claim.challenges.forEach(function (c) { |
|
|
|
var auth = c; |
|
|
@ -344,41 +300,33 @@ |
|
|
|
, dnsHost: auth.dnsHost |
|
|
|
, dnsAnswer: auth.keyAuthorizationDigest |
|
|
|
}; |
|
|
|
//#console.log("claims[i].challenge", data);
|
|
|
|
|
|
|
|
console.log(''); |
|
|
|
console.log('CHALLENGE'); |
|
|
|
console.log(claim); |
|
|
|
console.log(c); |
|
|
|
console.log(data); |
|
|
|
console.log(''); |
|
|
|
|
|
|
|
var verification = document.createElement("div"); |
|
|
|
var $tpl = document.createElement("div"); |
|
|
|
if (claim.wildcard) { |
|
|
|
obj.wildcard.push(data); |
|
|
|
verification.innerHTML = wildTpl; |
|
|
|
//verification.querySelector(".js-acme-ver-hostname").innerHTML = data.hostname;
|
|
|
|
verification.querySelector(".js-acme-ver-txt-host").innerHTML = data.dnsHost; |
|
|
|
verification.querySelector(".js-acme-ver-txt-value").innerHTML = data.dnsAnswer; |
|
|
|
$wildList.appendChild(verification); |
|
|
|
$tpl.innerHTML = wildTpl; |
|
|
|
$tpl.querySelector(".js-acme-ver-txt-host").innerHTML = data.dnsHost; |
|
|
|
$tpl.querySelector(".js-acme-ver-txt-value").innerHTML = data.dnsAnswer; |
|
|
|
$wildList.appendChild($tpl); |
|
|
|
} else if(obj[data.type]) { |
|
|
|
|
|
|
|
obj[data.type].push(data); |
|
|
|
|
|
|
|
if ('dns-01' === data.type) { |
|
|
|
verification.innerHTML = dnsTpl; |
|
|
|
//verification.querySelector(".js-acme-ver-hostname").innerHTML = data.hostname;
|
|
|
|
verification.querySelector(".js-acme-ver-txt-host").innerHTML = data.dnsHost; |
|
|
|
verification.querySelector(".js-acme-ver-txt-value").innerHTML = data.dnsAnswer; |
|
|
|
$dnsList.appendChild(verification); |
|
|
|
$tpl.innerHTML = dnsTpl; |
|
|
|
$tpl.querySelector(".js-acme-ver-txt-host").innerHTML = data.dnsHost; |
|
|
|
$tpl.querySelector(".js-acme-ver-txt-value").innerHTML = data.dnsAnswer; |
|
|
|
$dnsList.appendChild($tpl); |
|
|
|
} else if ('http-01' === data.type) { |
|
|
|
verification.innerHTML = httpTpl; |
|
|
|
verification.querySelector(".js-acme-ver-file-location").innerHTML = data.httpPath.split("/").slice(-1); |
|
|
|
verification.querySelector(".js-acme-ver-content").innerHTML = data.httpAuth; |
|
|
|
verification.querySelector(".js-acme-ver-uri").innerHTML = data.httpPath; |
|
|
|
verification.querySelector(".js-download-verify-link").href = |
|
|
|
$tpl.innerHTML = httpTpl; |
|
|
|
$tpl.querySelector(".js-acme-ver-file-location").innerHTML = data.httpPath.split("/").slice(-1); |
|
|
|
$tpl.querySelector(".js-acme-ver-content").innerHTML = data.httpAuth; |
|
|
|
$tpl.querySelector(".js-acme-ver-uri").innerHTML = data.httpPath; |
|
|
|
$tpl.querySelector(".js-download-verify-link").href = |
|
|
|
"data:text/octet-stream;base64," + window.btoa(data.httpAuth); |
|
|
|
verification.querySelector(".js-download-verify-link").download = data.httpPath.split("/").slice(-1); |
|
|
|
$httpList.appendChild(verification); |
|
|
|
$tpl.querySelector(".js-download-verify-link").download = data.httpPath.split("/").slice(-1); |
|
|
|
$httpList.appendChild($tpl); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
@ -393,9 +341,9 @@ |
|
|
|
$qs('.js-acme-challenges').hidden = true; |
|
|
|
} |
|
|
|
|
|
|
|
updateChallengeType(); |
|
|
|
console.info("[housekeeping] challenges", info.challenges); |
|
|
|
|
|
|
|
console.log("MAGIC STEP NUMBER in 2 is:", i); |
|
|
|
updateChallengeType(); |
|
|
|
steps[i](); |
|
|
|
}); |
|
|
|
}).catch(function (err) { |
|
|
@ -407,23 +355,28 @@ |
|
|
|
}; |
|
|
|
|
|
|
|
steps[3] = function () { |
|
|
|
console.info("3. Present challenge options"); |
|
|
|
updateProgress(1); |
|
|
|
hideForms(); |
|
|
|
$qs('.js-acme-form-challenges').hidden = false; |
|
|
|
}; |
|
|
|
steps[3].submit = function () { |
|
|
|
console.info("[submit] 3. Fulfill challenges, fetch certificate"); |
|
|
|
|
|
|
|
var challengePriority = [ 'dns-01' ]; |
|
|
|
if ('http-01' === $qs('.js-acme-challenge-type:checked').value) { |
|
|
|
challengePriority.unshift('http-01'); |
|
|
|
} |
|
|
|
console.log('primary challenge type is:', challengePriority[0]); |
|
|
|
console.info("[challenge] selected ", challengePriority[0]); |
|
|
|
|
|
|
|
// for now just show the next page immediately (its a spinner)
|
|
|
|
steps[i](); |
|
|
|
|
|
|
|
return getAccountKeypair(info.email).then(function (jwk) { |
|
|
|
// for now just show the next page immediately (its a spinner)
|
|
|
|
// TODO put a test challenge in the list
|
|
|
|
// info.order.claims.push(...)
|
|
|
|
// TODO warn about wait-time if DNS
|
|
|
|
return getServerKeypair().then(function (serverJwk) { |
|
|
|
return getServerKeypair().then(function (serverJwk) { |
|
|
|
return acme.orders.complete({ |
|
|
|
account: info.account |
|
|
|
, accountKeypair: { privateKeyJwk: jwk } |
|
|
@ -431,10 +384,10 @@ |
|
|
|
, domains: info.domains |
|
|
|
, domainKeypair: { privateKeyJwk: serverJwk } |
|
|
|
, challengePriority: challengePriority |
|
|
|
, challenges: challenges |
|
|
|
, challenges: false |
|
|
|
}).then(function (certs) { |
|
|
|
return Keypairs.export({ jwk: serverJwk }).then(function (keyPem) { |
|
|
|
console.log('WINNING!'); |
|
|
|
console.info('WINNING!'); |
|
|
|
console.log(certs); |
|
|
|
$qs('#js-fullchain').innerHTML = [ |
|
|
|
certs.cert.trim() + "\n" |
|
|
@ -455,76 +408,76 @@ |
|
|
|
|
|
|
|
// spinner
|
|
|
|
steps[4] = function () { |
|
|
|
console.info('4. Show loading spinner'); |
|
|
|
updateProgress(1); |
|
|
|
hideForms(); |
|
|
|
$qs('.js-acme-form-poll').hidden = false; |
|
|
|
}; |
|
|
|
steps[4].submit = function () { |
|
|
|
console.log('Congrats! Auto advancing...'); |
|
|
|
console.info('[submit] 4. Order complete'); |
|
|
|
|
|
|
|
steps[i](); |
|
|
|
}; |
|
|
|
|
|
|
|
steps[5] = function () { |
|
|
|
console.info('5. Present certificates (yay!)'); |
|
|
|
updateProgress(2); |
|
|
|
hideForms(); |
|
|
|
$qs('.js-acme-form-download').hidden = false; |
|
|
|
}; |
|
|
|
|
|
|
|
var params = new URLSearchParams(window.location.search); |
|
|
|
var apiType = params.get('acme-api-type') || "staging-v02"; |
|
|
|
function init() { |
|
|
|
var params = new URLSearchParams(window.location.search); |
|
|
|
var apiType = params.get('acme-api-type') || "staging-v02"; |
|
|
|
|
|
|
|
$qsa('.js-acme-api-type').forEach(function ($el) { |
|
|
|
$el.addEventListener('change', updateApiType); |
|
|
|
}); |
|
|
|
$qsa('.js-acme-api-type').forEach(function ($el) { |
|
|
|
$el.addEventListener('change', updateApiType); |
|
|
|
}); |
|
|
|
|
|
|
|
updateApiType(); |
|
|
|
updateApiType(); |
|
|
|
|
|
|
|
$qsa('.js-acme-form').forEach(function ($el) { |
|
|
|
$el.addEventListener('submit', function (ev) { |
|
|
|
ev.preventDefault(); |
|
|
|
submitForm(ev); |
|
|
|
$qsa('.js-acme-form').forEach(function ($el) { |
|
|
|
$el.addEventListener('submit', function (ev) { |
|
|
|
ev.preventDefault(); |
|
|
|
submitForm(ev); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
$qsa('.js-acme-challenge-type').forEach(function ($el) { |
|
|
|
$el.addEventListener('change', updateChallengeType); |
|
|
|
}); |
|
|
|
$qsa('.js-acme-challenge-type').forEach(function ($el) { |
|
|
|
$el.addEventListener('change', updateChallengeType); |
|
|
|
}); |
|
|
|
|
|
|
|
if (params.has('acme-domains')) { |
|
|
|
console.log("acme-domains param: ", params.get('acme-domains')); |
|
|
|
$qs('.js-acme-domains').value = params.get('acme-domains'); |
|
|
|
if (params.has('acme-domains')) { |
|
|
|
$qs('.js-acme-domains').value = params.get('acme-domains'); |
|
|
|
|
|
|
|
$qsa('.js-acme-api-type').forEach(function(ele) { |
|
|
|
if(ele.value === apiType) { |
|
|
|
ele.checked = true; |
|
|
|
} |
|
|
|
}); |
|
|
|
$qsa('.js-acme-api-type').forEach(function(ele) { |
|
|
|
if(ele.value === apiType) { |
|
|
|
ele.checked = true; |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
updateApiType(); |
|
|
|
steps[2](); |
|
|
|
submitForm(); |
|
|
|
} |
|
|
|
updateApiType(); |
|
|
|
steps[2](); |
|
|
|
submitForm(); |
|
|
|
} |
|
|
|
|
|
|
|
$qs('body').hidden = false; |
|
|
|
} |
|
|
|
|
|
|
|
// The kickoff
|
|
|
|
steps[1](); |
|
|
|
|
|
|
|
return testKeypairSupport().then(function (rsaSupport) { |
|
|
|
if (rsaSupport) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
init(); |
|
|
|
$qs('body').hidden = false; |
|
|
|
|
|
|
|
return testEcdsaSupport().then(function () { |
|
|
|
console.info('[crypto] ECDSA is supported'); |
|
|
|
}).catch(function (err) { |
|
|
|
console.error('[crypto] could not use either RSA nor EC.'); |
|
|
|
console.error(err); |
|
|
|
window.alert("Generating secure certificates requires a browser with cryptography support." |
|
|
|
+ "Please consider a recent version of Chrome, Firefox, or Safari."); |
|
|
|
throw err; |
|
|
|
}); |
|
|
|
// in the background
|
|
|
|
info.cryptoCheck = testKeypairSupport().then(function () { |
|
|
|
console.info("[crypto] self-check: passed"); |
|
|
|
}).catch(function (err) { |
|
|
|
console.error('[crypto] could not use either RSA nor EC.'); |
|
|
|
console.error(err); |
|
|
|
window.alert("Generating secure certificates requires a browser with cryptography support." |
|
|
|
+ "Please consider a recent version of Chrome, Firefox, or Safari."); |
|
|
|
throw err; |
|
|
|
}); |
|
|
|
}()); |
|
|
|