policy(minor): improve loading of policy subclasses

This commit is contained in:
Langhammer, Jens 2019-10-04 10:22:06 +02:00
parent 0b86231a36
commit afca94ceb8
2 changed files with 18 additions and 13 deletions

View File

@ -8,8 +8,8 @@ from django.http import HttpRequest
from structlog import get_logger from structlog import get_logger
from passbook.core.models import Policy, User from passbook.core.models import Policy, User
from passbook.policy.struct import PolicyRequest, PolicyResult from passbook.policy.struct import PolicyRequest
from passbook.policy.task import PolicyTask from passbook.policy.process import PolicyProcess
LOGGER = get_logger() LOGGER = get_logger()
@ -23,7 +23,7 @@ class PolicyEngine:
__request: HttpRequest __request: HttpRequest
__user: User __user: User
__proc_list: List[Tuple[Connection, PolicyTask]] = [] __proc_list: List[Tuple[Connection, PolicyProcess]] = []
def __init__(self, policies, user: User = None, request: HttpRequest = None): def __init__(self, policies, user: User = None, request: HttpRequest = None):
self.policies = policies self.policies = policies
@ -40,6 +40,13 @@ class PolicyEngine:
self.__request = request self.__request = request
return self return self
def _select_subclasses(self) -> List[Policy]:
"""Make sure all Policies are their respective classes"""
return Policy.objects \
.filter(pk__in=[x.pk for x in self.policies]) \
.select_subclasses() \
.order_by('order')
def build(self) -> 'PolicyEngine': def build(self) -> 'PolicyEngine':
"""Build task group""" """Build task group"""
if not self.__user: if not self.__user:
@ -47,18 +54,15 @@ class PolicyEngine:
cached_policies = [] cached_policies = []
request = PolicyRequest(self.__user) request = PolicyRequest(self.__user)
request.http_request = self.__request request.http_request = self.__request
for policy in self.policies: for policy in self._select_subclasses():
cached_policy = cache.get(_cache_key(policy, self.__user), None) cached_policy = cache.get(_cache_key(policy, self.__user), None)
if cached_policy: if cached_policy:
LOGGER.debug("Taking result from cache", policy=policy.pk.hex) LOGGER.debug("Taking result from cache", policy=policy.pk.hex)
cached_policies.append(cached_policy) cached_policies.append(cached_policy)
else: else:
LOGGER.debug("Looking up real class of policy...")
# TODO: Rewrite this to lookup all policies at once
policy = Policy.objects.get_subclass(pk=policy.pk)
LOGGER.debug("Evaluating policy", policy=policy.pk.hex) LOGGER.debug("Evaluating policy", policy=policy.pk.hex)
our_end, task_end = Pipe(False) our_end, task_end = Pipe(False)
task = PolicyTask() task = PolicyProcess()
task.ret = task_end task.ret = task_end
task.request = request task.request = request
task.policy = policy task.policy = policy

View File

@ -8,13 +8,13 @@ from passbook.core.models import Policy
from passbook.policy.exceptions import PolicyException from passbook.policy.exceptions import PolicyException
from passbook.policy.struct import PolicyRequest, PolicyResult from passbook.policy.struct import PolicyRequest, PolicyResult
LOGGER = get_logger(__name__) LOGGER = get_logger()
def _cache_key(policy, user): def _cache_key(policy, user):
return "policy_%s#%s" % (policy.uuid, user.pk) return "policy_%s#%s" % (policy.uuid, user.pk)
class PolicyTask(Process): class PolicyProcess(Process):
"""Evaluate a single policy within a seprate process""" """Evaluate a single policy within a seprate process"""
ret: Connection ret: Connection
@ -23,8 +23,8 @@ class PolicyTask(Process):
def run(self): def run(self):
"""Task wrapper to run policy checking""" """Task wrapper to run policy checking"""
LOGGER.debug("Running policy `%s`#%s for user %s...", self.policy.name, LOGGER.debug("Running policy", policy=self.policy,
self.policy.pk.hex, self.request.user) user=self.request.user, process="PolicyProcess")
try: try:
policy_result = self.policy.passes(self.request) policy_result = self.policy.passes(self.request)
except PolicyException as exc: except PolicyException as exc:
@ -33,7 +33,8 @@ class PolicyTask(Process):
# Invert result if policy.negate is set # Invert result if policy.negate is set
if self.policy.negate: if self.policy.negate:
policy_result = not policy_result policy_result = not policy_result
LOGGER.debug("Policy %r#%s got %s", self.policy.name, self.policy.pk.hex, policy_result) LOGGER.debug("Got result", policy=self.policy, result=policy_result,
process="PolicyProcess")
# cache_key = _cache_key(self.policy, self.request.user) # cache_key = _cache_key(self.policy, self.request.user)
# cache.set(cache_key, (self.policy.action, policy_result, message)) # cache.set(cache_key, (self.policy.action, policy_result, message))
# LOGGER.debug("Cached entry as %s", cache_key) # LOGGER.debug("Cached entry as %s", cache_key)