Exemplo n.º 1
0
def forwards_func(apps, schema_editor):
    # add AuthzAction
    AuthzAction = apps.get_model('noclook', 'AuthzAction')
    list_aa, created = AuthzAction.objects.get_or_create(name="list")

    # get storage and guard
    storage, guard = sriutils.get_vakt_storage_and_guard()
    Context = apps.get_model('noclook', 'Context')
    DjPolicy = apps.get_model('djangovakt', 'Policy')

    # iterate over all the existent contexts to add
    # a list policy for each of them
    all_contexts = Context.objects.all()

    for context in all_contexts:
        # check if the policy exist first
        qs = DjPolicy.objects.filter(doc__actions__0__val=list_aa.name)
        qs = qs.filter(doc__context__module__elem__in=(context.name,))

        if not qs.exists():
            policy = Policy(
                uuid.uuid4(),
                actions=[vakt_rules.Eq(list_aa.name)],
                resources=[vakt_rules.Any()],
                subjects=[srirules.HasAuthAction(list_aa, context)],
                context={ 'module': srirules.ContainsElement(context.name) },
                effect=ALLOW_ACCESS,
                description='Automatically created policy'
            )
            storage.add(policy)
Exemplo n.º 2
0
def forwards_func(apps, schema_editor):
    # get storage and guard
    storage, guard = sriutils.get_vakt_storage_and_guard()

    # create policies using storage instead
    Context = apps.get_model('noclook', 'Context')
    AuthzAction = apps.get_model('noclook', 'AuthzAction')

    # iterate over all existent contexts and authzactions
    # and create policies for each of them
    all_contexts = Context.objects.all()
    rw_authzactions = AuthzAction.objects.filter(name__in=(
        sriutils.READ_AA_NAME,
        sriutils.WRITE_AA_NAME,
    ))

    # add read and write policies
    for context in all_contexts:
        for authzaction in rw_authzactions:
            policy = Policy(
                uuid.uuid4(),
                actions=[vakt_rules.Eq(authzaction.name)],
                resources=[srirules.BelongsContext(context)],
                subjects=[srirules.HasAuthAction(authzaction, context)],
                context={'module': srirules.ContainsElement(context.name)},
                effect=ALLOW_ACCESS,
                description='Automatically created policy')
            storage.add(policy)

    # add admin policies
    admin_aa = AuthzAction.objects.get(name=sriutils.ADMIN_AA_NAME)
    for context in all_contexts:
        policy = Policy(
            uuid.uuid4(),
            actions=[vakt_rules.Eq(admin_aa.name)],
            resources=[vakt_rules.Any()],
            subjects=[srirules.HasAuthAction(admin_aa, context)],
            context={'module': srirules.ContainsElement(context.name)},
            effect=ALLOW_ACCESS,
            description='Automatically created policy')
        storage.add(policy)
Exemplo n.º 3
0
    def test_crud(self):
        for dbpolicy in self.storage.get_all():
            self.storage.delete(dbpolicy.uid)

        # create policies
        self.policy1 = Policy(
            uuid.uuid4(),
            actions=[vrules.In('get', 'list', 'read')],
            resources=[vrules.StartsWith('repos/google/tensor')],
            subjects=[{
                'name': vrules.Any(),
                'role': vrules.Any()
            }],
            context={'module': vrules.Eq('Test')},
            effect=ALLOW_ACCESS,
            description=
            'Grant read-access for all Google repositories starting with "tensor" to any User'
        )

        self.policy2 = Policy(
            uuid.uuid4(),
            actions=[vrules.In('delete', 'prune', 'exterminate')],
            resources=[vrules.StartsWith('repos/')],
            subjects=[{
                'name': vrules.Any(),
                'role': vrules.Eq('admin')
            }],
            context={'module': vrules.Eq('Test')},
            effect=ALLOW_ACCESS,
            description='Grant admin access')

        ## Create (add)
        self.storage.add(self.policy1)

        # try to add it again, it should raise a exception
        try:
            self.storage.add(self.policy1)
            raise Exception(
                "The DjangoStorage should't store a policy more than once")
        except PolicyExistsError:
            pass

        ## Read
        # get
        test_policy = self.storage.get(self.policy1.uid)
        assert test_policy, "The storage doesn't return a policy from get"
        assert self.policy1.uid == test_policy.uid, "These policies must be equal"

        must_be_none = self.storage.get(self.policy2.uid)
        assert not must_be_none, "This policy shouldn't exists"

        # get all
        self.storage.add(self.policy2)
        test_policies = self.storage.get_all()

        assert test_policies, "This should return a policies list"
        assert test_policies[0].uid == self.policy1.uid \
            and test_policies[1].uid == self.policy2.uid,\
            "The returned list should match"

        ## Update
        policy1b = Policy(self.policy1.uid,
                          actions=[vrules.In('get', 'list')],
                          resources=[{
                              'category': vrules.Eq('administration'),
                              'sub': vrules.In('panel', 'switch')
                          }],
                          subjects=[{
                              'name': vrules.Any(),
                              'role': vrules.NotEq('developer')
                          }],
                          effect=ALLOW_ACCESS,
                          context={'module': vrules.Eq('Test')},
                          description="""
            Allow access to administration interface subcategories: 'panel', 'switch' if user is not
            a developer and came from local IP address.
            """)
        self.storage.update(policy1b)
        test_policy = self.storage.get(self.policy1.uid)
        assert self.policy1.uid == test_policy.uid and\
            test_policy.to_json() == policy1b.to_json(),\
            "The test policy values doesn't match with the updated version"

        ## Delete
        self.storage.delete(self.policy2.uid)
        test_policies = self.storage.get_all()

        test_none = self.storage.get(self.policy2.uid)
        assert not test_none, "This policy shouldn't be stored as it has been deleted"

        assert len(test_policies) == 1 and test_policies[0].uid == self.policy1.uid, \
            "The returned list should match"

        ## Find for inquiry
        # check a matching policy
        inquiry1 = Inquiry(action='get',
                           resource='repos/google/tensorflow',
                           subject={
                               'name': 'Jane',
                               'role': 'admin'
                           },
                           context={'module': 'Test'})
        matching_policies = self.storage.find_for_inquiry(
            inquiry1, self.guard.checker)
        assert matching_policies, "The matching policies list should not be empty"

        # check it doesn't match and inquiry
        inquiry2 = Inquiry(action='delete',
                           resource='repos/google/tensorflow',
                           subject={
                               'name': 'Max',
                               'role': 'developer'
                           },
                           context={'module': 'Test'})
        matching_policies = self.storage.find_for_inquiry(
            inquiry2, self.guard.checker)
        assert not matching_policies, "The matching policies list should be empty"
