authentik.endpoints.facts

  1from django.db.models import TextChoices
  2from django.utils.translation import gettext_lazy as _
  3from drf_spectacular.extensions import OpenApiSerializerFieldExtension
  4from drf_spectacular.plumbing import build_basic_type
  5from drf_spectacular.types import OpenApiTypes
  6from rest_framework.serializers import (
  7    BooleanField,
  8    CharField,
  9    ChoiceField,
 10    IntegerField,
 11    ListField,
 12    Serializer,
 13)
 14
 15from authentik.core.api.utils import JSONDictField
 16
 17
 18class BigIntegerFieldFix(OpenApiSerializerFieldExtension):
 19    target_class = "authentik.endpoints.facts.BigIntegerField"
 20
 21    def map_serializer_field(self, auto_schema, direction):
 22        return build_basic_type(OpenApiTypes.INT64)
 23
 24
 25class BigIntegerField(IntegerField): ...
 26
 27
 28class OSFamily(TextChoices):
 29    linux = "linux"
 30    unix = "unix"
 31    bsd = "bsd"
 32    windows = "windows"
 33    macOS = "mac_os"
 34    android = "android"
 35    iOS = "i_os"
 36    other = "other"
 37
 38
 39class DiskSerializer(Serializer):
 40    name = CharField(required=True)
 41    mountpoint = CharField(required=True)
 42    label = CharField(required=False, allow_blank=True)
 43    capacity_total_bytes = BigIntegerField(required=False)
 44    capacity_used_bytes = BigIntegerField(required=False)
 45    encryption_enabled = BooleanField(default=False, required=False)
 46
 47
 48class OperatingSystemSerializer(Serializer):
 49    """For example:
 50    {"family":"linux","name":"Ubuntu","version":"24.04.3 LTS (Noble Numbat)","arch":"amd64"}
 51    {"family": "windows","name":"Server 2022 Datacenter","version":"10.0.20348.4405","arch":"amd64"}
 52    {"family": "windows","name":"Server 2022 Datacenter","version":"10.0.20348.4405","arch":"amd64"}
 53    {"family": "mac_os", "name": "", "version": "26.2", "arch": "arm64"}
 54    """
 55
 56    family = ChoiceField(OSFamily.choices, required=True)
 57    name = CharField(
 58        required=False, help_text=_("Operating System name, such as 'Server 2022' or 'Ubuntu'")
 59    )
 60    version = CharField(
 61        required=False,
 62        help_text=_(
 63            "Operating System version, must always be the version number but may contain build name"
 64        ),
 65    )
 66    arch = CharField(required=False)
 67
 68
 69class NetworkInterfaceSerializer(Serializer):
 70    name = CharField(required=True)
 71    hardware_address = CharField(required=True)
 72    ip_addresses = ListField(child=CharField(), required=False)
 73    dns_servers = ListField(child=CharField(), required=False, allow_empty=True)
 74
 75
 76class NetworkSerializer(Serializer):
 77    hostname = CharField()
 78    firewall_enabled = BooleanField(required=False)
 79    interfaces = ListField(child=NetworkInterfaceSerializer(), allow_empty=True)
 80    gateway = CharField(required=False)
 81
 82
 83class HardwareSerializer(Serializer):
 84    model = CharField(required=False)
 85    manufacturer = CharField(required=False)
 86    serial = CharField()
 87
 88    cpu_name = CharField(required=False)
 89    cpu_count = IntegerField(required=False)
 90
 91    memory_bytes = BigIntegerField(required=False)
 92
 93
 94class SoftwareSerializer(Serializer):
 95    name = CharField(required=True)
 96    version = CharField(required=False, allow_blank=True)
 97    # Package manager/source for this software installation
 98    source = CharField(required=True)
 99    path = CharField(required=False)
