From 8c38b6941878d846d9bb69bf4018d5e5490cb30b Mon Sep 17 00:00:00 2001 From: Seb Bacon Date: Tue, 1 Nov 2016 18:24:51 +0000 Subject: [PATCH] Compatibility with earlier Python 2.7 versions Compatibility with Python 2.7 versions older than 2.7.7 * Use Django's constant_time_compare method * Include sparkpost in test requirements * Don't use non-public `EnvironmentVarGuard` in tests Fixes #41 (cherry picked from commit f0589e333834990e591dfd16a5b45e7c8f414c2f) --- anymail/webhooks/mailgun.py | 3 ++- anymail/webhooks/mandrill.py | 3 ++- setup.py | 2 +- tests/test_sparkpost_backend.py | 13 ++++--------- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/anymail/webhooks/mailgun.py b/anymail/webhooks/mailgun.py index ad110f85..bb0a785b 100644 --- a/anymail/webhooks/mailgun.py +++ b/anymail/webhooks/mailgun.py @@ -3,6 +3,7 @@ import hashlib import hmac +from django.utils.crypto import constant_time_compare from django.utils.timezone import utc from .base import AnymailBaseWebhookView @@ -34,7 +35,7 @@ def validate_request(self, request): raise AnymailWebhookValidationFailure("Mailgun webhook called without required security fields") expected_signature = hmac.new(key=self.api_key, msg='{}{}'.format(timestamp, token).encode('ascii'), digestmod=hashlib.sha256).hexdigest() - if not hmac.compare_digest(signature, expected_signature): + if not constant_time_compare(signature, expected_signature): raise AnymailWebhookValidationFailure("Mailgun webhook called with incorrect signature") def parse_events(self, request): diff --git a/anymail/webhooks/mandrill.py b/anymail/webhooks/mandrill.py index 3e6a2295..b1d0c639 100644 --- a/anymail/webhooks/mandrill.py +++ b/anymail/webhooks/mandrill.py @@ -4,6 +4,7 @@ import hashlib import hmac from base64 import b64encode +from django.utils.crypto import constant_time_compare from django.utils.timezone import utc from .base import AnymailBaseWebhookView @@ -44,7 +45,7 @@ def validate_request(self, request): expected_signature = b64encode(hmac.new(key=self.webhook_key, msg=signed_data.encode('utf-8'), digestmod=hashlib.sha1).digest()) - if not hmac.compare_digest(signature, expected_signature): + if not constant_time_compare(signature, expected_signature): raise AnymailWebhookValidationFailure("Mandrill webhook called with incorrect signature") diff --git a/setup.py b/setup.py index dfcdc430..f21631db 100644 --- a/setup.py +++ b/setup.py @@ -47,7 +47,7 @@ def long_description_from_readme(rst): }, include_package_data=True, test_suite="runtests.runtests", - tests_require=["mock"], + tests_require=["mock", "sparkpost"], classifiers=[ "Development Status :: 2 - Pre-Alpha", "Programming Language :: Python", diff --git a/tests/test_sparkpost_backend.py b/tests/test_sparkpost_backend.py index 624b7ee5..8f108a98 100644 --- a/tests/test_sparkpost_backend.py +++ b/tests/test_sparkpost_backend.py @@ -3,6 +3,7 @@ from datetime import datetime, date from email.mime.base import MIMEBase from email.mime.image import MIMEImage +import os import requests import six @@ -17,13 +18,6 @@ AnymailConfigurationError) from anymail.message import attach_inline_image_file -try: - # noinspection PyUnresolvedReferences - from test.support import EnvironmentVarGuard # python3 -except ImportError: - # noinspection PyUnresolvedReferences - from test.test_support import EnvironmentVarGuard # python2 - from .utils import AnymailTestMixin, decode_att, SAMPLE_IMAGE_FILENAME, sample_image_path, sample_image_content @@ -579,8 +573,9 @@ def test_missing_api_key(self): def test_api_key_in_env(self): """SparkPost package allows API key in env var; make sure Anymail works with that""" - with EnvironmentVarGuard() as env: - env['SPARKPOST_API_KEY'] = 'key_from_environment' + with patch.dict( + os.environ, + {'SPARKPOST_API_KEY': 'key_from_environment'}): conn = mail.get_connection() # Poke into implementation details to verify: self.assertIsNone(conn.api_key) # Anymail prop