summaryrefslogtreecommitdiff
path: root/macaroonbakery/tests/test_client.py
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2017-12-12 15:20:49 +0000
committerColin Watson <cjwatson@debian.org>2017-12-12 15:20:49 +0000
commit9e4403035a9953c99117083e6373ae3c441a76b5 (patch)
treed91b137df6767bfb8cb72de6b9fd21efb0c3dee4 /macaroonbakery/tests/test_client.py
parent949b7072cabce0daed6c94993ad44c8ea8648dbd (diff)
Import py-macaroon-bakery_1.1.0.orig.tar.gz
Diffstat (limited to 'macaroonbakery/tests/test_client.py')
-rw-r--r--macaroonbakery/tests/test_client.py130
1 files changed, 107 insertions, 23 deletions
diff --git a/macaroonbakery/tests/test_client.py b/macaroonbakery/tests/test_client.py
index e1a4009..ab20c3b 100644
--- a/macaroonbakery/tests/test_client.py
+++ b/macaroonbakery/tests/test_client.py
@@ -3,23 +3,24 @@
import base64
import datetime
import json
-from unittest import TestCase
-try:
- from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
-except ImportError:
- from http.server import HTTPServer, BaseHTTPRequestHandler
import threading
+from unittest import TestCase
-from httmock import (
- HTTMock,
- urlmatch
-)
+import macaroonbakery.bakery as bakery
+import macaroonbakery.checkers as checkers
+import macaroonbakery.httpbakery as httpbakery
+import pymacaroons
import requests
+import macaroonbakery._utils as utils
+
+from httmock import HTTMock, urlmatch
from six.moves.urllib.parse import parse_qs
+from six.moves.urllib.request import Request
-import macaroonbakery as bakery
-import macaroonbakery.httpbakery as httpbakery
-import macaroonbakery.checkers as checkers
+try:
+ from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+except ImportError:
+ from http.server import HTTPServer, BaseHTTPRequestHandler
AGES = datetime.datetime.utcnow() + datetime.timedelta(days=1)
TEST_OP = bakery.Op(entity='test', action='test')
@@ -30,7 +31,7 @@ class TestClient(TestCase):
b = new_bakery('loc', None, None)
def handler(*args):
- GetHandler(b, None, None, None, None, *args)
+ GetHandler(b, None, None, None, None, AGES, *args)
try:
httpd = HTTPServer(('', 0), handler)
thread = threading.Thread(target=httpd.serve_forever)
@@ -58,7 +59,7 @@ class TestClient(TestCase):
b = new_bakery('loc', None, None)
def handler(*args):
- GetHandler(b, None, None, None, None, *args)
+ GetHandler(b, None, None, None, None, AGES, *args)
try:
httpd = HTTPServer(('', 0), handler)
thread = threading.Thread(target=httpd.serve_forever)
@@ -81,7 +82,7 @@ class TestClient(TestCase):
finally:
httpd.shutdown()
- def test_repeated_request_with_body(self):
+ def test_expiry_cookie_is_set(self):
class _DischargerLocator(bakery.ThirdPartyLocator):
def __init__(self):
self.key = bakery.generate_key()
@@ -100,7 +101,8 @@ class TestClient(TestCase):
def discharge(url, request):
qs = parse_qs(request.body)
content = {q: qs[q][0] for q in qs}
- m = httpbakery.discharge(checkers.AuthContext(), content, d.key, d, alwaysOK3rd)
+ m = httpbakery.discharge(checkers.AuthContext(), content, d.key, d,
+ alwaysOK3rd)
return {
'status_code': 200,
'content': {
@@ -108,8 +110,10 @@ class TestClient(TestCase):
}
}
+ ages = datetime.datetime.utcnow() + datetime.timedelta(days=1)
+
def handler(*args):
- GetHandler(b, 'http://1.2.3.4', None, None, None, *args)
+ GetHandler(b, 'http://1.2.3.4', None, None, None, ages, *args)
try:
httpd = HTTPServer(('', 0), handler)
thread = threading.Thread(target=httpd.serve_forever)
@@ -122,10 +126,64 @@ class TestClient(TestCase):
cookies=client.cookies,
auth=client.auth())
resp.raise_for_status()
+ m = bakery.Macaroon.from_dict(json.loads(
+ base64.b64decode(client.cookies.get('macaroon-test')).decode('utf-8'))[0])
+ t = checkers.macaroons_expiry_time(
+ checkers.Namespace(), [m.macaroon])
+ self.assertEquals(ages, t)
self.assertEquals(resp.text, 'done')
finally:
httpd.shutdown()
+ def test_expiry_cookie_set_in_past(self):
+ class _DischargerLocator(bakery.ThirdPartyLocator):
+ def __init__(self):
+ self.key = bakery.generate_key()
+
+ def third_party_info(self, loc):
+ if loc == 'http://1.2.3.4':
+ return bakery.ThirdPartyInfo(
+ public_key=self.key.public_key,
+ version=bakery.LATEST_VERSION,
+ )
+
+ d = _DischargerLocator()
+ b = new_bakery('loc', d, None)
+
+ @urlmatch(path='.*/discharge')
+ def discharge(url, request):
+ qs = parse_qs(request.body)
+ content = {q: qs[q][0] for q in qs}
+ m = httpbakery.discharge(checkers.AuthContext(), content, d.key, d,
+ alwaysOK3rd)
+ return {
+ 'status_code': 200,
+ 'content': {
+ 'Macaroon': m.to_dict()
+ }
+ }
+
+ ages = datetime.datetime.utcnow() - datetime.timedelta(days=1)
+
+ def handler(*args):
+ GetHandler(b, 'http://1.2.3.4', None, None, None, ages, *args)
+ try:
+ httpd = HTTPServer(('', 0), handler)
+ thread = threading.Thread(target=httpd.serve_forever)
+ thread.start()
+ client = httpbakery.Client()
+ with HTTMock(discharge):
+ with self.assertRaises(httpbakery.BakeryException) as ctx:
+ requests.get(
+ url='http://' + httpd.server_address[0] + ':' +
+ str(httpd.server_address[1]),
+ cookies=client.cookies,
+ auth=client.auth())
+ self.assertEqual(ctx.exception.args[0],
+ 'too many (3) discharge requests')
+ finally:
+ httpd.shutdown()
+
def test_too_many_discharge(self):
class _DischargerLocator(bakery.ThirdPartyLocator):
def __init__(self):
@@ -155,7 +213,7 @@ class TestClient(TestCase):
}
def handler(*args):
- GetHandler(b, 'http://1.2.3.4', None, None, None, *args)
+ GetHandler(b, 'http://1.2.3.4', None, None, None, AGES, *args)
try:
httpd = HTTPServer(('', 0), handler)
thread = threading.Thread(target=httpd.serve_forever)
@@ -199,7 +257,7 @@ class TestClient(TestCase):
ThirdPartyCaveatCheckerF(check))
def handler(*args):
- GetHandler(b, 'http://1.2.3.4', None, None, None, *args)
+ GetHandler(b, 'http://1.2.3.4', None, None, None, AGES, *args)
try:
httpd = HTTPServer(('', 0), handler)
thread = threading.Thread(target=httpd.serve_forever)
@@ -244,7 +302,7 @@ class TestClient(TestCase):
}
def handler(*args):
- GetHandler(b, 'http://1.2.3.4', None, None, None, *args)
+ GetHandler(b, 'http://1.2.3.4', None, None, None, AGES, *args)
try:
httpd = HTTPServer(('', 0), handler)
@@ -273,11 +331,34 @@ class TestClient(TestCase):
finally:
httpd.shutdown()
+ def test_extract_macaroons_from_request(self):
+ def encode_macaroon(m):
+ macaroons = '[' + utils.macaroon_to_json_string(m) + ']'
+ return base64.urlsafe_b64encode(utils.to_bytes(macaroons)).decode('ascii')
+
+ req = Request('http://example.com')
+ m1 = pymacaroons.Macaroon(version=pymacaroons.MACAROON_V2, identifier='one')
+ req.add_header('Macaroons', encode_macaroon(m1))
+ m2 = pymacaroons.Macaroon(version=pymacaroons.MACAROON_V2, identifier='two')
+ jar = requests.cookies.RequestsCookieJar()
+ jar.set_cookie(utils.cookie(
+ name='macaroon-auth',
+ value=encode_macaroon(m2),
+ url='http://example.com',
+ ))
+ jar.add_cookie_header(req)
+
+ macaroons = httpbakery.extract_macaroons(req)
+ self.assertEquals(len(macaroons), 2)
+ macaroons.sort(key=lambda ms: ms[0].identifier)
+ self.assertEquals(macaroons[0][0].identifier, m1.identifier)
+ self.assertEquals(macaroons[1][0].identifier, m2.identifier)
+
class GetHandler(BaseHTTPRequestHandler):
'''A mock HTTP server that serves a GET request'''
def __init__(self, bakery, auth_location, mutate_error,
- caveats, version, *args):
+ caveats, version, expiry, *args):
'''
@param bakery used to check incoming requests and macaroons
for discharge-required errors.
@@ -288,14 +369,17 @@ class GetHandler(BaseHTTPRequestHandler):
discharge-required error before responding to the client.
@param caveats called to get caveats to add to the returned
macaroon.
- @param holds the version of the bakery that the
+ @param version holds the version of the bakery that the
server will purport to serve.
+ @param expiry holds the expiry for the macaroon that will be created
+ in _write_discharge_error
'''
self._bakery = bakery
self._auth_location = auth_location
self._mutate_error = mutate_error
self._caveats = caveats
self._server_version = version
+ self._expiry = expiry
BaseHTTPRequestHandler.__init__(self, *args)
def do_GET(self):
@@ -333,7 +417,7 @@ class GetHandler(BaseHTTPRequestHandler):
caveats.extend(self._caveats)
m = self._bakery.oven.macaroon(
- version=bakery.LATEST_VERSION, expiry=AGES,
+ version=bakery.LATEST_VERSION, expiry=self._expiry,
caveats=caveats, ops=[TEST_OP])
content, headers = httpbakery.discharge_required_response(