From 905a04146bb8b958b3858920581a5e0046579ad4 Mon Sep 17 00:00:00 2001 From: Laurent Peuch Date: Mon, 16 Jan 2017 09:24:41 +0100 Subject: [PATCH 1/3] [mod] start putting timeout in certificate code --- src/yunohost/certificate.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index 49de94996..ccd1a810f 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -37,6 +37,8 @@ import glob from OpenSSL import crypto from datetime import datetime +from requests.exceptions import Timeout + from yunohost.vendor.acme_tiny.acme_tiny import get_crt as sign_certificate from moulinette.core import MoulinetteError @@ -567,7 +569,11 @@ def _fetch_and_enable_new_certificate(domain, staging=False): raise MoulinetteError(errno.EINVAL, m18n.n( 'certmanager_cert_signing_failed')) - intermediate_certificate = requests.get(INTERMEDIATE_CERTIFICATE_URL).text + try: + intermediate_certificate = requests.get(INTERMEDIATE_CERTIFICATE_URL, timeout=30).text + except Timeout: + # XXX what should we do here? retry? + pass # Now save the key and signed certificate logger.info("Saving the key and signed certificate...") @@ -837,7 +843,10 @@ def _dns_ip_match_public_ip(public_ip, domain): def _domain_is_accessible_through_HTTP(ip, domain): try: - requests.head("http://" + ip, headers={"Host": domain}) + requests.head("http://" + ip, headers={"Host": domain}, timeout=30) + except Timeout as e: + # XXX what should we do here? retry? + pass except Exception as e: logger.debug("Couldn't reach domain '%s' by requesting this ip '%s' because: %s" % (domain, ip, e)) return False From 656b2e61ba3ef1056bdb4154f86076188037b8bd Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 25 Jan 2017 12:03:30 -0500 Subject: [PATCH 2/3] Implement timeout exceptions --- locales/en.json | 2 ++ src/yunohost/certificate.py | 9 ++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/locales/en.json b/locales/en.json index e145a1d38..cacac5d18 100644 --- a/locales/en.json +++ b/locales/en.json @@ -266,5 +266,7 @@ "domain_cannot_remove_main": "Cannot remove main domain. Set a new main domain first", "certmanager_self_ca_conf_file_not_found": "Configuration file not found for self-signing authority (file: {file:s})", "certmanager_acme_not_configured_for_domain": "Certificate for domain {domain:s} does not appear to be correctly installed. Please run cert-install for this domain first.", + "certmanager_http_check_timeout" : "Timed out when server tried to contact itself through HTTP using public IP address. You may be experiencing hairpinning or the firewall/router ahead of your server is misconfigured.", + "certmanager_couldnt_fetch_intermediate_cert" : "Timed out when trying to fetch intermediate certificate from Let's Encrypt. Certificate installation/renewal aborted - please try again later.", "certmanager_unable_to_parse_self_CA_name": "Unable to parse name of self-signing authority (file: {file:s})" } diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index ccd1a810f..386894f65 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -572,8 +572,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False): try: intermediate_certificate = requests.get(INTERMEDIATE_CERTIFICATE_URL, timeout=30).text except Timeout: - # XXX what should we do here? retry? - pass + raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_couldnt_fetch_intermediate_cert')) # Now save the key and signed certificate logger.info("Saving the key and signed certificate...") @@ -843,10 +842,10 @@ def _dns_ip_match_public_ip(public_ip, domain): def _domain_is_accessible_through_HTTP(ip, domain): try: - requests.head("http://" + ip, headers={"Host": domain}, timeout=30) + requests.head("http://" + ip, headers={"Host": domain}, timeout=10) except Timeout as e: - # XXX what should we do here? retry? - pass + logger.warning(m18n.n('certmanager_http_check_timeout')) + return False except Exception as e: logger.debug("Couldn't reach domain '%s' by requesting this ip '%s' because: %s" % (domain, ip, e)) return False From cd88428248494fac1c22db4d53887fb5b25cc575 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Wed, 25 Jan 2017 18:38:30 -0500 Subject: [PATCH 3/3] Implementing opi's comments --- locales/en.json | 2 +- src/yunohost/certificate.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/locales/en.json b/locales/en.json index cacac5d18..5e9d02e06 100644 --- a/locales/en.json +++ b/locales/en.json @@ -266,7 +266,7 @@ "domain_cannot_remove_main": "Cannot remove main domain. Set a new main domain first", "certmanager_self_ca_conf_file_not_found": "Configuration file not found for self-signing authority (file: {file:s})", "certmanager_acme_not_configured_for_domain": "Certificate for domain {domain:s} does not appear to be correctly installed. Please run cert-install for this domain first.", - "certmanager_http_check_timeout" : "Timed out when server tried to contact itself through HTTP using public IP address. You may be experiencing hairpinning or the firewall/router ahead of your server is misconfigured.", + "certmanager_http_check_timeout" : "Timed out when server tried to contact itself through HTTP using public IP address (domain {domain:s} with ip {ip:s}). You may be experiencing hairpinning or the firewall/router ahead of your server is misconfigured.", "certmanager_couldnt_fetch_intermediate_cert" : "Timed out when trying to fetch intermediate certificate from Let's Encrypt. Certificate installation/renewal aborted - please try again later.", "certmanager_unable_to_parse_self_CA_name": "Unable to parse name of self-signing authority (file: {file:s})" } diff --git a/src/yunohost/certificate.py b/src/yunohost/certificate.py index 386894f65..bd7d02962 100644 --- a/src/yunohost/certificate.py +++ b/src/yunohost/certificate.py @@ -571,7 +571,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False): try: intermediate_certificate = requests.get(INTERMEDIATE_CERTIFICATE_URL, timeout=30).text - except Timeout: + except Timeout as e: raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_couldnt_fetch_intermediate_cert')) # Now save the key and signed certificate @@ -844,7 +844,7 @@ def _domain_is_accessible_through_HTTP(ip, domain): try: requests.head("http://" + ip, headers={"Host": domain}, timeout=10) except Timeout as e: - logger.warning(m18n.n('certmanager_http_check_timeout')) + logger.warning(m18n.n('certmanager_http_check_timeout', domain=domain, ip=ip)) return False except Exception as e: logger.debug("Couldn't reach domain '%s' by requesting this ip '%s' because: %s" % (domain, ip, e))