diff --git a/management/daemon.py b/management/daemon.py index d223b040..6ba111d7 100755 --- a/management/daemon.py +++ b/management/daemon.py @@ -327,6 +327,19 @@ def dns_get_dump(): # SSL +@app.route('/ssl/status') +@authorized_personnel_only +def ssl_get_status(): + from ssl_certificates import get_certificates_to_provision + from web_update import get_web_domains_info + provision, cant_provision = get_certificates_to_provision(env, ok_as_problem=False) + domains_status = get_web_domains_info(env) + return json_response({ + "can_provision": list(provision), + "cant_provision": [{ "domain": domain, "problem": cant_provision[domain] } for domain in utils.sort_domains(cant_provision, env) ], + "status": [{ "domain": d["domain"], "status": d["ssl_certificate"][0], "text": d["ssl_certificate"][1] } for d in domains_status ], + }) + @app.route('/ssl/csr/', methods=['POST']) @authorized_personnel_only def ssl_get_csr(domain): diff --git a/management/ssl_certificates.py b/management/ssl_certificates.py index 0f019796..fd922ede 100755 --- a/management/ssl_certificates.py +++ b/management/ssl_certificates.py @@ -156,7 +156,7 @@ def get_domain_ssl_files(domain, ssl_certificates, env, allow_missing_cert=False # PROVISIONING CERTIFICATES FROM LETSENCRYPT -def get_certificates_to_provision(env): +def get_certificates_to_provision(env, ok_as_problem=True): # Get a set of domain names that we should now provision certificates # for. Provision if a domain name has no valid certificate or if any # certificate is expiring in 14 days. If provisioning anything, also @@ -196,8 +196,13 @@ def get_certificates_to_provision(env): elif cert.not_valid_after-now < datetime.timedelta(days=30): domains_if_any.add(domain) - # It's valid. - problems[domain] = "The certificate is valid for at least another 30 days --- no need to replace." + # It's valid. Should we report its validness? + if ok_as_problem: + problems[domain] = "The certificate is valid for at least another 30 days --- no need to replace." + + # Warn the user about domains hosted elsewhere. + for domain in set(get_web_domains(env, exclude_dns_elsewhere=False)) - set(get_web_domains(env)): + problems[domain] = "The domain's DNS is pointed elsewhere, so a TLS certificate is not necessary here and cannot be provisioned automatically anyway." # Filter out domains that we can't provision a certificate for. def can_provision_for_domain(domain): diff --git a/management/templates/ssl.html b/management/templates/ssl.html index 48fc91c8..2f9a1cab 100644 --- a/management/templates/ssl.html +++ b/management/templates/ssl.html @@ -3,10 +3,30 @@

TLS (SSL) Certificates

+

An SSL certificate is a cryptographic file that proves to anyone connecting to this machine (like you right now) that the connection is secure.

+ +

You need an SSL certificate for this box’s hostname ({{hostname}}), and although optional you should also get one for every domain name and subdomain managed by this box (unless you’ve directed DNS for a domain elsewhere through custom or external DNS).

+ +

Provision a Certificate

+ +

We can provision an SSL certificate for you from Let’s Encrypt, a free SSL certificate provider.

+ +

+ + + + + + + + + + + +

Certificate Status

- - +
@@ -60,24 +80,47 @@