100
101
102class ProcessSerializer(Serializer):
103    id = IntegerField(required=True)
104    name = CharField()
105    user = CharField(required=False)
106
107
108class DeviceUserSerializer(Serializer):
109    id = CharField(required=True)
110    username = CharField(required=False)
111    name = CharField(required=False)
112    home = CharField(required=False)
113
114
115class DeviceGroupSerializer(Serializer):
116    id = CharField(required=True)
117    name = CharField(required=False)
118
119
120class DeviceFacts(Serializer):
121    os = OperatingSystemSerializer(required=False, allow_null=True)
122    disks = ListField(child=DiskSerializer(), required=False, allow_null=True)
123    network = NetworkSerializer(required=False, allow_null=True)
124    hardware = HardwareSerializer(required=False, allow_null=True)
125    software = ListField(child=SoftwareSerializer(), required=False, allow_null=True)
126    processes = ListField(child=ProcessSerializer(), required=False, allow_null=True)
127    users = ListField(child=DeviceUserSerializer(), required=False, allow_null=True)
128    groups = ListField(child=DeviceGroupSerializer(), required=False, allow_null=True)
129    vendor = JSONDictField(required=False)
class BigIntegerFieldFix(drf_spectacular.plumbing.OpenApiGeneratorExtension[ForwardRef('OpenApiSerializerFieldExtension')]):
19class BigIntegerFieldFix(OpenApiSerializerFieldExtension):
20    target_class = "authentik.endpoints.facts.BigIntegerField"
21
22    def map_serializer_field(self, auto_schema, direction):
23        return build_basic_type(OpenApiTypes.INT64)

Extension for replacing an insufficient or specifying an unknown SerializerField schema.

To augment the default schema, you can get what drf-spectacular would generate with auto_schema._map_serializer_field(self.target, direction, bypass_extensions=True). and edit the returned schema at your discretion. Beware that this may still emit warnings, in which case manual construction is advisable.

map_serializer_field() is expected to return a valid OpenAPI schema object <https://spec.openapis.org/oas/v3.0.3#schema-object>_.

target_class = 'BigIntegerField'
def map_serializer_field(self, auto_schema, direction):
22    def map_serializer_field(self, auto_schema, direction):
23        return build_basic_type(OpenApiTypes.INT64)

override for customized serializer field mapping

class BigIntegerField(rest_framework.fields.IntegerField):
26class BigIntegerField(IntegerField): ...
class OSFamily(django.db.models.enums.TextChoices):
29class OSFamily(TextChoices):
30    linux = "linux"
31    unix = "unix"
32    bsd = "bsd"
33    windows = "windows"
34    macOS = "mac_os"
35    android = "android"
36    iOS = "i_os"
37    other = "other"

Class for creating enumerated string choices.

linux = OSFamily.linux
unix = OSFamily.unix
bsd = OSFamily.bsd
windows = OSFamily.windows
macOS = OSFamily.macOS
android = OSFamily.android
iOS = OSFamily.iOS
other = OSFamily.other
class DiskSerializer(rest_framework.serializers.Serializer):
40class DiskSerializer(Serializer):
41    name = CharField(required=True)
42    mountpoint = CharField(required=True)
43    label = CharField(required=False, allow_blank=True)
44    capacity_total_bytes = BigIntegerField(required=False)
45    capacity_used_bytes = BigIntegerField(required=False)
46    encryption_enabled = BooleanField(default=False, required=False)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

name
mountpoint
label
capacity_total_bytes
capacity_used_bytes
encryption_enabled
class OperatingSystemSerializer(rest_framework.serializers.Serializer):
49class OperatingSystemSerializer(Serializer):
50    """For example:
51    {"family":"linux","name":"Ubuntu","version":"24.04.3 LTS (Noble Numbat)","arch":"amd64"}
52    {"family": "windows","name":"Server 2022 Datacenter","version":"10.0.20348.4405","arch":"amd64"}
53    {"family": "windows","name":"Server 2022 Datacenter","version":"10.0.20348.4405","arch":"amd64"}
54    {"family": "mac_os", "name": "", "version": "26.2", "arch": "arm64"}
55    """
56
57    family = ChoiceField(OSFamily.choices, required=True)
58    name = CharField(
59        required=False, help_text=_("Operating System name, such as 'Server 2022' or 'Ubuntu'")
60    )
61    version = CharField(
62        required=False,
63        help_text=_(
64            "Operating System version, must always be the version number but may contain build name"
65        ),
66    )
67    arch = CharField(required=False)

