Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into doc-on-venv-memory
Browse files Browse the repository at this point in the history
  • Loading branch information
timdream committed Oct 26, 2016
2 parents 643aa70 + 1dafaec commit 93f0b02
Show file tree
Hide file tree
Showing 106 changed files with 2,095 additions and 1,640 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ tags
*.sw?
\#*#
.idea
.ropeproject

# auth --cert-path --chain-path
/*.pem
Expand Down
38 changes: 18 additions & 20 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,60 +19,59 @@ env:

matrix:
include:
- python: "2.6"
env: TOXENV=py26 BOULDER_INTEGRATION=1
- python: "2.7"
env: TOXENV=cover BOULDER_INTEGRATION=1
sudo: true
after_failure:
- sudo cat /var/log/mysql/error.log
- ps aux | grep mysql
- python: "2.6"
env: TOXENV=py26-oldest BOULDER_INTEGRATION=1
- python: "2.7"
env: TOXENV=lint
- python: "2.7"
env: TOXENV=py27-oldest BOULDER_INTEGRATION=1
sudo: true
after_failure:
- sudo cat /var/log/mysql/error.log
- ps aux | grep mysql
- python: "2.7"
env: TOXENV=apacheconftest
sudo: required
- python: "2.7"
env: TOXENV=nginxroundtrip
- python: "2.7"
env: TOXENV=py27 BOULDER_INTEGRATION=1
- python: "2.6"
env: TOXENV=py26 BOULDER_INTEGRATION=1
sudo: true
after_failure:
- sudo cat /var/log/mysql/error.log
- ps aux | grep mysql
- python: "2.7"
env: TOXENV=py27-oldest BOULDER_INTEGRATION=1
- python: "2.6"
env: TOXENV=py26-oldest BOULDER_INTEGRATION=1
sudo: true
after_failure:
- sudo cat /var/log/mysql/error.log
- ps aux | grep mysql
- python: "2.7"
env: TOXENV=lint
- sudo: required
env: TOXENV=le_auto
env: TOXENV=nginx_compat
services: docker
before_install:
addons:
- sudo: required
env: TOXENV=apache_compat
env: TOXENV=le_auto
services: docker
before_install:
addons:
- sudo: required
env: TOXENV=nginx_compat
env: TOXENV=apache_compat
services: docker
before_install:
addons:
- python: "2.7"
env: TOXENV=cover
env: TOXENV=apacheconftest
sudo: required
- python: "3.3"
env: TOXENV=py33
- python: "3.4"
env: TOXENV=py34
- python: "3.5"
env: TOXENV=py35
- python: "2.7"
env: TOXENV=nginxroundtrip


# Only build pushes to the master branch, PRs, and branches beginning with
# `test-`. This reduces the number of simultaneous Travis runs, which speeds
Expand Down Expand Up @@ -104,7 +103,6 @@ addons:
- python-dev
- python-virtualenv
- gcc
- dialog
- libaugeas0
- libssl-dev
- libffi-dev
Expand Down
11 changes: 4 additions & 7 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
ChangeLog
=========

Please note:
the change log will only get updated after first release - for now please use the
`commit log <https://github.com/certbot/certbot/commits/master>`_.
To see the changes in a given release, view the issues closed in a given
release's GitHub milestone:

To see the changes in a given release, inspect the github milestone for the
release. For instance:

https://github.com/certbot/certbot/issues?utf8=%E2%9C%93&q=milestone%3A0.3.0
- `Past releases <https://github.com/certbot/certbot/milestones?state=closed>`_
- `Upcoming releases <https://github.com/certbot/certbot/milestones>`_
19 changes: 18 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,21 @@ to the Sphinx generated docs is provided below.
-->

https://certbot.eff.org/docs/contributing.html
# Certbot Contributing Guide

Hi! Welcome to the Certbot project. We look forward to collaborating with you.

If you're reporting a bug in Certbot, please make sure to include:
- The version of Certbot you're running.
- The operating system you're running it on.
- The commands you ran.
- What you expected to happen, and
- What actually happened.

If you're a developer, we have some helpful information in our
[Developer's Guide](https://certbot.eff.org/docs/contributing.html) to get you
started. In particular, we recommend you read these sections

- [Finding issues to work on](https://certbot.eff.org/docs/contributing.html#find-issues-to-work-on)
- [Coding style](https://certbot.eff.org/docs/contributing.html#coding-style)
- [Submitting a pull request](https://certbot.eff.org/docs/contributing.html#submitting-a-pull-request)
26 changes: 14 additions & 12 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,17 @@ the User Guide.
Links
=====

.. Do not modify this comment unless you know what you're doing. tag:links-begin
Documentation: https://certbot.eff.org/docs

Software project: https://github.com/certbot/certbot

Notes for developers: https://certbot.eff.org/docs/contributing.html

Main Website: https://letsencrypt.org/
Main Website: https://certbot.eff.org

Let's Encrypt Website: https://letsencrypt.org

IRC Channel: #letsencrypt on `Freenode`_ or #certbot on `OFTC`_

Expand All @@ -96,13 +100,13 @@ ACME working area in github: https://github.com/ietf-wg-acme/acme
Mailing list: `client-dev`_ (to subscribe without a Google account, send an
email to client-dev+subscribe@letsencrypt.org)

.. _Freenode: https://webchat.freenode.net?channels=%23letsencrypt
.. _OFTC: https://webchat.oftc.net?channels=%23certbot
.. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev

|build-status| |coverage| |docs| |container|

.. _Freenode: https://webchat.freenode.net?channels=%23letsencrypt

.. _OFTC: https://webchat.oftc.net?channels=%23certbot

.. _client-dev: https://groups.google.com/a/letsencrypt.org/forum/#!forum/client-dev

.. |build-status| image:: https://travis-ci.org/certbot/certbot.svg?branch=master
:target: https://travis-ci.org/certbot/certbot
Expand All @@ -120,10 +124,7 @@ email to client-dev+subscribe@letsencrypt.org)
:target: https://quay.io/repository/letsencrypt/letsencrypt
:alt: Docker Repository on Quay.io

.. _`installation instructions`:
https://letsencrypt.readthedocs.org/en/latest/using.html#getting-certbot

.. _watch demo video: https://www.youtube.com/watch?v=Gas_sSB-5SU
.. Do not modify this comment unless you know what you're doing. tag:links-end
System Requirements
===================
Expand Down Expand Up @@ -151,11 +152,12 @@ Current Features

* Supports multiple web servers:

- apache/2.x (working on Debian 8+ and Ubuntu 12.04+)
- standalone (runs its own simple webserver to prove you control a domain)
- apache/2.x (beta support for auto-configuration)
- nginx/0.8.48+ (alpha support for auto-configuration)
- webroot (adds files to webroot directories in order to prove control of
domains and obtain certs)
- nginx/0.8.48+ (highly experimental, not included in certbot-auto)
- standalone (runs its own simple webserver to prove you control a domain)
- other server software via `third party plugins <https://certbot.eff.org/docs/using.html#third-party-plugins>`_

* The private key is generated locally on your system.
* Can talk to the Let's Encrypt CA or optionally to other ACME
Expand Down
1 change: 1 addition & 0 deletions Vagrantfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# VM needs more memory to run test suite, got "OSError: [Errno 12]
# Cannot allocate memory" when running
# letsencrypt.client.tests.display.util_test.NcursesDisplayTest
# We may no longer need this.
v.memory = 1024

# Handle cases when the host is behind a private network by making the
Expand Down
11 changes: 6 additions & 5 deletions acme/acme/challenges.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import OpenSSL
import requests

from acme import dns_resolver
from acme import errors
from acme import crypto_util
from acme import fields
Expand Down Expand Up @@ -232,11 +233,11 @@ def simple_verify(self, chall, domain, account_public_key):
logger.debug("Verifying %s at %s...", chall.typ, validation_domain_name)

try:
from acme import dns_resolver
except ImportError: # pragma: no cover
raise errors.Error("Local validation for 'dns-01' challenges "
"requires 'dnspython'")
txt_records = dns_resolver.txt_records_for_name(validation_domain_name)
txt_records = dns_resolver.txt_records_for_name(
validation_domain_name)
except errors.DependencyError:
raise errors.DependencyError("Local validation for 'dns-01' "
"challenges requires 'dnspython'")
exists = validation in txt_records
if not exists:
logger.debug("Key authorization from response (%r) doesn't match "
Expand Down
60 changes: 37 additions & 23 deletions acme/acme/challenges_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from acme import errors
from acme import jose
from acme import test_util

from acme.dns_resolver import DNS_REQUIREMENT

CERT = test_util.load_comparable_cert('cert.pem')
KEY = jose.JWKRSA(key=test_util.load_rsa_private_key('rsa512_key.pem'))
Expand Down Expand Up @@ -92,6 +92,7 @@ def setUp(self):
from acme.challenges import DNS01
self.chall = DNS01(token=(b'x' * 16))
self.response = self.chall.response(KEY)
self.records_for_name_path = "acme.dns_resolver.txt_records_for_name"

def test_to_partial_json(self):
self.assertEqual(self.jmsg, self.msg.to_partial_json())
Expand All @@ -108,28 +109,41 @@ def test_simple_verify_bad_key_authorization(self):
key2 = jose.JWKRSA.load(test_util.load_vector('rsa256_key.pem'))
self.response.simple_verify(self.chall, "local", key2.public_key())

@mock.patch("acme.dns_resolver.txt_records_for_name")
def test_simple_verify_good_validation(self, mock_resolver):
mock_resolver.return_value = [self.chall.validation(KEY.public_key())]
self.assertTrue(self.response.simple_verify(
self.chall, "local", KEY.public_key()))
mock_resolver.assert_called_once_with(
self.chall.validation_domain_name("local"))

@mock.patch("acme.dns_resolver.txt_records_for_name")
def test_simple_verify_good_validation_multiple_txts(self, mock_resolver):
mock_resolver.return_value = [
"!", self.chall.validation(KEY.public_key())]
self.assertTrue(self.response.simple_verify(
self.chall, "local", KEY.public_key()))
mock_resolver.assert_called_once_with(
self.chall.validation_domain_name("local"))

@mock.patch("acme.dns_resolver.txt_records_for_name")
def test_simple_verify_bad_validation(self, mock_dns):
mock_dns.return_value = ["!"]
self.assertFalse(self.response.simple_verify(
self.chall, "local", KEY.public_key()))
@mock.patch('acme.dns_resolver.DNS_AVAILABLE', False)
def test_simple_verify_without_dns(self):
self.assertRaises(
errors.DependencyError, self.response.simple_verify,
self.chall, 'local', KEY.public_key())

@test_util.skip_unless(test_util.requirement_available(DNS_REQUIREMENT),
"optional dependency dnspython is not available")
def test_simple_verify_good_validation(self): # pragma: no cover
with mock.patch(self.records_for_name_path) as mock_resolver:
mock_resolver.return_value = [
self.chall.validation(KEY.public_key())]
self.assertTrue(self.response.simple_verify(
self.chall, "local", KEY.public_key()))
mock_resolver.assert_called_once_with(
self.chall.validation_domain_name("local"))

@test_util.skip_unless(test_util.requirement_available(DNS_REQUIREMENT),
"optional dependency dnspython is not available")
def test_simple_verify_good_validation_multitxts(self): # pragma: no cover
with mock.patch(self.records_for_name_path) as mock_resolver:
mock_resolver.return_value = [
"!", self.chall.validation(KEY.public_key())]
self.assertTrue(self.response.simple_verify(
self.chall, "local", KEY.public_key()))
mock_resolver.assert_called_once_with(
self.chall.validation_domain_name("local"))

@test_util.skip_unless(test_util.requirement_available(DNS_REQUIREMENT),
"optional dependency dnspython is not available")
def test_simple_verify_bad_validation(self): # pragma: no cover
with mock.patch(self.records_for_name_path) as mock_resolver:
mock_resolver.return_value = ["!"]
self.assertFalse(self.response.simple_verify(
self.chall, "local", KEY.public_key()))


class DNS01Test(unittest.TestCase):
Expand Down
4 changes: 3 additions & 1 deletion acme/acme/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ def revoke(self, cert):
class ClientNetwork(object): # pylint: disable=too-many-instance-attributes
"""Client network."""
JSON_CONTENT_TYPE = 'application/json'
JOSE_CONTENT_TYPE = 'application/jose+json'
JSON_ERROR_CONTENT_TYPE = 'application/problem+json'
REPLAY_NONCE_HEADER = 'Replay-Nonce'

Expand Down Expand Up @@ -641,9 +642,10 @@ def _get_nonce(self, url):
self._add_nonce(self.head(url))
return self._nonces.pop()

def post(self, url, obj, content_type=JSON_CONTENT_TYPE, **kwargs):
def post(self, url, obj, content_type=JOSE_CONTENT_TYPE, **kwargs):
"""POST object wrapped in `.JWS` and check response."""
data = self._wrap_in_jws(obj, self._get_nonce(url))
kwargs.setdefault('headers', {'Content-Type': content_type})
response = self._send_request('POST', url, data=data, **kwargs)
self._add_nonce(response)
return self._check_response(response, content_type=content_type)
4 changes: 4 additions & 0 deletions acme/acme/client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,10 @@ def test_get(self):
self.send_request.assert_called_once_with(
'GET', 'http://example.com/', bar='baz')

def test_post_no_content_type(self):
self.content_type = self.net.JOSE_CONTENT_TYPE
self.assertEqual(self.checked_response, self.net.post('uri', self.obj))

def test_post(self):
# pylint: disable=protected-access
self.assertEqual(self.checked_response, self.net.post(
Expand Down
19 changes: 17 additions & 2 deletions acme/acme/dns_resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,20 @@
"""
import logging

import dns.resolver
import dns.exception
from acme import errors
from acme import util

DNS_REQUIREMENT = 'dnspython>=1.12'

try:
util.activate(DNS_REQUIREMENT)
# pragma: no cover
import dns.exception
import dns.resolver
DNS_AVAILABLE = True
except errors.DependencyError: # pragma: no cover
DNS_AVAILABLE = False


logger = logging.getLogger(__name__)

Expand All @@ -18,6 +30,9 @@ def txt_records_for_name(name):
:rtype: list of unicode
"""
if not DNS_AVAILABLE:
raise errors.DependencyError(
'{0} is required to use this function'.format(DNS_REQUIREMENT))
try:
dns_response = dns.resolver.query(name, 'TXT')
except dns.resolver.NXDOMAIN as error:
Expand Down
Loading

0 comments on commit 93f0b02

Please sign in to comment.