From 145ca0a8b3d746da569b7041eb8fac15668be6bc Mon Sep 17 00:00:00 2001 From: Adam King Date: Wed, 3 Jul 2024 15:27:03 -0400 Subject: [PATCH] mgr/cephadm: integrate nvmeof spec certs/keys into cert/key store Now that we're taking actual certs/keys in the spec, they should go into the cert/key store with the others Signed-off-by: Adam King (cherry picked from commit 3b1ec5851902c6b672db2ea81ae7eebcb1002101) (cherry picked from commit 5f24d366af30bf8a4334e208daa9be2fcf024f3b) --- src/pybind/mgr/cephadm/inventory.py | 42 ++++++++++++ src/pybind/mgr/cephadm/tests/test_cephadm.py | 71 +++++++++++++++++++- 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/src/pybind/mgr/cephadm/inventory.py b/src/pybind/mgr/cephadm/inventory.py index f7d33d6d1ae..221918d25c7 100644 --- a/src/pybind/mgr/cephadm/inventory.py +++ b/src/pybind/mgr/cephadm/inventory.py @@ -19,6 +19,7 @@ from ceph.deployment.service_spec import ( IngressSpec, RGWSpec, IscsiServiceSpec, + NvmeofServiceSpec, ) from ceph.utils import str_to_datetime, datetime_to_str, datetime_now from orchestrator import OrchestratorError, HostSpec, OrchestratorEvent, service_to_daemon_types @@ -390,6 +391,31 @@ class SpecStore(): ingress_spec.ssl_key, service_name=ingress_spec.service_name(), user_made=True) + elif spec.service_type == 'nvmeof': + nvmeof_spec = cast(NvmeofServiceSpec, spec) + for cert_attr in [ + 'server_cert', + 'client_cert', + 'root_ca_cert' + ]: + cert = getattr(nvmeof_spec, cert_attr, None) + if cert: + self.mgr.cert_key_store.save_cert( + f'nvmeof_{cert_attr}', + cert, + service_name=nvmeof_spec.service_name(), + user_made=True) + for key_attr in [ + 'server_key', + 'client_key', + ]: + key = getattr(nvmeof_spec, key_attr, None) + if key: + self.mgr.cert_key_store.save_key( + f'nvmeof_{key_attr}', + key, + service_name=nvmeof_spec.service_name(), + user_made=True) def rm(self, service_name: str) -> bool: if service_name not in self._specs: @@ -428,6 +454,12 @@ class SpecStore(): if spec.service_type == 'ingress': self.mgr.cert_key_store.rm_cert('ingress_ssl_cert', service_name=spec.service_name()) self.mgr.cert_key_store.rm_key('ingress_ssl_key', service_name=spec.service_name()) + if spec.service_type == 'nvmeof': + self.mgr.cert_key_store.rm_cert('nvmeof_server_cert', service_name=spec.service_name()) + self.mgr.cert_key_store.rm_cert('nvmeof_client_cert', service_name=spec.service_name()) + self.mgr.cert_key_store.rm_cert('nvmeof_root_ca_cert', service_name=spec.service_name()) + self.mgr.cert_key_store.rm_key('nvmeof_server_key', service_name=spec.service_name()) + self.mgr.cert_key_store.rm_key('nvmeof_client_key', service_name=spec.service_name()) def get_created(self, spec: ServiceSpec) -> Optional[datetime.datetime]: return self.spec_created.get(spec.service_name()) @@ -1842,6 +1874,9 @@ class CertKeyStore(): 'rgw_frontend_ssl_cert', 'iscsi_ssl_cert', 'ingress_ssl_cert', + 'nvmeof_server_cert', + 'nvmeof_client_cert', + 'nvmeof_root_ca_cert', ] host_cert = [ @@ -1861,6 +1896,8 @@ class CertKeyStore(): service_name_key = [ 'iscsi_ssl_key', 'ingress_ssl_key', + 'nvmeof_server_key', + 'nvmeof_client_key', ] known_certs: Dict[str, Any] = {} @@ -1877,6 +1914,9 @@ class CertKeyStore(): 'rgw_frontend_ssl_cert': {}, # service-name -> cert 'iscsi_ssl_cert': {}, # service-name -> cert 'ingress_ssl_cert': {}, # service-name -> cert + 'nvmeof_server_cert': {}, # service-name -> cert + 'nvmeof_client_cert': {}, # service-name -> cert + 'nvmeof_root_ca_cert': {}, # service-name -> cert 'agent_endpoint_root_cert': Cert(), # cert 'service_discovery_root_cert': Cert(), # cert 'grafana_cert': {}, # host -> cert @@ -1896,6 +1936,8 @@ class CertKeyStore(): 'node_exporter_key': {}, # host -> key 'iscsi_ssl_key': {}, # service-name -> key 'ingress_ssl_key': {}, # service-name -> key + 'nvmeof_server_key': {}, # service-name -> key + 'nvmeof_client_key': {}, # service-name -> key } def get_cert(self, entity: str, service_name: str = '', host: str = '') -> str: diff --git a/src/pybind/mgr/cephadm/tests/test_cephadm.py b/src/pybind/mgr/cephadm/tests/test_cephadm.py index d9b1f5f8e78..82f10d35db7 100644 --- a/src/pybind/mgr/cephadm/tests/test_cephadm.py +++ b/src/pybind/mgr/cephadm/tests/test_cephadm.py @@ -1704,14 +1704,23 @@ class TestCephadm(object): agent_endpoint_root_cert = 'fake-agent-cert' alertmanager_host1_cert = 'fake-alertm-host1-cert' rgw_frontend_rgw_foo_host2_cert = 'fake-rgw-cert' + nvmeof_client_cert = 'fake-nvmeof-client-cert' + nvmeof_server_cert = 'fake-nvmeof-server-cert' + nvmeof_root_ca_cert = 'fake-nvmeof-root-ca-cert' cephadm_module.cert_key_store.save_cert('agent_endpoint_root_cert', agent_endpoint_root_cert) cephadm_module.cert_key_store.save_cert('alertmanager_cert', alertmanager_host1_cert, host='host1') cephadm_module.cert_key_store.save_cert('rgw_frontend_ssl_cert', rgw_frontend_rgw_foo_host2_cert, service_name='rgw.foo', user_made=True) + cephadm_module.cert_key_store.save_cert('nvmeof_server_cert', nvmeof_server_cert, service_name='nvmeof.foo', user_made=True) + cephadm_module.cert_key_store.save_cert('nvmeof_client_cert', nvmeof_client_cert, service_name='nvmeof.foo', user_made=True) + cephadm_module.cert_key_store.save_cert('nvmeof_root_ca_cert', nvmeof_root_ca_cert, service_name='nvmeof.foo', user_made=True) expected_calls = [ mock.call(f'{CERT_STORE_CERT_PREFIX}agent_endpoint_root_cert', json.dumps(Cert(agent_endpoint_root_cert).to_json())), mock.call(f'{CERT_STORE_CERT_PREFIX}alertmanager_cert', json.dumps({'host1': Cert(alertmanager_host1_cert).to_json()})), mock.call(f'{CERT_STORE_CERT_PREFIX}rgw_frontend_ssl_cert', json.dumps({'rgw.foo': Cert(rgw_frontend_rgw_foo_host2_cert, True).to_json()})), + mock.call(f'{CERT_STORE_CERT_PREFIX}nvmeof_server_cert', json.dumps({'nvmeof.foo': Cert(nvmeof_server_cert, True).to_json()})), + mock.call(f'{CERT_STORE_CERT_PREFIX}nvmeof_client_cert', json.dumps({'nvmeof.foo': Cert(nvmeof_client_cert, True).to_json()})), + mock.call(f'{CERT_STORE_CERT_PREFIX}nvmeof_root_ca_cert', json.dumps({'nvmeof.foo': Cert(nvmeof_root_ca_cert, True).to_json()})), ] _set_store.assert_has_calls(expected_calls) @@ -1729,6 +1738,9 @@ class TestCephadm(object): 'alertmanager_cert': False, 'prometheus_cert': False, 'node_exporter_cert': False, + 'nvmeof_client_cert': False, + 'nvmeof_server_cert': False, + 'nvmeof_root_ca_cert': False, } assert cephadm_module.cert_key_store.cert_ls() == expected_ls @@ -1750,18 +1762,35 @@ class TestCephadm(object): expected_ls['rgw_frontend_ssl_cert']['rgw.bar'] = True assert cephadm_module.cert_key_store.cert_ls() == expected_ls + cephadm_module.cert_key_store.save_cert('nvmeof_client_cert', 'xxx', service_name='nvmeof.foo', user_made=True) + cephadm_module.cert_key_store.save_cert('nvmeof_server_cert', 'xxx', service_name='nvmeof.foo', user_made=True) + cephadm_module.cert_key_store.save_cert('nvmeof_root_ca_cert', 'xxx', service_name='nvmeof.foo', user_made=True) + expected_ls['nvmeof_client_cert'] = {} + expected_ls['nvmeof_client_cert']['nvmeof.foo'] = True + expected_ls['nvmeof_server_cert'] = {} + expected_ls['nvmeof_server_cert']['nvmeof.foo'] = True + expected_ls['nvmeof_root_ca_cert'] = {} + expected_ls['nvmeof_root_ca_cert']['nvmeof.foo'] = True + assert cephadm_module.cert_key_store.cert_ls() == expected_ls + @mock.patch("cephadm.module.CephadmOrchestrator.set_store") def test_cert_store_save_key(self, _set_store, cephadm_module: CephadmOrchestrator): cephadm_module.cert_key_store._init_known_cert_key_dicts() agent_endpoint_key = 'fake-agent-key' - grafana_host1_key = 'fake-grafana-host1-cert' + grafana_host1_key = 'fake-grafana-host1-key' + nvmeof_client_key = 'nvmeof-client-key' + nvmeof_server_key = 'nvmeof-server-key' cephadm_module.cert_key_store.save_key('agent_endpoint_key', agent_endpoint_key) cephadm_module.cert_key_store.save_key('grafana_key', grafana_host1_key, host='host1') + cephadm_module.cert_key_store.save_key('nvmeof_client_key', nvmeof_client_key, service_name='nvmeof.foo') + cephadm_module.cert_key_store.save_key('nvmeof_server_key', nvmeof_server_key, service_name='nvmeof.foo') expected_calls = [ mock.call(f'{CERT_STORE_KEY_PREFIX}agent_endpoint_key', json.dumps(PrivKey(agent_endpoint_key).to_json())), mock.call(f'{CERT_STORE_KEY_PREFIX}grafana_key', json.dumps({'host1': PrivKey(grafana_host1_key).to_json()})), + mock.call(f'{CERT_STORE_KEY_PREFIX}nvmeof_client_key', json.dumps({'nvmeof.foo': PrivKey(nvmeof_client_key).to_json()})), + mock.call(f'{CERT_STORE_KEY_PREFIX}nvmeof_server_key', json.dumps({'nvmeof.foo': PrivKey(nvmeof_server_key).to_json()})), ] _set_store.assert_has_calls(expected_calls) @@ -1778,6 +1807,8 @@ class TestCephadm(object): 'node_exporter_key': False, 'iscsi_ssl_key': False, 'ingress_ssl_key': False, + 'nvmeof_client_key': False, + 'nvmeof_server_key': False, } assert cephadm_module.cert_key_store.key_ls() == expected_ls @@ -1792,6 +1823,14 @@ class TestCephadm(object): expected_ls['alertmanager_key']['host2'] = True assert cephadm_module.cert_key_store.key_ls() == expected_ls + cephadm_module.cert_key_store.save_key('nvmeof_client_key', 'xxx', service_name='nvmeof.foo') + cephadm_module.cert_key_store.save_key('nvmeof_server_key', 'xxx', service_name='nvmeof.foo') + expected_ls['nvmeof_server_key'] = {} + expected_ls['nvmeof_server_key']['nvmeof.foo'] = True + expected_ls['nvmeof_client_key'] = {} + expected_ls['nvmeof_client_key']['nvmeof.foo'] = True + assert cephadm_module.cert_key_store.key_ls() == expected_ls + @mock.patch("cephadm.module.CephadmOrchestrator.get_store_prefix") def test_cert_store_load(self, _get_store_prefix, cephadm_module: CephadmOrchestrator): cephadm_module.cert_key_store._init_known_cert_key_dicts() @@ -1801,18 +1840,28 @@ class TestCephadm(object): rgw_frontend_rgw_foo_host2_cert = 'fake-rgw-cert' agent_endpoint_key = 'fake-agent-key' grafana_host1_key = 'fake-grafana-host1-cert' + nvmeof_server_cert = 'nvmeof-server-cert' + nvmeof_client_cert = 'nvmeof-client-cert' + nvmeof_root_ca_cert = 'nvmeof-root-ca-cert' + nvmeof_server_key = 'nvmeof-server-key' + nvmeof_client_key = 'nvmeof-client-key' def _fake_prefix_store(key): if key == 'cert_store.cert.': return { f'{CERT_STORE_CERT_PREFIX}agent_endpoint_root_cert': json.dumps(Cert(agent_endpoint_root_cert).to_json()), f'{CERT_STORE_CERT_PREFIX}alertmanager_cert': json.dumps({'host1': Cert(alertmanager_host1_cert).to_json()}), - f'{CERT_STORE_CERT_PREFIX}rgw_frontend_ssl_cert': json.dumps({'rgw.foo': Cert(rgw_frontend_rgw_foo_host2_cert, True).to_json()}) + f'{CERT_STORE_CERT_PREFIX}rgw_frontend_ssl_cert': json.dumps({'rgw.foo': Cert(rgw_frontend_rgw_foo_host2_cert, True).to_json()}), + f'{CERT_STORE_CERT_PREFIX}nvmeof_server_cert': json.dumps({'nvmeof.foo': Cert(nvmeof_server_cert, True).to_json()}), + f'{CERT_STORE_CERT_PREFIX}nvmeof_client_cert': json.dumps({'nvmeof.foo': Cert(nvmeof_client_cert, True).to_json()}), + f'{CERT_STORE_CERT_PREFIX}nvmeof_root_ca_cert': json.dumps({'nvmeof.foo': Cert(nvmeof_root_ca_cert, True).to_json()}), } elif key == 'cert_store.key.': return { f'{CERT_STORE_KEY_PREFIX}agent_endpoint_key': json.dumps(PrivKey(agent_endpoint_key).to_json()), f'{CERT_STORE_KEY_PREFIX}grafana_key': json.dumps({'host1': PrivKey(grafana_host1_key).to_json()}), + f'{CERT_STORE_KEY_PREFIX}nvmeof_server_key': json.dumps({'nvmeof.foo': PrivKey(nvmeof_server_key).to_json()}), + f'{CERT_STORE_KEY_PREFIX}nvmeof_client_key': json.dumps({'nvmeof.foo': PrivKey(nvmeof_client_key).to_json()}), } else: raise Exception(f'Get store with unexpected value {key}') @@ -1822,8 +1871,13 @@ class TestCephadm(object): assert cephadm_module.cert_key_store.known_certs['agent_endpoint_root_cert'] == Cert(agent_endpoint_root_cert) assert cephadm_module.cert_key_store.known_certs['alertmanager_cert']['host1'] == Cert(alertmanager_host1_cert) assert cephadm_module.cert_key_store.known_certs['rgw_frontend_ssl_cert']['rgw.foo'] == Cert(rgw_frontend_rgw_foo_host2_cert, True) + assert cephadm_module.cert_key_store.known_certs['nvmeof_server_cert']['nvmeof.foo'] == Cert(nvmeof_server_cert, True) + assert cephadm_module.cert_key_store.known_certs['nvmeof_client_cert']['nvmeof.foo'] == Cert(nvmeof_client_cert, True) + assert cephadm_module.cert_key_store.known_certs['nvmeof_root_ca_cert']['nvmeof.foo'] == Cert(nvmeof_root_ca_cert, True) assert cephadm_module.cert_key_store.known_keys['agent_endpoint_key'] == PrivKey(agent_endpoint_key) assert cephadm_module.cert_key_store.known_keys['grafana_key']['host1'] == PrivKey(grafana_host1_key) + assert cephadm_module.cert_key_store.known_keys['nvmeof_server_key']['nvmeof.foo'] == PrivKey(nvmeof_server_key) + assert cephadm_module.cert_key_store.known_keys['nvmeof_client_key']['nvmeof.foo'] == PrivKey(nvmeof_client_key) def test_cert_store_get_cert_key(self, cephadm_module: CephadmOrchestrator): cephadm_module.cert_key_store._init_known_cert_key_dicts() @@ -1831,16 +1885,23 @@ class TestCephadm(object): agent_endpoint_root_cert = 'fake-agent-cert' alertmanager_host1_cert = 'fake-alertm-host1-cert' rgw_frontend_rgw_foo_host2_cert = 'fake-rgw-cert' + nvmeof_client_cert = 'fake-nvmeof-client-cert' + nvmeof_server_cert = 'fake-nvmeof-server-cert' cephadm_module.cert_key_store.save_cert('agent_endpoint_root_cert', agent_endpoint_root_cert) cephadm_module.cert_key_store.save_cert('alertmanager_cert', alertmanager_host1_cert, host='host1') cephadm_module.cert_key_store.save_cert('rgw_frontend_ssl_cert', rgw_frontend_rgw_foo_host2_cert, service_name='rgw.foo', user_made=True) + cephadm_module.cert_key_store.save_cert('nvmeof_server_cert', nvmeof_server_cert, service_name='nvmeof.foo', user_made=True) + cephadm_module.cert_key_store.save_cert('nvmeof_client_cert', nvmeof_client_cert, service_name='nvmeof.foo', user_made=True) assert cephadm_module.cert_key_store.get_cert('agent_endpoint_root_cert') == agent_endpoint_root_cert assert cephadm_module.cert_key_store.get_cert('alertmanager_cert', host='host1') == alertmanager_host1_cert assert cephadm_module.cert_key_store.get_cert('rgw_frontend_ssl_cert', service_name='rgw.foo') == rgw_frontend_rgw_foo_host2_cert + assert cephadm_module.cert_key_store.get_cert('nvmeof_server_cert', service_name='nvmeof.foo') == nvmeof_server_cert + assert cephadm_module.cert_key_store.get_cert('nvmeof_client_cert', service_name='nvmeof.foo') == nvmeof_client_cert assert cephadm_module.cert_key_store.get_cert('service_discovery_root_cert') == '' assert cephadm_module.cert_key_store.get_cert('grafana_cert', host='host1') == '' assert cephadm_module.cert_key_store.get_cert('iscsi_ssl_cert', service_name='iscsi.foo') == '' + assert cephadm_module.cert_key_store.get_cert('nvmeof_root_ca_cert', service_name='nvmeof.foo') == '' with pytest.raises(OrchestratorError, match='Attempted to access cert for unknown entity'): cephadm_module.cert_key_store.get_cert('unknown_entity') @@ -1851,11 +1912,17 @@ class TestCephadm(object): agent_endpoint_key = 'fake-agent-key' grafana_host1_key = 'fake-grafana-host1-cert' + nvmeof_server_key = 'nvmeof-server-key' + cephadm_module.cert_key_store.save_key('agent_endpoint_key', agent_endpoint_key) + cephadm_module.cert_key_store.save_key('grafana_key', grafana_host1_key, host='host1') cephadm_module.cert_key_store.save_key('agent_endpoint_key', agent_endpoint_key) cephadm_module.cert_key_store.save_key('grafana_key', grafana_host1_key, host='host1') + cephadm_module.cert_key_store.save_key('nvmeof_server_key', nvmeof_server_key, service_name='nvmeof.foo') assert cephadm_module.cert_key_store.get_key('agent_endpoint_key') == agent_endpoint_key assert cephadm_module.cert_key_store.get_key('grafana_key', host='host1') == grafana_host1_key + assert cephadm_module.cert_key_store.get_key('nvmeof_server_key', service_name='nvmeof.foo') == nvmeof_server_key + assert cephadm_module.cert_key_store.get_key('nvmeof_client_key', service_name='nvmeof.foo') == '' assert cephadm_module.cert_key_store.get_key('service_discovery_key') == '' assert cephadm_module.cert_key_store.get_key('alertmanager_key', host='host1') == '' -- 2.39.5