Skip to content

Commit 173b538

Browse files
mgr/smb: add a new tls credential resource type
Add a new TLS credential resource type that can currently store one TLS certificate, TLS key, or TLS CA certificate. This is a new top-level resource so that they can be use across clusters or managed independently by different people and or private information can be kept out a cluster resource stored in a file committed somewhere. Signed-off-by: John Mulligan <[email protected]>
1 parent 39f73e2 commit 173b538

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

src/pybind/mgr/smb/resources.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import Dict, List, Optional, Tuple, Union, cast
22

33
import base64
4+
import dataclasses
45
import errno
56
import json
67

@@ -24,6 +25,7 @@
2425
LoginCategory,
2526
PasswordFilter,
2627
SMBClustering,
28+
TLSCredentialType,
2729
UserGroupSourceType,
2830
)
2931
from .proto import Self, Simplified
@@ -623,6 +625,50 @@ def convert(self, operation: ConversionOp) -> Self:
623625
)
624626

625627

628+
@resourcelib.resource('ceph.smb.tls.credential')
629+
class TLSCredential(_RBase):
630+
"""Contains a TLS certificate or key that can be used to configure
631+
SMB services that make use of TLS/SSL.
632+
"""
633+
634+
tls_credential_id: str
635+
intent: Intent = Intent.PRESENT
636+
credential_type: Optional[TLSCredentialType] = None
637+
value: Optional[str] = None
638+
# linked resources can only be used by the resource they are linked to
639+
# and are automatically removed when the "parent" resource is removed
640+
linked_to_cluster: Optional[str] = None
641+
642+
def validate(self) -> None:
643+
if not self.tls_credential_id:
644+
raise ValueError('tls_credential_id requires a value')
645+
validation.check_id(self.tls_credential_id)
646+
if self.linked_to_cluster is not None:
647+
validation.check_id(self.linked_to_cluster)
648+
if self.intent is Intent.PRESENT:
649+
if self.credential_type is None:
650+
raise ValueError('credential_type must be specified')
651+
if not self.value:
652+
raise ValueError('a value must be specified')
653+
654+
@resourcelib.customize
655+
def _customize_resource(rc: resourcelib.Resource) -> resourcelib.Resource:
656+
rc.value.wrapper_type = BigString
657+
return rc
658+
659+
def convert(self, operation: ConversionOp) -> Self:
660+
"""When hiding sensitive data hide TLS/SSL certs too. However, the
661+
BASE64 filter enum will act as a no-op. Our certs are already long
662+
Base64 encoded strings that are resistant to casual shoulder-surfing.
663+
"""
664+
if (
665+
operation == (PasswordFilter.NONE, PasswordFilter.HIDDEN)
666+
and self.value
667+
):
668+
return dataclasses.replace(self, value=_MASKED)
669+
return self
670+
671+
626672
# SMBResource is a union of all valid top-level smb resource types.
627673
SMBResource = Union[
628674
Cluster,
@@ -631,6 +677,7 @@ def convert(self, operation: ConversionOp) -> Self:
631677
RemovedShare,
632678
Share,
633679
UsersAndGroups,
680+
TLSCredential,
634681
]
635682

636683

0 commit comments

Comments
 (0)