From 831b32c2796aa5694dd4c104daf6274f09c91471 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Mon, 21 Jun 2021 15:54:43 +0200 Subject: [PATCH] core: fix PropertyMapping's globals not matching Expression policy Signed-off-by: Jens Langhammer --- authentik/core/expression.py | 21 +++++++++++++++------ authentik/core/models.py | 2 +- authentik/providers/oauth2/managed.py | 14 +++++++------- authentik/providers/proxy/managed.py | 2 +- authentik/providers/saml/managed.py | 14 +++++++------- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/authentik/core/expression.py b/authentik/core/expression.py index 220e37b13..13d196136 100644 --- a/authentik/core/expression.py +++ b/authentik/core/expression.py @@ -3,23 +3,33 @@ from traceback import format_tb from typing import Optional from django.http import HttpRequest +from guardian.utils import get_anonymous_user -from authentik.core.models import User +from authentik.core.models import PropertyMapping, User from authentik.events.models import Event, EventAction from authentik.lib.expression.evaluator import BaseEvaluator +from authentik.policies.types import PolicyRequest class PropertyMappingEvaluator(BaseEvaluator): """Custom Evalautor that adds some different context variables.""" def set_context( - self, user: Optional[User], request: Optional[HttpRequest], **kwargs + self, + user: Optional[User], + request: Optional[HttpRequest], + mapping: PropertyMapping, + **kwargs, ): """Update context with context from PropertyMapping's evaluate""" + req = PolicyRequest(user=get_anonymous_user()) + req.obj = mapping if user: + req.user = user self._context["user"] = user if request: - self._context["request"] = request + req.http_request = request + self._context["request"] = req self._context.update(**kwargs) def handle_error(self, exc: Exception, expression_source: str): @@ -30,9 +40,8 @@ class PropertyMappingEvaluator(BaseEvaluator): expression=expression_source, message=error_string, ) - if "user" in self._context: - event.set_user(self._context["user"]) if "request" in self._context: - event.from_http(self._context["request"]) + req: PolicyRequest = self._context["request"] + event.from_http(req.http_request, req.user) return event.save() diff --git a/authentik/core/models.py b/authentik/core/models.py index 7e1c377d4..029a51895 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -461,7 +461,7 @@ class PropertyMapping(SerializerModel, ManagedModel): from authentik.core.expression import PropertyMappingEvaluator evaluator = PropertyMappingEvaluator() - evaluator.set_context(user, request, **kwargs) + evaluator.set_context(user, request, self, **kwargs) try: return evaluator.evaluate(self.expression) except (ValueError, SyntaxError) as exc: diff --git a/authentik/providers/oauth2/managed.py b/authentik/providers/oauth2/managed.py index 873640942..9f4a3136a 100644 --- a/authentik/providers/oauth2/managed.py +++ b/authentik/providers/oauth2/managed.py @@ -9,7 +9,7 @@ return {} """ SCOPE_EMAIL_EXPRESSION = """ return { - "email": user.email, + "email": request.user.email, "email_verified": True } """ @@ -17,14 +17,14 @@ SCOPE_PROFILE_EXPRESSION = """ return { # Because authentik only saves the user's full name, and has no concept of first and last names, # the full name is used as given name. - # You can override this behaviour in custom mappings, i.e. `user.name.split(" ")` - "name": user.name, - "given_name": user.name, + # You can override this behaviour in custom mappings, i.e. `request.user.name.split(" ")` + "name": request.user.name, + "given_name": request.user.name, "family_name": "", - "preferred_username": user.username, - "nickname": user.username, + "preferred_username": request.user.username, + "nickname": request.user.username, # groups is not part of the official userinfo schema, but is a quasi-standard - "groups": [group.name for group in user.ak_groups.all()], + "groups": [group.name for group in request.user.ak_groups.all()], } """ diff --git a/authentik/providers/proxy/managed.py b/authentik/providers/proxy/managed.py index 24f197b5c..fb7cf35c2 100644 --- a/authentik/providers/proxy/managed.py +++ b/authentik/providers/proxy/managed.py @@ -8,7 +8,7 @@ SCOPE_AK_PROXY_EXPRESSION = """ # which are used for example for the HTTP-Basic Authentication mapping. return { "ak_proxy": { - "user_attributes": user.group_attributes() + "user_attributes": request.user.group_attributes() } }""" diff --git a/authentik/providers/saml/managed.py b/authentik/providers/saml/managed.py index e191759d5..4023fccaa 100644 --- a/authentik/providers/saml/managed.py +++ b/authentik/providers/saml/managed.py @@ -3,7 +3,7 @@ from authentik.managed.manager import EnsureExists, ObjectManager from authentik.providers.saml.models import SAMLPropertyMapping GROUP_EXPRESSION = """ -for group in user.ak_groups.all(): +for group in request.user.ak_groups.all(): yield group.name """ @@ -18,7 +18,7 @@ class SAMLProviderManager(ObjectManager): "goauthentik.io/providers/saml/upn", name="authentik default SAML Mapping: UPN", saml_name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", - expression="return user.attributes.get('upn', user.email)", + expression="return request.user.attributes.get('upn', request.user.email)", friendly_name="", ), EnsureExists( @@ -26,7 +26,7 @@ class SAMLProviderManager(ObjectManager): "goauthentik.io/providers/saml/name", name="authentik default SAML Mapping: Name", saml_name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", - expression="return user.name", + expression="return request.user.name", friendly_name="", ), EnsureExists( @@ -34,7 +34,7 @@ class SAMLProviderManager(ObjectManager): "goauthentik.io/providers/saml/email", name="authentik default SAML Mapping: Email", saml_name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", - expression="return user.email", + expression="return request.user.email", friendly_name="", ), EnsureExists( @@ -42,7 +42,7 @@ class SAMLProviderManager(ObjectManager): "goauthentik.io/providers/saml/username", name="authentik default SAML Mapping: Username", saml_name="http://schemas.goauthentik.io/2021/02/saml/username", - expression="return user.username", + expression="return request.user.username", friendly_name="", ), EnsureExists( @@ -50,7 +50,7 @@ class SAMLProviderManager(ObjectManager): "goauthentik.io/providers/saml/uid", name="authentik default SAML Mapping: User ID", saml_name="http://schemas.goauthentik.io/2021/02/saml/uid", - expression="return user.pk", + expression="return request.user.pk", friendly_name="", ), EnsureExists( @@ -68,7 +68,7 @@ class SAMLProviderManager(ObjectManager): saml_name=( "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname" ), - expression="return user.username", + expression="return request.user.username", friendly_name="", ), ]