diff --git a/.travis.yml b/.travis.yml index 1d2f7b1db..e253081d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,20 +38,20 @@ matrix: env: TOXENV=py27 BOULDER_INTEGRATION=1 - python: "2.7" env: TOXENV=py27-oldest BOULDER_INTEGRATION=1 - - python: "2.7" - env: TOXENV=cover - python: "2.7" env: TOXENV=lint + - sudo: required + env: TOXENV=le_auto + services: docker + before_install: + - python: "2.7" + env: TOXENV=cover - python: "3.3" env: TOXENV=py33 - python: "3.4" env: TOXENV=py34 - python: "3.5" env: TOXENV=py35 - - sudo: required - env: TOXENV=le_auto - services: docker - before_install: # Only build pushes to the master branch, PRs, and branches beginning with # `test-`. This reduces the number of simultaneous Travis runs, which speeds @@ -65,9 +65,14 @@ branches: sudo: false addons: - # make sure simplehttp simple verification works (custom /etc/hosts) + # Custom /etc/hosts required for SimpleHTTP simple verification, + # simple_verify for http01 and tls-sni-01, and letsencrypt_test_nginx hosts: - le.wtf + - le1.wtf + - le2.wtf + - le3.wtf + - nginx.wtf mariadb: "10.0" apt: sources: diff --git a/Vagrantfile b/Vagrantfile index 678abdf72..e5975442f 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -5,10 +5,19 @@ VAGRANTFILE_API_VERSION = "2" # Setup instructions from docs/contributing.rst +# Script installs dependencies for tox and boulder integration $ubuntu_setup_script = <> /home/vagrant/.profile; fi +if ! grep -Fxq "export PATH=\\$GOROOT/bin:\\$PATH" /home/vagrant/.profile ; then echo "export PATH=\\$GOROOT/bin:\\$PATH" >> /home/vagrant/.profile; fi +if ! grep -Fxq "export GOPATH=\\$HOME/go" /home/vagrant/.profile ; then echo "export GOPATH=\\$HOME/go" >> /home/vagrant/.profile; fi +if ! grep -Fxq "cd /vagrant/; ./tests/boulder-start.sh &" /etc/rc.local ; then sed -i -e '$i \cd /vagrant/; ./tests/boulder-start.sh &\n' /etc/rc.local; fi +export DEBIAN_FRONTEND=noninteractive +sudo -E apt-get -q -y install git make libltdl-dev mariadb-server rabbitmq-server nginx-light SETUP_SCRIPT Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| diff --git a/docs/ciphers.rst b/docs/ciphers.rst index c8ff26117..ef644b7a0 100644 --- a/docs/ciphers.rst +++ b/docs/ciphers.rst @@ -139,7 +139,7 @@ client's priorities. The Mozilla security team is likely to have more resources and expertise to bring to bear on evaluating reasons why its recommendations should be updated. -The Let's Encrpyt project will entertain proposals to create a *very* +The Let's Encrypt project will entertain proposals to create a *very* small number of alternative configurations (apart from Modern, Intermediate, and Old) that there's reason to believe would be widely used by sysadmins; this would usually be a preferable course to modifying diff --git a/docs/contributing.rst b/docs/contributing.rst index 36dff01b9..69604780c 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -96,6 +96,14 @@ Integration testing with the boulder CA Generally it is sufficient to open a pull request and let Github and Travis run integration tests for you. +However, if you prefer to run tests, you can use Vagrant, using the Vagrantfile +in Let's Encrypt's repository. To execute the tests on a Vagrant box, the only +command you are required to run is:: + + ./tests/boulder-integration.sh + +Otherwise, please follow the following instructions. + Mac OS X users: Run ``./tests/mac-bootstrap.sh`` instead of ``boulder-start.sh`` to install dependencies, configure the environment, and start boulder. @@ -127,9 +135,9 @@ Afterwards, you'd be able to start Boulder_ using the following command:: The script will download, compile and run the executable; please be patient - it will take some time... Once its ready, you will see -``Server running, listening on 127.0.0.1:4000...``. Add an -``/etc/hosts`` entry pointing ``le.wtf`` to 127.0.0.1. You may now -run (in a separate terminal):: +``Server running, listening on 127.0.0.1:4000...``. Add ``/etc/hosts`` +entries pointing ``le.wtf``, ``le1.wtf``, ``le2.wtf``, ``le3.wtf`` +and ``nginx.wtf`` to 127.0.0.1. You may now run (in a separate terminal):: ./tests/boulder-integration.sh && echo OK || echo FAIL diff --git a/letsencrypt-apache/letsencrypt_apache/constants.py b/letsencrypt-apache/letsencrypt_apache/constants.py index 50156444b..77f71a461 100644 --- a/letsencrypt-apache/letsencrypt_apache/constants.py +++ b/letsencrypt-apache/letsencrypt_apache/constants.py @@ -54,6 +54,23 @@ CLI_DEFAULTS_GENTOO = dict( MOD_SSL_CONF_SRC=pkg_resources.resource_filename( "letsencrypt_apache", "options-ssl-apache.conf") ) +CLI_DEFAULTS_DARWIN = dict( + server_root="/etc/apache2", + vhost_root="/etc/apache2/other", + vhost_files="*.conf", + version_cmd=['/usr/sbin/httpd', '-v'], + define_cmd=['/usr/sbin/httpd', '-t', '-D', 'DUMP_RUN_CFG'], + restart_cmd=['apachectl', 'graceful'], + conftest_cmd=['apachectl', 'configtest'], + enmod=None, + dismod=None, + le_vhost_ext="-le-ssl.conf", + handle_mods=False, + handle_sites=False, + challenge_location="/etc/apache2/other", + MOD_SSL_CONF_SRC=pkg_resources.resource_filename( + "letsencrypt_apache", "options-ssl-apache.conf") +) CLI_DEFAULTS = { "debian": CLI_DEFAULTS_DEBIAN, "ubuntu": CLI_DEFAULTS_DEBIAN, @@ -61,7 +78,8 @@ CLI_DEFAULTS = { "centos linux": CLI_DEFAULTS_CENTOS, "fedora": CLI_DEFAULTS_CENTOS, "red hat enterprise linux server": CLI_DEFAULTS_CENTOS, - "gentoo base system": CLI_DEFAULTS_GENTOO + "gentoo base system": CLI_DEFAULTS_GENTOO, + "darwin": CLI_DEFAULTS_DARWIN, } """CLI defaults.""" diff --git a/letsencrypt-auto-source/letsencrypt-auto b/letsencrypt-auto-source/letsencrypt-auto index 0630c649a..b542c8d3e 100755 --- a/letsencrypt-auto-source/letsencrypt-auto +++ b/letsencrypt-auto-source/letsencrypt-auto @@ -1640,6 +1640,7 @@ UNLIKELY_EOF # Report error. (Otherwise, be quiet.) echo "Had a problem while downloading and verifying Python packages:" echo "$PEEP_OUT" + rm -rf "$VENV_PATH" exit 1 fi echo "Installation succeeded." diff --git a/letsencrypt-auto-source/letsencrypt-auto.template b/letsencrypt-auto-source/letsencrypt-auto.template index 22dfba1b2..bccd9e2c9 100755 --- a/letsencrypt-auto-source/letsencrypt-auto.template +++ b/letsencrypt-auto-source/letsencrypt-auto.template @@ -210,6 +210,7 @@ UNLIKELY_EOF # Report error. (Otherwise, be quiet.) echo "Had a problem while downloading and verifying Python packages:" echo "$PEEP_OUT" + rm -rf "$VENV_PATH" exit 1 fi echo "Installation succeeded." diff --git a/letsencrypt-auto-source/tests/auto_test.py b/letsencrypt-auto-source/tests/auto_test.py index 32d591190..90e09f57f 100644 --- a/letsencrypt-auto-source/tests/auto_test.py +++ b/letsencrypt-auto-source/tests/auto_test.py @@ -5,7 +5,7 @@ from contextlib import contextmanager from functools import partial from json import dumps from os import chmod, environ -from os.path import abspath, dirname, join +from os.path import abspath, dirname, exists, join import re from shutil import copy, rmtree import socket @@ -338,6 +338,12 @@ class AutoTests(TestCase): self.assertIn("THE FOLLOWING PACKAGES DIDN'T MATCH THE " "HASHES SPECIFIED IN THE REQUIREMENTS", exc.output) + ok_(not exists(join(venv_dir, 'letsencrypt')), + msg="The virtualenv was left around, even though " + "installation didn't succeed. We shouldn't do " + "this, as it foils our detection of whether we " + "need to recreate the virtualenv, which hinges " + "on the presence of $VENV_BIN/letsencrypt.") else: self.fail("Peep didn't detect a bad hash and stop the " "installation.") diff --git a/letsencrypt/configuration.py b/letsencrypt/configuration.py index 2bbf1b019..c49751a6c 100644 --- a/letsencrypt/configuration.py +++ b/letsencrypt/configuration.py @@ -1,8 +1,8 @@ """Let's Encrypt user-supplied configuration.""" import copy import os -import urlparse +from six.moves.urllib import parse # pylint: disable=import-error import zope.interface from letsencrypt import constants @@ -50,7 +50,7 @@ class NamespaceConfig(object): @property def server_path(self): """File path based on ``server``.""" - parsed = urlparse.urlparse(self.namespace.server) + parsed = parse.urlparse(self.namespace.server) return (parsed.netloc + parsed.path).replace('/', os.path.sep) @property diff --git a/letsencrypt/interfaces.py b/letsencrypt/interfaces.py index db5d2c5e8..1921b1e54 100644 --- a/letsencrypt/interfaces.py +++ b/letsencrypt/interfaces.py @@ -169,7 +169,9 @@ class IAuthenticator(IPlugin): Authenticator will never be able to perform (error). :rtype: :class:`list` of - :class:`acme.challenges.ChallengeResponse` + :class:`acme.challenges.ChallengeResponse`, + where responses are required to be returned in + the same order as corresponding input challenges :raises .PluginError: If challenges cannot be performed diff --git a/letsencrypt/le_util.py b/letsencrypt/le_util.py index 527c9bdae..c8a9d24c2 100644 --- a/letsencrypt/le_util.py +++ b/letsencrypt/le_util.py @@ -6,6 +6,7 @@ import logging import os import platform import re +import socket import stat import subprocess import sys @@ -317,6 +318,18 @@ def enforce_domain_sanity(domain): # Remove trailing dot domain = domain[:-1] if domain.endswith('.') else domain + # Explain separately that IP addresses aren't allowed (apart from not + # being FQDNs) because hope springs eternal concerning this point + try: + socket.inet_aton(domain) + raise errors.ConfigurationError( + "Requested name {0} is an IP address. The Let's Encrypt " + "certificate authority will not issue certificates for a " + "bare IP address.".format(domain)) + except socket.error: + # It wasn't an IP address, so that's good + pass + # FQDN checks from # http://www.mkyong.com/regular-expressions/domain-name-regular-expression-example/ # Characters used, domain parts < 63 chars, tld > 1 < 64 chars diff --git a/letsencrypt/plugins/common.py b/letsencrypt/plugins/common.py index bf996ba5e..37738f5c0 100644 --- a/letsencrypt/plugins/common.py +++ b/letsencrypt/plugins/common.py @@ -1,11 +1,11 @@ """Plugin common functions.""" import os -import pkg_resources import re import shutil import tempfile import OpenSSL +import pkg_resources import zope.interface from acme.jose import util as jose_util diff --git a/letsencrypt/plugins/disco_test.py b/letsencrypt/plugins/disco_test.py index 0df4f88f1..1aeaf81c1 100644 --- a/letsencrypt/plugins/disco_test.py +++ b/letsencrypt/plugins/disco_test.py @@ -1,8 +1,8 @@ """Tests for letsencrypt.plugins.disco.""" -import pkg_resources import unittest import mock +import pkg_resources import zope.interface from letsencrypt import errors diff --git a/letsencrypt/tests/cli_test.py b/letsencrypt/tests/cli_test.py index 8184a557e..77a4b5892 100644 --- a/letsencrypt/tests/cli_test.py +++ b/letsencrypt/tests/cli_test.py @@ -351,6 +351,11 @@ class CLITest(unittest.TestCase): # pylint: disable=too-many-public-methods self._call, ['-d', '*.wildcard.tld']) + # Bare IP address (this is actually a different error message now) + self.assertRaises(errors.ConfigurationError, + self._call, + ['-d', '204.11.231.35']) + def _get_argument_parser(self): plugins = disco.PluginsRegistry.find_all() return functools.partial(cli.prepare_and_parse_args, plugins) diff --git a/letsencrypt/tests/client_test.py b/letsencrypt/tests/client_test.py index dbc57565e..f712ea94c 100644 --- a/letsencrypt/tests/client_test.py +++ b/letsencrypt/tests/client_test.py @@ -74,6 +74,15 @@ class RegisterTest(unittest.TestCase): self.config.email = None self.assertRaises(errors.Error, self._call) + @mock.patch("letsencrypt.client.logger") + def test_without_email(self, mock_logger): + with mock.patch("letsencrypt.client.acme_client.Client"): + with mock.patch("letsencrypt.account.report_new_account"): + self.config.email = None + self.config.register_unsafely_without_email = True + self._call() + mock_logger.warn.assert_called_once_with(mock.ANY) + class ClientTest(unittest.TestCase): """Tests for letsencrypt.client.Client.""" diff --git a/letsencrypt/tests/storage_test.py b/letsencrypt/tests/storage_test.py index 071d6d7bb..7bc31dab3 100644 --- a/letsencrypt/tests/storage_test.py +++ b/letsencrypt/tests/storage_test.py @@ -1,13 +1,13 @@ """Tests for letsencrypt.storage.""" import datetime -import pytz import os -import tempfile import shutil +import tempfile import unittest import configobj import mock +import pytz from letsencrypt import configuration from letsencrypt import errors diff --git a/tests/letstest/scripts/test_letsencrypt_auto_certonly_standalone.sh b/tests/letstest/scripts/test_letsencrypt_auto_certonly_standalone.sh index ecef9814b..f4aef11fe 100755 --- a/tests/letstest/scripts/test_letsencrypt_auto_certonly_standalone.sh +++ b/tests/letstest/scripts/test_letsencrypt_auto_certonly_standalone.sh @@ -8,7 +8,7 @@ #private_ip=$(curl -s http://169.254.169.254/2014-11-05/meta-data/local-ipv4) cd letsencrypt -./letsencrypt-auto --os-packages-only +./letsencrypt-auto --os-packages-only --debug --version ./letsencrypt-auto certonly --no-self-upgrade -v --standalone --debug \ --text --agree-dev-preview --agree-tos \ --renew-by-default --redirect \