Skip to content

Commit ab77c8d

Browse files
committed
mgr/cephadm: add migration for certs/keys to cert store
Signed-off-by: Adam King <[email protected]>
1 parent 621f2e0 commit ab77c8d

File tree

5 files changed

+109
-14
lines changed

5 files changed

+109
-14
lines changed

src/pybind/mgr/cephadm/agent.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,6 @@ def cherrypy_filter(record: logging.LogRecord) -> bool:
4444

4545
class AgentEndpoint:
4646

47-
# TODO: move these constants to migrations
48-
KV_STORE_AGENT_ROOT_CERT = 'cephadm_agent/root/cert'
49-
KV_STORE_AGENT_ROOT_KEY = 'cephadm_agent/root/key'
50-
5147
def __init__(self, mgr: "CephadmOrchestrator") -> None:
5248
self.mgr = mgr
5349
self.ssl_certs = SSLCerts()

src/pybind/mgr/cephadm/migrations.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
if TYPE_CHECKING:
1515
from .module import CephadmOrchestrator
1616

17-
LAST_MIGRATION = 6
17+
LAST_MIGRATION = 7
1818

1919
logger = logging.getLogger(__name__)
2020

@@ -105,6 +105,10 @@ def migrate(self, startup: bool = False) -> None:
105105
if self.migrate_5_6():
106106
self.set(6)
107107

108+
if self.mgr.migration_current == 6:
109+
if self.migrate_6_7():
110+
self.set(7)
111+
108112
def migrate_0_1(self) -> bool:
109113
"""
110114
Migration 0 -> 1
@@ -410,6 +414,60 @@ def migrate_5_6(self) -> bool:
410414
self.rgw_migration_queue = []
411415
return True
412416

417+
def migrate_6_7(self) -> bool:
418+
# start by placing certs/keys from rgw, iscsi, and ingress specs into cert store
419+
for spec in self.mgr.spec_store.all_specs.values():
420+
if spec.service_type in ['rgw', 'ingress', 'iscsi']:
421+
logger.info(f'Migrating certs/keys for {spec.service_name()} spec to cert store')
422+
self.mgr.spec_store._save_certs_and_keys(spec)
423+
424+
# Migrate service discovery and agent endpoint certs
425+
# These constants were taken from where these certs were
426+
# originally generated and should be the location they
427+
# were store at prior to the cert store
428+
KV_STORE_AGENT_ROOT_CERT = 'cephadm_agent/root/cert'
429+
KV_STORE_AGENT_ROOT_KEY = 'cephadm_agent/root/key'
430+
KV_STORE_SD_ROOT_CERT = 'service_discovery/root/cert'
431+
KV_STORE_SD_ROOT_KEY = 'service_discovery/root/key'
432+
433+
agent_endpoint_cert = self.mgr.get_store(KV_STORE_AGENT_ROOT_CERT)
434+
if agent_endpoint_cert:
435+
logger.info('Migrating agent root cert to cert store')
436+
self.mgr.cert_key_store.save_cert('agent_endpoint_root_cert', agent_endpoint_cert)
437+
agent_endpoint_key = self.mgr.get_store(KV_STORE_AGENT_ROOT_KEY)
438+
if agent_endpoint_key:
439+
logger.info('Migrating agent root key to cert store')
440+
self.mgr.cert_key_store.save_key('agent_endpoint_key', agent_endpoint_key)
441+
service_discovery_cert = self.mgr.get_store(KV_STORE_SD_ROOT_CERT)
442+
if service_discovery_cert:
443+
logger.info('Migrating service discovery cert to cert store')
444+
self.mgr.cert_key_store.save_cert('service_discovery_root_cert', service_discovery_cert)
445+
service_discovery_key = self.mgr.get_store(KV_STORE_SD_ROOT_KEY)
446+
if service_discovery_key:
447+
logger.info('Migrating service discovery key to cert store')
448+
self.mgr.cert_key_store.save_key('service_discovery_key', service_discovery_key)
449+
450+
# grafana certs are stored based on the host they are placed on
451+
for grafana_daemon in self.mgr.cache.get_daemons_by_type('grafana'):
452+
logger.info(f'Checking for cert/key for {grafana_daemon.name()}')
453+
hostname = grafana_daemon.hostname
454+
assert hostname is not None # for mypy
455+
grafana_cert_path = f'{hostname}/grafana_crt'
456+
grafana_key_path = f'{hostname}/grafana_key'
457+
grafana_cert = self.mgr.get_store(grafana_cert_path)
458+
if grafana_cert:
459+
logger.info(f'Migrating {grafana_daemon.name()} cert to cert store')
460+
self.mgr.cert_key_store.save_cert('grafana_cert', grafana_cert, host=hostname)
461+
grafana_key = self.mgr.get_store(grafana_key_path)
462+
if grafana_key:
463+
logger.info(f'Migrating {grafana_daemon.name()} key to cert store')
464+
self.mgr.cert_key_store.save_key('grafana_key', grafana_key, host=hostname)
465+
466+
# NOTE: prometheus, alertmanager, and node-exporter certs were not stored
467+
# and appeared to just be generated at daemon deploy time if secure_monitoring_stack
468+
# was set to true. Therefore we have nothing to migrate for those daemons
469+
return True
470+
413471

414472
def queue_migrate_rgw_spec(mgr: "CephadmOrchestrator", spec_dict: Dict[Any, Any]) -> None:
415473
"""

src/pybind/mgr/cephadm/service_discovery.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ class Route(NamedTuple):
4545

4646
class ServiceDiscovery:
4747

