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
|