Beispiel #1
0
    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))
Beispiel #2
0
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()
Beispiel #3
0
 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()
Beispiel #4
0
 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
Beispiel #5
0
    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()
Beispiel #6
0
 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()
Beispiel #7
0
 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
Beispiel #8
0
    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())
Beispiel #9
0
 def setUp(self):
     self.storage = DjangoStorage()
     self.guard = Guard(self.storage, RulesChecker())
     self.storage.delete_all()
Beispiel #10
0
def get_checker():
    if ARGS.checker == 'rules':
        return RulesChecker()
    return RegexChecker(ARGS.cache) if ARGS.cache else RegexChecker()
Beispiel #11
0
    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
Beispiel #12
0
def get_vakt_storage_and_guard():
    storage = DjangoStorage()
    guard = Guard(storage, RulesChecker())

    return storage, guard