]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/smb: initial support for content conversions - password filtering
authorJohn Mulligan <jmulligan@redhat.com>
Wed, 12 Mar 2025 18:28:15 +0000 (14:28 -0400)
committerJohn Mulligan <jmulligan@redhat.com>
Tue, 1 Apr 2025 12:02:39 +0000 (08:02 -0400)
Add the core of a basic support for converting the content of various
resources. The current goal being filtering passwords to either obscure
them (base64) or hide them (hidden). The default continues to be plain
text as before.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
src/pybind/mgr/smb/enums.py
src/pybind/mgr/smb/resources.py

index 7f7b04df55936e6b042b9954c8cd453257a38356..5606c3faf3c8620b7d453e6dff33e7da6ca32e6a 100644 (file)
@@ -107,3 +107,11 @@ class SMBClustering(_StrEnum):
 class ShowResults(_StrEnum):
     FULL = 'full'
     COLLAPSED = 'collapsed'
+
+
+class PasswordFilter(_StrEnum):
+    """Filter type for password values."""
+
+    NONE = 'none'
+    BASE64 = 'base64'
+    HIDDEN = 'hidden'
index d91485f9992bb4a9e2e419db77e3996c404433b7..13e4165bd802269fecac6061ce44c999d4fcffd6 100644 (file)
@@ -1,5 +1,6 @@
 from typing import Dict, List, Optional, Tuple, Union, cast
 
+import base64
 import errno
 import json
 
@@ -20,12 +21,15 @@ from .enums import (
     JoinSourceType,
     LoginAccess,
     LoginCategory,
+    PasswordFilter,
     SMBClustering,
     UserGroupSourceType,
 )
 from .proto import Self, Simplified
 from .utils import checked
 
+ConversionOp = Tuple[PasswordFilter, PasswordFilter]
+
 
 def _get_intent(data: Simplified) -> Intent:
     """Helper function that returns the intent value from a data dict."""
@@ -94,6 +98,9 @@ class _RBase:
         rc = getattr(self, '_resource_config')
         return rc.object_to_simplified(self)
 
+    def convert(self, operation: ConversionOp) -> Self:
+        return self
+
 
 @resourcelib.component()
 class CephFSStorage(_RBase):
@@ -240,6 +247,12 @@ class JoinAuthValues(_RBase):
     username: str
     password: str
 
+    def convert(self, operation: ConversionOp) -> Self:
+        return self.__class__(
+            username=self.username,
+            password=_password_convert(self.password, operation),
+        )
+
 
 @resourcelib.component()
 class JoinSource(_RBase):
@@ -471,6 +484,14 @@ class JoinAuth(_RBase):
         rc.on_construction_error(InvalidResourceError.wrap)
         return rc
 
+    def convert(self, operation: ConversionOp) -> Self:
+        return self.__class__(
+            auth_id=self.auth_id,
+            intent=self.intent,
+            auth=None if not self.auth else self.auth.convert(operation),
+            linked_to_cluster=self.linked_to_cluster,
+        )
+
 
 @resourcelib.resource('ceph.smb.usersgroups')
 class UsersAndGroups(_RBase):
@@ -537,3 +558,18 @@ def load(data: Simplified) -> List[SMBResource]:
     structured types.
     """
     return resourcelib.load(data)
+
+
+def _password_convert(pvalue: str, operation: ConversionOp) -> str:
+    if operation == (PasswordFilter.NONE, PasswordFilter.BASE64):
+        pvalue = base64.b64encode(pvalue.encode("utf8")).decode("utf8")
+    elif operation == (PasswordFilter.NONE, PasswordFilter.HIDDEN):
+        pvalue = "*" * 16
+    elif operation == (PasswordFilter.BASE64, PasswordFilter.NONE):
+        pvalue = base64.b64decode(pvalue.encode("utf8")).decode("utf8")
+    else:
+        osrc, odst = operation
+        raise ValueError(
+            f"can not convert password value encoding from {osrc} to {odst}"
+        )
+    return pvalue