Exemplo n.º 4
0
    def test_rulechecker(self):
        # ensure empty policy set
        for dbpolicy in self.storage.get_all():
            self.storage.delete(dbpolicy.uid)

        # add policies
        policy1 = Policy(
            uuid.uuid4(),
            actions=[vrules.Eq('read')],
            resources=[vrules.StartsWith('forum/')],
            subjects=[{
                'group': vrules.In('can_read', 'can_write', 'can_admin')
            }],
            context={'module': vrules.Eq('forum')},
            effect=ALLOW_ACCESS,
            description=
            'Grant read-access to the forum section to users with a certain profile'
        )

        policy2 = Policy(
            uuid.uuid4(),
            actions=[vrules.Eq('write')],
            resources=[vrules.StartsWith('forum/')],
            subjects=[{
                'group': vrules.In('can_write', 'can_admin')
            }],
            context={'module': vrules.Eq('forum')},
            effect=ALLOW_ACCESS,
            description=
            'Grant write-access to the forum section to users with a certain profile'
        )

        policy3 = Policy(
            uuid.uuid4(),
            actions=[vrules.Eq('admin')],
            resources=[vrules.StartsWith('forum/')],
            subjects=[{
                'group': vrules.In('can_admin')
            }],
            context={'module': vrules.Eq('forum')},
            effect=ALLOW_ACCESS,
            description=
            'Grant admin-access to the forum section to users with a certain profile'
        )

        policy4 = Policy(
            uuid.uuid4(),
            actions=[vrules.Any()],
            resources=[vrules.StartsWith('forum/')],
            subjects=[{
                'group':
                vrules.NotIn('can_read', 'can_write', 'can_admin')
            }],
            context={'module': vrules.Eq('forum')},
            effect=DENY_ACCESS,
            description='Deny access to any user without a group defined')

        self.storage.add(policy1)
        self.storage.add(policy2)
        self.storage.add(policy3)
        self.storage.add(policy4)

        # forge successful inquiry for 1st policy
        inqu1_ok = Inquiry(action='read',
                           resource='forum/users/list',
                           subject={
                               'name': 'Jane',
                               'group': 'can_read'
                           },
                           context={'module': 'forum'})

        assert self.guard.is_allowed(
            inqu1_ok), "This inquiry should be allowed"

        inq1_ko = Inquiry(action='read',
                          resource='forum/users/list',
                          subject={
                              'name': 'James',
                              'group': 'new_users'
                          },
                          context={'module': 'forum'})

        assert not self.guard.is_allowed(
            inq1_ko), "This inquiry should be denied"
