@ -62,6 +62,7 @@ from authentik.core.api.utils import (
|
|||||||
ModelSerializer,
|
ModelSerializer,
|
||||||
PassiveSerializer,
|
PassiveSerializer,
|
||||||
)
|
)
|
||||||
|
from authentik.core.avatars import get_avatar
|
||||||
from authentik.core.middleware import (
|
from authentik.core.middleware import (
|
||||||
SESSION_KEY_IMPERSONATE_ORIGINAL_USER,
|
SESSION_KEY_IMPERSONATE_ORIGINAL_USER,
|
||||||
SESSION_KEY_IMPERSONATE_USER,
|
SESSION_KEY_IMPERSONATE_USER,
|
||||||
@ -81,7 +82,6 @@ from authentik.flows.exceptions import FlowNonApplicableException
|
|||||||
from authentik.flows.models import FlowToken
|
from authentik.flows.models import FlowToken
|
||||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner
|
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner
|
||||||
from authentik.flows.views.executor import QS_KEY_TOKEN
|
from authentik.flows.views.executor import QS_KEY_TOKEN
|
||||||
from authentik.lib.avatars import get_avatar
|
|
||||||
from authentik.rbac.decorators import permission_required
|
from authentik.rbac.decorators import permission_required
|
||||||
from authentik.rbac.models import get_permission_choices
|
from authentik.rbac.models import get_permission_choices
|
||||||
from authentik.stages.email.models import EmailStage
|
from authentik.stages.email.models import EmailStage
|
||||||
|
|||||||
@ -27,10 +27,10 @@ from structlog.stdlib import get_logger
|
|||||||
|
|
||||||
from authentik.blueprints.models import ManagedModel
|
from authentik.blueprints.models import ManagedModel
|
||||||
from authentik.common.expression.exceptions import ControlFlowException
|
from authentik.common.expression.exceptions import ControlFlowException
|
||||||
|
from authentik.core.avatars import get_avatar
|
||||||
from authentik.core.expression.exceptions import PropertyMappingExpressionException
|
from authentik.core.expression.exceptions import PropertyMappingExpressionException
|
||||||
from authentik.core.types import UILoginButton, UserSettingSerializer
|
from authentik.core.types import UILoginButton, UserSettingSerializer
|
||||||
from authentik.crypto.generators import generate_id
|
from authentik.crypto.generators import generate_id
|
||||||
from authentik.lib.avatars import get_avatar
|
|
||||||
from authentik.lib.merge import MERGE_LIST_UNIQUE
|
from authentik.lib.merge import MERGE_LIST_UNIQUE
|
||||||
from authentik.lib.models import (
|
from authentik.lib.models import (
|
||||||
CreatedUpdatedModel,
|
CreatedUpdatedModel,
|
||||||
|
|||||||
@ -14,6 +14,7 @@ from rest_framework.request import Request
|
|||||||
from sentry_sdk import start_span
|
from sentry_sdk import start_span
|
||||||
from structlog.stdlib import BoundLogger, get_logger
|
from structlog.stdlib import BoundLogger, get_logger
|
||||||
|
|
||||||
|
from authentik.core.avatars import DEFAULT_AVATAR, get_avatar
|
||||||
from authentik.core.models import Application, User
|
from authentik.core.models import Application, User
|
||||||
from authentik.flows.challenge import (
|
from authentik.flows.challenge import (
|
||||||
AccessDeniedChallenge,
|
AccessDeniedChallenge,
|
||||||
@ -28,7 +29,6 @@ from authentik.flows.challenge import (
|
|||||||
from authentik.flows.exceptions import StageInvalidException
|
from authentik.flows.exceptions import StageInvalidException
|
||||||
from authentik.flows.models import InvalidResponseAction
|
from authentik.flows.models import InvalidResponseAction
|
||||||
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_PENDING_USER
|
from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_PENDING_USER
|
||||||
from authentik.lib.avatars import DEFAULT_AVATAR, get_avatar
|
|
||||||
from authentik.lib.utils.reflection import class_to_path
|
from authentik.lib.utils.reflection import class_to_path
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|||||||
@ -1,82 +0,0 @@
|
|||||||
"""Test HTTP Helpers"""
|
|
||||||
|
|
||||||
from django.test import RequestFactory, TestCase
|
|
||||||
|
|
||||||
from authentik.core.models import Token, TokenIntents, UserTypes
|
|
||||||
from authentik.core.tests.utils import create_test_admin_user
|
|
||||||
from authentik.lib.views import bad_request_message
|
|
||||||
from authentik.root.middleware import ClientIPMiddleware
|
|
||||||
|
|
||||||
|
|
||||||
class TestHTTP(TestCase):
|
|
||||||
"""Test HTTP Helpers"""
|
|
||||||
|
|
||||||
def setUp(self) -> None:
|
|
||||||
self.user = create_test_admin_user()
|
|
||||||
self.factory = RequestFactory()
|
|
||||||
|
|
||||||
def test_bad_request_message(self):
|
|
||||||
"""test bad_request_message"""
|
|
||||||
request = self.factory.get("/")
|
|
||||||
self.assertEqual(bad_request_message(request, "foo").status_code, 400)
|
|
||||||
|
|
||||||
def test_normal(self):
|
|
||||||
"""Test normal request"""
|
|
||||||
request = self.factory.get("/")
|
|
||||||
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.1")
|
|
||||||
|
|
||||||
def test_forward_for(self):
|
|
||||||
"""Test x-forwarded-for request"""
|
|
||||||
request = self.factory.get("/", HTTP_X_FORWARDED_FOR="127.0.0.2")
|
|
||||||
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.2")
|
|
||||||
|
|
||||||
def test_forward_for_invalid(self):
|
|
||||||
"""Test invalid forward for"""
|
|
||||||
request = self.factory.get("/", HTTP_X_FORWARDED_FOR="foobar")
|
|
||||||
self.assertEqual(ClientIPMiddleware.get_client_ip(request), ClientIPMiddleware.default_ip)
|
|
||||||
|
|
||||||
def test_fake_outpost(self):
|
|
||||||
"""Test faked IP which is overridden by an outpost"""
|
|
||||||
token = Token.objects.create(
|
|
||||||
identifier="test", user=self.user, intent=TokenIntents.INTENT_API
|
|
||||||
)
|
|
||||||
# Invalid, non-existent token
|
|
||||||
request = self.factory.get(
|
|
||||||
"/",
|
|
||||||
**{
|
|
||||||
ClientIPMiddleware.outpost_remote_ip_header: "1.2.3.4",
|
|
||||||
ClientIPMiddleware.outpost_token_header: "abc",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.1")
|
|
||||||
# Invalid, user doesn't have permissions
|
|
||||||
request = self.factory.get(
|
|
||||||
"/",
|
|
||||||
**{
|
|
||||||
ClientIPMiddleware.outpost_remote_ip_header: "1.2.3.4",
|
|
||||||
ClientIPMiddleware.outpost_token_header: token.key,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.1")
|
|
||||||
# Invalid, not a real IP
|
|
||||||
self.user.type = UserTypes.INTERNAL_SERVICE_ACCOUNT
|
|
||||||
self.user.save()
|
|
||||||
request = self.factory.get(
|
|
||||||
"/",
|
|
||||||
**{
|
|
||||||
ClientIPMiddleware.outpost_remote_ip_header: "foobar",
|
|
||||||
ClientIPMiddleware.outpost_token_header: token.key,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.1")
|
|
||||||
# Valid
|
|
||||||
self.user.type = UserTypes.INTERNAL_SERVICE_ACCOUNT
|
|
||||||
self.user.save()
|
|
||||||
request = self.factory.get(
|
|
||||||
"/",
|
|
||||||
**{
|
|
||||||
ClientIPMiddleware.outpost_remote_ip_header: "1.2.3.4",
|
|
||||||
ClientIPMiddleware.outpost_token_header: token.key,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "1.2.3.4")
|
|
||||||
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from authentik.common.exceptions import NotReportedException, before_send
|
from authentik.common.exceptions import NotReportedException
|
||||||
|
from authentik.root.sentry import before_send
|
||||||
|
|
||||||
|
|
||||||
class TestSentry(TestCase):
|
class TestSentry(TestCase):
|
||||||
|
|||||||
19
authentik/lib/tests/test_views.py
Normal file
19
authentik/lib/tests/test_views.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
"""Test HTTP Helpers"""
|
||||||
|
|
||||||
|
from django.test import RequestFactory, TestCase
|
||||||
|
|
||||||
|
from authentik.core.tests.utils import create_test_admin_user
|
||||||
|
from authentik.lib.views import bad_request_message
|
||||||
|
|
||||||
|
|
||||||
|
class TestViews(TestCase):
|
||||||
|
"""Test Views Helpers"""
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
self.user = create_test_admin_user()
|
||||||
|
self.factory = RequestFactory()
|
||||||
|
|
||||||
|
def test_bad_request_message(self):
|
||||||
|
"""test bad_request_message"""
|
||||||
|
request = self.factory.get("/")
|
||||||
|
self.assertEqual(bad_request_message(request, "foo").status_code, 400)
|
||||||
@ -30,7 +30,7 @@ from tenant_schemas_celery.app import CeleryApp as TenantAwareCeleryApp
|
|||||||
|
|
||||||
from authentik import get_full_version
|
from authentik import get_full_version
|
||||||
from authentik.lib.utils.errors import exception_to_string
|
from authentik.lib.utils.errors import exception_to_string
|
||||||
from authentik.root.sentry import before_send
|
from authentik.root.sentry import should_ignore_exception
|
||||||
|
|
||||||
# set the default Django settings module for the 'celery' program.
|
# set the default Django settings module for the 'celery' program.
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
||||||
@ -83,7 +83,7 @@ def task_error_hook(task_id: str, exception: Exception, traceback, *args, **kwar
|
|||||||
|
|
||||||
LOGGER.warning("Task failure", task_id=task_id.replace("-", ""), exc=exception)
|
LOGGER.warning("Task failure", task_id=task_id.replace("-", ""), exc=exception)
|
||||||
CTX_TASK_ID.set(...)
|
CTX_TASK_ID.set(...)
|
||||||
if before_send({}, {"exc_info": (None, exception, None)}) is not None:
|
if not should_ignore_exception(exception):
|
||||||
Event.new(
|
Event.new(
|
||||||
EventAction.SYSTEM_EXCEPTION, message=exception_to_string(exception), task_id=task_id
|
EventAction.SYSTEM_EXCEPTION, message=exception_to_string(exception), task_id=task_id
|
||||||
).save()
|
).save()
|
||||||
|
|||||||
@ -7,6 +7,9 @@ from tempfile import gettempdir
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from authentik.core.models import Token, TokenIntents, UserTypes
|
||||||
|
from authentik.root.middleware import ClientIPMiddleware
|
||||||
|
|
||||||
|
|
||||||
class TestRoot(TestCase):
|
class TestRoot(TestCase):
|
||||||
"""Test root application"""
|
"""Test root application"""
|
||||||
@ -39,3 +42,64 @@ class TestRoot(TestCase):
|
|||||||
def test_monitoring_ready(self):
|
def test_monitoring_ready(self):
|
||||||
"""Test ReadyView"""
|
"""Test ReadyView"""
|
||||||
self.assertEqual(self.client.get(reverse("health-ready")).status_code, 200)
|
self.assertEqual(self.client.get(reverse("health-ready")).status_code, 200)
|
||||||
|
|
||||||
|
def test_normal(self):
|
||||||
|
"""Test normal request"""
|
||||||
|
request = self.factory.get("/")
|
||||||
|
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.1")
|
||||||
|
|
||||||
|
def test_forward_for(self):
|
||||||
|
"""Test x-forwarded-for request"""
|
||||||
|
request = self.factory.get("/", HTTP_X_FORWARDED_FOR="127.0.0.2")
|
||||||
|
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.2")
|
||||||
|
|
||||||
|
def test_forward_for_invalid(self):
|
||||||
|
"""Test invalid forward for"""
|
||||||
|
request = self.factory.get("/", HTTP_X_FORWARDED_FOR="foobar")
|
||||||
|
self.assertEqual(ClientIPMiddleware.get_client_ip(request), ClientIPMiddleware.default_ip)
|
||||||
|
|
||||||
|
def test_fake_outpost(self):
|
||||||
|
"""Test faked IP which is overridden by an outpost"""
|
||||||
|
token = Token.objects.create(
|
||||||
|
identifier="test", user=self.user, intent=TokenIntents.INTENT_API
|
||||||
|
)
|
||||||
|
# Invalid, non-existent token
|
||||||
|
request = self.factory.get(
|
||||||
|
"/",
|
||||||
|
**{
|
||||||
|
ClientIPMiddleware.outpost_remote_ip_header: "1.2.3.4",
|
||||||
|
ClientIPMiddleware.outpost_token_header: "abc",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.1")
|
||||||
|
# Invalid, user doesn't have permissions
|
||||||
|
request = self.factory.get(
|
||||||
|
"/",
|
||||||
|
**{
|
||||||
|
ClientIPMiddleware.outpost_remote_ip_header: "1.2.3.4",
|
||||||
|
ClientIPMiddleware.outpost_token_header: token.key,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.1")
|
||||||
|
# Invalid, not a real IP
|
||||||
|
self.user.type = UserTypes.INTERNAL_SERVICE_ACCOUNT
|
||||||
|
self.user.save()
|
||||||
|
request = self.factory.get(
|
||||||
|
"/",
|
||||||
|
**{
|
||||||
|
ClientIPMiddleware.outpost_remote_ip_header: "foobar",
|
||||||
|
ClientIPMiddleware.outpost_token_header: token.key,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "127.0.0.1")
|
||||||
|
# Valid
|
||||||
|
self.user.type = UserTypes.INTERNAL_SERVICE_ACCOUNT
|
||||||
|
self.user.save()
|
||||||
|
request = self.factory.get(
|
||||||
|
"/",
|
||||||
|
**{
|
||||||
|
ClientIPMiddleware.outpost_remote_ip_header: "1.2.3.4",
|
||||||
|
ClientIPMiddleware.outpost_token_header: token.key,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(ClientIPMiddleware.get_client_ip(request), "1.2.3.4")
|
||||||
|
|||||||
@ -15,6 +15,7 @@ from rest_framework.serializers import ValidationError
|
|||||||
from sentry_sdk import start_span
|
from sentry_sdk import start_span
|
||||||
|
|
||||||
from authentik.core.api.utils import PassiveSerializer
|
from authentik.core.api.utils import PassiveSerializer
|
||||||
|
from authentik.core.avatars import DEFAULT_AVATAR
|
||||||
from authentik.core.models import Application, Source, User
|
from authentik.core.models import Application, Source, User
|
||||||
from authentik.events.utils import sanitize_item
|
from authentik.events.utils import sanitize_item
|
||||||
from authentik.flows.challenge import (
|
from authentik.flows.challenge import (
|
||||||
@ -26,7 +27,6 @@ from authentik.flows.models import FlowDesignation
|
|||||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||||
from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, ChallengeStageView
|
from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, ChallengeStageView
|
||||||
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_GET
|
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_GET
|
||||||
from authentik.lib.avatars import DEFAULT_AVATAR
|
|
||||||
from authentik.lib.utils.reflection import all_subclasses
|
from authentik.lib.utils.reflection import all_subclasses
|
||||||
from authentik.lib.utils.urls import reverse_with_qs
|
from authentik.lib.utils.urls import reverse_with_qs
|
||||||
from authentik.root.middleware import ClientIPMiddleware
|
from authentik.root.middleware import ClientIPMiddleware
|
||||||
|
|||||||
Reference in New Issue
Block a user