def get_access(self, struct_inquiry): '''Inquires about an access request given an attribute dictionary.''' if not struct_inquiry: return False g = Guard(self._storage, RulesChecker()) return g.is_allowed(Inquiry.from_json(struct_inquiry))
def get_checker(): if ARGS.checker == 'rules': return RulesChecker() elif ARGS.checker == 'exact': return StringExactChecker() elif ARGS.checker == 'fuzzy': return StringFuzzyChecker() return RegexChecker(ARGS.cache) if ARGS.cache else RegexChecker()
def test_general_flow(self, log_mock): cache_storage = MemoryStorage() back_storage = MemoryStorage() inq = Inquiry(action='get') chk1 = RulesChecker() p1 = Policy(1, description='initial') p2 = Policy(2, description='initial') p3 = Policy(3, description='added later') # initialize backend storage back_storage.add(p1) back_storage.add(p2) # create enfold-cache but do not populate it ec = EnfoldCache(back_storage, cache=cache_storage, populate=False) # make sure policies are returned from the backend assert [p1, p2] == list(ec.find_for_inquiry(inquiry=inq, checker=chk1)) # make sure we logged warning about cache miss log_mock.warning.assert_called_with( '%s cache miss for find_for_inquiry. Trying it from backend storage', 'EnfoldCache') log_mock.reset_mock() # populate cache with backend policies so that we do not make cache hit misses ec.populate() # make sure policies are returned assert [p1, p2] == list(ec.find_for_inquiry(inquiry=inq, checker=chk1)) # make sure we do not have cache misses assert 0 == log_mock.warning.call_count log_mock.reset_mock() # let's add a new policy via enfold-cache ec.add(p3) # make sure policies are returned assert [p1, p2, p3] == list(ec.find_for_inquiry(inquiry=inq, checker=chk1)) # make sure we do not have cache misses assert 0 == log_mock.warning.call_count log_mock.reset_mock() # make sure we have those policies in the backend-storage assert [p1, p2, p3] == list( back_storage.find_for_inquiry(inquiry=inq, checker=chk1)) # make sure we have those policies in the cache-storage assert [p1, p2, p3] == list( cache_storage.find_for_inquiry(inquiry=inq, checker=chk1)) # ----------------------- # ----------------------- # ----------------------- # let's re-create enfold cache. This time with initial population cache_storage2 = MemoryStorage() ec2 = EnfoldCache(back_storage, cache=cache_storage2, populate=True) # make sure we have all policies in the cache-storage assert [p1, p2, p3] == list( cache_storage2.find_for_inquiry(inquiry=inq, checker=chk1)) # make sure policies are returned by find_for_inquiry assert [p1, p2, p3] == list(ec2.find_for_inquiry(inquiry=inq, checker=chk1)) # make sure we do not have cache misses assert 0 == log_mock.warning.call_count log_mock.reset_mock()
def test_find_for_inquiry_for_populated_cache(self, log_mock): cache_storage = MemoryStorage() back_storage = MemoryStorage() inq = Inquiry(action='get') chk1 = RulesChecker() p1 = Policy(1, description='foo') p2 = Policy(2, description='bar') cache_storage.add(p1) cache_storage.add(p2) ec = EnfoldCache(back_storage, cache=cache_storage, populate=True) # Make first request assert [p1, p2] == list(ec.find_for_inquiry(inquiry=inq, checker=chk1)) assert 0 == log_mock.warning.call_count log_mock.reset_mock() # Make second request assert [p1, p2] == list(ec.find_for_inquiry(inquiry=inq, checker=chk1)) assert 0 == log_mock.warning.call_count
def test_cache_is_invalidated_on_policy_change(self): def assert_after_modification(): assert 0 == cache.info().hits assert 0 == cache.info().misses assert 0 == cache.info().currsize assert not guard.is_allowed(inq1) assert not guard.is_allowed(inq1) assert guard.is_allowed(inq2) assert guard.is_allowed(inq2) assert guard.is_allowed(inq2) assert 3 == cache.info().hits assert 2 == cache.info().misses assert 2 == cache.info().currsize inq1 = Inquiry(action='get', resource='book', subject='Max') inq2 = Inquiry(action='get', resource='book', subject='Jim') guard, storage, cache = create_cached_guard(MemoryStorage(), RulesChecker(), maxsize=256) p1 = Policy(1, actions=[Eq('get')], resources=[Eq('book')], subjects=[Eq('Max')], effect=ALLOW_ACCESS) p2 = Policy(2, actions=[Eq('get')], resources=[Eq('magazine')], subjects=[Eq('Max')], effect=ALLOW_ACCESS) storage.add(p1) assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert 1 == cache.info().hits assert 1 == cache.info().misses assert 1 == cache.info().currsize # start modifications p1.subjects = [Eq('Jim')] storage.update(p1) assert_after_modification() storage.add(p2) assert_after_modification() storage.delete(p2) assert_after_modification()
def test_find_for_inquiry_for_non_populated_cache(self, log_mock): cache_storage = MemoryStorage() back_storage = MemoryStorage() inq = Inquiry(action='get') chk1 = RulesChecker() p1 = Policy(1, description='foo') p2 = Policy(2, description='bar') back_storage.add(p1) back_storage.add(p2) ec = EnfoldCache(back_storage, cache=cache_storage, populate=False) # Make first request assert [p1, p2] == list(ec.find_for_inquiry(inquiry=inq, checker=chk1)) log_mock.warning.assert_called_with( '%s cache miss for find_for_inquiry. Trying it from backend storage', 'EnfoldCache') log_mock.reset_mock() # Make second request assert [p1, p2] == list(ec.find_for_inquiry(inquiry=inq, checker=chk1)) assert 1 == log_mock.warning.call_count log_mock.reset_mock()
def test_same_inquiries_are_cached(self): guard, storage, cache = create_cached_guard(MemoryStorage(), RulesChecker(), maxsize=256) p1 = Policy(1, actions=[Eq('get')], resources=[Eq('book')], subjects=[Eq('Max')], effect=ALLOW_ACCESS) storage.add(p1) inq1 = Inquiry(action='get', resource='book', subject='Max') inq2 = Inquiry(action='get', resource='book', subject='Jamey') assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert guard.is_allowed(inq1) assert not guard.is_allowed(inq2) assert 4 == cache.info().hits assert 2 == cache.info().misses assert 2 == cache.info().currsize
def __init__(self, auto=None): self._storage = MemoryStorage() if auto: self._from_file(auto) self.add_policy( ied=Any(), action=[Eq('publish'), Eq('subscribe')], address={'mac': Not(StartsWith('01:0c:cd:01'))}, protocol=Eq('GOOSE'), access=DENY_ACCESS) self.add_policy( ied=Any(), action=[Eq('publish'), Eq('subscribe')], address={'mac': Not(StartsWith('01:0c:cd:04'))}, protocol=Eq('SV'), access=DENY_ACCESS) self._guard = Guard(self._storage, RulesChecker())
def setUp(self): self.storage = DjangoStorage() self.guard = Guard(self.storage, RulesChecker()) self.storage.delete_all()
def get_checker(): if ARGS.checker == 'rules': return RulesChecker() return RegexChecker(ARGS.cache) if ARGS.cache else RegexChecker()
def get_http_req_access(self, req, subject_data, opt_resource=None): """ Transforms an HTTP request (req) and retrieves subject data in a PDP request. Evaluates if the user/subject given has access given its current attributes. Returs result as a boolean. """ if not subject_data: return False subject_data.update( {'admin': self._pgdb.isAdmin(subject_data['iupi'])}) resource_path = req.path.split("/") resource = {} if resource_path[1] in ['rooms', 'types', 'sensors']: resource.update(opt_resource) if opt_resource and 'sensor' in opt_resource: sensor_type = str( self._pgdb.getSensorTypeID(opt_resource['sensor'])) try: sensor_roomid = (self._pgdb.getSensor( opt_resource['sensor']))['room_id'] resource.update({ 'type': sensor_type, 'room': sensor_roomid }) except TypeError: resource.update({'type': sensor_type}) elif resource_path[1] == 'type': # get/modify/delete type if len(resource_path) >= 3: resource.update({resource_path[1]: resource_path[2]}) if len(resource_path) > 3: # it's a sensor of a type if opt_resource: resource.update(opt_resource) sensor_type = str( self._pgdb.getSensorTypeID(opt_resource['sensor'])) resource.update({'type': sensor_type}) # create type elif opt_resource: resource.update(opt_resource) elif resource_path[1] == 'room': # it's a get/modify/delete on a specific room if len(resource_path) >= 3: resource.update({resource_path[1]: resource_path[2]}) # it's a sensor on a room (list get) if len(resource_path) > 3: # get its sensors if resource_path[3] == "sensors": if opt_resource: resource.update(opt_resource) sensor_type = str( self._pgdb.getSensorTypeID(opt_resource['sensor'])) resource.update({'type': sensor_type}) elif resource_path[3] == "types": # it's a type on a room (list get) if opt_resource: resource.update(opt_resource) elif len(resource_path) == 3: if opt_resource: resource.update(opt_resource) sensor_type = str( self._pgdb.getSensorTypeID(opt_resource['sensor'])) resource.update({'type': sensor_type}) elif opt_resource: # it's an update or delete resource.update(opt_resource) elif resource_path[1] == 'sensor': if len(resource_path) < 3: # create sensor if opt_resource: resource.update(opt_resource) else: # get the respective sensor's room and type attributes alongside its id (for any action) sensor_type = str(self._pgdb.getSensorTypeID(resource_path[2])) try: sensor_roomid = (self._pgdb.getSensor( resource_path[2]))['room_id'] resource.update({ resource_path[1]: resource_path[2], 'type': sensor_type, 'room': sensor_roomid }) except TypeError: resource.update({ resource_path[1]: resource_path[2], 'type': sensor_type }) # request a value from a sensor if len(resource_path) > 3 and resource_path[3] == 'measure': resource.update({resource_path[3]: resource_path[4]}) current_date = arrow.utcnow() time = current_date.strftime("%H:%M:%S") day = current_date.strftime("%Y-%m-%dT%H:%M:%SZ") inq = Inquiry( subject=subject_data, action=req.method, resource=resource, #context={'hour': ABAC.daytime_in_s(time), 'date': ABAC.unix_timestamp(day)} context={ 'ip': req.headers['X-Forwarded-For'].split(',')[0].strip(), 'hour': ABAC.daytime_in_s(time), 'date': ABAC.unix_timestamp(day) }) print(inq.to_json()) g = Guard(self._storage, RulesChecker()) res = g.is_allowed(inq) print(res) return res
def get_vakt_storage_and_guard(): storage = DjangoStorage() guard = Guard(storage, RulesChecker()) return storage, guard