48-
# TODO: these constants should only be needed for migration purposes
49-
# after completion of the cert store. Make sure to move them.
50-
KV_STORE_SD_ROOT_CERT = 'service_discovery/root/cert'
51-
KV_STORE_SD_ROOT_KEY = 'service_discovery/root/key'
52-
5348
def __init__(self, mgr: "CephadmOrchestrator") -> None:
5449
self.mgr = mgr
5550
self.ssl_certs = SSLCerts()

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,6 @@ def generate_config(self, daemon_spec: CephadmDaemonDeploySpec) -> Tuple[Dict[st
121121
return config_file, sorted(deps)
122122

123123
def prepare_certificates(self, daemon_spec: CephadmDaemonDeploySpec) -> Tuple[str, str]:
124-
# TODO: move these variables to migrations
125-
# cert_path = f'{daemon_spec.host}/grafana_crt'
126-
# key_path = f'{daemon_spec.host}/grafana_key'
127124
cert = self.mgr.cert_key_store.get_cert('grafana_cert', host=daemon_spec.host)
128125
pkey = self.mgr.cert_key_store.get_key('grafana_key', host=daemon_spec.host)
129126
certs_present = (cert and pkey)

src/pybind/mgr/cephadm/tests/test_migration.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
import json
22
import pytest
33

4-
from ceph.deployment.service_spec import PlacementSpec, ServiceSpec, HostPlacementSpec
4+
from ceph.deployment.service_spec import (
5+
PlacementSpec,
6+
ServiceSpec,
7+
HostPlacementSpec,
8+
RGWSpec,
9+
IngressSpec,
10+
IscsiServiceSpec
11+
)
512
from ceph.utils import datetime_to_str, datetime_now
613
from cephadm import CephadmOrchestrator
714
from cephadm.inventory import SPEC_STORE_PREFIX
815
from cephadm.migrations import LAST_MIGRATION
916
from cephadm.tests.fixtures import _run_cephadm, wait, with_host, receive_agent_metadata_all_hosts
1017
from cephadm.serve import CephadmServe
18+
from orchestrator import DaemonDescription
1119
from tests import mock
1220

1321

@@ -338,3 +346,44 @@ def test_migrate_rgw_spec(cephadm_module: CephadmOrchestrator, rgw_spec_store_en
338346
# if it was migrated, so we can use this to test the spec
339347
# was untouched
340348
assert 'rgw.foo' not in cephadm_module.spec_store.all_specs
349+
350+
351+
def test_migrate_cert_store(cephadm_module: CephadmOrchestrator):
352+
rgw_spec = RGWSpec(service_id='foo', rgw_frontend_ssl_certificate='rgw_cert', ssl=True)
353+
iscsi_spec = IscsiServiceSpec(service_id='foo', pool='foo', ssl_cert='iscsi_cert', ssl_key='iscsi_key')
354+
ingress_spec = IngressSpec(service_id='rgw.foo', ssl_cert='ingress_cert', ssl_key='ingress_key', ssl=True)
355+
cephadm_module.spec_store._specs = {
356+
'rgw.foo': rgw_spec,
357+
'iscsi.foo': iscsi_spec,
358+
'ingress.rgw.foo': ingress_spec
359+
}
360+
361+
cephadm_module.set_store('cephadm_agent/root/cert', 'agent_cert')
362+
cephadm_module.set_store('cephadm_agent/root/key', 'agent_key')
363+
cephadm_module.set_store('service_discovery/root/cert', 'service_discovery_cert')
364+
cephadm_module.set_store('service_discovery/root/key', 'service_discovery_key')
365+
366+
cephadm_module.set_store('host1/grafana_crt', 'grafana_cert1')
367+
cephadm_module.set_store('host1/grafana_key', 'grafana_key1')
368+
cephadm_module.set_store('host2/grafana_crt', 'grafana_cert2')
369+
cephadm_module.set_store('host2/grafana_key', 'grafana_key2')
370+
cephadm_module.cache.daemons = {'host1': {'grafana.host1': DaemonDescription('grafana', 'host1', 'host1')},
371+
'host2': {'grafana.host2': DaemonDescription('grafana', 'host2', 'host2')}}
372+
373+
cephadm_module.migration.migrate_6_7()
374+
375+
assert cephadm_module.cert_key_store.get_cert('rgw_frontend_ssl_cert', service_name='rgw.foo')
376+
assert cephadm_module.cert_key_store.get_cert('iscsi_ssl_cert', service_name='iscsi.foo')
377+
assert cephadm_module.cert_key_store.get_key('iscsi_ssl_key', service_name='iscsi.foo')
378+
assert cephadm_module.cert_key_store.get_cert('ingress_ssl_cert', service_name='ingress.rgw.foo')
379+
assert cephadm_module.cert_key_store.get_key('ingress_ssl_key', service_name='ingress.rgw.foo')
380+
381+
assert cephadm_module.cert_key_store.get_cert('agent_endpoint_root_cert')
382+
assert cephadm_module.cert_key_store.get_key('agent_endpoint_key')
383+
assert cephadm_module.cert_key_store.get_cert('service_discovery_root_cert')
384+
assert cephadm_module.cert_key_store.get_key('service_discovery_key')
385+
386+
assert cephadm_module.cert_key_store.get_cert('grafana_cert', host='host1')
387+
assert cephadm_module.cert_key_store.get_cert('grafana_cert', host='host2')
388+
assert cephadm_module.cert_key_store.get_key('grafana_key', host='host1')
389+
assert cephadm_module.cert_key_store.get_key('grafana_key', host='host2')

0 commit comments

Comments
 (0)