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

15
.vscode/settings.json vendored
View File

@ -20,15 +20,20 @@
"todo-tree.tree.showCountsInTree": true, "todo-tree.tree.showCountsInTree": true,
"todo-tree.tree.showBadges": true, "todo-tree.tree.showBadges": true,
"python.formatting.provider": "black", "python.formatting.provider": "black",
"yaml.customTags": [ "yaml.customTags": ["!Find sequence", "!KeyOf scalar"],
"!Find sequence",
"!KeyOf scalar"
],
"typescript.preferences.importModuleSpecifier": "non-relative", "typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifierEnding": "index", "typescript.preferences.importModuleSpecifierEnding": "index",
"typescript.tsdk": "./web/node_modules/typescript/lib", "typescript.tsdk": "./web/node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true, "typescript.enablePromptUseWorkspaceTsdk": true,
"yaml.schemas": { "yaml.schemas": {
"./blueprints/schema.json": "blueprints/**/*.yaml" "./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""" """authentik events models"""
import time import time
from collections import Counter from collections import Counter
from copy import deepcopy
from datetime import timedelta from datetime import timedelta
from inspect import currentframe from inspect import currentframe
from smtplib import SMTPException from smtplib import SMTPException
@ -210,7 +211,7 @@ class Event(SerializerModel, ExpiringModel):
current = currentframe() current = currentframe()
parent = current.f_back parent = current.f_back
app = parent.f_globals["__name__"] 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) event = Event(action=action, app=app, context=cleaned_kwargs)
return event return event

View File

@ -1,13 +1,17 @@
"""evaluator tests""" """evaluator tests"""
from django.test import TestCase from django.test import RequestFactory, TestCase
from guardian.shortcuts import get_anonymous_user from guardian.shortcuts import get_anonymous_user
from rest_framework.serializers import ValidationError from rest_framework.serializers import ValidationError
from rest_framework.test import APITestCase 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.exceptions import PolicyException
from authentik.policies.expression.api import ExpressionPolicySerializer from authentik.policies.expression.api import ExpressionPolicySerializer
from authentik.policies.expression.evaluator import PolicyEvaluator from authentik.policies.expression.evaluator import PolicyEvaluator
from authentik.policies.expression.models import ExpressionPolicy 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 from authentik.policies.types import PolicyRequest
@ -15,7 +19,15 @@ class TestEvaluator(TestCase):
"""Evaluator tests""" """Evaluator tests"""
def setUp(self): 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 = PolicyRequest(user=get_anonymous_user())
self.request.obj = self.obj
self.request.http_request = self.http_request
def test_full(self): def test_full(self):
"""Test full with Policy instance""" """Test full with Policy instance"""
@ -63,6 +75,41 @@ class TestEvaluator(TestCase):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
evaluator.validate(template) 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): class TestExpressionPolicyAPI(APITestCase):
"""Test expression policy's API""" """Test expression policy's API"""

View File

@ -56,8 +56,6 @@ class PolicyProcess(PROCESS_CLASS):
def create_event(self, action: str, message: str, **kwargs): def create_event(self, action: str, message: str, **kwargs):
"""Create event with common values from `self.request` and `self.binding`.""" """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( event = Event.new(
action=action, action=action,
message=message, message=message,
@ -67,8 +65,8 @@ class PolicyProcess(PROCESS_CLASS):
**kwargs, **kwargs,
) )
event.set_user(self.request.user) event.set_user(self.request.user)
if http_request: if self.request.http_request:
event.from_http(http_request) event.from_http(self.request.http_request)
else: else:
event.save() event.save()