mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-24 17:38:37 -06:00
Introduce IPNetworkSerializer to serialize allowed token IPs
This commit is contained in:
parent
e3b7bba84f
commit
3c15419bd0
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
#### PoE Interface Attributes ([#1099](https://github.com/netbox-community/netbox/issues/1099))
|
#### PoE Interface Attributes ([#1099](https://github.com/netbox-community/netbox/issues/1099))
|
||||||
|
|
||||||
|
#### Restrict API Tokens by Client IP ([#8233](https://github.com/netbox-community/netbox/issues/8233))
|
||||||
|
|
||||||
### Enhancements
|
### Enhancements
|
||||||
|
|
||||||
* [#1202](https://github.com/netbox-community/netbox/issues/1202) - Support overlapping assignment of NAT IP addresses
|
* [#1202](https://github.com/netbox-community/netbox/issues/1202) - Support overlapping assignment of NAT IP addresses
|
||||||
@ -21,7 +23,6 @@
|
|||||||
* [#7120](https://github.com/netbox-community/netbox/issues/7120) - Add `termination_date` field to Circuit
|
* [#7120](https://github.com/netbox-community/netbox/issues/7120) - Add `termination_date` field to Circuit
|
||||||
* [#7744](https://github.com/netbox-community/netbox/issues/7744) - Add `status` field to Location
|
* [#7744](https://github.com/netbox-community/netbox/issues/7744) - Add `status` field to Location
|
||||||
* [#8222](https://github.com/netbox-community/netbox/issues/8222) - Enable the assignment of a VM to a specific host device within a cluster
|
* [#8222](https://github.com/netbox-community/netbox/issues/8222) - Enable the assignment of a VM to a specific host device within a cluster
|
||||||
* [#8233](https://github.com/netbox-community/netbox/issues/8233) - Restrict API token access by source IP
|
|
||||||
* [#8471](https://github.com/netbox-community/netbox/issues/8471) - Add `status` field to Cluster
|
* [#8471](https://github.com/netbox-community/netbox/issues/8471) - Add `status` field to Cluster
|
||||||
* [#8495](https://github.com/netbox-community/netbox/issues/8495) - Enable custom field grouping
|
* [#8495](https://github.com/netbox-community/netbox/issues/8495) - Enable custom field grouping
|
||||||
* [#8995](https://github.com/netbox-community/netbox/issues/8995) - Enable arbitrary ordering of REST API results
|
* [#8995](https://github.com/netbox-community/netbox/issues/8995) - Enable arbitrary ordering of REST API results
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from .fields import ChoiceField, ContentTypeField, SerializedPKRelatedField
|
from .fields import *
|
||||||
from .routers import NetBoxRouter
|
from .routers import NetBoxRouter
|
||||||
from .serializers import BulkOperationSerializer, ValidatedModelSerializer, WritableNestedSerializer
|
from .serializers import BulkOperationSerializer, ValidatedModelSerializer, WritableNestedSerializer
|
||||||
|
|
||||||
@ -7,6 +7,7 @@ __all__ = (
|
|||||||
'BulkOperationSerializer',
|
'BulkOperationSerializer',
|
||||||
'ChoiceField',
|
'ChoiceField',
|
||||||
'ContentTypeField',
|
'ContentTypeField',
|
||||||
|
'IPNetworkSerializer',
|
||||||
'NetBoxRouter',
|
'NetBoxRouter',
|
||||||
'SerializedPKRelatedField',
|
'SerializedPKRelatedField',
|
||||||
'ValidatedModelSerializer',
|
'ValidatedModelSerializer',
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
import pytz
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from netaddr import IPNetwork
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
|
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
'ChoiceField',
|
||||||
|
'ContentTypeField',
|
||||||
|
'IPNetworkSerializer',
|
||||||
|
'SerializedPKRelatedField',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class ChoiceField(serializers.Field):
|
class ChoiceField(serializers.Field):
|
||||||
"""
|
"""
|
||||||
@ -104,6 +110,17 @@ class ContentTypeField(RelatedField):
|
|||||||
return f"{obj.app_label}.{obj.model}"
|
return f"{obj.app_label}.{obj.model}"
|
||||||
|
|
||||||
|
|
||||||
|
class IPNetworkSerializer(serializers.Serializer):
|
||||||
|
"""
|
||||||
|
Representation of an IP network value (e.g. 192.0.2.0/24).
|
||||||
|
"""
|
||||||
|
def to_representation(self, instance):
|
||||||
|
return str(instance)
|
||||||
|
|
||||||
|
def to_internal_value(self, value):
|
||||||
|
return IPNetwork(value)
|
||||||
|
|
||||||
|
|
||||||
class SerializedPKRelatedField(PrimaryKeyRelatedField):
|
class SerializedPKRelatedField(PrimaryKeyRelatedField):
|
||||||
"""
|
"""
|
||||||
Extends PrimaryKeyRelatedField to return a serialized object on read. This is useful for representing related
|
Extends PrimaryKeyRelatedField to return a serialized object on read. This is useful for representing related
|
||||||
|
@ -2,7 +2,7 @@ from django.contrib.auth.models import Group, User
|
|||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from netbox.api import ContentTypeField, SerializedPKRelatedField, ValidatedModelSerializer
|
from netbox.api import ContentTypeField, IPNetworkSerializer, SerializedPKRelatedField, ValidatedModelSerializer
|
||||||
from users.models import ObjectPermission, Token
|
from users.models import ObjectPermission, Token
|
||||||
from .nested_serializers import *
|
from .nested_serializers import *
|
||||||
|
|
||||||
@ -64,6 +64,7 @@ class TokenSerializer(ValidatedModelSerializer):
|
|||||||
url = serializers.HyperlinkedIdentityField(view_name='users-api:token-detail')
|
url = serializers.HyperlinkedIdentityField(view_name='users-api:token-detail')
|
||||||
key = serializers.CharField(min_length=40, max_length=40, allow_blank=True, required=False)
|
key = serializers.CharField(min_length=40, max_length=40, allow_blank=True, required=False)
|
||||||
user = NestedUserSerializer()
|
user = NestedUserSerializer()
|
||||||
|
allowed_ips = serializers.ListField(child=IPNetworkSerializer())
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Token
|
model = Token
|
||||||
|
@ -4,12 +4,12 @@ import os
|
|||||||
from django.contrib.auth.models import Group, User
|
from django.contrib.auth.models import Group, User
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.contrib.postgres.fields import ArrayField
|
from django.contrib.postgres.fields import ArrayField
|
||||||
from django.core.exceptions import ValidationError
|
|
||||||
from django.core.validators import MinLengthValidator
|
from django.core.validators import MinLengthValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from netaddr import IPNetwork
|
||||||
|
|
||||||
from ipam.fields import IPNetworkField
|
from ipam.fields import IPNetworkField
|
||||||
from netbox.config import get_config
|
from netbox.config import get_config
|
||||||
@ -17,8 +17,6 @@ from utilities.querysets import RestrictedQuerySet
|
|||||||
from utilities.utils import flatten_dict
|
from utilities.utils import flatten_dict
|
||||||
from .constants import *
|
from .constants import *
|
||||||
|
|
||||||
import ipaddress
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'ObjectPermission',
|
'ObjectPermission',
|
||||||
'Token',
|
'Token',
|
||||||
@ -259,7 +257,7 @@ class Token(models.Model):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
for ip_network in self.allowed_ips:
|
for ip_network in self.allowed_ips:
|
||||||
if client_ip in ipaddress.ip_network(ip_network):
|
if client_ip in IPNetwork(ip_network):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import ipaddress
|
from netaddr import IPAddress
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'get_client_ip',
|
'get_client_ip',
|
||||||
@ -19,7 +19,7 @@ def get_client_ip(request, additional_headers=()):
|
|||||||
if header in request.META:
|
if header in request.META:
|
||||||
client_ip = request.META[header].split(',')[0]
|
client_ip = request.META[header].split(',')[0]
|
||||||
try:
|
try:
|
||||||
return ipaddress.ip_address(client_ip)
|
return IPAddress(client_ip)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError(f"Invalid IP address set for {header}: {client_ip}")
|
raise ValueError(f"Invalid IP address set for {header}: {client_ip}")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user