From 2b8f2cc1130976ce8d14cd69388c5d5c588feb39 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sat, 28 Feb 2015 20:40:33 +0000 Subject: [PATCH 01/31] rm letsencrypt.py, chmod -x, remove sheebangs --- letsencrypt.py | 1 - letsencrypt/client/standalone_authenticator.py | 0 letsencrypt/scripts/main.py | 1 - setup.py | 1 - 4 files changed, 3 deletions(-) delete mode 120000 letsencrypt.py mode change 100755 => 100644 letsencrypt/client/standalone_authenticator.py mode change 100755 => 100644 letsencrypt/scripts/main.py mode change 100755 => 100644 setup.py diff --git a/letsencrypt.py b/letsencrypt.py deleted file mode 120000 index 77b93ee70..000000000 --- a/letsencrypt.py +++ /dev/null @@ -1 +0,0 @@ -letsencrypt/scripts/main.py \ No newline at end of file diff --git a/letsencrypt/client/standalone_authenticator.py b/letsencrypt/client/standalone_authenticator.py old mode 100755 new mode 100644 diff --git a/letsencrypt/scripts/main.py b/letsencrypt/scripts/main.py old mode 100755 new mode 100644 index 989e07f96..d1df56c09 --- a/letsencrypt/scripts/main.py +++ b/letsencrypt/scripts/main.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python """Parse command line and call the appropriate functions. .. todo:: Sanity check all input. Be sure to avoid shell code etc... diff --git a/setup.py b/setup.py old mode 100755 new mode 100644 index 1fc643304..60d68f4a1 --- a/setup.py +++ b/setup.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python import codecs import os import re From 7d41cadc99532906253a98d8ef8867889af21380 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Mon, 16 Mar 2015 22:58:33 -0700 Subject: [PATCH 02/31] make _path_satisfied conform to API --- letsencrypt/client/auth_handler.py | 4 +++- letsencrypt/client/tests/auth_handler_test.py | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/letsencrypt/client/auth_handler.py b/letsencrypt/client/auth_handler.py index 4e3b5f68f..980a7d7cd 100644 --- a/letsencrypt/client/auth_handler.py +++ b/letsencrypt/client/auth_handler.py @@ -203,7 +203,9 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes def _path_satisfied(self, dom): """Returns whether a path has been completely satisfied.""" - return all(self.responses[dom][i] is not None for i in self.paths[dom]) + return all( + self.responses[dom][i] is not None and + self.responses[dom][i] is not False for i in self.paths[dom]) def _get_chall_pref(self, domain): """Return list of challenge preferences. diff --git a/letsencrypt/client/tests/auth_handler_test.py b/letsencrypt/client/tests/auth_handler_test.py index 91874dc0c..734f4cc65 100644 --- a/letsencrypt/client/tests/auth_handler_test.py +++ b/letsencrypt/client/tests/auth_handler_test.py @@ -481,7 +481,7 @@ class PathSatisfiedTest(unittest.TestCase): self.handler.responses[dom[0]] = [None, "sat", "sat2", None] self.handler.paths[dom[1]] = [0] - self.handler.responses[dom[1]] = ["sat", None, None, None] + self.handler.responses[dom[1]] = ["sat", None, None, False] self.handler.paths[dom[2]] = [0] self.handler.responses[dom[2]] = ["sat"] @@ -496,7 +496,7 @@ class PathSatisfiedTest(unittest.TestCase): self.assertTrue(self.handler._path_satisfied(dom[i])) def test_not_satisfied(self): - dom = ["0", "1", "2"] + dom = ["0", "1", "2", "3"] self.handler.paths[dom[0]] = [1, 2] self.handler.responses[dom[0]] = ["sat1", None, "sat2", None] @@ -506,6 +506,9 @@ class PathSatisfiedTest(unittest.TestCase): self.handler.paths[dom[2]] = [0] self.handler.responses[dom[2]] = [None] + self.handler.paths[dom[2]] = [0] + self.handler.responses[dom[2]] = [False] + for i in xrange(3): self.assertFalse(self.handler._path_satisfied(dom[i])) From b47cc8eb8f27b3f5f56b15afdcf425f195ac94c7 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Mon, 16 Mar 2015 23:00:31 -0700 Subject: [PATCH 03/31] fix _path_satisfied test --- letsencrypt/client/tests/auth_handler_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/letsencrypt/client/tests/auth_handler_test.py b/letsencrypt/client/tests/auth_handler_test.py index 734f4cc65..e0169ab15 100644 --- a/letsencrypt/client/tests/auth_handler_test.py +++ b/letsencrypt/client/tests/auth_handler_test.py @@ -506,8 +506,8 @@ class PathSatisfiedTest(unittest.TestCase): self.handler.paths[dom[2]] = [0] self.handler.responses[dom[2]] = [None] - self.handler.paths[dom[2]] = [0] - self.handler.responses[dom[2]] = [False] + self.handler.paths[dom[3]] = [0] + self.handler.responses[dom[3]] = [False] for i in xrange(3): self.assertFalse(self.handler._path_satisfied(dom[i])) From 2f2e973552396ce3734b7d6474dbcc3ddd255d0a Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Fri, 20 Mar 2015 11:43:16 -0700 Subject: [PATCH 04/31] Add the standalone mode to the README --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 712eb3b22..5d9f888d3 100644 --- a/README.rst +++ b/README.rst @@ -57,6 +57,7 @@ Current Features * web servers supported: - apache2.x (tested and working on Ubuntu Linux) + - standalone (runs its own webserver to prove you control the domain) * the private key is generated locally on your system * can talk to the Let's Encrypt (demo) CA or optionally to other ACME From fb12b715bd3ffd0dfcf2291d5cb5b2110607106e Mon Sep 17 00:00:00 2001 From: Ada Lovelace Date: Fri, 20 Mar 2015 12:39:07 -0700 Subject: [PATCH 05/31] added swig to list of dependencies to install in CONTRIBUTING.rst --- CONTRIBUTING.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 9cb73a654..4e206afa4 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -4,10 +4,14 @@ Hacking ======= In order to start hacking, you will first have to create a development -environment: +environment. Start by installing the required system packages: :: + sudo apt-get install python-2.7 python-pip swig +Now you can install the development packages in your virtualenv: + +:: ./venv/bin/python setup.py dev The code base, including your pull requests, **must** have 100% test statement From b288bcf4a691f62b33bc61269e5a32d481317f0b Mon Sep 17 00:00:00 2001 From: Ada Lovelace Date: Fri, 20 Mar 2015 13:15:29 -0700 Subject: [PATCH 06/31] include setup instructions in CONTRIBUTING.rst --- CONTRIBUTING.rst | 67 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 4e206afa4..048cd2b10 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,15 +1,69 @@ +Prerequisites +============= + +The demo code is supported and known to work on **Ubuntu only** (even +closely related `Debian is known to fail`_). + +Therefore, prerequisites for other platforms listed below are provided +mainly for the :ref:`developers ` reference. + +In general: + +* `swig`_ is required for compiling `m2crypto`_ +* `augeas`_ is required for the ``python-augeas`` bindings + +.. _Debian is known to fail: https://github.com/letsencrypt/lets-encrypt-preview/issues/68 + +Ubuntu +------ + +:: + + sudo apt-get install python python-setuptools python-virtualenv python-dev \ + gcc swig dialog libaugeas0 libssl-dev libffi-dev \ + ca-certificates + +.. Please keep the above command in sync with .travis.yml (before_install) + +Mac OSX +------- + +:: + + sudo brew install augeas swig + + +Installation +============ + +:: + + virtualenv --no-site-packages -p python2 venv + ./venv/bin/python setup.py install + sudo ./venv/bin/letsencrypt + + +Usage +===== + +The letsencrypt commandline tool has a builtin help: + +:: + + ./venv/bin/letsencrypt --help + + +.. _augeas: http://augeas.net/ +.. _m2crypto: https://github.com/M2Crypto/M2Crypto +.. _swig: http://www.swig.org/ + .. _hacking: Hacking ======= In order to start hacking, you will first have to create a development -environment. Start by installing the required system packages: - -:: - sudo apt-get install python-2.7 python-pip swig - -Now you can install the development packages in your virtualenv: +environment. Start by installing the development packages: :: ./venv/bin/python setup.py dev @@ -29,6 +83,7 @@ The following tools are there to help you: .. _coding-style: +.. _setup instructions: https://letsencrypt.readthedocs.org/en/latest/using.html Coding style ============ From dee212fc90e530a8028a164806c62b42bd71c122 Mon Sep 17 00:00:00 2001 From: Ada Lovelace Date: Fri, 20 Mar 2015 13:23:44 -0700 Subject: [PATCH 07/31] fixes typos in CONTRIBUTING --- CONTRIBUTING.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 048cd2b10..ca3a4c92e 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -5,7 +5,7 @@ The demo code is supported and known to work on **Ubuntu only** (even closely related `Debian is known to fail`_). Therefore, prerequisites for other platforms listed below are provided -mainly for the :ref:`developers ` reference. +mainly for the `hacking`_ reference. In general: @@ -66,10 +66,11 @@ In order to start hacking, you will first have to create a development environment. Start by installing the development packages: :: + ./venv/bin/python setup.py dev The code base, including your pull requests, **must** have 100% test statement -coverage **and** be compliant with the :ref:`coding-style`. +coverage **and** be compliant with the coding-style_. The following tools are there to help you: @@ -83,8 +84,6 @@ The following tools are there to help you: .. _coding-style: -.. _setup instructions: https://letsencrypt.readthedocs.org/en/latest/using.html - Coding style ============ From 75e4e5d48b14dc0954984aec01c8ecf7024fa3ff Mon Sep 17 00:00:00 2001 From: William Budington Date: Fri, 20 Mar 2015 20:56:44 +0000 Subject: [PATCH 08/31] Gitignore .swp for vim --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e1dca3a57..f2cec0721 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ venv/ .tox/ .coverage m3 +*.swp From 2a2e4d2e8dd235a71fcfb2ce306b6a7b83f0bf4b Mon Sep 17 00:00:00 2001 From: Garrett Robinson Date: Fri, 20 Mar 2015 14:05:48 -0700 Subject: [PATCH 09/31] Pin pylint and astroid to workaround #289 --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 46aca4434..e2190f61d 100755 --- a/setup.py +++ b/setup.py @@ -40,7 +40,9 @@ install_requires = [ ] dev_extras = [ - 'pylint>=1.4.0', # upstream #248 + # Pin astroid==1.3.5, pylint==1.4.2 as a workaround for #289 + 'astroid==1.3.5', + 'pylint==1.4.2', # upstream #248 ] docs_extras = [ From a7059e6818566b62e97fcca727fa00d34f37543a Mon Sep 17 00:00:00 2001 From: cooperq Date: Fri, 20 Mar 2015 15:13:49 -0700 Subject: [PATCH 10/31] replace text with link to docs --- CONTRIBUTING.rst | 64 +++--------------------------------------------- 1 file changed, 4 insertions(+), 60 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index ca3a4c92e..bfd0a1c0f 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -1,69 +1,12 @@ -Prerequisites -============= - -The demo code is supported and known to work on **Ubuntu only** (even -closely related `Debian is known to fail`_). - -Therefore, prerequisites for other platforms listed below are provided -mainly for the `hacking`_ reference. - -In general: - -* `swig`_ is required for compiling `m2crypto`_ -* `augeas`_ is required for the ``python-augeas`` bindings - -.. _Debian is known to fail: https://github.com/letsencrypt/lets-encrypt-preview/issues/68 - -Ubuntu ------- - -:: - - sudo apt-get install python python-setuptools python-virtualenv python-dev \ - gcc swig dialog libaugeas0 libssl-dev libffi-dev \ - ca-certificates - -.. Please keep the above command in sync with .travis.yml (before_install) - -Mac OSX -------- - -:: - - sudo brew install augeas swig - - -Installation -============ - -:: - - virtualenv --no-site-packages -p python2 venv - ./venv/bin/python setup.py install - sudo ./venv/bin/letsencrypt - - -Usage -===== - -The letsencrypt commandline tool has a builtin help: - -:: - - ./venv/bin/letsencrypt --help - - -.. _augeas: http://augeas.net/ -.. _m2crypto: https://github.com/M2Crypto/M2Crypto -.. _swig: http://www.swig.org/ - .. _hacking: Hacking ======= In order to start hacking, you will first have to create a development -environment. Start by installing the development packages: +environment. Start by `installing dependencies and setting up Let's Encrypt`_. + +Now you can install the development packages: :: @@ -82,6 +25,7 @@ The following tools are there to help you: - ``./venv/bin/tox -e lint`` checks the style of the whole project, while ``./venv/bin/pylint --rcfile=.pylintrc file`` will check a single `file` only. +.. _installing dependencies and setting up Let's Encrypt: https://letsencrypt.readthedocs.org/en/latest/using.html .. _coding-style: Coding style From e6b07f66d5f50a7368fc9c7dd0936c8fb222b84a Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Fri, 20 Mar 2015 23:17:41 +0000 Subject: [PATCH 11/31] Remove decoder2/encoder2 --- letsencrypt/acme/jose/json_util.py | 39 ++++++------------------- letsencrypt/acme/jose/json_util_test.py | 31 +++----------------- 2 files changed, 13 insertions(+), 57 deletions(-) diff --git a/letsencrypt/acme/jose/json_util.py b/letsencrypt/acme/jose/json_util.py index 8abcf5e32..8d32d5b8b 100644 --- a/letsencrypt/acme/jose/json_util.py +++ b/letsencrypt/acme/jose/json_util.py @@ -30,13 +30,7 @@ class Field(object): :class:`~letsencrypt.acme.jose.errors.SerializationError` (:class:`~letsencrypt.acme.jose.errors.DeserializationError`). - For greater flexibility, ``encoder2`` and ``decoder2`` accept two - parameters: the whole object ("``self``" in case of encoding, and - JSON serialized object ``jobj`` in case of decoding) and the value - to be encoded/decoded. - - Note, that ``decoder`` and ``decoder2`` should perform partial - serialization only. + Note, that ``decoder`` should perform partial serialization only. :ivar str json_name: Name of the field when encoded to JSON. :ivar default: Default value (used when not present in JSON object). @@ -52,14 +46,12 @@ class Field(object): 'fdec', 'fenc', 'fdec2', 'fenc2') def __init__(self, json_name, default=None, omitempty=False, - decoder=None, encoder=None, decoder2=None, encoder2=None): + decoder=None, encoder=None): # pylint: disable=too-many-arguments self.json_name = json_name self.default = default self.omitempty = omitempty - self.fdec2 = decoder2 - self.fenc2 = encoder2 self.fdec = self.default_decoder if decoder is None else decoder self.fenc = self.default_encoder if encoder is None else encoder @@ -80,37 +72,24 @@ class Field(object): def _update_params(self, **kwargs): current = dict(json_name=self.json_name, default=self.default, omitempty=self.omitempty, - decoder=self.fdec, encoder=self.fenc, - decoder2=self.fdec2, encoder2=self.fenc2) + decoder=self.fdec, encoder=self.fenc) current.update(kwargs) return type(self)(**current) # pylint: disable=star-args def decoder(self, fdec): """Descriptor to change the decoder on JSON object field.""" - return self._update_params(decoder=fdec, decoder2=None) + return self._update_params(decoder=fdec) def encoder(self, fenc): """Descriptor to change the encoder on JSON object field.""" - return self._update_params(encoder=fenc, encoder2=None) + return self._update_params(encoder=fenc) - def decoder2(self, fdec2): - """Descriptor to change the decoder2 on JSON object field.""" - return self._update_params(decoder2=fdec2, decoder=None) - - def encoder2(self, fenc2): - """Descriptor to change the encoder2 on JSON object field.""" - return self._update_params(encoder2=fenc2, encoder=None) - - def decode(self, value, jobj=None): + def decode(self, value): """Decode a value, optionally with context JSON object.""" - if self.fdec2 is not None: - return self.fdec2(jobj, value) return self.fdec(value) - def encode(self, value, obj=None): + def encode(self, value): """Encode a value, optionally with context JSON object.""" - if self.fenc2 is not None: - return self.fenc2(obj, value) return self.fenc(value) @classmethod @@ -241,7 +220,7 @@ class JSONObjectWithFields(util.ImmutableMap, interfaces.JSONDeSerializable): logging.debug('Ommiting empty field "%s" (%s)', slot, value) else: try: - jobj[field.json_name] = field.encode(value, self) + jobj[field.json_name] = field.encode(value) except errors.SerializationError as error: raise errors.SerializationError( 'Could not encode {0} ({1}): {2}'.format( @@ -274,7 +253,7 @@ class JSONObjectWithFields(util.ImmutableMap, interfaces.JSONDeSerializable): else: value = jobj[field.json_name] try: - fields[slot] = field.decode(value, jobj) + fields[slot] = field.decode(value) except errors.DeserializationError as error: raise errors.DeserializationError( 'Could not decode {0!r} ({1!r}): {2}'.format( diff --git a/letsencrypt/acme/jose/json_util_test.py b/letsencrypt/acme/jose/json_util_test.py index da548aaee..e5bffd294 100644 --- a/letsencrypt/acme/jose/json_util_test.py +++ b/letsencrypt/acme/jose/json_util_test.py @@ -21,8 +21,6 @@ class FieldTest(unittest.TestCase): """Tests for letsencrypt.acme.jose.json_util.Field.""" def test_descriptors(self): - mock_jobj = mock.MagicMock() - mock_obj = mock.MagicMock() mock_value = mock.MagicMock() # pylint: disable=missing-docstring @@ -33,36 +31,15 @@ class FieldTest(unittest.TestCase): def encoder(unused_value): return 'e' - def decoder2(jobj, unused_value): - self.assertTrue(jobj is mock_jobj) - return 'd2' - - def encoder2(obj, unused_value): - self.assertTrue(obj is mock_obj) - return 'e2' - from letsencrypt.acme.jose.json_util import Field - field = Field('foo', decoder=decoder, encoder=encoder, - decoder2=decoder2, encoder2=encoder2) - - self.assertEqual('e2', field.encode(mock_value, mock_obj)) - self.assertEqual('d2', field.decode(mock_value, mock_jobj)) + field = Field('foo') field = field.encoder(encoder) - self.assertEqual('e', field.encode(mock_value, mock_obj)) - self.assertEqual('d2', field.decode(mock_value, mock_jobj)) + self.assertEqual('e', field.encode(mock_value)) field = field.decoder(decoder) - self.assertEqual('e', field.encode(mock_value, mock_obj)) - self.assertEqual('d', field.decode(mock_value, mock_jobj)) - - field = field.encoder2(encoder2) - self.assertEqual('e2', field.encode(mock_value, mock_obj)) - self.assertEqual('d', field.decode(mock_value, mock_jobj)) - - field = field.decoder2(decoder2) - self.assertEqual('e2', field.encode(mock_value, mock_obj)) - self.assertEqual('d2', field.decode(mock_value, mock_jobj)) + self.assertEqual('e', field.encode(mock_value)) + self.assertEqual('d', field.decode(mock_value)) def test_default_encoder_is_partial(self): class MockField(interfaces.JSONDeSerializable): From a863a8f9aca62b5cfd784ea8f5e420f34be6e02a Mon Sep 17 00:00:00 2001 From: Peter Eckersley Date: Fri, 20 Mar 2015 18:55:35 -0700 Subject: [PATCH 12/31] Link to the CONTRIBUTING file --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index 5d9f888d3..c27279ade 100644 --- a/README.rst +++ b/README.rst @@ -80,6 +80,8 @@ Documentation: https://letsencrypt.readthedocs.org/ Software project: https://github.com/letsencrypt/lets-encrypt-preview +Notes for developers: [CONTRIBUTING.rst](/CONTRIBUTING.rst) + Main Website: https://letsencrypt.org/ IRC Channel: #letsencrypt on `Freenode`_ From 615b2c789d6512e9ac56e139273b792b9ceb8a0b Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sat, 21 Mar 2015 07:30:55 +0000 Subject: [PATCH 13/31] _JWAHS.verify constant compare warning --- letsencrypt/acme/jose/jwa.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/letsencrypt/acme/jose/jwa.py b/letsencrypt/acme/jose/jwa.py index 99c9a8631..984a10f41 100644 --- a/letsencrypt/acme/jose/jwa.py +++ b/letsencrypt/acme/jose/jwa.py @@ -71,7 +71,12 @@ class _JWAHS(JWASignature): return HMAC.new(key, msg, self.digestmod).digest() def verify(self, key, msg, sig): - # TODO: use constant compare to mitigate timing attack? + """Verify the signature. + + .. warning:: + Does not protect against timing attack (no constant compare). + + """ return self.sign(key, msg) == sig From 5eb007cc317db5a12e01ded18e344a73155f7c1e Mon Sep 17 00:00:00 2001 From: Garrett Robinson Date: Fri, 20 Mar 2015 09:25:36 -0700 Subject: [PATCH 14/31] Add Vagrantfile, document use * Adds workaround to setup.py for issue with Vagrant sync filesystem and hard linking (used by distutils in Python < 2.7.9). This workaround is only used in a Vagrant environment. * Adds Vagrant-related files to .gitignore --- .gitignore | 2 ++ CONTRIBUTING.rst | 27 ++++++++++++++++++++++++++- Vagrantfile | 32 ++++++++++++++++++++++++++++++++ setup.py | 6 ++++++ 4 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 Vagrantfile diff --git a/.gitignore b/.gitignore index e1dca3a57..5b5cfb530 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ venv/ .tox/ .coverage m3 +*~ +.vagrant diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 9cb73a654..19dd8ab89 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -23,8 +23,33 @@ The following tools are there to help you: - ``./venv/bin/tox -e lint`` checks the style of the whole project, while ``./venv/bin/pylint --rcfile=.pylintrc file`` will check a single `file` only. - .. _coding-style: + +Vagrant +======= + +If you are a Vagrant user, Let's Encrypt comes with a Vagrantfile that automates +setting up a development environment in an Ubuntu 14.04 LTS VM. To set it up, +simply run ``vagrant up``. The repository is synced to ``/vagrant``, so you can +get started with: + +:: + + vagrant ssh + cd /vagrant + ./venv/bin/python setup.py install + sudo ./venv/bin/letsencrypt + +Support for other Linux distributions coming soon. + +**Note:** Unfortunately, Python distutils and, by extension, setup.py and tox, +use hard linking quite extensively. Hard linking is not supported by the +default sync filesystem in Vagrant. As a result, all actions with these +commands are *significantly slower* in Vagrant. One potential fix is to `use +NFS`_ (`related issue`_). + +.. _use NFS: http://docs.vagrantup.com/v2/synced-folders/nfs.html +.. _related issue: https://github.com/ClusterHQ/flocker/issues/516 Coding style ============ diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 000000000..a9e5494ac --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,32 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +# Setup instructions from docs/using.rst +$ubuntu_setup_script = < Date: Sat, 21 Mar 2015 20:17:29 +0000 Subject: [PATCH 15/31] Remove remnants of fdec2/fenc2 --- letsencrypt/acme/jose/json_util.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/letsencrypt/acme/jose/json_util.py b/letsencrypt/acme/jose/json_util.py index 8d32d5b8b..01eada89c 100644 --- a/letsencrypt/acme/jose/json_util.py +++ b/letsencrypt/acme/jose/json_util.py @@ -42,8 +42,7 @@ class Field(object): deserializing. """ - __slots__ = ('json_name', 'default', 'omitempty', - 'fdec', 'fenc', 'fdec2', 'fenc2') + __slots__ = ('json_name', 'default', 'omitempty', 'fdec', 'fenc') def __init__(self, json_name, default=None, omitempty=False, decoder=None, encoder=None): From 71d8999e7cf59a213bcb9ace3055f7446a9bcab0 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sat, 21 Mar 2015 20:50:43 +0000 Subject: [PATCH 16/31] Bump up minimum coverage to 86% --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 485816d45..bb5ac1bb7 100644 --- a/tox.ini +++ b/tox.ini @@ -19,7 +19,7 @@ setenv = basepython = python2.7 commands = pip install -e .[testing] - python setup.py nosetests --with-coverage --cover-min-percentage=85 + python setup.py nosetests --with-coverage --cover-min-percentage=86 [testenv:lint] # recent versions of pylint do not support Python 2.6 (#97, #187) From 006fcbbf46b01d4de4664a80ff70032cc637c6e1 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sat, 21 Mar 2015 20:54:02 +0000 Subject: [PATCH 17/31] py26 compat: with x, y -> with x: with y --- letsencrypt/acme/jose/jws_test.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/letsencrypt/acme/jose/jws_test.py b/letsencrypt/acme/jose/jws_test.py index 28dfd0c2f..6e6b51350 100644 --- a/letsencrypt/acme/jose/jws_test.py +++ b/letsencrypt/acme/jose/jws_test.py @@ -205,29 +205,33 @@ class CLITest(unittest.TestCase): def test_unverified(self): from letsencrypt.acme.jose.jws import CLI - with mock.patch('sys.stdin') as sin, mock.patch('sys.stdout'): + with mock.patch('sys.stdin') as sin: sin.read.return_value = '{"payload": "foo", "signature": "xxx"}' - self.assertEqual(-1, CLI.run(['verify'])) + with mock.patch('sys.stdout'): + self.assertEqual(-1, CLI.run(['verify'])) def test_json(self): from letsencrypt.acme.jose.jws import CLI - with mock.patch('sys.stdin') as sin, mock.patch('sys.stdout') as sout: + with mock.patch('sys.stdin') as sin: sin.read.return_value = 'foo' - CLI.run(['sign', '-k', self.key_path, '-a', 'RS256', - '-p', 'jwk']) - sin.read.return_value = sout.write.mock_calls[0][1][0] - self.assertEqual(0, CLI.run(['verify'])) + with mock.patch('sys.stdout') as sout: + CLI.run(['sign', '-k', self.key_path, '-a', 'RS256', + '-p', 'jwk']) + sin.read.return_value = sout.write.mock_calls[0][1][0] + self.assertEqual(0, CLI.run(['verify'])) def test_compact(self): from letsencrypt.acme.jose.jws import CLI - with mock.patch('sys.stdin') as sin, mock.patch('sys.stdout') as sout: + with mock.patch('sys.stdin') as sin: sin.read.return_value = 'foo' - CLI.run(['--compact', 'sign', '-k', self.key_path]) - sin.read.return_value = sout.write.mock_calls[0][1][0] - self.assertEqual(0, CLI.run([ - '--compact', 'verify', '--kty', 'RSA', '-k', self.key_path])) + with mock.patch('sys.stdout') as sout: + CLI.run(['--compact', 'sign', '-k', self.key_path]) + sin.read.return_value = sout.write.mock_calls[0][1][0] + self.assertEqual(0, CLI.run([ + '--compact', 'verify', '--kty', 'RSA', + '-k', self.key_path])) if __name__ == '__main__': From d06cd7aa39484035fb2a4e881afb6644e897f115 Mon Sep 17 00:00:00 2001 From: pde and jdkasten Date: Sat, 21 Mar 2015 13:56:40 -0700 Subject: [PATCH 18/31] Update dev docs - Import and edit James's API docs into CONTRIBUTING.rst - Linke correctly to CONTRIBUTING from the main README --- CONTRIBUTING.rst | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ README.rst | 3 +- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index bfd0a1c0f..654d5569b 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -27,6 +27,83 @@ The following tools are there to help you: .. _installing dependencies and setting up Let's Encrypt: https://letsencrypt.readthedocs.org/en/latest/using.html +CODE COMPONENTS AND LAYOUT +========================== + +letsencrypt/acme - contains all protocol specific code +letsencrypt/client - all client code +letsencrypt/scripts - just the starting point of the code, main.py + +Plugin-architecture +------------------- + +Let's Encrypt has a plugin architecture to facilitate support for different +webservers, other TLS servers, and operating systems. + +The most common kind of plugin is a "Configurator", which is likely to +implement the "Authenticator" and "Installer" interfaces (though some +Configurators may implement just one of those). + +Defined here: +https://github.com/letsencrypt/lets-encrypt-preview/blob/master/letsencrypt/client/interfaces.py + +There are also "Display" plugins, which implement bindings to alternative UI +libraries. + +Authenticators +-------------- + +Authenticators are plugins designed to solve challenges received from the +ACME server. From the protocol, there are essentially two different types +of challenges. Challenges that must be solved by individual plugins in +order to satisfy domain validation (dvsni, simpleHttps, dns) and client +specific challenges (recoveryToken, recoveryContact, pop). Client specific +challenges are always handled by the "Authenticator" +client_authenticator.py. Right now we have two DV Authenticators, +apache/configurator.py and the standalone_authenticator.py. The Standalone +and Apache authenticators only solve the DVSNI challenge currently. (You +can set which challenges your authenticator can handle through the +get_chall_pref(domain) function) + +(FYI: We also have a partial implementation for a dns_authenticator in a +separate branch). + +Challenge types are defined here... +( +https://github.com/letsencrypt/lets-encrypt-preview/blob/master/letsencrypt/client/constants.py#L16 +) + +Installer +--------- + +Installers classes exist to actually setup the certificate and be able +to enhance the configuration. (Turn on HSTS, redirect to HTTPS, etc). You +can indicate your abilities through the supported_enhancements call. We +currently only have one Installer written (still developing), +apache/configurator.py + +Installers and Authenticators will oftentimes be the same class/object. +Installers and Authenticators are kept separate because it should be +possible to use the standalone_authenticator (it sets up its own Python +server to perform challenges) with a program that cannot solve challenges +itself. (I am imagining MTA installers). + +*Display* - we currently offer a pythondialog and "text" mode for +displays. I have rewritten the interface which should be merged within the +next day (the rewrite is in the revoker branch of the repo and should be +merged within the next day) + +Here is what the display interface will look like +https://github.com/letsencrypt/lets-encrypt-preview/blob/revoker/letsencrypt/client/interfaces.py#L217 + +Augeus +------ + +Some plugins, especially those designed to reconfigure UNIX servers, can take +inherit from the augeus_configurator.py class in order to more efficiently +handle common operations on UNIX server configuration files. + + .. _coding-style: Coding style ============ diff --git a/README.rst b/README.rst index c27279ade..86d85ed1d 100644 --- a/README.rst +++ b/README.rst @@ -80,7 +80,7 @@ Documentation: https://letsencrypt.readthedocs.org/ Software project: https://github.com/letsencrypt/lets-encrypt-preview -Notes for developers: [CONTRIBUTING.rst](/CONTRIBUTING.rst) +Notes for developers: CONTRIBUTING.rst_ Main Website: https://letsencrypt.org/ @@ -91,3 +91,4 @@ email to client-dev+subscribe@letsencrypt.org) .. _Freenode: https://freenode.net .. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev +.. _CONTRIBUTING.rst: https://github.com/letsencrypt/lets-encrypt-preview/blob/master/CONTRIBUTING.rst From 4e21703503f181b493b5fef93f830c91df0e7c61 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Sat, 21 Mar 2015 15:14:58 -0700 Subject: [PATCH 19/31] add acme.jose and acme.schemata packages to setup.py --- setup.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/setup.py b/setup.py index 570f77f13..038c0554a 100755 --- a/setup.py +++ b/setup.py @@ -93,6 +93,8 @@ setup( packages=[ 'letsencrypt', 'letsencrypt.acme', + 'letsencrypt.acme.jose', + 'letsencrypt.acme.schemata', 'letsencrypt.client', 'letsencrypt.client.apache', 'letsencrypt.client.display', From 12287e70fc149b3a8c0edd1c3b32b07169dd8f0f Mon Sep 17 00:00:00 2001 From: James Kasten Date: Sat, 21 Mar 2015 16:20:32 -0700 Subject: [PATCH 20/31] remove schemata --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 038c0554a..e0b1dcd63 100755 --- a/setup.py +++ b/setup.py @@ -94,7 +94,6 @@ setup( 'letsencrypt', 'letsencrypt.acme', 'letsencrypt.acme.jose', - 'letsencrypt.acme.schemata', 'letsencrypt.client', 'letsencrypt.client.apache', 'letsencrypt.client.display', From 0a981e02f42808f44ad6c6f68b1823ccf078894f Mon Sep 17 00:00:00 2001 From: Garrett Robinson Date: Fri, 20 Mar 2015 09:25:36 -0700 Subject: [PATCH 21/31] Bring back Vagrant documentation (fixes #309). --- CONTRIBUTING.rst | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 654d5569b..eda8045f3 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -27,6 +27,34 @@ The following tools are there to help you: .. _installing dependencies and setting up Let's Encrypt: https://letsencrypt.readthedocs.org/en/latest/using.html + +Vagrant +======= + +If you are a Vagrant user, Let's Encrypt comes with a Vagrantfile that automates +setting up a development environment in an Ubuntu 14.04 LTS VM. To set it up, +simply run ``vagrant up``. The repository is synced to ``/vagrant``, so you can +get started with: + +:: + + vagrant ssh + cd /vagrant + ./venv/bin/python setup.py install + sudo ./venv/bin/letsencrypt + +Support for other Linux distributions coming soon. + +**Note:** Unfortunately, Python distutils and, by extension, setup.py and tox, +use hard linking quite extensively. Hard linking is not supported by the +default sync filesystem in Vagrant. As a result, all actions with these +commands are *significantly slower* in Vagrant. One potential fix is to `use +NFS`_ (`related issue`_). + +.. _use NFS: http://docs.vagrantup.com/v2/synced-folders/nfs.html +.. _related issue: https://github.com/ClusterHQ/flocker/issues/516 + + CODE COMPONENTS AND LAYOUT ========================== From 37a7ef216064d2f01fb515888a8d93c23af5baaf Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sun, 22 Mar 2015 14:07:58 +0000 Subject: [PATCH 22/31] Reorg CONTRIBUTING --- CONTRIBUTING | 18 ++++++++++++++++++ CONTRIBUTING.rst => docs/contributing.rst | 4 ++++ docs/index.rst | 2 +- docs/project.rst | 5 ----- 4 files changed, 23 insertions(+), 6 deletions(-) create mode 100644 CONTRIBUTING rename CONTRIBUTING.rst => docs/contributing.rst (99%) delete mode 100644 docs/project.rst diff --git a/CONTRIBUTING b/CONTRIBUTING new file mode 100644 index 000000000..d54f7beee --- /dev/null +++ b/CONTRIBUTING @@ -0,0 +1,18 @@ + + +http://letsencrypt.readthedocs.org/en/latest/contributing.html diff --git a/CONTRIBUTING.rst b/docs/contributing.rst similarity index 99% rename from CONTRIBUTING.rst rename to docs/contributing.rst index eda8045f3..d2104aee1 100644 --- a/CONTRIBUTING.rst +++ b/docs/contributing.rst @@ -1,3 +1,7 @@ +============ +Contributing +============ + .. _hacking: Hacking diff --git a/docs/index.rst b/docs/index.rst index b290b2231..34615168c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -6,7 +6,7 @@ Welcome to the Let's Encrypt client documentation! intro using - project + contributing .. toctree:: :maxdepth: 1 diff --git a/docs/project.rst b/docs/project.rst deleted file mode 100644 index 421f0b062..000000000 --- a/docs/project.rst +++ /dev/null @@ -1,5 +0,0 @@ -================================ -The Let's Encrypt Client Project -================================ - -.. include:: ../CONTRIBUTING.rst From 3206eb674a744c020330a4e1dbf009888b858377 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sun, 22 Mar 2015 22:25:50 +0000 Subject: [PATCH 23/31] rst cleanup: contributing, using --- docs/conf.py | 2 +- docs/contributing.rst | 178 +++++++++++++++++++++++------------------- docs/using.rst | 22 +++--- 3 files changed, 108 insertions(+), 94 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 6e2c484ca..a6e5da4ff 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -101,7 +101,7 @@ exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +default_role = 'py:obj' # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True diff --git a/docs/contributing.rst b/docs/contributing.rst index d2104aee1..e3b81b3d4 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -8,16 +8,18 @@ Hacking ======= In order to start hacking, you will first have to create a development -environment. Start by `installing dependencies and setting up Let's Encrypt`_. +environment. Start by :doc:`installing dependencies and setting up +Let's Encrypt `. Now you can install the development packages: -:: +.. code-block:: shell - ./venv/bin/python setup.py dev + ./venv/bin/python setup.py dev -The code base, including your pull requests, **must** have 100% test statement -coverage **and** be compliant with the coding-style_. +The code base, including your pull requests, **must** have 100% test +statement coverage **and** be compliant with the :ref:`coding style +`. The following tools are there to help you: @@ -27,116 +29,127 @@ The following tools are there to help you: - ``./venv/bin/tox -e cover`` checks the test coverage only. - ``./venv/bin/tox -e lint`` checks the style of the whole project, - while ``./venv/bin/pylint --rcfile=.pylintrc file`` will check a single `file` only. + while ``./venv/bin/pylint --rcfile=.pylintrc file`` will check a + single ``file`` only. + +.. _installing dependencies and setting up Let's Encrypt: + https://letsencrypt.readthedocs.org/en/latest/using.html -.. _installing dependencies and setting up Let's Encrypt: https://letsencrypt.readthedocs.org/en/latest/using.html - Vagrant -======= +------- -If you are a Vagrant user, Let's Encrypt comes with a Vagrantfile that automates -setting up a development environment in an Ubuntu 14.04 LTS VM. To set it up, -simply run ``vagrant up``. The repository is synced to ``/vagrant``, so you can -get started with: +If you are a Vagrant user, Let's Encrypt comes with a Vagrantfile that +automates setting up a development environment in an Ubuntu 14.04 +LTS VM. To set it up, simply run ``vagrant up``. The repository is +synced to ``/vagrant``, so you can get started with: -:: +.. code-block:: shell - vagrant ssh - cd /vagrant - ./venv/bin/python setup.py install - sudo ./venv/bin/letsencrypt + vagrant ssh + cd /vagrant + ./venv/bin/python setup.py install + sudo ./venv/bin/letsencrypt Support for other Linux distributions coming soon. -**Note:** Unfortunately, Python distutils and, by extension, setup.py and tox, -use hard linking quite extensively. Hard linking is not supported by the -default sync filesystem in Vagrant. As a result, all actions with these -commands are *significantly slower* in Vagrant. One potential fix is to `use -NFS`_ (`related issue`_). +.. note:: + Unfortunately, Python distutils and, by extension, setup.py and + tox, use hard linking quite extensively. Hard linking is not + supported by the default sync filesystem in Vagrant. As a result, + all actions with these commands are *significantly slower* in + Vagrant. One potential fix is to `use NFS`_ (`related issue`_). .. _use NFS: http://docs.vagrantup.com/v2/synced-folders/nfs.html .. _related issue: https://github.com/ClusterHQ/flocker/issues/516 -CODE COMPONENTS AND LAYOUT +Code components and layout ========================== -letsencrypt/acme - contains all protocol specific code -letsencrypt/client - all client code -letsencrypt/scripts - just the starting point of the code, main.py +letsencrypt/acme + contains all protocol specific code +letsencrypt/client + all client code +letsencrypt/scripts + just the starting point of the code, main.py + Plugin-architecture ------------------- -Let's Encrypt has a plugin architecture to facilitate support for different -webservers, other TLS servers, and operating systems. +Let's Encrypt has a plugin architecture to facilitate support for +different webservers, other TLS servers, and operating systems. The most common kind of plugin is a "Configurator", which is likely to -implement the "Authenticator" and "Installer" interfaces (though some +implement the `~letsencrypt.client.interfaces.IAuthenticator` and +`~letsencrypt.client.interfaces.IInstaller` interfaces (though some Configurators may implement just one of those). -Defined here: -https://github.com/letsencrypt/lets-encrypt-preview/blob/master/letsencrypt/client/interfaces.py +There are also `~letsencrypt.client.interfaces.IDisplay` plugins, +which implement bindings to alternative UI libraries. -There are also "Display" plugins, which implement bindings to alternative UI -libraries. Authenticators -------------- -Authenticators are plugins designed to solve challenges received from the -ACME server. From the protocol, there are essentially two different types -of challenges. Challenges that must be solved by individual plugins in -order to satisfy domain validation (dvsni, simpleHttps, dns) and client -specific challenges (recoveryToken, recoveryContact, pop). Client specific -challenges are always handled by the "Authenticator" -client_authenticator.py. Right now we have two DV Authenticators, -apache/configurator.py and the standalone_authenticator.py. The Standalone -and Apache authenticators only solve the DVSNI challenge currently. (You -can set which challenges your authenticator can handle through the -get_chall_pref(domain) function) +Authenticators are plugins designed to solve challenges received from +the ACME server. From the protocol, there are essentially two +different types of challenges. Challenges that must be solved by +individual plugins in order to satisfy domain validation (subclasses +of `~.DVChallenge`, i.e. `~.challenges.DVSNI`, +`~.challenges.SimpleHTTPS`, `~.challenges.DNS`) and client specific +challenges (subclasses of `~.ClientChallenge`, +i.e. `~.challenges.RecoveryToken`, `~.challenges.RecoveryContact`, +`~.challenges.ProofOfPossession`). Client specific challenges are +always handled by the `~.ClientAuthenticator`. Right now we have two +DV Authenticators, `~.ApacheConfigurator` and the +`~.StandaloneAuthenticator`. The Standalone and Apache authenticators +only solve the `~.challenges.DVSNI` challenge currently. (You can set +which challenges your authenticator can handle through the +:meth:`~.IAuthenticator.get_chall_pref`. -(FYI: We also have a partial implementation for a dns_authenticator in a -separate branch). +(FYI: We also have a partial implementation for a `~.DNSAuthenticator` +in a separate branch). -Challenge types are defined here... -( -https://github.com/letsencrypt/lets-encrypt-preview/blob/master/letsencrypt/client/constants.py#L16 -) Installer --------- Installers classes exist to actually setup the certificate and be able -to enhance the configuration. (Turn on HSTS, redirect to HTTPS, etc). You -can indicate your abilities through the supported_enhancements call. We -currently only have one Installer written (still developing), -apache/configurator.py +to enhance the configuration. (Turn on HSTS, redirect to HTTPS, +etc). You can indicate your abilities through the +:meth:`~.IInstaller.supported_enhancements` call. We currently only +have one Installer written (still developing), `~.ApacheConfigurator`. -Installers and Authenticators will oftentimes be the same class/object. -Installers and Authenticators are kept separate because it should be -possible to use the standalone_authenticator (it sets up its own Python -server to perform challenges) with a program that cannot solve challenges -itself. (I am imagining MTA installers). +Installers and Authenticators will oftentimes be the same +class/object. Installers and Authenticators are kept separate because +it should be possible to use the `~.StandaloneAuthenticator` (it sets +up its own Python server to perform challenges) with a program that +cannot solve challenges itself. (I am imagining MTA installers). -*Display* - we currently offer a pythondialog and "text" mode for -displays. I have rewritten the interface which should be merged within the -next day (the rewrite is in the revoker branch of the repo and should be -merged within the next day) -Here is what the display interface will look like -https://github.com/letsencrypt/lets-encrypt-preview/blob/revoker/letsencrypt/client/interfaces.py#L217 +Display +~~~~~~~ -Augeus +We currently offer a pythondialog and "text" mode for displays. I have +rewritten the interface which should be merged within the next day +(the rewrite is in the revoker branch of the repo and should be merged +within the next day). Display plugins implement +`~letsencrypt.client.interfaces.IDisplay` interface. + + +Augeas ------ -Some plugins, especially those designed to reconfigure UNIX servers, can take -inherit from the augeus_configurator.py class in order to more efficiently -handle common operations on UNIX server configuration files. +Some plugins, especially those designed to reconfigure UNIX servers, +can take inherit from `~.AugeasConfigurator` class in order to more +efficiently handle common operations on UNIX server configuration +files. .. _coding-style: + Coding style ============ @@ -147,9 +160,7 @@ Please: 2. Read `PEP 8 - Style Guide for Python Code`_. 3. Follow the `Google Python Style Guide`_, with the exception that we - use `Sphinx-style`_ documentation: - - :: + use `Sphinx-style`_ documentation:: def foo(arg): """Short description. @@ -164,20 +175,23 @@ Please: 4. Remember to use ``./venv/bin/pylint``. -.. _Google Python Style Guide: https://google-styleguide.googlecode.com/svn/trunk/pyguide.html +.. _Google Python Style Guide: + https://google-styleguide.googlecode.com/svn/trunk/pyguide.html .. _Sphinx-style: http://sphinx-doc.org/ -.. _PEP 8 - Style Guide for Python Code: https://www.python.org/dev/peps/pep-0008 +.. _PEP 8 - Style Guide for Python Code: + https://www.python.org/dev/peps/pep-0008 -Updating the Documentation +Updating the documentation ========================== -In order to generate the Sphinx documentation, run the following commands. +In order to generate the Sphinx documentation, run the following +commands: -:: +.. code-block:: shell - cd docs - make clean html SPHINXBUILD=../venv/bin/sphinx-build + cd docs + make clean html SPHINXBUILD=../venv/bin/sphinx-build - -This should generate documentation in the ``docs/_build/html`` directory. +This should generate documentation in the ``docs/_build/html`` +directory. diff --git a/docs/using.rst b/docs/using.rst index 9b09833e4..362b75d81 100644 --- a/docs/using.rst +++ b/docs/using.rst @@ -21,30 +21,30 @@ In general: Ubuntu ------ -:: +.. code-block:: shell - sudo apt-get install python python-setuptools python-virtualenv python-dev \ - gcc swig dialog libaugeas0 libssl-dev libffi-dev \ - ca-certificates + sudo apt-get install python python-setuptools python-virtualenv python-dev \ + gcc swig dialog libaugeas0 libssl-dev libffi-dev \ + ca-certificates .. Please keep the above command in sync with .travis.yml (before_install) Mac OSX ------- -:: +.. code-block:: shell - sudo brew install augeas swig + sudo brew install augeas swig Installation ============ -:: +.. code-block:: shell - virtualenv --no-site-packages -p python2 venv - ./venv/bin/python setup.py install - sudo ./venv/bin/letsencrypt + virtualenv --no-site-packages -p python2 venv + ./venv/bin/python setup.py install + sudo ./venv/bin/letsencrypt Usage @@ -52,7 +52,7 @@ Usage The letsencrypt commandline tool has a builtin help: -:: +.. code-block:: shell ./venv/bin/letsencrypt --help From 55a80e768a84847ccb543edb4aef71bf0289b8f9 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sun, 22 Mar 2015 22:29:24 +0000 Subject: [PATCH 24/31] CONTRIBUTING: md file suffix --- CONTRIBUTING => CONTRIBUTING.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename CONTRIBUTING => CONTRIBUTING.md (100%) diff --git a/CONTRIBUTING b/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING rename to CONTRIBUTING.md From 6d38b1b09e491ef78ac4db2eb2c3f1eb1927d039 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Sun, 22 Mar 2015 22:30:57 +0000 Subject: [PATCH 25/31] HTTPS ReadTheDocs link in CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d54f7beee..bf19b18e1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -15,4 +15,4 @@ to the Sphinx generated docs is provided below. --> -http://letsencrypt.readthedocs.org/en/latest/contributing.html +https://letsencrypt.readthedocs.org/en/latest/contributing.html From 1a0af51f6f6133116f33f3668ac3a2a5e7db230f Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Mon, 23 Mar 2015 08:25:44 +0000 Subject: [PATCH 26/31] Fix Sphinx M2Crypto.X509 import errors --- letsencrypt/acme/jose/jws.py | 2 +- letsencrypt/acme/jose/jws_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/letsencrypt/acme/jose/jws.py b/letsencrypt/acme/jose/jws.py index 81106dd2c..3b962aede 100644 --- a/letsencrypt/acme/jose/jws.py +++ b/letsencrypt/acme/jose/jws.py @@ -3,7 +3,7 @@ import argparse import base64 import sys -import M2Crypto.X509 +import M2Crypto from letsencrypt.acme.jose import b64 from letsencrypt.acme.jose import errors diff --git a/letsencrypt/acme/jose/jws_test.py b/letsencrypt/acme/jose/jws_test.py index 6e6b51350..215960e15 100644 --- a/letsencrypt/acme/jose/jws_test.py +++ b/letsencrypt/acme/jose/jws_test.py @@ -5,7 +5,7 @@ import pkg_resources import unittest import Crypto.PublicKey.RSA -import M2Crypto.X509 +import M2Crypto import mock from letsencrypt.acme.jose import b64 From 53bdf5e24627cf94526a3c12f30e48b164d891e7 Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Mon, 23 Mar 2015 08:27:57 +0000 Subject: [PATCH 27/31] Fix _enable_redirect docstring --- letsencrypt/client/apache/configurator.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/letsencrypt/client/apache/configurator.py b/letsencrypt/client/apache/configurator.py index 93db689f8..89a2ff4e2 100644 --- a/letsencrypt/client/apache/configurator.py +++ b/letsencrypt/client/apache/configurator.py @@ -548,8 +548,9 @@ class ApacheConfigurator(augeas_configurator.AugeasConfigurator): def _enable_redirect(self, ssl_vhost, unused_options): """Redirect all equivalent HTTP traffic to ssl_vhost. - .. todo:: This enhancement should be rewritten and will unfortunately - require lots of debugging by hand. + .. todo:: This enhancement should be rewritten and will + unfortunately require lots of debugging by hand. + Adds Redirect directive to the port 80 equivalent of ssl_vhost First the function attempts to find the vhost with equivalent ip addresses that serves on non-ssl ports From 533cfa42c74fa0f314805ea22846cda2e294615d Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Mon, 23 Mar 2015 08:35:36 +0000 Subject: [PATCH 28/31] MANIFEST: Update CONTRIBUTING extension --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index bea6fd9bb..3bd657b87 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,6 +1,6 @@ include README.rst include CHANGES.rst -include CONTRIBUTING.rst +include CONTRIBUTING.md include linter_plugin.py include letsencrypt/EULA recursive-include letsencrypt *.json From 71e17df03a5f9f3d87a244d7fd9656c0d2b8285d Mon Sep 17 00:00:00 2001 From: Jakub Warmuz Date: Mon, 23 Mar 2015 09:19:13 +0000 Subject: [PATCH 29/31] InsecurePlatformWarning (fixes #304) --- letsencrypt/client/network.py | 3 +++ setup.py | 2 ++ 2 files changed, 5 insertions(+) diff --git a/letsencrypt/client/network.py b/letsencrypt/client/network.py index de6db575b..2719583c3 100644 --- a/letsencrypt/client/network.py +++ b/letsencrypt/client/network.py @@ -11,6 +11,9 @@ from letsencrypt.acme import messages from letsencrypt.client import errors +# https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning +requests.packages.urllib3.contrib.pyopenssl.inject_into_urllib3() + logging.getLogger("requests").setLevel(logging.WARNING) diff --git a/setup.py b/setup.py index 520147433..45873e9e8 100755 --- a/setup.py +++ b/setup.py @@ -32,7 +32,9 @@ install_requires = [ 'ConfArgParse', 'jsonschema', 'mock', + 'ndg-httpsclient', # urllib3 InsecurePlatformWarning (#304) 'psutil>=2.1.0', # net_connections introduced in 2.1.0 + 'pyasn1', # urllib3 InsecurePlatformWarning (#304) 'pycrypto', 'PyOpenSSL', 'python-augeas', From 8e3a496b8b3f7be3e934d7b0ce1d87971862ab24 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Tue, 24 Mar 2015 16:21:09 -0700 Subject: [PATCH 30/31] simplify path_satisfied test --- letsencrypt/client/auth_handler.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/letsencrypt/client/auth_handler.py b/letsencrypt/client/auth_handler.py index 41c7a9f68..05f3722cf 100644 --- a/letsencrypt/client/auth_handler.py +++ b/letsencrypt/client/auth_handler.py @@ -203,9 +203,8 @@ class AuthHandler(object): # pylint: disable=too-many-instance-attributes def _path_satisfied(self, dom): """Returns whether a path has been completely satisfied.""" - return all( - self.responses[dom][i] is not None and - self.responses[dom][i] is not False for i in self.paths[dom]) + # Make sure that there are no 'None' or 'False' entries along path. + return all(self.responses[dom][i] for i in self.paths[dom]) def _get_chall_pref(self, domain): """Return list of challenge preferences. From a1fe6039d874a15b8defaf45dc40ddd8cdad0db3 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Tue, 24 Mar 2015 17:49:38 -0700 Subject: [PATCH 31/31] Fix bug with no DVSNI challenges --- letsencrypt/client/apache/dvsni.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/letsencrypt/client/apache/dvsni.py b/letsencrypt/client/apache/dvsni.py index b980fdb36..033bcde20 100644 --- a/letsencrypt/client/apache/dvsni.py +++ b/letsencrypt/client/apache/dvsni.py @@ -50,7 +50,7 @@ class ApacheDvsni(object): def perform(self): """Peform a DVSNI challenge.""" if not self.achalls: - return None + return [] # Save any changes to the configuration as a precaution # About to make temporary changes to the config self.configurator.save() @@ -160,19 +160,19 @@ class ApacheDvsni(object): ips = " ".join(str(i) for i in ip_addrs) document_root = os.path.join( self.configurator.config.config_dir, "dvsni_page/") - return ("\n" - "ServerName " + achall.nonce_domain + "\n" - "UseCanonicalName on\n" - "SSLStrictSNIVHostCheck on\n" - "\n" - "LimitRequestBody 1048576\n" - "\n" - "Include " + self.configurator.parser.loc["ssl_options"] + "\n" - "SSLCertificateFile " + self.get_cert_file(achall) + "\n" - "SSLCertificateKeyFile " + achall.key.file + "\n" - "\n" - "DocumentRoot " + document_root + "\n" - "\n\n") + return ("{0}" + "ServerName " + achall.nonce_domain + "{0}" + "UseCanonicalName on{0}" + "SSLStrictSNIVHostCheck on{0}" + "{0}" + "LimitRequestBody 1048576{0}" + "{0}" + "Include " + self.configurator.parser.loc["ssl_options"] + "{0}" + "SSLCertificateFile " + self.get_cert_file(achall) + "{0}" + "SSLCertificateKeyFile " + achall.key.file + "{0}" + "{0}" + "DocumentRoot " + document_root + "{0}" + "{0}{0}".format(os.linesep)) def get_cert_file(self, achall): """Returns standardized name for challenge certificate.