mirror of
https://github.com/goauthentik/authentik
synced 2026-04-25 17:15:26 +02:00
endpoints/connectors: add ability to enroll a device as ephemeral
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@@ -75,6 +75,7 @@ class EnrollSerializer(PassiveSerializer):
|
||||
|
||||
device_serial = CharField(required=True)
|
||||
device_name = CharField(required=True)
|
||||
ephemeral = BooleanField(default=False)
|
||||
|
||||
|
||||
class AgentTokenResponseSerializer(PassiveSerializer):
|
||||
|
||||
@@ -40,15 +40,16 @@ from authentik.endpoints.models import Device
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.flows.planner import PLAN_CONTEXT_DEVICE
|
||||
from authentik.lib.utils.reflection import ConditionalInheritance
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
|
||||
|
||||
|
||||
class AgentConnectorSerializer(ConnectorSerializer):
|
||||
|
||||
class Meta(ConnectorSerializer.Meta):
|
||||
model = AgentConnector
|
||||
fields = ConnectorSerializer.Meta.fields + [
|
||||
"snapshot_expiry",
|
||||
"ephemeral_device_expiry",
|
||||
"auth_session_duration",
|
||||
"auth_terminate_session_on_expiry",
|
||||
"refresh_interval",
|
||||
@@ -63,7 +64,6 @@ class AgentConnectorSerializer(ConnectorSerializer):
|
||||
|
||||
|
||||
class MDMConfigSerializer(PassiveSerializer):
|
||||
|
||||
platform = ChoiceField(choices=OSFamily.choices)
|
||||
enrollment_token = PrimaryKeyRelatedField(queryset=EnrollmentToken.objects.all())
|
||||
|
||||
@@ -87,7 +87,6 @@ class AgentConnectorViewSet(
|
||||
UsedByMixin,
|
||||
ModelViewSet,
|
||||
):
|
||||
|
||||
queryset = AgentConnector.objects.all()
|
||||
serializer_class = AgentConnectorSerializer
|
||||
search_fields = ["name"]
|
||||
@@ -124,13 +123,18 @@ class AgentConnectorViewSet(
|
||||
token: EnrollmentToken = request.auth
|
||||
data = EnrollSerializer(data=request.data)
|
||||
data.is_valid(raise_exception=True)
|
||||
defaults = {
|
||||
"name": data.validated_data["device_name"],
|
||||
"expiring": False,
|
||||
"access_group": token.device_group,
|
||||
}
|
||||
if data.validated_data["ephemeral"]:
|
||||
connector: AgentConnector = token.connector
|
||||
defaults["expiring"] = True
|
||||
defaults["expires"] = now() + timedelta_from_string(connector.ephemeral_device_expiry)
|
||||
device, _ = Device.objects.get_or_create(
|
||||
identifier=data.validated_data["device_serial"],
|
||||
defaults={
|
||||
"name": data.validated_data["device_name"],
|
||||
"expiring": False,
|
||||
"access_group": token.device_group,
|
||||
},
|
||||
defaults=defaults,
|
||||
)
|
||||
connection, _ = AgentDeviceConnection.objects.update_or_create(
|
||||
device=device,
|
||||
@@ -170,6 +174,11 @@ class AgentConnectorViewSet(
|
||||
data.is_valid(raise_exception=True)
|
||||
connection: AgentDeviceConnection = token.device
|
||||
connection.create_snapshot(data.validated_data)
|
||||
device = connection.device
|
||||
if device.expiring:
|
||||
connector = AgentConnector.objects.get(pk=connection.connector.pk)
|
||||
device.expires = now() + timedelta_from_string(connector.ephemeral_device_expiry)
|
||||
device.save()
|
||||
return Response(status=204)
|
||||
|
||||
@extend_schema(
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.2.11 on 2026-02-20 17:48
|
||||
|
||||
import authentik.lib.utils.time
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
(
|
||||
"authentik_endpoints_connectors_agent",
|
||||
"0004_agentconnector_challenge_idle_timeout_and_more",
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="agentconnector",
|
||||
name="ephemeral_device_expiry",
|
||||
field=models.TextField(
|
||||
default="hours=2", validators=[authentik.lib.utils.time.timedelta_string_validator]
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -32,6 +32,10 @@ class AgentConnector(Connector):
|
||||
validators=[timedelta_string_validator],
|
||||
)
|
||||
|
||||
ephemeral_device_expiry = models.TextField(
|
||||
default="hours=2", validators=[timedelta_string_validator]
|
||||
)
|
||||
|
||||
auth_session_duration = models.TextField(
|
||||
default="hours=8", validators=[timedelta_string_validator]
|
||||
)
|
||||
|
||||
@@ -58,6 +58,18 @@ class TestAgentAPI(APITestCase):
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_enroll_ephemeral(self):
|
||||
identifier = generate_id()
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:agentconnector-enroll"),
|
||||
data={"device_serial": identifier, "device_name": "bar", "ephemeral": True},
|
||||
HTTP_AUTHORIZATION=f"Bearer {self.token.key}",
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
device = Device.objects.filter(identifier=identifier).first()
|
||||
self.assertIsNotNone(device)
|
||||
self.assertTrue(device.expiring)
|
||||
|
||||
def test_enroll_token_delete(self):
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:agentconnector-enroll"),
|
||||
|
||||
@@ -6304,6 +6304,11 @@
|
||||
"minLength": 1,
|
||||
"title": "Snapshot expiry"
|
||||
},
|
||||
"ephemeral_device_expiry": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"title": "Ephemeral device expiry"
|
||||
},
|
||||
"auth_session_duration": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
|
||||
11
schema.yml
11
schema.yml
@@ -33843,6 +33843,8 @@ components:
|
||||
readOnly: true
|
||||
snapshot_expiry:
|
||||
type: string
|
||||
ephemeral_device_expiry:
|
||||
type: string
|
||||
auth_session_duration:
|
||||
type: string
|
||||
auth_terminate_session_on_expiry:
|
||||
@@ -33893,6 +33895,9 @@ components:
|
||||
snapshot_expiry:
|
||||
type: string
|
||||
minLength: 1
|
||||
ephemeral_device_expiry:
|
||||
type: string
|
||||
minLength: 1
|
||||
auth_session_duration:
|
||||
type: string
|
||||
minLength: 1
|
||||
@@ -38296,6 +38301,9 @@ components:
|
||||
device_name:
|
||||
type: string
|
||||
minLength: 1
|
||||
ephemeral:
|
||||
type: boolean
|
||||
default: false
|
||||
required:
|
||||
- device_name
|
||||
- device_serial
|
||||
@@ -47112,6 +47120,9 @@ components:
|
||||
snapshot_expiry:
|
||||
type: string
|
||||
minLength: 1
|
||||
ephemeral_device_expiry:
|
||||
type: string
|
||||
minLength: 1
|
||||
auth_session_duration:
|
||||
type: string
|
||||
minLength: 1
|
||||
|
||||
Reference in New Issue
Block a user