def test_add(self, st): id = str(uuid.uuid4()) p = Policy( uid=id, description='foo bar баз', subjects=('Edward Rooney', 'Florence Sparrow'), actions=['好'], resources=['<.*>'], context={ 'secret': Equal('i-am-a-teacher'), 'rating': And(Eq(80), Greater(80)) }, ) st.add(p) back = st.get(id) assert id == back.uid assert 'foo bar баз' == back.description assert isinstance(back.context['secret'], Equal) assert isinstance(back.context['rating'], And) assert '好' == back.actions[0] st.add( Policy('2', actions=[Eq('get'), Eq('put')], subjects=[Any()], resources=[{ 'books': Eq('Harry') }])) assert '2' == st.get('2').uid assert 2 == len(st.get('2').actions) assert 1 == len(st.get('2').subjects) assert isinstance(st.get('2').subjects[0], Any) assert 1 == len(st.get('2').resources) assert isinstance(st.get('2').resources[0]['books'], Eq) assert 'Harry' == st.get('2').resources[0]['books'].val
def test_policy_type_on_attribute_change(): p = Policy(1, actions=['<foo.bar>'], resources=['asdf'], subjects=['<qwerty>']) assert TYPE_STRING_BASED == p.type p.effect = ALLOW_ACCESS assert TYPE_STRING_BASED == p.type with pytest.raises(PolicyCreationError): p.actions = [{'ip': CIDR('0.0.0.0')}] assert TYPE_STRING_BASED == p.type with pytest.raises(PolicyCreationError): p.subjects = [{'ip': CIDR('0.0.0.0')}] with pytest.raises(PolicyCreationError): p.actions = [Any()] assert TYPE_STRING_BASED == p.type p.actions = ['<.*>'] assert TYPE_STRING_BASED == p.type p.subjects = ['<.*>'] assert TYPE_STRING_BASED == p.type p.type = TYPE_RULE_BASED # explicit assign doesn't help assert TYPE_STRING_BASED == p.type # testing the from the opposite direction p = Policy(2, actions=[Any()], resources=[{ 'book': Eq('UX Manual') }], subjects=[Eq('Sally'), Eq('Bob')]) assert TYPE_RULE_BASED == p.type p.effect = ALLOW_ACCESS assert TYPE_RULE_BASED == p.type with pytest.raises(PolicyCreationError): p.actions = ['<foo.bar>'] assert TYPE_RULE_BASED == p.type with pytest.raises(PolicyCreationError): p.subjects = ['<foo.bar>', 'baz'] with pytest.raises(PolicyCreationError): p.actions = ['baz<.*>'] assert TYPE_RULE_BASED == p.type p.actions = [Any()] assert TYPE_RULE_BASED == p.type p.subjects = [Any()] assert TYPE_RULE_BASED == p.type p.type = TYPE_STRING_BASED # explicit assign doesn't help assert TYPE_RULE_BASED == p.type
def test_update(st): policy = Policy('1') st.add(policy) assert '1' == st.get('1').uid assert None is st.get('1').description policy.description = 'foo' st.update(policy) assert '1' == st.get('1').uid assert 'foo' == st.get('1').description p = Policy(2, actions=[Any()], subjects=[Eq('max'), Eq('bob')]) st.add(p) assert 2 == st.get(2).uid p.actions = [Eq('get')] st.update(p) assert 1 == len(st.get(2).actions) assert 'get' == st.get(2).actions[0].val
def test_add(st): st.add(Policy('1', description='foo')) assert '1' == st.get('1').uid assert 'foo' == st.get('1').description st.add( Policy('2', actions=[Eq('get'), Eq('put')], subjects=[Any()], resources=[{ 'books': Eq('Harry') }])) assert '2' == st.get('2').uid assert 2 == len(st.get('2').actions) assert 1 == len(st.get('2').subjects) assert isinstance(st.get('2').subjects[0], Any) assert 1 == len(st.get('2').resources) assert isinstance(st.get('2').resources[0]['books'], Eq) assert 'Harry' == st.get('2').resources[0]['books'].val
def test_update(self, st): id = str(uuid.uuid4()) policy = Policy(id) st.add(policy) assert id == st.get(id).uid assert None is st.get(id).description assert () == st.get(id).actions or [] == st.get(id).actions policy.description = 'foo' policy.actions = ['a', 'b', 'c'] st.update(policy) assert id == st.get(id).uid assert 'foo' == st.get(id).description assert ['a', 'b', 'c'] == st.get(id).actions p = Policy(2, actions=[Any()], subjects=[Eq('max'), Eq('bob')]) st.add(p) assert 2 == st.get(2).uid p.actions = [Eq('get')] st.update(p) assert 1 == len(st.get(2).actions) assert 'get' == st.get(2).actions[0].val
def test_update(self, st): # SQL storage stores all uids as string id = str(uuid.uuid4()) policy = Policy(id) st.add(policy) assert id == st.get(id).uid assert None is st.get(id).description assert [] == st.get(id).actions policy.description = 'foo' policy.actions = ['a', 'b', 'c'] st.update(policy) assert id == st.get(id).uid assert 'foo' == st.get(id).description assert ['a', 'b', 'c'] == st.get(id).actions p = Policy('2', actions=[Any()], subjects=[Eq('max'), Eq('bob')]) st.add(p) assert '2' == st.get('2').uid p.actions = [Eq('get')] st.update(p) assert 1 == len(st.get('2').actions) assert 'get' == st.get('2').actions[0].val
class BadMemoryStorage(MemoryStorage): def find_for_inquiry(self, inquiry=None, checker=None): raise Exception('This is test class that raises errors') g = Guard(BadMemoryStorage(), RegexChecker()) assert not g.is_allowed( Inquiry(subject='foo', action='bar', resource='baz')) @pytest.mark.parametrize('desc, policy, inquiry, result', [ ( 'match for non-attribute', Policy( uid=1, effect=ALLOW_ACCESS, subjects=[Any()], actions=[SubjectMatch()], resources=[Any()], ), Inquiry(subject='b', action='b', resource='a'), True, ), ( 'not match for non-attribute', Policy( uid=1, effect=ALLOW_ACCESS, subjects=[Any()], actions=[SubjectMatch()], resources=[Any()], ),
assert 'sub' in p1.context assert isinstance(p1.context['ip'], CIDR) assert isinstance(p1.context['sub'], Equal) assert p1.context['sub'].satisfied('baz') assert p1.context['ip'].satisfied('127.0.0.1') assert not hasattr(p1, 'rules') @pytest.mark.parametrize('policy', [ Policy(1, subjects=[{ 'name': Eq('Max'), 'rate': Greater(90) }], actions=[Eq('get'), Eq('post')], resources=[Any()]), Policy(2, subjects=[{ 'login': Eq('sally') }], actions=[Eq('get'), Eq('post')], context={'ip': Eq('127.0.0.1')}), Policy(3, subjects=[{ 'rating': AnyIn(1, 2) }], actions=[And(Eq('get'), Eq('post'))]), Policy(4, subjects=[{ 'rating': AnyIn(1, 2) }],
p = Policy('789', rules={'ip': CIDR('127.0.0.1'), 'sub': Equal('baz')}) s = p.to_json() p1 = Policy.from_json(s) assert '789' == p1.uid assert 2 == len(p1.context) assert 'ip' in p1.context assert 'sub' in p1.context assert isinstance(p1.context['ip'], CIDR) assert isinstance(p1.context['sub'], Equal) assert p1.context['sub'].satisfied('baz') assert p1.context['ip'].satisfied('127.0.0.1') assert not hasattr(p1, 'rules') @pytest.mark.parametrize('policy', [ Policy(1, subjects=[{'name': Eq('Max'), 'rate': Greater(90)}], actions=[Eq('get'), Eq('post')], resources=[Any()]), Policy(2, subjects=[{'login': Eq('sally')}], actions=[Eq('get'), Eq('post')], context={'ip': Eq('127.0.0.1')}), Policy(3, subjects=[{'rating': AnyIn(1, 2)}], actions=[And(Eq('get'), Eq('post'))]), Policy(4, subjects=[{'rating': AnyIn(1, 2)}], actions=[And(Eq('get'), Eq('post'))]), Policy(5, actions=[Eq('get')]), ]) def test_json_roundtrip_of_a_rules_based_policy(policy): pj = policy.to_json() p2 = Policy.from_json(pj) assert policy.to_json() == p2.to_json() @pytest.mark.parametrize('data, exception, msg', [ ('{}', PolicyCreationError, "'uid'"), ('{"uid":}', ValueError, ''), ('', ValueError, ''),
'action': NotEq('POST') }], resources=[{ 'endpoint': Eq('/metrics/cpu') }]), Inquiry(subject={'name': 'Sally'}, action={'action': 'GET'}, resource={'endpoint': '/metrics/cpu'}), RulesChecker(), True, ), ( 'RulesChecker: Should match since everything matches by Any condition', Policy(uid=1, effect=ALLOW_ACCESS, subjects=[Any()], actions=[Any()], resources=[Eq('/metrics/cpu'), Eq('/metrics/mem')]), Inquiry(subject='Sally', action='GET', resource='/metrics/cpu'), RulesChecker(), True, ), ( 'RulesChecker: Should match because of user\'s stars and correct book', Policy(uid=1, effect=ALLOW_ACCESS, subjects=[Eq('Admin'), { 'stars': Greater(50) }], actions=[Any()],