For example: {"family":"linux","name":"Ubuntu","version":"24.04.3 LTS (Noble Numbat)","arch":"amd64"} {"family": "windows","name":"Server 2022 Datacenter","version":"10.0.20348.4405","arch":"amd64"} {"family": "windows","name":"Server 2022 Datacenter","version":"10.0.20348.4405","arch":"amd64"} {"family": "mac_os", "name": "", "version": "26.2", "arch": "arm64"}

family
name
version
arch
class NetworkInterfaceSerializer(rest_framework.serializers.Serializer):
70class NetworkInterfaceSerializer(Serializer):
71    name = CharField(required=True)
72    hardware_address = CharField(required=True)
73    ip_addresses = ListField(child=CharField(), required=False)
74    dns_servers = ListField(child=CharField(), required=False, allow_empty=True)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

name
hardware_address
ip_addresses
dns_servers
class NetworkSerializer(rest_framework.serializers.Serializer):
77class NetworkSerializer(Serializer):
78    hostname = CharField()
79    firewall_enabled = BooleanField(required=False)
80    interfaces = ListField(child=NetworkInterfaceSerializer(), allow_empty=True)
81    gateway = CharField(required=False)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

hostname
firewall_enabled
interfaces
gateway
class HardwareSerializer(rest_framework.serializers.Serializer):
84class HardwareSerializer(Serializer):
85    model = CharField(required=False)
86    manufacturer = CharField(required=False)
87    serial = CharField()
88
89    cpu_name = CharField(required=False)
90    cpu_count = IntegerField(required=False)
91
92    memory_bytes = BigIntegerField(required=False)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

model
manufacturer
serial
cpu_name
cpu_count
memory_bytes
class SoftwareSerializer(rest_framework.serializers.Serializer):
 95class SoftwareSerializer(Serializer):
 96    name = CharField(required=True)
 97    version = CharField(required=False, allow_blank=True)
 98    # Package manager/source for this software installation
 99    source = CharField(required=True)
100    path = CharField(required=False)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

name
version
source
path
class ProcessSerializer(rest_framework.serializers.Serializer):
103class ProcessSerializer(Serializer):
104    id = IntegerField(required=True)
105    name = CharField()
106    user = CharField(required=False)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

id
name
user
class DeviceUserSerializer(rest_framework.serializers.Serializer):
109class DeviceUserSerializer(Serializer):
110    id = CharField(required=True)
111    username = CharField(required=False)
112    name = CharField(required=False)
113    home = CharField(required=False)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

id
username
name
home
class DeviceGroupSerializer(rest_framework.serializers.Serializer):
116class DeviceGroupSerializer(Serializer):
117    id = CharField(required=True)
118    name = CharField(required=False)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

id
name
class DeviceFacts(rest_framework.serializers.Serializer):
121class DeviceFacts(Serializer):
122    os = OperatingSystemSerializer(required=False, allow_null=True)
123    disks = ListField(child=DiskSerializer(), required=False, allow_null=True)
124    network = NetworkSerializer(required=False, allow_null=True)
125    hardware = HardwareSerializer(required=False, allow_null=True)
126    software = ListField(child=SoftwareSerializer(), required=False, allow_null=True)
127    processes = ListField(child=ProcessSerializer(), required=False, allow_null=True)
128    users = ListField(child=DeviceUserSerializer(), required=False, allow_null=True)
129    groups = ListField(child=DeviceGroupSerializer(), required=False, allow_null=True)
130    vendor = JSONDictField(required=False)

The BaseSerializer class provides a minimal class which may be used for writing custom serializer implementations.

Note that we strongly restrict the ordering of operations/properties that may be used on the serializer in order to enforce correct usage.

In particular, if a data= argument is passed then:

.is_valid() - Available. .initial_data - Available. .validated_data - Only available after calling is_valid() .errors - Only available after calling is_valid() .data - Only available after calling is_valid()

If a data= argument is not passed then:

.is_valid() - Not available. .initial_data - Not available. .validated_data - Not available. .errors - Not available. .data - Available.

os
disks
network
hardware
software
processes
users
groups
vendor