Better handle policy timeouts

This commit is contained in:
Jens Langhammer 2019-03-21 14:53:57 +01:00
parent 5b8e3689ec
commit 6be8d0cbb2
1 changed files with 18 additions and 4 deletions

View File

@ -1,7 +1,9 @@
"""passbook core policy engine""" """passbook core policy engine"""
from logging import getLogger from logging import getLogger
from amqp.exceptions import UnexpectedFrame
from celery import group from celery import group
from celery.exceptions import TimeoutError as CeleryTimeoutError
from ipware import get_client_ip from ipware import get_client_ip
from passbook.core.celery import CELERY_APP from passbook.core.celery import CELERY_APP
@ -38,6 +40,7 @@ class PolicyEngine:
_group = None _group = None
_request = None _request = None
_user = None _user = None
_get_timeout = 0
def __init__(self, policies): def __init__(self, policies):
self.policies = policies self.policies = policies
@ -67,7 +70,14 @@ class PolicyEngine:
if not kwargs['remote_ip']: if not kwargs['remote_ip']:
kwargs['remote_ip'] = '255.255.255.255' kwargs['remote_ip'] = '255.255.255.255'
for policy in self.policies: for policy in self.policies:
signatures.append(_policy_engine_task.s(self._user.pk, policy.pk.hex, **kwargs)) signatures.append(_policy_engine_task.signature(
args=(self._user.pk, policy.pk.hex),
kwargs=kwargs,
time_limit=policy.timeout))
self._get_timeout += policy.timeout
self._get_timeout += 3
self._get_timeout = (self._get_timeout / len(self.policies)) * 1.5
LOGGER.debug("Set total policy timeout to %r", self._get_timeout)
self._group = group(signatures)() self._group = group(signatures)()
return self return self
@ -76,10 +86,14 @@ class PolicyEngine:
"""Get policy-checking result""" """Get policy-checking result"""
messages = [] messages = []
try: try:
# ValueError can be thrown from _policy_engine_task when user is None group_result = self._group.get(timeout=self._get_timeout)
group_result = self._group.get()
except ValueError as exc: except ValueError as exc:
return False, str(exc) # ValueError can be thrown from _policy_engine_task when user is None
return False, [str(exc)]
except UnexpectedFrame as exc:
return False, [str(exc)]
except CeleryTimeoutError as exc:
return False, [str(exc)]
for policy_action, policy_result, policy_message in group_result: for policy_action, policy_result, policy_message in group_result:
passing = (policy_action == Policy.ACTION_ALLOW and policy_result) or \ passing = (policy_action == Policy.ACTION_ALLOW and policy_result) or \
(policy_action == Policy.ACTION_DENY and not policy_result) (policy_action == Policy.ACTION_DENY and not policy_result)