Skip to content

Commit 657fe40

Browse files
mgr/smb: add tls credential and remote control support to handler
Use the new tls credential resource and remote control cluster field to configure the tls creds for the remote control sidecar in the service spec. Signed-off-by: John Mulligan <[email protected]>
1 parent b624222 commit 657fe40

File tree

1 file changed

+80
-2
lines changed

1 file changed

+80
-2
lines changed

src/pybind/mgr/smb/handler.py

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
ClusterEntry,
3333
JoinAuthEntry,
3434
ShareEntry,
35+
TLSCredentialEntry,
3536
UsersAndGroupsEntry,
3637
)
3738
from .proto import (
@@ -45,7 +46,13 @@
4546
)
4647
from .resources import SMBResource
4748
from .results import ErrorResult, Result, ResultGroup
48-
from .staging import Staging, auth_refs, cross_check_resource, ug_refs
49+
from .staging import (
50+
Staging,
51+
auth_refs,
52+
cross_check_resource,
53+
tls_refs,
54+
ug_refs,
55+
)
4956
from .utils import checked, ynbool
5057

5158
ClusterRef = Union[resources.Cluster, resources.RemovedCluster]
@@ -54,6 +61,7 @@
5461
_DOMAIN = 'domain'
5562
_CLUSTERED = 'clustered'
5663
_CEPHFS_PROXY = 'cephfs-proxy'
64+
_REMOTE_CONTROL = 'remote-control'
5765
log = logging.getLogger(__name__)
5866

5967

@@ -72,11 +80,13 @@ def __init__(
7280
shares: List[resources.Share],
7381
join_auths: List[resources.JoinAuth],
7482
users_and_groups: List[resources.UsersAndGroups],
83+
tls_credentials: List[resources.TLSCredential],
7584
):
7685
self.cluster = cluster
7786
self.shares = shares
7887
self.join_auths = join_auths
7988
self.users_and_groups = users_and_groups
89+
self.tls_credentials = tls_credentials
8090
# a cache for modified entries
8191
self.cache = config_store.EntryCache()
8292

@@ -446,6 +456,12 @@ def _sync_clusters(
446456
self._users_and_groups_entry(_id).get_users_and_groups()
447457
for _id in ug_refs(cluster)
448458
],
459+
[
460+
TLSCredentialEntry.from_store(
461+
self.internal_store, _id
462+
).get_tls_credential()
463+
for _id in tls_refs(cluster)
464+
],
449465
)
450466
change_groups.append(change_group)
451467
for change_group in change_groups:
@@ -479,6 +495,7 @@ def _find_modifications(self, updated: ResultGroup) -> Collection[str]:
479495
chg_cluster_ids: Set[str] = set()
480496
chg_join_ids: Set[str] = set()
481497
chg_ug_ids: Set[str] = set()
498+
chg_tls_ids: Set[str] = set()
482499
for result in updated:
483500
state = (result.status or {}).get('state', None)
484501
if state in (State.PRESENT, State.NOT_PRESENT):
@@ -497,11 +514,13 @@ def _find_modifications(self, updated: ResultGroup) -> Collection[str]:
497514
chg_join_ids.add(result.src.auth_id)
498515
elif isinstance(result.src, resources.UsersAndGroups):
499516
chg_ug_ids.add(result.src.users_groups_id)
517+
elif isinstance(result.src, resources.TLSCredential):
518+
chg_tls_ids.add(result.src.tls_credential_id)
500519

501520
# TODO: here's a lazy bit. if any join auths or users/groups changed we
502521
# will regen all clusters because these can be shared by >1 cluster.
503522
# In future, make this only pick clusters using the named resources.
504-
if chg_join_ids or chg_ug_ids:
523+
if chg_join_ids or chg_ug_ids or chg_tls_ids:
505524
chg_cluster_ids.update(ClusterEntry.ids(self.internal_store))
506525
return chg_cluster_ids
507526

