diff --git a/EULA b/EULA index 70cdea4aa..dd7759361 100644 --- a/EULA +++ b/EULA @@ -2,4 +2,4 @@ This is a PREVIEW RELEASE of a client application for the Let's Encrypt certific Until publicly-trusted certificates can be issued by Let's Encrypt, this software CANNOT OBTAIN A PUBLICLY-TRUSTED CERTIFICATE FOR YOUR WEB SERVER. You should only use this program if you are a developer interested in experimenting with the ACME protocol or in helping to improve this software. If you want to configure your web site with HTTPS in the meantime, please obtain a certificate from a different authority. -For updates on the status of Let's Encrypt, please visit the Let's Encrypt home page at https://www.lets-encrypt.org/. +For updates on the status of Let's Encrypt, please visit the Let's Encrypt home page at https://letsencrypt.org/. diff --git a/letsencrypt/client/apache_configurator.py b/letsencrypt/client/apache_configurator.py index 102184278..170c5bbe3 100644 --- a/letsencrypt/client/apache_configurator.py +++ b/letsencrypt/client/apache_configurator.py @@ -371,7 +371,7 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): Checks if addr has a NameVirtualHost directive in the Apache config - :param str addr: vhost address ie. \*:443 + :param str addr: vhost address ie. *:443 :returns: Success :rtype: bool @@ -1177,26 +1177,7 @@ LogLevel warn \n\ :rtype: bool """ - # TODO: This should be written to use the process returncode - try: - proc = subprocess.Popen(['/etc/init.d/apache2', 'restart'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - text = proc.communicate() - - if proc.returncode != 0: - # Enter recovery routine... - logger.error("Configtest failed") - logger.error(text[0]) - logger.error(text[1]) - return False - - except (OSError, ValueError): - logger.fatal(("Apache Restart Failed - " - "Please Check the Configuration")) - sys.exit(1) - - return True + return apache_restart(quiet) def _add_httpd_transform(self, incl): """Add a transform to Augeas. @@ -1241,6 +1222,9 @@ LogLevel warn \n\ # Challenges Section ########################################################################### + # TODO: Change list_sni_tuple to namedtuple. Also include key within tuple. + # This allows the keys to be different for each SNI challenge + def perform(self, chall_dict): """Perform the configuration related challenge. @@ -1255,14 +1239,14 @@ LogLevel warn \n\ def dvsni_perform(self, chall_dict): """Peform a DVSNI challenge. - Composed of: + `chall_dict` composed of: list_sni_tuple: - List of tuples with form `(addr, r, nonce)`, where - `addr` (`str`), `r` (base64 `str`), nonce (hex `str`) + List of tuples with form `(addr, r, nonce)`, where + `addr` (`str`), `r` (base64 `str`), `nonce` (hex `str`) dvsni_key: - DVSNI key (:class:`letsencrypt.client.client.Client.Key`) + DVSNI key (:class:`letsencrypt.client.client.Client.Key`) :param dict chall_dict: dvsni challenge - see documentation @@ -1451,6 +1435,29 @@ def check_ssl_loaded(): return False +def apache_restart(quiet=False): + # TODO: This should be written to use the process returncode + try: + proc = subprocess.Popen(['/etc/init.d/apache2', 'restart'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + text = proc.communicate() + + if proc.returncode != 0: + # Enter recovery routine... + logger.error("Configtest failed") + logger.error(text[0]) + logger.error(text[1]) + return False + + except (OSError, ValueError): + logger.fatal(("Apache Restart Failed - " + "Please Check the Configuration")) + sys.exit(1) + + return True + + def verify_setup(): """Verify the setup to ensure safe operating environment. diff --git a/letsencrypt/client/client.py b/letsencrypt/client/client.py index 2bcecf527..490daebf4 100644 --- a/letsencrypt/client/client.py +++ b/letsencrypt/client/client.py @@ -69,10 +69,10 @@ class Client(object): try: self._validate_csr_key_cli() - except errors.LetsEncryptClientError as e: + except errors.LetsEncryptClientError as exc: # TODO: Something nice here... logger.fatal(("%s - until the programmers get their act together, " - "we are just going to exit" % str(e))) + "we are just going to exit" % str(exc))) sys.exit(1) self.server_url = "https://%s/acme/" % self.server @@ -96,8 +96,6 @@ class Client(object): if not self.config.config_test(): sys.exit(1) - self.redirect = redirect - # Display preview warning if not eula: with open('EULA') as eula_file: @@ -146,7 +144,7 @@ class Client(object): cert_file = self.install_certificate(certificate_dict, vhost) # Perform optimal config changes - self.optimize_config(vhost) + self.optimize_config(vhost, redirect) self.config.save("Completed Let's Encrypt Authentication") @@ -433,11 +431,19 @@ class Client(object): return cert_file - def optimize_config(self, vhost): - if self.redirect is None: - self.redirect = display.redirect_by_default() + def optimize_config(self, vhost, redirect): + """Optimize the configuration. - if self.redirect: + :param vhost: vhost to optimize + :type vhost: :class:`apache_configurator.VH` + + :param bool redirect: If traffic should be forwarded from HTTP to HTTPS + + """ + if redirect is None: + redirect = display.redirect_by_default() + + if redirect: self.redirect_to_ssl(vhost) self.config.restart(quiet=self.curses) @@ -452,6 +458,11 @@ class Client(object): # continue def cleanup_challenges(self, challenges): + """Cleanup configuration challenges + + :param dict challenges: challenges from a challenge message + + """ logger.info("Cleaning up challenges...") for chall in challenges: if chall["type"] in CONFIG.CONFIG_CHALLENGES: @@ -546,6 +557,12 @@ class Client(object): return True def redirect_to_ssl(self, vhost): + """Redirect all traffic from HTTP to HTTPS + + :param vhost: list of ssl_vhosts + :type vhost: :class:`apache_configurator.VH` + + """ for ssl_vh in vhost: success, redirect_vhost = self.config.enable_redirect(ssl_vh) logger.info("\nRedirect vhost: " + redirect_vhost.file + @@ -555,6 +572,14 @@ class Client(object): self.config.enable_site(redirect_vhost) def get_virtual_hosts(self, domains): + """Retrieve the appropriate virtual host for the domain + + :param list domains: Domains to find ssl vhosts for + + :returns: associated vhosts + :rtype: :class:`apache_configurator.VH` + + """ vhost = set() for name in domains: host = self.config.choose_virtual_host(name) diff --git a/letsencrypt/client/recovery_contact_challenge.py b/letsencrypt/client/recovery_contact_challenge.py index 6a4fa429e..8e9f005b3 100644 --- a/letsencrypt/client/recovery_contact_challenge.py +++ b/letsencrypt/client/recovery_contact_challenge.py @@ -1,4 +1,9 @@ -"""Recovery Contact Identifier Validation Challenge.""" +"""Recovery Contact Identifier Validation Challenge. + +NOTE: THIS CLASS IS NOT FULLY IMPLEMENTED INTO THE PROJECT +YET. + +""" import time import dialog @@ -101,7 +106,6 @@ class RecoveryContact(challenge.Challenge): return ans.startswith('y') or ans.startswith('Y') - def generate_response(self): if not self.token: return {"type": "recoveryContact"} diff --git a/letsencrypt/client/recovery_token_challenge.py b/letsencrypt/client/recovery_token_challenge.py index ff96babf9..86140c88e 100644 --- a/letsencrypt/client/recovery_token_challenge.py +++ b/letsencrypt/client/recovery_token_challenge.py @@ -1,4 +1,9 @@ -"""Recovery Token Identifier Validation Challenge.""" +"""Recovery Token Identifier Validation Challenge. + +NOTE: THIS CHALLENGE IS NOT IMPLEMENTED OR INCLUDED +IN THE PROJECT CURRENTLY + +""" import dialog from letsencrypt.client import challenge diff --git a/letsencrypt/client/schemata/challengeobject.json b/letsencrypt/client/schemata/challengeobject.json index b760e246e..5641b407e 100644 --- a/letsencrypt/client/schemata/challengeobject.json +++ b/letsencrypt/client/schemata/challengeobject.json @@ -1,5 +1,5 @@ { - "id": "https://lets-encrypt.org/schema/01/challengeobject#", + "id": "https://letsencrypt.org/schema/01/challengeobject#", "$schema": "http://json-schema.org/draft-04/schema#", "description": "Subschema for an individual challenge (within challenge)", "anyOf": [ diff --git a/letsencrypt/client/schemata/jwk.json b/letsencrypt/client/schemata/jwk.json index 536585e79..b9cca8840 100644 --- a/letsencrypt/client/schemata/jwk.json +++ b/letsencrypt/client/schemata/jwk.json @@ -1,5 +1,5 @@ { - "id": "https://lets-encrypt.org/schema/01/jwk#", + "id": "https://letsencrypt.org/schema/01/jwk#", "$schema": "http://json-schema.org/draft-04/schema#", "description": "Schema for a jwk (**kty RSA/e=65537 ONLY**)", "type": "object", diff --git a/letsencrypt/client/schemata/responseobject.json b/letsencrypt/client/schemata/responseobject.json index 7e45853e6..dfb1fac28 100644 --- a/letsencrypt/client/schemata/responseobject.json +++ b/letsencrypt/client/schemata/responseobject.json @@ -1,5 +1,5 @@ { - "id": "https://lets-encrypt.org/schema/01/responseobject#", + "id": "https://letsencrypt.org/schema/01/responseobject#", "$schema": "http://json-schema.org/draft-04/schema#", "description": "Subschema for an individual challenge response (within authorizationRequest)", "anyOf": [ diff --git a/letsencrypt/client/schemata/signature.json b/letsencrypt/client/schemata/signature.json index 54828d332..e70652e7c 100644 --- a/letsencrypt/client/schemata/signature.json +++ b/letsencrypt/client/schemata/signature.json @@ -1,5 +1,5 @@ { - "id": "https://lets-encrypt.org/schema/01/signature#", + "id": "https://letsencrypt.org/schema/01/signature#", "$schema": "http://json-schema.org/draft-04/schema#", "description": "Schema for a signature (alg RS256/e=65537 or P-256 ONLY)", "type": "object",