1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2026-03-04 15:54:48 +01:00

second part of provisioning tls certificates from the control panel

This commit is contained in:
Joshua Tauberer
2016-01-04 18:22:02 -05:00
parent 812ef024ef
commit 2882e63dd8
3 changed files with 160 additions and 31 deletions

View File

@@ -7,13 +7,22 @@
<p>You need a TLS certificate for this box&rsquo;s hostname ({{hostname}}) and every other domain name and subdomain that this box is hosting a website for (see the list below).</p>
<div id="ssl_provision">
<h3>Provision a Certificate</h3>
<p>We can provision an SSL certificate for you from <a href="https://letsencrypt.org/" target="_blank">Let&rsquo;s Encrypt</a>, a free SSL certificate provider.</p>
<div id="ssl_provision_p" style="display: none; margin-top: 1.5em">
<button onclick='return provision_tls_cert();' class='btn btn-primary' style="float: left; margin: 0 1.5em 1em 0;">Provision</button>
<p>A TLS certificate can be automatically provisioned from <a href="https://letsencrypt.org/" target="_blank">Let&rsquo;s Encrypt</a>, a free TLS certificate provider, for:<br>
<span class="text-primary"></span></p>
</div>
<p id="ssl_provision_status"></p>
<div class="clearfix"> </div>
<table id="ssl_provision_problems" style="display: none" class="table">
<div id="ssl_provision_result"></div>
<div id="ssl_provision_problems_div" style="display: none;">
<p style="margin-bottom: .5em;">Certificates cannot be automatically provisioned for:</p>
<table id="ssl_provision_problems" style="margin-top: 0;" class="table">
<thead>
<tr>
<th>Domain</th>
@@ -23,9 +32,14 @@
<tbody>
</tbody>
</table>
<p>Use the <em>Install Certificate</em> button below for these domains.</p>
</div>
</div>
<h3>Certificate Status</h3>
<p style="margin-top: 1.5em">Certificates expire after a period of time. All certificates will be automatically renewed through <a href="https://letsencrypt.org/" target="_blank">Let&rsquo;s Encrypt</a> 14 days prior to expiration.</p>
<table id="ssl_domains" class="table" style="margin-bottom: 2em; width: auto; display: none">
<thead>
<tr>
@@ -38,7 +52,6 @@
</tbody>
</table>
<p>A multi-domain or wildcard certificate will be automatically applied to any domains it is valid for.</p>
<h3 id="ssl_install_header">Install Certificate</h3>
@@ -48,6 +61,8 @@
<p><select id="ssldomain" onchange="show_csr()" class="form-control" style="width: auto"></select></p>
<p>(A multi-domain or wildcard certificate will be automatically applied to any domains it is valid for besides the one you choose above.)</p>
<p>What country are you in? This is required by some TLS certificate providers. You may leave this blank if you know your TLS certificate provider doesn't require it.</p>
<p><select id="sslcc" onchange="show_csr()" class="form-control" style="width: auto">
@@ -78,7 +93,7 @@
</div>
<script>
function show_tls() {
function show_tls(keep_provisioning_shown) {
api(
"/ssl/status",
"GET",
@@ -86,20 +101,15 @@ function show_tls() {
},
function(res) {
// provisioning status
if (res.can_provision.length > 0) {
$('#ssl_provision_status')
.removeClass("text-warning").removeClass("text-success").addClass("text-danger")
.text("Domains: " + res.can_provision.join(", "));
} else if (res.cant_provision.length == 0) {
$('#ssl_provision_status')
.addClass("text-success").removeClass("text-warning").removeClass("text-danger")
.text("No domains hosted on this box need a new TLS certificate at this time.");
} else {
$('#ssl_provision_status')
.removeClass("text-success").addClass("text-warning").removeClass("text-danger")
.text("No TLS certificates can be provisoned at this time:");
}
$('#ssl_provision_problems').toggle(res.cant_provision.length > 0);
if (!keep_provisioning_shown)
$('#ssl_provision').toggle(res.can_provision.length + res.cant_provision.length > 0)
$('#ssl_provision_p').toggle(res.can_provision.length > 0);
if (res.can_provision.length > 0)
$('#ssl_provision_p span').text(res.can_provision.join(", "));
$('#ssl_provision_problems_div').toggle(res.cant_provision.length > 0);
$('#ssl_provision_problems tbody').text("");
for (var i = 0; i < res.cant_provision.length; i++) {
var domain = res.cant_provision[i];
@@ -123,6 +133,10 @@ function show_tls() {
row.attr('data-domain', domains[i].domain);
row.find('.domain a').text(domains[i].domain);
row.find('.domain a').attr('href', 'https://' + domains[i].domain);
if (domains[i].status == "not-applicable") {
domains[i].status = "muted"; // text-muted css class
row.find('.actions a').remove(); // no actions applicable
}
row.addClass("text-" + domains[i].status);
row.find('.status').text(domains[i].text);
if (domains[i].status == "success") {
@@ -139,14 +153,15 @@ function show_tls() {
function ssl_install(elem) {
var domain = $(elem).parents('tr').attr('data-domain');
$('#ssldomain').val(domain);
$('#csr_info').slideDown();
$('#ssl_csr').text('Loading...');
show_csr();
$('html, body').animate({ scrollTop: $('#ssl_install_header').offset().top - $('.navbar-fixed-top').height() - 20 })
return false;
}
function show_csr() {
if ($('#ssldomain').val() == "") return;
$('#csr_info').slideDown();
$('#ssl_csr').text('Loading...');
api(
"/ssl/csr/" + $('#ssldomain').val(),
"POST",
@@ -176,4 +191,94 @@ function install_cert() {
}
});
}
var agree_to_tos_url_prompt = null;
var agree_to_tos_url = null;
function provision_tls_cert() {
// Automatically provision any certs.
$('#ssl_provision_p .btn').attr('disabled', '1'); // prevent double-clicks
api(
"/ssl/provision",
"POST",
{
agree_to_tos_url: agree_to_tos_url
},
function(status) {
// Clear last attempt.
agree_to_tos_url = null;
$('#ssl_provision_result').text("");
may_reenable_provision_button = true;
// Nothing was done. There might also be problem domains, but we've already displayed those.
if (status.requests.length == 0) {
show_modal_error("TLS Certificate Provisioning", "There were no domain names to provision certificates for.");
// don't return - haven't re-enabled the provision button
}
// Each provisioning API call returns zero or more "requests" which represent
// a request to Let's Encrypt for a single certificate. Normally there is just
// one request (for a single multi-domain certificate).
for (var i = 0; i < status.requests.length; i++) {
var r = status.requests[i];
// create an HTML block to display the results of this request
var n = $("<div><h4/><p/></div>");
$('#ssl_provision_result').append(n);
// show a header only to disambiguate request blocks
if (status.requests.length > 0)
n.find("h4").text(r.domains.join(", "));
if (r.result == "agree-to-tos") {
// user needs to agree to Let's Encrypt's TOS
agree_to_tos_url_prompt = r.url;
$('#ssl_provision_p .btn').attr('disabled', '1');
n.find("p").html("Please open and review <a href='" + r.url + "' target='_blank'>Let's Encrypt's terms of service agreement</a>. You must agree to their terms for a certificate to be automatically provisioned from them.");
n.append($('<button onclick="agree_to_tos_url = agree_to_tos_url_prompt; return provision_tls_cert();" class="btn btn-success" style="margin-left: 2em">Agree &amp; Try Again</button>'));
// don't re-enable the Provision button -- user must use the Agree button
may_reenable_provision_button = false;
} else if (r.result == "error") {
n.find("p").addClass("text-danger").text(r.message);
} else if (r.result == "wait") {
// Show a button that counts down to zero, at which point it becomes enabled.
n.find("p").text("A certificate is now in the process of being provisioned, but it takes some time. Please wait until the Finish button is enabled, and then click it to acquire the certificate.");
var b = $('<button onclick="return provision_tls_cert();" class="btn btn-success" style="margin-left: 2em">Finish</button>');
b.attr("disabled", "1");
var now = new Date();
n.append(b);
function ready_to_finish() {
var remaining = r.seconds - Math.round((new Date() - now)/1000);
if (remaining > 0) {
setTimeout(ready_to_finish, 1000);
b.text("Finish (" + remaining + "...)")
} else {
b.text("Finish (ready)")
b.removeAttr("disabled");
}
}
ready_to_finish();
// don't re-enable the Provision button -- user must use the Retry button when it becomes enabled
may_reenable_provision_button = false;
} else if (r.result == "installed") {
n.find("p").addClass("text-success").text("The TLS certificate was provisioned and installed.");
setTimeout("show_tls(true)", 1); // update main table of certificate statuses, call with arg keep_provisioning_shown true so that we don't clear what we just outputted
}
// display the detailed log info in case of problems
var trace = $("<div class='small text-muted' style='margin-top: 1.5em'>Log:</div>");
n.append(trace);
for (var j = 0; j < r.log.length; j++)
trace.append($("<div/>").text(r.log[j]));
}
if (may_reenable_provision_button)
$('#ssl_provision_p .btn').removeAttr("disabled");
});
}
</script>