mirror of
https://github.com/goauthentik/authentik
synced 2026-05-14 02:46:29 +02:00
internal: Automated internal backport: GHSA-973w-j457-rp2m.sec.patch to authentik-main (#22305)
Automated internal backport of patch GHSA-973w-j457-rp2m.sec.patch to authentik-main Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
ee954d64f8
commit
f4e868210d
@@ -42,11 +42,29 @@ def validate_auth(header: bytes, format="bearer") -> str | None:
|
||||
return auth_credentials
|
||||
|
||||
|
||||
class IPCUser(AnonymousUser):
|
||||
class VirtualUser(AnonymousUser):
|
||||
is_active = True
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return UserTypes.INTERNAL_SERVICE_ACCOUNT
|
||||
|
||||
@property
|
||||
def is_anonymous(self):
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_authenticated(self):
|
||||
return True
|
||||
|
||||
def all_roles(self):
|
||||
return []
|
||||
|
||||
|
||||
class IPCUser(VirtualUser):
|
||||
"""'Virtual' user for IPC communication between authentik core and the authentik router"""
|
||||
|
||||
username = "authentik:system"
|
||||
is_active = True
|
||||
is_superuser = True
|
||||
|
||||
@property
|
||||
@@ -62,17 +80,6 @@ class IPCUser(AnonymousUser):
|
||||
def has_module_perms(self, module):
|
||||
return True
|
||||
|
||||
@property
|
||||
def is_anonymous(self):
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_authenticated(self):
|
||||
return True
|
||||
|
||||
def all_roles(self):
|
||||
return []
|
||||
|
||||
|
||||
class TokenAuthentication(BaseAuthentication):
|
||||
"""Token-based authentication using HTTP Bearer authentication"""
|
||||
|
||||
@@ -7,7 +7,7 @@ from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_sche
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.exceptions import PermissionDenied, ValidationError
|
||||
from rest_framework.fields import ChoiceField
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from rest_framework.relations import PrimaryKeyRelatedField
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
@@ -44,7 +44,6 @@ from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_ME
|
||||
|
||||
|
||||
class AgentConnectorSerializer(ConnectorSerializer):
|
||||
|
||||
class Meta(ConnectorSerializer.Meta):
|
||||
model = AgentConnector
|
||||
fields = ConnectorSerializer.Meta.fields + [
|
||||
@@ -63,7 +62,6 @@ class AgentConnectorSerializer(ConnectorSerializer):
|
||||
|
||||
|
||||
class MDMConfigSerializer(PassiveSerializer):
|
||||
|
||||
platform = ChoiceField(choices=OSFamily.choices)
|
||||
enrollment_token = PrimaryKeyRelatedField(
|
||||
queryset=EnrollmentToken.objects.including_expired().all()
|
||||
@@ -89,7 +87,6 @@ class AgentConnectorViewSet(
|
||||
UsedByMixin,
|
||||
ModelViewSet,
|
||||
):
|
||||
|
||||
queryset = AgentConnector.objects.all()
|
||||
serializer_class = AgentConnectorSerializer
|
||||
search_fields = ["name"]
|
||||
@@ -121,6 +118,8 @@ class AgentConnectorViewSet(
|
||||
methods=["POST"],
|
||||
detail=False,
|
||||
authentication_classes=[AgentEnrollmentAuth],
|
||||
# Permissions are handled via AgentEnrollmentAuth
|
||||
permission_classes=[AllowAny],
|
||||
)
|
||||
def enroll(self, request: Request):
|
||||
token: EnrollmentToken = request.auth
|
||||
@@ -151,7 +150,13 @@ class AgentConnectorViewSet(
|
||||
request=OpenApiTypes.NONE,
|
||||
responses=AgentConfigSerializer(),
|
||||
)
|
||||
@action(methods=["GET"], detail=False, authentication_classes=[AgentAuth])
|
||||
@action(
|
||||
methods=["GET"],
|
||||
detail=False,
|
||||
authentication_classes=[AgentAuth],
|
||||
# Permissions are handled via AgentAuth
|
||||
permission_classes=[AllowAny],
|
||||
)
|
||||
def agent_config(self, request: Request):
|
||||
token: DeviceToken = request.auth
|
||||
connector: AgentConnector = token.device.connector.agentconnector
|
||||
@@ -165,7 +170,13 @@ class AgentConnectorViewSet(
|
||||
request=DeviceFacts(),
|
||||
responses={204: OpenApiResponse(description="Successfully checked in")},
|
||||
)
|
||||
@action(methods=["POST"], detail=False, authentication_classes=[AgentAuth])
|
||||
@action(
|
||||
methods=["POST"],
|
||||
detail=False,
|
||||
authentication_classes=[AgentAuth],
|
||||
# Permissions are handled via AgentAuth
|
||||
permission_classes=[AllowAny],
|
||||
)
|
||||
def check_in(self, request: Request):
|
||||
token: DeviceToken = request.auth
|
||||
data = DeviceFacts(data=request.data)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from typing import Any
|
||||
|
||||
from django.db.models import Model
|
||||
from django.http import HttpRequest
|
||||
from django.utils.timezone import now
|
||||
from drf_spectacular.extensions import OpenApiAuthenticationExtension
|
||||
@@ -9,7 +10,7 @@ from rest_framework.exceptions import PermissionDenied
|
||||
from rest_framework.request import Request
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.api.authentication import IPCUser, validate_auth
|
||||
from authentik.api.authentication import VirtualUser, validate_auth
|
||||
from authentik.core.middleware import CTX_AUTH_VIA
|
||||
from authentik.core.models import User
|
||||
from authentik.crypto.apps import MANAGED_KEY
|
||||
@@ -25,9 +26,19 @@ LOGGER = get_logger()
|
||||
PLATFORM_ISSUER = "goauthentik.io/platform"
|
||||
|
||||
|
||||
class DeviceUser(IPCUser):
|
||||
class DeviceUser(VirtualUser):
|
||||
|
||||
username = "authentik:endpoints:device"
|
||||
|
||||
def has_perm(self, perm: str, obj: Model | None = None) -> bool:
|
||||
print(perm)
|
||||
if perm in [
|
||||
"authentik_core.view_user",
|
||||
"authentik_core.view_group",
|
||||
]:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class AgentEnrollmentAuth(BaseAuthentication):
|
||||
|
||||
|
||||
@@ -223,3 +223,17 @@ class TestAgentAPI(APITestCase):
|
||||
data={"platform": OSFamily.macOS, "enrollment_token": self.token.pk},
|
||||
)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
|
||||
def test_users_list(self):
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:user-list"),
|
||||
HTTP_AUTHORIZATION=f"Bearer+agent {self.device_token.key}",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_other_api_forbidden(self):
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:application-list"),
|
||||
HTTP_AUTHORIZATION=f"Bearer+agent {self.device_token.key}",
|
||||
)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
@@ -2,6 +2,7 @@ from django.urls import reverse
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from structlog.stdlib import get_logger
|
||||
@@ -25,7 +26,13 @@ class AgentConnectorViewSetMixin:
|
||||
request=OpenApiTypes.NONE,
|
||||
responses=AgentAuthenticationResponse(),
|
||||
)
|
||||
@action(methods=["POST"], detail=False, authentication_classes=[AgentAuth])
|
||||
@action(
|
||||
methods=["POST"],
|
||||
detail=False,
|
||||
authentication_classes=[AgentAuth],
|
||||
# Permissions are handled via AgentAuth
|
||||
permission_classes=[AllowAny],
|
||||
)
|
||||
@enterprise_action
|
||||
def auth_ia(self, request: Request) -> Response:
|
||||
token: DeviceToken = request.auth
|
||||
|
||||
@@ -5386,6 +5386,8 @@ paths:
|
||||
using this object
|
||||
tags:
|
||||
- endpoints
|
||||
security:
|
||||
- {}
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
@@ -5430,6 +5432,8 @@ paths:
|
||||
using this object
|
||||
tags:
|
||||
- endpoints
|
||||
security:
|
||||
- {}
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
@@ -5453,6 +5457,8 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/DeviceFactsRequest'
|
||||
security:
|
||||
- {}
|
||||
responses:
|
||||
'204':
|
||||
description: Successfully checked in
|
||||
@@ -5473,6 +5479,8 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/EnrollRequest'
|
||||
required: true
|
||||
security:
|
||||
- {}
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
|
||||
Reference in New Issue
Block a user