Skip to content

Commit 91d4896

Browse files
authored
Merge pull request ceph#57712 from rhcs-dashboard/dashboard-nvmf-mtls-conf
mgr/dashboard: use secure_channel for grpc requests Reviewed-by: Adam King <[email protected]> Reviewed-by: baum <NOT@FOUND> Reviewed-by: Ernesto Puerta <[email protected]> Reviewed-by: Redouane Kachach <[email protected]>
2 parents e392142 + 5a89eae commit 91d4896

File tree

13 files changed

+352
-26
lines changed

13 files changed

+352
-26
lines changed

src/cephadm/cephadmlib/daemons/nvmeof.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,30 @@ def _get_container_mounts(data_dir: str, log_dir: str) -> Dict[str, str]:
7676
mounts[log_dir] = '/var/log/ceph:z'
7777
return mounts
7878

79+
def _get_tls_cert_key_mounts(
80+
self, data_dir: str, files: Dict[str, str]
81+
) -> Dict[str, str]:
82+
mounts = dict()
83+
for fn in [
84+
'server_cert',
85+
'server_key',
86+
'client_cert',
87+
'client_key',
88+
'root_ca_cert',
89+
]:
90+
if fn in files:
91+
mounts[
92+
os.path.join(data_dir, fn)
93+
] = f'/{fn.replace("_", ".")}'
94+
return mounts
95+
7996
def customize_container_mounts(
8097
self, ctx: CephadmContext, mounts: Dict[str, str]
8198
) -> None:
8299
data_dir = self.identity.data_dir(ctx.data_dir)
83100
log_dir = os.path.join(ctx.log_dir, self.identity.fsid)
84101
mounts.update(self._get_container_mounts(data_dir, log_dir))
102+
mounts.update(self._get_tls_cert_key_mounts(data_dir, self.files))
85103

86104
def customize_container_binds(
87105
self, ctx: CephadmContext, binds: List[List[str]]

src/pybind/mgr/cephadm/inventory.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
IngressSpec,
2020
RGWSpec,
2121
IscsiServiceSpec,
22+
NvmeofServiceSpec,
2223
)
2324
from ceph.utils import str_to_datetime, datetime_to_str, datetime_now
2425
from orchestrator import OrchestratorError, HostSpec, OrchestratorEvent, service_to_daemon_types
@@ -47,6 +48,26 @@ class HostCacheStatus(enum.Enum):
4748
devices = 'devices'
4849

4950

