authentik/passbook/policies/process.py

79 lines
2.5 KiB
Python
Raw Normal View History

"""passbook policy task"""
from multiprocessing import Process
from multiprocessing.connection import Connection
2020-05-09 19:54:11 +01:00
from typing import Optional
2019-10-07 15:33:48 +01:00
from django.core.cache import cache
2019-10-01 09:24:10 +01:00
from structlog import get_logger
2019-10-07 15:33:48 +01:00
from passbook.policies.exceptions import PolicyException
from passbook.policies.models import PolicyBinding
from passbook.policies.types import PolicyRequest, PolicyResult
LOGGER = get_logger()
def cache_key(binding: PolicyBinding, request: PolicyRequest) -> str:
2019-10-07 15:33:48 +01:00
"""Generate Cache key for policy"""
prefix = f"policy_{binding.policy_binding_uuid.hex}_{binding.policy.pk.hex}"
if request.http_request:
prefix += f"_{request.http_request.session.session_key}"
if request.user:
prefix += f"#{request.user.pk}"
return prefix
2019-12-31 11:51:16 +00:00
class PolicyProcess(Process):
"""Evaluate a single policy within a seprate process"""
2019-10-04 12:44:26 +01:00
connection: Connection
binding: PolicyBinding
request: PolicyRequest
def __init__(
self,
binding: PolicyBinding,
request: PolicyRequest,
connection: Optional[Connection],
):
2019-10-04 12:44:26 +01:00
super().__init__()
self.binding = binding
2019-10-04 12:44:26 +01:00
self.request = request
if not isinstance(self.request, PolicyRequest):
raise ValueError(f"{self.request} is not a Policy Request.")
if connection:
self.connection = connection
2019-10-04 12:44:26 +01:00
def execute(self) -> PolicyResult:
"""Run actual policy, returns result"""
2019-12-31 11:51:16 +00:00
LOGGER.debug(
"P_ENG(proc): Running policy",
policy=self.binding.policy,
2019-12-31 11:51:16 +00:00
user=self.request.user,
process="PolicyProcess",
)
2019-10-02 21:28:39 +01:00
try:
policy_result = self.binding.policy.passes(self.request)
2019-10-02 21:28:39 +01:00
except PolicyException as exc:
LOGGER.debug("P_ENG(proc): error", exc=exc)
2019-10-02 21:28:39 +01:00
policy_result = PolicyResult(False, str(exc))
# Invert result if policy.negate is set
if self.binding.negate:
policy_result.passing = not policy_result.passing
2019-12-31 11:51:16 +00:00
LOGGER.debug(
"P_ENG(proc): Finished",
policy=self.binding.policy,
2019-12-31 11:51:16 +00:00
result=policy_result,
process="PolicyProcess",
passing=policy_result.passing,
user=self.request.user,
)
key = cache_key(self.binding, self.request)
2019-10-07 15:33:48 +01:00
cache.set(key, policy_result)
LOGGER.debug("P_ENG(proc): Cached policy evaluation", key=key)
return policy_result
def run(self):
"""Task wrapper to run policy checking"""
self.connection.send(self.execute())