From: John Mulligan Date: Wed, 7 Feb 2024 21:15:28 +0000 (-0500) Subject: pybind/mgr/smb: add validation.py for generic module validation funcs X-Git-Tag: v20.0.0~2047^2~25 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=467b784590141869c83a3b407dffd37e0fb2986e;p=ceph.git pybind/mgr/smb: add validation.py for generic module validation funcs Signed-off-by: John Mulligan --- diff --git a/src/pybind/mgr/smb/validation.py b/src/pybind/mgr/smb/validation.py new file mode 100644 index 000000000000..3e04650dea95 --- /dev/null +++ b/src/pybind/mgr/smb/validation.py @@ -0,0 +1,62 @@ +import posixpath +import re + +# Initially, this regex is pretty restrictive. But I (JJM) find that +# starting out more restricitive is better than not because it's generally +# easier to relax strict rules then discover someone relies on lax rules +# that fail somewhere and now you've got backwards-compatibilty issues +# to worry about. +# +# The names are valid dns fragments as well since the cluster_id can be +# combined with the hostname for a virtual hostname for the container. +_name_re = re.compile('^[a-zA-Z0-9]($|[a-zA-Z0-9-]{,16}[a-zA-Z0-9]$)') + +# We might want to open up share names to non-special unicode chars too. +# but as above it's easier to start strict. +_share_re = re.compile('^[a-zA-Z0-9_][a-zA-Z0-9. _-]{,63}$') + + +def valid_id(value: str) -> bool: + """Return true if value is a valid (cluster|share|etc) ID.""" + return bool(_name_re.match(value)) + + +def check_id(value: str) -> None: + """Raise ValueError if value is not a valid ID.""" + if not valid_id(value): + raise ValueError(f"{value:!r} is not a valid ID") + + +def valid_share_name(value: str) -> bool: + """Return true if value is a valid share name.""" + return bool(_share_re.match(value)) + + +def check_share_name(value: str) -> None: + """Raise ValueError if value is not a valid share name.""" + if not valid_share_name(value): + raise ValueError(f"{value:!r} is not a valid share name") + + +# alias for normpath so other smb libs can just import validation module +normalize_path = posixpath.normpath + + +def valid_path(value: str) -> bool: + """Return true if value is a valid path for a share.""" + path = normalize_path(value) + # ensure that post-normalization there are no relative path elements or + # empty segments + if path == '/': + # special case / to refer to the root of the volume/subvolume. + # it is always valid. + return True + return not any( + p in ('.', '..', '') for p in path.lstrip('/').split(posixpath.sep) + ) + + +def check_path(value: str) -> None: + """Raise ValueError if value is not a valid share path.""" + if not valid_path(value): + raise ValueError(f'{value!r} is not a valid share path')