51+
class OrchSecretNotFound(OrchestratorError):
52+
def __init__(
53+
self,
54+
message: Optional[str] = '',
55+
entity: Optional[str] = '',
56+
service_name: Optional[str] = '',
57+
hostname: Optional[str] = ''
58+
):
59+
if not message:
60+
message = f'No secret found for entity {entity}'
61+
if service_name:
62+
message += f' with service name {service_name}'
63+
if hostname:
64+
message += f' with hostname {hostname}'
65+
super().__init__(message)
66+
self.entity = entity
67+
self.service_name = service_name
68+
self.hostname = hostname
69+
70+
5071
class Inventory:
5172
"""
5273
The inventory stores a HostSpec for all hosts persistently.
@@ -390,6 +411,31 @@ def _save_certs_and_keys(self, spec: ServiceSpec) -> None:
390411
ingress_spec.ssl_key,
391412
service_name=ingress_spec.service_name(),
392413
user_made=True)
414+
elif spec.service_type == 'nvmeof':
415+
nvmeof_spec = cast(NvmeofServiceSpec, spec)
416+
for cert_attr in [
417+
'server_cert',
418+
'client_cert',
419+
'root_ca_cert'
420+
]:
421+
cert = getattr(nvmeof_spec, cert_attr, None)
422+
if cert:
423+
self.mgr.cert_key_store.save_cert(
424+
f'nvmeof_{cert_attr}',
425+
cert,
426+
service_name=nvmeof_spec.service_name(),
427+
user_made=True)
428+
for key_attr in [
429+
'server_key',
430+
'client_key',
431+
]:
432+
key = getattr(nvmeof_spec, key_attr, None)
433+
if key:
434+
self.mgr.cert_key_store.save_key(
435+
f'nvmeof_{key_attr}',
436+
key,
437+
service_name=nvmeof_spec.service_name(),
438+
user_made=True)
393439

394440
def rm(self, service_name: str) -> bool:
395441
if service_name not in self._specs:
@@ -428,6 +474,12 @@ def _rm_certs_and_keys(self, spec: ServiceSpec) -> None:
428474
if spec.service_type == 'ingress':
429475
self.mgr.cert_key_store.rm_cert('ingress_ssl_cert', service_name=spec.service_name())
430476
self.mgr.cert_key_store.rm_key('ingress_ssl_key', service_name=spec.service_name())
477+
if spec.service_type == 'nvmeof':
478+
self.mgr.cert_key_store.rm_cert('nvmeof_server_cert', service_name=spec.service_name())
479+
self.mgr.cert_key_store.rm_cert('nvmeof_client_cert', service_name=spec.service_name())
480+
self.mgr.cert_key_store.rm_cert('nvmeof_root_ca_cert', service_name=spec.service_name())
481+
self.mgr.cert_key_store.rm_key('nvmeof_server_key', service_name=spec.service_name())
482+
self.mgr.cert_key_store.rm_key('nvmeof_client_key', service_name=spec.service_name())
431483

432484
def get_created(self, spec: ServiceSpec) -> Optional[datetime.datetime]:
433485
return self.spec_created.get(spec.service_name())
@@ -1853,6 +1905,9 @@ class CertKeyStore():
18531905
'rgw_frontend_ssl_cert',
18541906
'iscsi_ssl_cert',
18551907
'ingress_ssl_cert',
1908+
'nvmeof_server_cert',
1909+
'nvmeof_client_cert',
1910+
'nvmeof_root_ca_cert',
18561911
]
18571912

18581913
host_cert = [
@@ -1872,6 +1927,8 @@ class CertKeyStore():
18721927
service_name_key = [
18731928
'iscsi_ssl_key',
18741929
'ingress_ssl_key',
1930+
'nvmeof_server_key',
1931+
'nvmeof_client_key',
18751932
]
18761933

18771934
known_certs: Dict[str, Any] = {}
@@ -1888,6 +1945,9 @@ def _init_known_cert_key_dicts(self) -> None:
18881945
'rgw_frontend_ssl_cert': {}, # service-name -> cert
18891946
'iscsi_ssl_cert': {}, # service-name -> cert
18901947
'ingress_ssl_cert': {}, # service-name -> cert
1948+
'nvmeof_server_cert': {}, # service-name -> cert
1949+
'nvmeof_client_cert': {}, # service-name -> cert
1950+
'nvmeof_root_ca_cert': {}, # service-name -> cert
18911951
'agent_endpoint_root_cert': Cert(), # cert
18921952
'mgmt_gw_root_cert': Cert(), # cert
18931953
'service_discovery_root_cert': Cert(), # cert
@@ -1909,6 +1969,8 @@ def _init_known_cert_key_dicts(self) -> None:
19091969
'node_exporter_key': {}, # host -> key
19101970
'iscsi_ssl_key': {}, # service-name -> key
19111971
'ingress_ssl_key': {}, # service-name -> key
1972+
'nvmeof_server_key': {}, # service-name -> key
1973+
'nvmeof_client_key': {}, # service-name -> key
19121974
}
19131975

19141976
def get_cert(self, entity: str, service_name: str = '', host: str = '') -> str:

src/pybind/mgr/cephadm/module.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
TunedProfileStore,
8989
NodeProxyCache,
9090
CertKeyStore,
91+
OrchSecretNotFound,
9192
)
9293
from .upgrade import CephadmUpgrade
9394
from .template import TemplateMgr
@@ -3154,6 +3155,30 @@ def cert_store_cert_ls(self) -> Dict[str, Any]:
31543155
def cert_store_key_ls(self) -> Dict[str, Any]:
31553156
return self.cert_key_store.key_ls()
31563157

3158+
@handle_orch_error
3159+
def cert_store_get_cert(
3160+
self,
3161+
entity: str,
3162+
service_name: Optional[str] = None,
3163+
hostname: Optional[str] = None
3164+
) -> str:
3165+
cert = self.cert_key_store.get_cert(entity, service_name or '', hostname or '')
3166+
if not cert:
3167+
raise OrchSecretNotFound(entity=entity, service_name=service_name, hostname=hostname)
3168+
return cert
3169+
3170+
@handle_orch_error
3171+
def cert_store_get_key(
3172+
self,
3173+
entity: str,
3174+
service_name: Optional[str] = None,
3175+
hostname: Optional[str] = None
3176+
) -> str:
3177+
key = self.cert_key_store.get_key(entity, service_name or '', hostname or '')
3178+
if not key:
3179+
raise OrchSecretNotFound(entity=entity, service_name=service_name, hostname=hostname)
3180+
return key
3181+
31573182
@handle_orch_error
31583183
def apply_mon(self, spec: ServiceSpec) -> str:
31593184
return self._apply(spec)

src/pybind/mgr/cephadm/services/nvmeof.py

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ def prepare_create(self, daemon_spec: CephadmDaemonDeploySpec) -> CephadmDaemonD
5353

5454
daemon_spec.keyring = keyring
5555
daemon_spec.extra_files = {'ceph-nvmeof.conf': gw_conf}
56+
57+
if spec.enable_auth:
58+
if (
59+
not spec.client_cert
60+
or not spec.client_key
61+
or not spec.server_cert
62+
or not spec.server_key
63+
or not spec.root_ca_cert
64+
):
65+
err_msg = 'enable_auth is true but '
66+
for cert_key_attr in ['server_key', 'server_cert', 'client_key', 'client_cert', 'root_ca_cert']:
67+
if not hasattr(spec, cert_key_attr):
68+
err_msg += f'{cert_key_attr}, '
69+
err_msg += 'attribute(s) missing from nvmeof spec'
70+
self.mgr.log.error(err_msg)
71+
else:
72+
daemon_spec.extra_files['server_cert'] = spec.server_cert
73+
daemon_spec.extra_files['client_cert'] = spec.client_cert
74+
daemon_spec.extra_files['server_key'] = spec.server_key
75+
daemon_spec.extra_files['client_key'] = spec.client_key
76+
daemon_spec.extra_files['root_ca_cert'] = spec.root_ca_cert
77+
5678
daemon_spec.final_config, daemon_spec.deps = self.generate_config(daemon_spec)
5779
daemon_spec.deps = []
5880
return daemon_spec
@@ -67,9 +89,10 @@ def get_set_cmd_dicts(out: str) -> List[dict]:
6789

6890
for dd in daemon_descrs:
6991
assert dd.hostname is not None
92+
service_name = dd.service_name()
7093

7194
if not spec:
72-
logger.warning(f'No ServiceSpec found for {dd.service_name()}')
95+
logger.warning(f'No ServiceSpec found for {service_name}')
7396
continue
7497

7598
ip = utils.resolve_ip(self.mgr.inventory.get_addr(dd.hostname))
@@ -82,7 +105,7 @@ def get_set_cmd_dicts(out: str) -> List[dict]:
82105
cmd_dicts.append({
83106
'prefix': 'dashboard nvmeof-gateway-add',
84107
'inbuf': service_url,
85-
'name': dd.hostname
108+
'name': service_name
86109
})
87110
return cmd_dicts
88111

@@ -118,11 +141,12 @@ def post_remove(self, daemon: DaemonDescription, is_failed_deploy: bool) -> None
118141
"""
119142
# to clean the keyring up
120143
super().post_remove(daemon, is_failed_deploy=is_failed_deploy)
144+
service_name = daemon.service_name()
121145

122146
# remove config for dashboard nvmeof gateways if any
123147
ret, out, err = self.mgr.mon_command({
124148
'prefix': 'dashboard nvmeof-gateway-rm',
125-
'name': daemon.hostname,
149+
'name': service_name,
126150
})
127151
if not ret:
128152
logger.info(f'{daemon.hostname} removed from nvmeof gateways dashboard config')

src/pybind/mgr/cephadm/templates/services/nvmeof/ceph-nvmeof.conf.j2

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@ config_file = /etc/ceph/ceph.conf
4141
id = {{ rados_id }}
4242

4343
[mtls]
44-
server_key = {{ spec.server_key }}
45-
client_key = {{ spec.client_key }}
46-
server_cert = {{ spec.server_cert }}
47-
client_cert = {{ spec.client_cert }}
44+
server_key = /server.key
45+
client_key = /client.key
46+
server_cert = /server.cert
47+
client_cert = /client.cert
48+
root_ca_cert = /root.ca.cert
4849

4950
[spdk]
5051
tgt_path = {{ spec.tgt_path }}

0 commit comments

Comments
 (0)