From ab06ac1f1f604063b1e64c1eb1bbb7b38320fa78 Mon Sep 17 00:00:00 2001 From: wangruidong <940853815@qq.com> Date: Thu, 3 Jul 2025 19:22:23 +0800 Subject: [PATCH] perf: Update IP group validation to include address validation --- apps/acls/serializers/rules/rules.py | 17 ++++++++++++++++- apps/terminal/serializers/endpoint.py | 11 ++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/apps/acls/serializers/rules/rules.py b/apps/acls/serializers/rules/rules.py index 4c88d0ac7..956111648 100644 --- a/apps/acls/serializers/rules/rules.py +++ b/apps/acls/serializers/rules/rules.py @@ -1,5 +1,7 @@ # coding: utf-8 # +from urllib.parse import urlparse + from django.utils.translation import gettext_lazy as _ from rest_framework import serializers @@ -8,7 +10,7 @@ from common.utils.ip import is_ip_address, is_ip_network, is_ip_segment logger = get_logger(__file__) -__all__ = ['RuleSerializer', 'ip_group_child_validator', 'ip_group_help_text'] +__all__ = ['RuleSerializer', 'ip_group_child_validator', 'ip_group_help_text', 'address_validator'] def ip_group_child_validator(ip_group_child): @@ -21,6 +23,19 @@ def ip_group_child_validator(ip_group_child): raise serializers.ValidationError(error) +def address_validator(value): + parsed = urlparse(value) + is_basic_url = parsed.scheme in ('http', 'https') and parsed.netloc + is_valid = value == '*' \ + or is_ip_address(value) \ + or is_ip_network(value) \ + or is_ip_segment(value) \ + or is_basic_url + if not is_valid: + error = _('address invalid: `{}`').format(value) + raise serializers.ValidationError(error) + + ip_group_help_text = _( 'With * indicating a match all. ' 'Such as: ' diff --git a/apps/terminal/serializers/endpoint.py b/apps/terminal/serializers/endpoint.py index a9337f9da..5ece73ab3 100644 --- a/apps/terminal/serializers/endpoint.py +++ b/apps/terminal/serializers/endpoint.py @@ -1,7 +1,7 @@ from django.utils.translation import gettext_lazy as _ from rest_framework import serializers -from acls.serializers.rules import ip_group_child_validator, ip_group_help_text +from acls.serializers.rules import address_validator, ip_group_help_text from common.serializers import BulkModelSerializer from common.serializers.fields import ObjectRelatedField from ..models import Endpoint, EndpointRule @@ -16,7 +16,7 @@ class EndpointSerializer(BulkModelSerializer): fields_small = [ 'host', 'https_port', 'http_port', 'ssh_port', 'rdp_port', 'mysql_port', 'mariadb_port', 'postgresql_port', 'redis_port', 'vnc_port', - 'oracle_port', 'sqlserver_port', 'mongodb_port','is_active' + 'oracle_port', 'sqlserver_port', 'mongodb_port', 'is_active' ] fields = fields_mini + fields_small + [ 'comment', 'date_created', 'date_updated', 'created_by' @@ -29,6 +29,7 @@ class EndpointSerializer(BulkModelSerializer): ) }, } + def get_extra_kwargs(self): extra_kwargs = super().get_extra_kwargs() model_fields = self.Meta.model._meta.fields @@ -49,13 +50,13 @@ class EndpointSerializer(BulkModelSerializer): class EndpointRuleSerializer(BulkModelSerializer): _ip_group_help_text = '{}, {}
{}'.format( - _('The assets within this IP range, the following endpoint will be used for the connection'), + _('The assets within this IP range or Host, the following endpoint will be used for the connection'), _('If asset IP addresses under different endpoints conflict, use asset labels'), ip_group_help_text, ) ip_group = serializers.ListField( - default=['*'], label=_('Asset IP'), help_text=_ip_group_help_text, - child=serializers.CharField(max_length=1024, validators=[ip_group_child_validator]) + default=['*'], label=_('Address'), help_text=_ip_group_help_text, + child=serializers.CharField(max_length=1024, validators=[address_validator]), ) endpoint = ObjectRelatedField( allow_null=True, required=False, queryset=Endpoint.objects, label=_('Endpoint')