1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
# Copyright 2017 Canonical Ltd.
# Licensed under the LGPLv3, see LICENCE file for details.
from unittest import TestCase
import macaroonbakery.bakery as bakery
import macaroonbakery.checkers as checkers
class TestAuthorizer(TestCase):
def test_authorize_func(self):
def f(ctx, identity, op):
self.assertEqual(identity.id(), 'bob')
if op.entity == 'a':
return False, None
elif op.entity == 'b':
return True, None
elif op.entity == 'c':
return True, [checkers.Caveat(location='somewhere',
condition='c')]
elif op.entity == 'd':
return True, [checkers.Caveat(location='somewhere',
condition='d')]
else:
self.fail('unexpected entity: ' + op.Entity)
ops = [bakery.Op('a', 'x'), bakery.Op('b', 'x'),
bakery.Op('c', 'x'), bakery.Op('d', 'x')]
allowed, caveats = bakery.AuthorizerFunc(f).authorize(
checkers.AuthContext(),
bakery.SimpleIdentity('bob'),
ops
)
self.assertEqual(allowed, [False, True, True, True])
self.assertEqual(caveats, [
checkers.Caveat(location='somewhere', condition='c'),
checkers.Caveat(location='somewhere', condition='d')
])
def test_acl_authorizer(self):
ctx = checkers.AuthContext()
tests = [
('no ops, no problem',
bakery.ACLAuthorizer(allow_public=True, get_acl=lambda x, y: []),
None,
[],
[]),
('identity that does not implement ACLIdentity; '
'user should be denied except for everyone group',
bakery.ACLAuthorizer(
allow_public=True,
get_acl=lambda ctx, op: [bakery.EVERYONE] if op.entity == 'a' else ['alice'],
),
SimplestIdentity('bob'),
[bakery.Op(entity='a', action='a'),
bakery.Op(entity='b', action='b')],
[True, False]),
('identity that does not implement ACLIdentity with user == Id; '
'user should be denied except for everyone group',
bakery.ACLAuthorizer(
allow_public=True,
get_acl=lambda ctx, op: [bakery.EVERYONE] if op.entity == 'a' else ['bob'],
),
SimplestIdentity('bob'),
[bakery.Op(entity='a', action='a'),
bakery.Op(entity='b', action='b')],
[True, False]),
('permission denied for everyone without AllowPublic',
bakery.ACLAuthorizer(
allow_public=False,
get_acl=lambda x, y: [bakery.EVERYONE],
),
SimplestIdentity('bob'),
[bakery.Op(entity='a', action='a')],
[False]),
('permission granted to anyone with no identity with AllowPublic',
bakery.ACLAuthorizer(
allow_public=True,
get_acl=lambda x, y: [bakery.EVERYONE],
),
None,
[bakery.Op(entity='a', action='a')],
[True])
]
for test in tests:
allowed, caveats = test[1].authorize(ctx, test[2], test[3])
self.assertEqual(len(caveats), 0)
self.assertEqual(allowed, test[4])
def test_context_wired_properly(self):
ctx = checkers.AuthContext({'a': 'aval'})
class Visited:
in_f = False
in_allow = False
in_get_acl = False
def f(ctx, identity, op):
self.assertEqual(ctx.get('a'), 'aval')
Visited.in_f = True
return False, None
bakery.AuthorizerFunc(f).authorize(
ctx, bakery.SimpleIdentity('bob'), ['op1']
)
self.assertTrue(Visited.in_f)
class TestIdentity(SimplestIdentity, bakery.ACLIdentity):
def allow(other, ctx, acls):
self.assertEqual(ctx.get('a'), 'aval')
Visited.in_allow = True
return False
def get_acl(ctx, acl):
self.assertEqual(ctx.get('a'), 'aval')
Visited.in_get_acl = True
return []
bakery.ACLAuthorizer(
allow_public=False,
get_acl=get_acl,
).authorize(ctx, TestIdentity('bob'), ['op1'])
self.assertTrue(Visited.in_get_acl)
self.assertTrue(Visited.in_allow)
class SimplestIdentity(bakery.Identity):
# SimplestIdentity implements Identity for a string. Unlike
# SimpleIdentity, it does not implement ACLIdentity.
def __init__(self, user):
self._identity = user
def domain(self):
return ''
def id(self):
return self._identity
|