Exemplo n.º 5
0
    def create_policy(self, req, internal=False):
        # '''Creates a policy based on the JSON-type request body and stores it onto the PRP.'''
        if internal:
            req_json = req
        else:
            if not req.data:
                return False, "ERROR: request body is empty"

                # load JSON body
            try:
                req_json = req.json
            except:
                return False, "ERROR: malformed JSON - syntax error"

        try:
            ####
            # 'subjects' is mandatory and has to be a list of key-value subject definitions
            ####
            if type(req_json['subjects']) is not list:
                return False, "ERROR: malformed access JSON - 'subjects' must be a list."

            subject = []

            for s in req_json['subjects']:
                sub = {}
                for k in s:
                    if k in ['admin', 'student', 'teacher']:
                        sub.update({
                            k: (rules.Truthy()
                                if s[k].lower() == 'true' else rules.Falsy())
                        })
                    elif k in ['student_courses', 'teacher_courses']:
                        sub.update({k: rules.AnyIn(*s[k])})
                    else:
                        sub.update({k: rules.string.Equal(s[k])})

                    if 'admin' not in sub:
                        sub.update({'admin': rules.Falsy()})

                subject.append(sub)

            if not subject:
                return False, "ERROR: malformed access JSON - 'subjects' doesn't have attributes defined."
            ####
            # 'actions' value has to be a json list, although not mandatory
            ####

            action = [rules.Any()]
            if 'actions' in req_json:
                if type(req_json['actions']) is not list:
                    return False, "ERROR: malformed access JSON - 'actions' must be a list."

                action = [rules.string.Equal(a) for a in req_json['actions']]

            ####
            # 'resource' is not mandatory, defaults to any element
            ####
            resource = []
            if 'resources' in req_json:
                if type(req_json['resources']) is not list:
                    return False, "ERROR: malformed access JSON - 'actions' must be a list."
                for s in req_json['resources']:
                    elem_res = {}
                    for k in s:
                        elem_res[k] = rules.string.Equal(s[k])

                    #resource = [{k : rules.string.Equal(s[k])} for s in req_json['resources']]
                    resource.append(elem_res)

            if not resource:
                resource = [rules.Any()]

            ####
            # 'context' is not mandatory, defaults to empty
            ####
            context = {}
            if 'context' in req_json:
                for k in req_json['context']:
                    if k == 'hour':
                        if 'from' in req_json['context'][
                                'hour'] and 'to' in req_json['context']['hour']:
                            context['hour'] = rules.And(
                                rules.GreaterOrEqual(
                                    ABAC.daytime_in_s(time=req_json['context']
                                                      ['hour']['from'])),
                                rules.LessOrEqual(
                                    ABAC.daytime_in_s(time=req_json['context']
                                                      ['hour']['to'])))
                        else:
                            return False, "ERROR: Malformed access JSON - context's hours needs 'from' and 'to' attributes!"
                    elif k == 'date':
                        if 'from' in req_json['context'][
                                'date'] and 'to' in req_json['context']['date']:
                            context['date'] = rules.And(
                                rules.GreaterOrEqual(
                                    ABAC.unix_timestamp(
                                        req_json['context']['date']['from'])),
                                rules.LessOrEqual(
                                    ABAC.unix_timestamp(
                                        req_json['context']['date']['to'])))
                        elif 'from' in req_json['context']['date']:
                            context['date'] = rules.GreaterOrEqual(
                                ABAC.unix_timestamp(
                                    req_json['context']['date']['from']))
                        elif 'to' in req_json['context']['date']:
                            context['date'] = rules.LessOrEqual(
                                ABAC.unix_timestamp(
                                    req_json['context']['date']['to']))
                        else:
                            return False, "ERROR: Malformed access JSON - context's date needs 'from' and 'to' attributes!"
                    elif k == 'ip':
                        internal_rule = rules.Or(rules.CIDR('10.0.0.0/8'),
                                                 rules.CIDR('172.16.0.0/12'),
                                                 rules.CIDR('192.168.0.0/16'))
                        if req_json['context']['ip'].lower() == "internal":
                            context['ip'] = internal_rule
                        else:
                            context['ip'] = rules.Any()
                    else:
                        context[k] = rules.string.Equal(req_json['context'][k])
            ####
            # 'description is not mandatory, defaults to None
            ####
            description = None
            if 'description' in req_json:
                description = req_json['description']

            ####
            # 'effect' is not mandatory, defaults to allow
            ####
            effect = ALLOW_ACCESS  # default effect - not needed in JSON
            if 'effect' in req_json:
                effect = ALLOW_ACCESS if 'allow' in req_json['effect'].lower(
                ) else DENY_ACCESS

        except KeyError as e:
            return False, f"ERROR: malformed policy JSON - invalid '{str(e)}' key."

        # add uid to JSON
        uid = str(uuid4())
        req_json.update({'uid': uid})

        self._raw_policy_collection.insert_one(req_json)
        self._storage.add(
            Policy(uid,
                   subjects=subject,
                   effect=effect,
                   resources=resource,
                   actions=action,
                   context=context,
                   description=description))

        return True, "OK"