events: deepcopy event kwargs to prevent objects being removed, remove workaround

closes #4041

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2022-11-21 12:31:17 +01:00
parent 2e2a4aaa78
commit 426f0bc9dd
4 changed files with 62 additions and 11 deletions

13
.vscode/settings.json vendored
View File

@ -20,15 +20,20 @@
"todo-tree.tree.showCountsInTree": true,
"todo-tree.tree.showBadges": true,
"python.formatting.provider": "black",
"yaml.customTags": [
"!Find sequence",
"!KeyOf scalar"
],
"yaml.customTags": ["!Find sequence", "!KeyOf scalar"],
"typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifierEnding": "index",
"typescript.tsdk": "./web/node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true,
"yaml.schemas": {
"./blueprints/schema.json": "blueprints/**/*.yaml"
},
"gitlens.autolinks": [
{
"alphanumeric": true,
"prefix": "#<num>",
"url": "https://github.com/goauthentik/authentik/issues/<num>",
"ignoreCase": false
}
]
}

View File

@ -1,6 +1,7 @@
"""authentik events models"""
import time
from collections import Counter
from copy import deepcopy
from datetime import timedelta
from inspect import currentframe
from smtplib import SMTPException
@ -210,7 +211,7 @@ class Event(SerializerModel, ExpiringModel):
current = currentframe()
parent = current.f_back
app = parent.f_globals["__name__"]
cleaned_kwargs = cleanse_dict(sanitize_dict(kwargs))
cleaned_kwargs = cleanse_dict(sanitize_dict(deepcopy(kwargs)))
event = Event(action=action, app=app, context=cleaned_kwargs)
return event

View File

@ -1,13 +1,17 @@
"""evaluator tests"""
from django.test import TestCase
from django.test import RequestFactory, TestCase
from guardian.shortcuts import get_anonymous_user
from rest_framework.serializers import ValidationError
from rest_framework.test import APITestCase
from authentik.core.models import Application
from authentik.lib.generators import generate_id
from authentik.policies.exceptions import PolicyException
from authentik.policies.expression.api import ExpressionPolicySerializer
from authentik.policies.expression.evaluator import PolicyEvaluator
from authentik.policies.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding
from authentik.policies.process import PolicyProcess
from authentik.policies.types import PolicyRequest
@ -15,7 +19,15 @@ class TestEvaluator(TestCase):
"""Evaluator tests"""
def setUp(self):
factory = RequestFactory()
self.http_request = factory.get("/")
self.obj = Application.objects.create(
name=generate_id(),
slug=generate_id(),
)
self.request = PolicyRequest(user=get_anonymous_user())
self.request.obj = self.obj
self.request.http_request = self.http_request
def test_full(self):
"""Test full with Policy instance"""
@ -63,6 +75,41 @@ class TestEvaluator(TestCase):
with self.assertRaises(ValidationError):
evaluator.validate(template)
def test_execution_logging(self):
"""test execution_logging"""
expr = ExpressionPolicy.objects.create(
name=generate_id(),
execution_logging=True,
expression="ak_message(request.http_request.path)\nreturn True",
)
evaluator = PolicyEvaluator("test")
evaluator.set_policy_request(self.request)
proc = PolicyProcess(PolicyBinding(policy=expr), request=self.request, connection=None)
res = proc.profiling_wrapper()
self.assertEqual(res.messages, ("/",))
def test_call_policy(self):
"""test ak_call_policy"""
expr = ExpressionPolicy.objects.create(
name=generate_id(),
execution_logging=True,
expression="ak_message(request.http_request.path)\nreturn True",
)
tmpl = (
"""
ak_message(request.http_request.path)
res = ak_call_policy('%s')
ak_message(request.http_request.path)
for msg in res.messages:
ak_message(msg)
"""
% expr.name
)
evaluator = PolicyEvaluator("test")
evaluator.set_policy_request(self.request)
res = evaluator.evaluate(tmpl)
self.assertEqual(res.messages, ("/", "/", "/"))
class TestExpressionPolicyAPI(APITestCase):
"""Test expression policy's API"""

View File

@ -56,8 +56,6 @@ class PolicyProcess(PROCESS_CLASS):
def create_event(self, action: str, message: str, **kwargs):
"""Create event with common values from `self.request` and `self.binding`."""
# Keep a reference to http_request even if its None, because cleanse_dict will remove it
http_request = self.request.http_request
event = Event.new(
action=action,
message=message,
@ -67,8 +65,8 @@ class PolicyProcess(PROCESS_CLASS):
**kwargs,
)
event.set_user(self.request.user)
if http_request:
event.from_http(http_request)
if self.request.http_request:
event.from_http(self.request.http_request)
else:
event.save()