diff --git a/locales/en.json b/locales/en.json index dc020645..e145a1d3 100644 --- a/locales/en.json +++ b/locales/en.json @@ -253,6 +253,7 @@ "certmanager_domain_http_not_working": "It seems that the domain {domain:s} cannot be accessed through HTTP. Please check your DNS and nginx configuration is okay", "certmanager_error_no_A_record": "No DNS 'A' record found for {domain:s}. You need to make your domain name point to your machine to be able to install a Let's Encrypt certificate! (If you know what you are doing, use --no-checks to disable those checks.)", "certmanager_domain_dns_ip_differs_from_public_ip": "The DNS 'A' record for domain {domain:s} is different from this server IP. If you recently modified your A record, please wait for it to propagate (some DNS propagation checkers are available online). (If you know what you are doing, use --no-checks to disable those checks.)", + "certmanager_domain_not_resolved_locally": "The domain {domain:s} cannot be resolved from inside your Yunohost server. This might happen if you recently modified your DNS record. If so, please wait a few hours for it to propagate. If the issue persists, consider adding {domain:s} to /etc/hosts. (If you know what you are doing, use --no-checks to disable those checks.)", "certmanager_cannot_read_cert": "Something wrong happened when trying to open current certificate for domain {domain:s} (file: {file:s}), reason: {reason:s}", "certmanager_cert_install_success_selfsigned": "Successfully installed a self-signed certificate for domain {domain:s}!", "certmanager_cert_install_success": "Successfully installed Let's Encrypt certificate for domain {domain:s}!", diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index f4680450..9d52f3a5 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -31,6 +31,7 @@ import grp import smtplib import requests import subprocess +import socket import dns.resolver import glob @@ -812,6 +813,13 @@ def _check_domain_is_ready_for_ACME(domain): raise MoulinetteError(errno.EINVAL, m18n.n( 'certmanager_domain_http_not_working', domain=domain)) + # Check if domain is resolved locally (Might happen despite the previous + # checks because of dns propagation ?... Acme-tiny won't work in that case, + # because it explicitly requests() the domain.) + if not _domain_is_resolved_locally(public_ip, domain): + raise MoulinetteError(errno.EINVAL, m18n.n( + 'certmanager_domain_not_resolved_locally', domain=domain)) + def _dns_ip_match_public_ip(public_ip, domain): try: @@ -836,6 +844,17 @@ def _domain_is_accessible_through_HTTP(ip, domain): return True +def _domain_is_resolved_locally(public_ip, domain): + try: + ip = socket.gethostbyname(domain) + except socket.error as e: + logger.debug("Couldn't get domain '%s' ip because: %s" % (domain, e)) + return False + + logger.debug("Domain '%s' ip is %s, except it to be 127.0.0.1 or %s" % (domain, public_ip)) + return ip in ["127.0.0.1", public_ip] + + def _name_self_CA(): ca_conf = os.path.join(SSL_DIR, "openssl.ca.cnf")