From: Shweta Bhosale Date: Wed, 8 Apr 2026 13:26:17 +0000 (+0530) Subject: python-common: Validate Ingress spec peer/frontend/monitor ports X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e0db1494d70253bf4950cf398acf2483bc6e17ad;p=ceph.git python-common: Validate Ingress spec peer/frontend/monitor ports Fixes: https://tracker.ceph.com/issues/75704 Signed-off-by: Shweta Bhosale --- diff --git a/src/python-common/ceph/deployment/service_spec.py b/src/python-common/ceph/deployment/service_spec.py index 95d30222ab9d..b48efbedd298 100644 --- a/src/python-common/ceph/deployment/service_spec.py +++ b/src/python-common/ceph/deployment/service_spec.py @@ -37,7 +37,7 @@ from ceph.deployment.hostspec import HostSpec, SpecValidationError, assert_valid from ceph.deployment.utils import unwrap_ipv6, valid_addr, verify_non_negative_int from ceph.deployment.utils import verify_positive_int, verify_non_negative_number from ceph.deployment.utils import verify_boolean, verify_enum, verify_int -from ceph.deployment.utils import parse_combined_pem_file +from ceph.deployment.utils import parse_combined_pem_file, validate_port, validate_unique_ports from ceph.cephadm.d3n_types import D3NCacheSpec, D3NCacheError from ceph.utils import is_hex from ceph.smb import constants as smbconst @@ -2366,7 +2366,7 @@ class IngressSpec(ServiceSpec): is_nfs_backend = bool( self.backend_service and self.backend_service.split('.')[0] == 'nfs' ) - if self.haproxy_peer_communication_port or is_nfs_backend: + if self.haproxy_peer_communication_port is not None or is_nfs_backend: ports.append(cast(int, self.haproxy_peer_communication_port) or 1024) return ports @@ -2398,11 +2398,23 @@ class IngressSpec(ServiceSpec): raise SpecValidationError( f'Cannot add ingress: Invalid health_check_interval specified. ' f'Valid units are: {valid_units}') - if self.haproxy_peer_communication_port and self.backend_service.split('.')[0] != 'nfs': + if ( + self.haproxy_peer_communication_port is not None + and self.backend_service.split('.')[0] != 'nfs' + ): raise SpecValidationError( 'The haproxy_peer_communication_port is valid only for NFS backend.' ) + for port_val, fname in ( + (self.frontend_port, 'frontend_port'), + (self.monitor_port, 'monitor_port'), + (self.haproxy_peer_communication_port, 'haproxy_peer_communication_port'), + ): + if port_val is not None: + validate_port(port_val, fname) + validate_unique_ports(self.get_port_start()) + # validate SSL parametes if self.monitor_ssl: if not self.ssl: @@ -2504,7 +2516,7 @@ class MgmtGatewaySpec(ServiceSpec): def validate(self) -> None: super(MgmtGatewaySpec, self).validate() - self._validate_port(self.port) + validate_port(self.port, 'port') self._validate_certificate(self.ssl_cert, "ssl_cert") self._validate_private_key(self.ssl_key, "ssl_key") self._validate_boolean_switch(self.ssl_prefer_server_ciphers, "ssl_prefer_server_ciphers") @@ -2516,10 +2528,6 @@ class MgmtGatewaySpec(ServiceSpec): self._validate_boolean_switch(self.ssl_stapling_verify, "ssl_stapling_verify") self._validate_ssl_protocols(self.ssl_protocols) - def _validate_port(self, port: Optional[int]) -> None: - if port is not None and not (1 <= port <= 65535): - raise SpecValidationError(f"Invalid port: {port}. Must be between 1 and 65535.") - def _validate_certificate(self, cert: Optional[str], name: str) -> None: if cert is not None and not isinstance(cert, str): raise SpecValidationError(f"Invalid {name}. Must be a string.") diff --git a/src/python-common/ceph/deployment/utils.py b/src/python-common/ceph/deployment/utils.py index f28573b03fa5..3e901669f5cf 100644 --- a/src/python-common/ceph/deployment/utils.py +++ b/src/python-common/ceph/deployment/utils.py @@ -1,6 +1,6 @@ import ipaddress import socket -from typing import Tuple, Optional, Any +from typing import Tuple, Optional, Any, List from urllib.parse import urlparse from ceph.deployment.hostspec import SpecValidationError from numbers import Number @@ -176,3 +176,18 @@ def verify_enum(field: Any, field_name: str, allowed: list) -> None: if field.lower() not in allowed_lower: raise SpecValidationError( f'Invalid {field_name}. Valid values are: {", ".join(allowed)}') + + +def validate_port(port: Optional[int], field_name: str = 'port') -> None: + if port is not None and not (1 <= port <= 65535): + raise SpecValidationError( + f'Invalid {field_name}: {port}. Must be between 1 and 65535.' + ) + + +def validate_unique_ports(ports: List[int]) -> None: + """Raise SpecValidationError if any port is used more than once""" + if len(ports) != len(set(ports)): + raise SpecValidationError( + 'Invalid port: Duplicate ports are not allowed' + )