@@ -525,6 +544,7 @@ def _save_cluster_settings(
525544
)
526545
_save_pending_join_auths(self.priv_store, change_group)
527546
_save_pending_users_and_groups(self.priv_store, change_group)
547+
_save_pending_tls_credentials(self.priv_store, change_group)
528548
_save_pending_config(
529549
self.public_store,
530550
change_group,
@@ -567,11 +587,22 @@ def _save_cluster_settings(
567587
change_group.cache, cluster.cluster_id
568588
)
569589
]
590+
tls_credential_entries = {
591+
tc.tls_credential_id: change_group.cache[
592+
external.tls_credential_key(
593+
cluster.cluster_id,
594+
tc.tls_credential_id,
595+
checked(tc.credential_type),
596+
)
597+
]
598+
for tc in change_group.tls_credentials
599+
}
570600
smb_spec = _generate_smb_service_spec(
571601
cluster,
572602
config_entries=config_entries,
573603
join_source_entries=join_source_entries,
574604
user_source_entries=user_source_entries,
605+
tls_credential_entries=tls_credential_entries,
575606
data_entity=data_entity,
576607
needs_proxy=_has_proxied_vfs(change_group),
577608
)
@@ -815,6 +846,7 @@ def _generate_smb_service_spec(
815846
config_entries: List[ConfigEntry],
816847
join_source_entries: List[ConfigEntry],
817848
user_source_entries: List[ConfigEntry],
849+
tls_credential_entries: Dict[str, ConfigEntry],
818850
data_entity: str = '',
819851
needs_proxy: bool = False,
820852
) -> SMBSpec:
@@ -825,6 +857,8 @@ def _generate_smb_service_spec(
825857
features.append(_CLUSTERED)
826858
if needs_proxy:
827859
features.append(_CEPHFS_PROXY)
860+
if cluster.remote_control_is_enabled:
861+
features.append(_REMOTE_CONTROL)
828862
# only one config uri can be used, the input list should be
829863
# ordered from lowest to highest priority and the highest priority
830864
# item that exists in the store will be used.
@@ -846,6 +880,16 @@ def _generate_smb_service_spec(
846880
user_entities: Optional[List[str]] = None
847881
if data_entity:
848882
user_entities = [data_entity]
883+
rc_cert = rc_key = rc_ca_cert = None
884+
if cluster.remote_control_is_enabled:
885+
assert cluster.remote_control
886+
rc_cert = _tls_uri(
887+
cluster.remote_control.cert, tls_credential_entries
888+
)
889+
rc_key = _tls_uri(cluster.remote_control.key, tls_credential_entries)
890+
rc_ca_cert = _tls_uri(
891+
cluster.remote_control.ca_cert, tls_credential_entries
892+
)
849893
return SMBSpec(
850894
service_id=cluster.cluster_id,
851895
placement=cluster.placement,
@@ -859,6 +903,9 @@ def _generate_smb_service_spec(
859903
cluster_public_addrs=cluster.service_spec_public_addrs(),
860904
custom_ports=cluster.custom_ports,
861905
bind_addrs=cluster.service_spec_bind_addrs(),
906+
remote_control_ssl_cert=rc_cert,
907+
remote_control_ssl_key=rc_key,
908+
remote_control_ca_cert=rc_ca_cert,
862909
)
863910

864911

@@ -941,6 +988,27 @@ def _save_pending_users_and_groups(
941988
change_group.cache_updated_entry(ugentry)
942989

943990

991+
def _save_pending_tls_credentials(
992+
store: ConfigStore,
993+
change_group: ClusterChangeGroup,
994+
) -> None:
995+
cluster = change_group.cluster
996+
assert isinstance(cluster, resources.Cluster)
997+
refs = tls_refs(cluster)
998+
tls_creds = {t.tls_credential_id: t for t in change_group.tls_credentials}
999+
for ref in refs:
1000+
tc = tls_creds[ref]
1001+
ext_key = external.tls_credential_key(
1002+
cluster.cluster_id, ref, str(tc.credential_type)
1003+
)
1004+
tc_entry = store[ext_key]
1005+
if hasattr(tc_entry, 'set_data'):
1006+
tc_entry.set_data(tc.value)
1007+
else:
1008+
raise ValueError('store does not support raw entries')
1009+
change_group.cache_updated_entry(tc_entry)
1010+
1011+
9441012
def _save_pending_config(
9451013
store: ConfigStore,
9461014
change_group: ClusterChangeGroup,
@@ -997,3 +1065,13 @@ def _has_proxied_vfs(change_group: ClusterChangeGroup) -> bool:
9971065

9981066
def _smb_port(cluster: resources.Cluster, default: int = 445) -> int:
9991067
return (cluster.custom_ports or {}).get("smb", default)
1068+
1069+
1070+
def _tls_uri(
1071+
src: Optional[resources.TLSSource],
1072+
tls_credential_entries: Dict[str, ConfigEntry],
1073+
) -> Optional[str]:
1074+
if src is None:
1075+
return None
1076+
uri = tls_credential_entries[src.ref].uri
1077+
return f'URI:{uri}'

0 commit comments

Comments
 (0)