Skip to content

Commit 9dc630b

Browse files
guitsrkachach
authored andcommitted
mgr/cephadm: add SSL support to ceph-exporter
This commit adds SSL support to the ceph-exporter deployment made by cephadm. When `secure_monitoring_stack` is set to `True`, the `ceph-exporter` container is restarted with SSL enabled. Signed-off-by: Guillaume Abrioux <[email protected]> Signed-off-by: Redouane Kachach <[email protected]>
1 parent 862a38e commit 9dc630b

File tree

6 files changed

+94
-5
lines changed

6 files changed

+94
-5
lines changed

src/cephadm/cephadm.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
from cephadmlib.daemons.ceph import get_ceph_mounts_for_type, ceph_daemons
168168
from cephadmlib.daemons import (
169169
Ceph,
170+
CephExporter,
170171
CephIscsi,
171172
CephNvmeof,
172173
CustomContainer,
@@ -867,6 +868,10 @@ def create_daemon_dirs(
867868
node_proxy = NodeProxy.init(ctx, fsid, ident.daemon_id)
868869
node_proxy.create_daemon_dirs(data_dir, uid, gid)
869870

871+
elif daemon_type == CephExporter.daemon_type:
872+
ceph_exporter = CephExporter.init(ctx, fsid, ident.daemon_id)
873+
ceph_exporter.create_daemon_dirs(data_dir, uid, gid)
874+
870875
else:
871876
daemon = daemon_form_create(ctx, ident)
872877
if isinstance(daemon, ContainerDaemonForm):

src/cephadm/cephadmlib/daemons/ceph.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,14 @@
1616
from ..context import CephadmContext
1717
from ..deployment_utils import to_deployment_container
1818
from ..exceptions import Error
19-
from ..file_utils import make_run_dir, pathify
19+
from ..file_utils import (
20+
make_run_dir,
21+
pathify,
22+
populate_files,
23+
makedirs,
24+
recursive_chown,
25+
)
26+
from ..data_utils import dict_get
2027
from ..host_facts import HostFacts
2128
from ..logging import Highlight
2229
from ..net_utils import get_hostname, get_ip_addresses
@@ -298,6 +305,8 @@ def __init__(
298305
self.port = config_json.get('port', self.DEFAULT_PORT)
299306
self.prio_limit = config_json.get('prio-limit', 5)
300307
self.stats_period = config_json.get('stats-period', 5)
308+
self.https_enabled: bool = config_json.get('https_enabled', False)
309+
self.files = dict_get(config_json, 'files', {})
301310

302311
@classmethod
303312
def init(
@@ -323,6 +332,15 @@ def get_daemon_args(self) -> List[str]:
323332
f'--prio-limit={self.prio_limit}',
324333
f'--stats-period={self.stats_period}',
325334
]
335+
if self.https_enabled:
336+
args.extend(
337+
[
338+
'--cert-file',
339+
'/etc/certs/ceph-exporter.crt',
340+
'--key-file',
341+
'/etc/certs/ceph-exporter.key',
342+
]
343+
)
326344
return args
327345

328346
def validate(self) -> None:
@@ -348,6 +366,9 @@ def customize_container_mounts(
348366
) -> None:
349367
cm = Ceph.get_ceph_mounts(ctx, self.identity)
350368
mounts.update(cm)
369+
if self.https_enabled:
370+
data_dir = self.identity.data_dir(ctx.data_dir)
371+
mounts.update({os.path.join(data_dir, 'etc/certs'): '/etc/certs'})
351372

352373
def customize_process_args(
353374
self, ctx: CephadmContext, args: List[str]
@@ -376,6 +397,23 @@ def prepare_data_dir(self, data_dir: str, uid: int, gid: int) -> None:
376397
# it until now
377398
self.validate()
378399

400+
def create_daemon_dirs(self, data_dir: str, uid: int, gid: int) -> None:
401+
"""Create files under the container data dir"""
402+
if not os.path.isdir(data_dir):
403+
raise OSError('data_dir is not a directory: %s' % (data_dir))
404+
logger.info('Writing ceph-exporter config...')
405+
config_dir = os.path.join(data_dir, 'etc/')
406+
ssl_dir = os.path.join(data_dir, 'etc/certs')
407+
for ddir in [config_dir, ssl_dir]:
408+
makedirs(ddir, uid, gid, 0o755)
409+
recursive_chown(ddir, uid, gid)
410+
cert_files = {
411+
fname: content
412+
for fname, content in self.files.items()
413+
if fname.endswith('.crt') or fname.endswith('.key')
414+
}
415+
populate_files(ssl_dir, cert_files, uid, gid)
416+
379417

380418
def get_ceph_mounts_for_type(
381419
ctx: CephadmContext, fsid: str, daemon_type: str

src/pybind/mgr/cephadm/module.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2992,7 +2992,8 @@ def get_daemon_names(daemons: List[str]) -> List[str]:
29922992
# this daemon type doesn't need deps mgmt
29932993
pass
29942994

2995-
if daemon_type in ['prometheus', 'node-exporter', 'alertmanager', 'grafana']:
2995+
if daemon_type in ['prometheus', 'node-exporter', 'alertmanager', 'grafana',
2996+
'ceph-exporter']:
29962997
deps.append(f'secure_monitoring_stack:{self.secure_monitoring_stack}')
29972998

29982999
return sorted(deps)

src/pybind/mgr/cephadm/serve.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,7 @@ def _check_daemons(self) -> None:
10951095
action = 'reconfig'
10961096
# we need only redeploy if secure_monitoring_stack or mgmt-gateway value has changed:
10971097
# TODO(redo): check if we should just go always with redeploy (it's fast enough)
1098-
if dd.daemon_type in ['prometheus', 'node-exporter', 'alertmanager']:
1098+
if dd.daemon_type in ['prometheus', 'node-exporter', 'alertmanager', 'ceph-exporter']:
10991099
diff = list(set(last_deps).symmetric_difference(set(deps)))
11001100
REDEPLOY_TRIGGERS = ['secure_monitoring_stack', 'mgmt-gateway']
11011101
if any(svc in e for e in diff for svc in REDEPLOY_TRIGGERS):

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ def prepare_create(self, daemon_spec: CephadmDaemonDeploySpec) -> CephadmDaemonD
12631263
'mon', 'allow r',
12641264
'mgr', 'allow r',
12651265
'osd', 'allow r'])
1266-
exporter_config = {}
1266+
exporter_config: Dict[str, Any] = {}
12671267
if spec.sock_dir:
12681268
exporter_config.update({'sock-dir': spec.sock_dir})
12691269
if spec.port:
@@ -1297,6 +1297,7 @@ def get_certificates(self, daemon_spec: CephadmDaemonDeploySpec) -> Tuple[str, s
12971297
host_fqdn = self.mgr.get_fqdn(daemon_spec.host)
12981298
return self.mgr.cert_mgr.generate_cert(host_fqdn, node_ip)
12991299

1300+
13001301
class CephfsMirrorService(CephService):
13011302
TYPE = 'cephfs-mirror'
13021303

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

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import pytest
88

9-
from unittest.mock import MagicMock, call, patch, ANY
9+
from unittest.mock import Mock, MagicMock, call, patch, ANY
1010

1111
from cephadm.serve import CephadmServe
1212
from cephadm.services.cephadmservice import MonService, MgrService, MdsService, RgwService, \
@@ -693,6 +693,50 @@ def test_alertmanager_config_security_enabled(self, _get_fqdn, _run_cephadm, cep
693693
use_current_daemon_image=False,
694694
)
695695

696+
@patch("cephadm.serve.CephadmServe._run_cephadm")
697+
@patch("socket.getfqdn")
698+
@patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '::1')
699+
@patch('cephadm.cert_mgr.CertMgr.get_root_ca', lambda instance: 'cephadm_root_cert')
700+
@patch('cephadm.cert_mgr.CertMgr.generate_cert', lambda instance, fqdn, ip: ('mycert', 'mykey'))
701+
@patch('cephadm.services.cephadmservice.CephExporterService.get_keyring_with_caps', Mock(return_value='[client.ceph-exporter.test]\nkey = fake-secret\n'))
702+
def test_ceph_exporter_config_security_enabled(self, _get_fqdn, _run_cephadm, cephadm_module: CephadmOrchestrator):
703+
_run_cephadm.side_effect = async_side_effect(('{}', '', 0))
704+
705+
fqdn = 'host1.test'
706+
_get_fqdn.return_value = fqdn
707+
708+
with with_host(cephadm_module, 'test'):
709+
cephadm_module.secure_monitoring_stack = True
710+
with with_service(cephadm_module, CephExporterSpec()):
711+
_run_cephadm.assert_called_with('test', 'ceph-exporter.test',
712+
['_orch', 'deploy'], [],
713+
stdin=json.dumps({
714+
"fsid": "fsid",
715+
"name": "ceph-exporter.test",
716+
"image": "",
717+
"deploy_arguments": [],
718+
"params": {},
719+
"meta": {
720+
"service_name": "ceph-exporter",
721+
"ports": [],
722+
"ip": None,
723+
"deployed_by": [],
724+
"rank": None,
725+
"rank_generation": None,
726+
"extra_container_args": None,
727+
"extra_entrypoint_args": None
728+
},
729+
"config_blobs": {
730+
"config": "",
731+
"keyring": "[client.ceph-exporter.test]\nkey = fake-secret\n",
732+
"prio-limit": "5",
733+
"stats-period": "5",
734+
"https_enabled": True,
735+
"files": {
736+
"ceph-exporter.crt": "mycert",
737+
"ceph-exporter.key": "mykey"}}}),
738+
use_current_daemon_image=False)
739+
696740
@patch("cephadm.serve.CephadmServe._run_cephadm")
697741
@patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '::1')
698742
def test_prometheus_config_security_disabled(self, _run_cephadm, cephadm_module: CephadmOrchestrator):

0 commit comments

Comments
 (0)