From 8737e45de79d3407aed49f063b17bb979f2c3fcb Mon Sep 17 00:00:00 2001 From: Serghei Mihai Date: Thu, 16 Jul 2015 16:44:38 +0200 Subject: [PATCH] fix key type in request signing (#7866) Tests for api access and signature check added --- passerelle/base/signature.py | 2 ++ tests/test_api_access.py | 81 ++++++++++++++++++++++++++++++++++++++++++++ tests/test_signature.py | 23 +++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 tests/test_api_access.py create mode 100644 tests/test_signature.py diff --git a/passerelle/base/signature.py b/passerelle/base/signature.py index 153785a..b1d5f9d 100644 --- a/passerelle/base/signature.py +++ b/passerelle/base/signature.py @@ -33,6 +33,8 @@ def sign_query(query, key, algo='sha256', timestamp=None, nonce=None): def sign_string(s, key, algo='sha256', timedelta=30): digestmod = getattr(hashlib, algo) + if isinstance(key, unicode): + key = key.encode('utf-8') hash = hmac.HMAC(key, digestmod=digestmod, msg=s) return hash.digest() diff --git a/tests/test_api_access.py b/tests/test_api_access.py new file mode 100644 index 0000000..37106b7 --- /dev/null +++ b/tests/test_api_access.py @@ -0,0 +1,81 @@ +import re +import sys +import mock + +from django.contrib.auth.models import User +from django.core.wsgi import get_wsgi_application +import pytest +from webtest import TestApp + +from passerelle.base import signature + +pytestmark = pytest.mark.django_db + +@pytest.fixture +def admin_user(): + try: + user = User.objects.get(username='admin') + except User.DoesNotExist: + user = User.objects.create_superuser('admin', email=None, password='admin') + return user + +def login(app, username='admin', password='admin'): + login_page = app.get('/login/') + login_form = login_page.forms[0] + login_form['username'] = username + login_form['password'] = password + resp = login_form.submit() + assert resp.status_int == 302 + return app + +def create_api_user(app): + # go to "Access Management" page + resp = app.get('/manage/access/', status=200) + assert 'Add API User' in resp.body + resp = resp.click('Add API User') + resp.forms[0]['username'] = 'eservices' + resp.forms[0]['fullname'] = 'Eservices User' + resp.forms[0]['keytype'] = 'SIGN' + resp.forms[0]['key'] = '12345' + resp = resp.forms[0].submit() + assert resp.status_int == 302 + assert resp.location == 'http://localhost:80/manage/access/' + resp = resp.follow() + assert 'Eservices User' in resp.body + assert 'SIGN' in resp.body + return app + +@mock.patch('bdp.models.requests.get') +def test_connector_access(mock_get, admin_user): + app = login(TestApp(get_wsgi_application())) + app = create_api_user(app) + resp = app.get('/manage/', status=200) + resp = resp.click('Add Connector') + assert 'Business Process Connectors' in resp.body + assert 'BDP Web Service' in resp.body + resp = resp.click('BDP Web Service') + resp.forms[0]['title'] = 'Test Connector' + resp.forms[0]['description'] = 'Connector for a simple test' + resp.forms[0]['service_url'] = 'http://service.url' + resp.forms[0]['username'] = 'username' + resp.forms[0]['password'] = 'password' + resp = resp.forms[0].submit() + assert resp.status_int == 302 + assert resp.location == 'http://localhost:80/bdp/test-connector/' + resp = resp.follow() + assert 'BDP - Test Connector' in resp.body + resp = app.get('/manage/', status=200) + assert 'Test Connector' in resp.body + resp = resp.click('Test Connector') + assert 'Add' in resp.body + resp = resp.click('Add') + resp.forms[0]['apiuser'] = 1 + resp.forms[0].submit() + # call with no signature + resp = app.get('/bdp/test-connector/resources/', status=403) + # sign url + url = signature.sign_url('/bdp/test-connector/resources/?orig=eservices', '12345') + response = mock.Mock() + response.json.return_value = {} + mock_get.return_value = response + resp = app.get(url, status=200) diff --git a/tests/test_signature.py b/tests/test_signature.py new file mode 100644 index 0000000..28ea747 --- /dev/null +++ b/tests/test_signature.py @@ -0,0 +1,23 @@ +import base64 + +from django.test import TestCase + +from passerelle.base import signature + +class SignatureTestCase(TestCase): + def setUp(self): + self.key = '12345' + self.message = 'orig=passerelle&NameID=secret' + self.algo = 'sha1' + + def test_sign_string_with_string_key(self): + encoded = base64.b64encode(signature.sign_string(self.message, self.key)) + self.assertEqual(encoded, 'JC6K3+PCt3YKxZ9eCtEOoF+JfzQBmMeZvvxJ6VhXUXY=') + + def test_sign_string_with_string_key_sha1(self): + encoded = base64.b64encode(signature.sign_string(self.message, self.key, algo=self.algo)) + self.assertEqual(encoded, 'lOt5eyEvLJDTVl11pSqOPDJImgM=') + + def test_sign_string_with_unicode_key(self): + encoded = base64.b64encode(signature.sign_string(self.message, unicode(self.key))) + self.assertEqual(encoded, 'JC6K3+PCt3YKxZ9eCtEOoF+JfzQBmMeZvvxJ6VhXUXY=') -- 2.1.4