From e17fb642b55456c2cc65da9cfa4eeb02e5186583 Mon Sep 17 00:00:00 2001 From: Redouane Kachach Date: Thu, 9 Oct 2025 10:55:50 +0200 Subject: [PATCH] mgr/cephadm: add the VIP to the internal mgmt-gateway cert SAN list Include the VIP as part of the mgmt-gateway internal server certificate SAN list when operating in HA mode. Otherwise the communication between internal services might fail. Fixes: https://tracker.ceph.com/issues/73384 Signed-off-by: Redouane Kachach --- .../mgr/cephadm/services/cephadmservice.py | 4 +- .../mgr/cephadm/services/mgmt_gateway.py | 3 +- src/pybind/mgr/cephadm/tests/test_services.py | 62 +++++++++++++++++-- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/pybind/mgr/cephadm/services/cephadmservice.py b/src/pybind/mgr/cephadm/services/cephadmservice.py index 03488933b0c..f166051d0ae 100644 --- a/src/pybind/mgr/cephadm/services/cephadmservice.py +++ b/src/pybind/mgr/cephadm/services/cephadmservice.py @@ -323,9 +323,9 @@ class CephadmService(metaclass=ABCMeta): def __init__(self, mgr: "CephadmOrchestrator"): self.mgr: "CephadmOrchestrator" = mgr - def get_self_signed_certificates_with_label(self, svc_spec: ServiceSpec, daemon_spec: CephadmDaemonDeploySpec, label: str) -> TLSCredentials: + def get_self_signed_certificates_with_label(self, svc_spec: ServiceSpec, daemon_spec: CephadmDaemonDeploySpec, label: str, ip_addr: Optional[str] = None) -> TLSCredentials: svc_name = svc_spec.service_name() - ip = self.mgr.inventory.get_addr(daemon_spec.host) + ip = ip_addr or self.mgr.inventory.get_addr(daemon_spec.host) host_fqdn = self.mgr.get_fqdn(daemon_spec.host) tls_creds = self.mgr.cert_mgr.get_self_signed_tls_credentials(svc_name, host_fqdn, label) if not tls_creds: diff --git a/src/pybind/mgr/cephadm/services/mgmt_gateway.py b/src/pybind/mgr/cephadm/services/mgmt_gateway.py index eb73878aeaf..f5f01a913a1 100644 --- a/src/pybind/mgr/cephadm/services/mgmt_gateway.py +++ b/src/pybind/mgr/cephadm/services/mgmt_gateway.py @@ -120,7 +120,8 @@ class MgmtGatewayService(CephadmService): 'enable_oauth2_proxy': bool(oauth2_proxy_endpoints), } - tls_creds = self.get_self_signed_certificates_with_label(svc_spec, daemon_spec, INTERNAL_CERT_LABEL) + ip = self.get_mgmt_gw_ip(svc_spec, daemon_spec) + tls_creds = self.get_self_signed_certificates_with_label(svc_spec, daemon_spec, INTERNAL_CERT_LABEL, ip) daemon_config = { "files": { "nginx.conf": self.mgr.template.render(self.SVC_TEMPLATE_PATH, main_context), diff --git a/src/pybind/mgr/cephadm/tests/test_services.py b/src/pybind/mgr/cephadm/tests/test_services.py index 65a9869012e..985284ca205 100644 --- a/src/pybind/mgr/cephadm/tests/test_services.py +++ b/src/pybind/mgr/cephadm/tests/test_services.py @@ -4960,7 +4960,7 @@ class TestMgmtGateway: @patch("cephadm.services.cephadmservice.CephadmService.get_certificates", lambda instance, dspec, ips=None: TLSCredentials(ceph_generated_cert, ceph_generated_key)) @patch("cephadm.services.mgmt_gateway.MgmtGatewayService.get_self_signed_certificates_with_label", - lambda instance, svc_spec, dspec, label: TLSCredentials(ceph_generated_cert, ceph_generated_key)) + lambda instance, svc_spec, dspec, label, ip: TLSCredentials(ceph_generated_cert, ceph_generated_key)) @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '::1') @patch('cephadm.cert_mgr.CertMgr.get_root_ca', lambda instance: cephadm_root_ca) @patch("cephadm.services.mgmt_gateway.get_dashboard_endpoints", lambda _: (["ceph-node-2:8443", "ceph-node-2:8443"], "https")) @@ -5206,7 +5206,7 @@ class TestMgmtGateway: @patch("cephadm.services.cephadmservice.CephadmService.get_certificates", lambda instance, dspec, ips=None: TLSCredentials(ceph_generated_cert, ceph_generated_key)) @patch("cephadm.services.mgmt_gateway.MgmtGatewayService.get_self_signed_certificates_with_label", - lambda instance, svc_spec, dspec, label: TLSCredentials(ceph_generated_cert, ceph_generated_key)) + lambda instance, svc_spec, dspec, label, ip: TLSCredentials(ceph_generated_cert, ceph_generated_key)) @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '::1') @patch('cephadm.cert_mgr.CertMgr.get_root_ca', lambda instance: cephadm_root_ca) @patch("cephadm.services.mgmt_gateway.get_dashboard_endpoints", lambda _: (["ceph-node-2:8443", "ceph-node-2:8443"], "https")) @@ -5544,12 +5544,66 @@ class TestMgmtGateway: use_current_daemon_image=False, ) + @patch("cephadm.serve.CephadmServe._run_cephadm") + @patch("cephadm.services.mgmt_gateway.MgmtGatewayService.get_service_endpoints") + @patch("cephadm.services.mgmt_gateway.MgmtGatewayService.get_service_discovery_endpoints") + @patch("cephadm.services.mgmt_gateway.MgmtGatewayService.get_self_signed_certificates_with_label") + @patch("cephadm.services.cephadmservice.CephadmService.get_certificates", + lambda instance, dspec, ips=None: TLSCredentials(ceph_generated_cert, ceph_generated_key)) + @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '::1') + @patch('cephadm.cert_mgr.CertMgr.get_root_ca', lambda instance: cephadm_root_ca) + @patch("cephadm.services.mgmt_gateway.get_dashboard_endpoints", + lambda _: (["ceph-node-2:8443", "ceph-node-2:8443"], "https")) + def test_mgmt_gateway_internal_cert_san_includes_vip( + self, + get_self_signed_mock, + get_service_discovery_endpoints_mock, + get_service_endpoints_mock, + _run_cephadm, + cephadm_module: CephadmOrchestrator, + ): + vip = "10.0.0.200" + + def get_services_endpoints(name): + if name == 'prometheus': + return ["192.168.100.100:9095", "192.168.100.101:9095"] + if name == 'grafana': + return ["ceph-node-2:3000", "ceph-node-2:3000"] + if name == 'alertmanager': + return ["192.168.100.100:9093", "192.168.100.102:9093"] + if name == 'oauth2-proxy': + return [] + return [] + + _run_cephadm.side_effect = async_side_effect(('{}', '', 0)) + get_service_endpoints_mock.side_effect = get_services_endpoints + get_service_discovery_endpoints_mock.return_value = ["ceph-node-0:8765", "ceph-node-2:8765"] + get_self_signed_mock.return_value = TLSCredentials(ceph_generated_cert, ceph_generated_key) + + server_port = 5555 + spec = MgmtGatewaySpec( + port=server_port, + virtual_ip=vip, # HA mode + ssl_cert=ceph_generated_cert, + ssl_key=ceph_generated_key, + ) + + with with_host(cephadm_module, 'ceph-node'): + with with_service(cephadm_module, spec): + # Ensure VIP was used when minting the internal cert (so it goes into SANs) + # get_self_signed_certificates_with_label(svc_spec, daemon_spec, label, ip) + args, _ = get_self_signed_mock.call_args + assert args[2] == 'internal' + assert args[3] == vip + deployed = json.loads(_run_cephadm.call_args.kwargs['stdin']) + assert deployed['config_blobs']['files']['nginx_internal.crt'] == ceph_generated_cert + @patch("cephadm.serve.CephadmServe._run_cephadm") @patch("cephadm.services.mgmt_gateway.MgmtGatewayService.get_service_endpoints") @patch("cephadm.services.cephadmservice.CephadmService.get_certificates", lambda instance, dspec, ips=None: TLSCredentials(ceph_generated_cert, ceph_generated_key)) @patch("cephadm.services.mgmt_gateway.MgmtGatewayService.get_self_signed_certificates_with_label", - lambda instance, svc_spec, dspec, label: TLSCredentials(ceph_generated_cert, ceph_generated_key)) + lambda instance, svc_spec, dspec, label, ip: TLSCredentials(ceph_generated_cert, ceph_generated_key)) @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '::1') @patch('cephadm.cert_mgr.CertMgr.get_root_ca', lambda instance: cephadm_root_ca) @patch("cephadm.services.mgmt_gateway.get_dashboard_endpoints", lambda _: (["ceph-node-2:8443", "ceph-node-2:8443"], "https")) @@ -5563,7 +5617,7 @@ class TestMgmtGateway: @patch("cephadm.services.oauth2_proxy.OAuth2ProxyService.get_certificates", lambda instance, dspec, ips=None: TLSCredentials(ceph_generated_cert, ceph_generated_key)) @patch("cephadm.services.mgmt_gateway.MgmtGatewayService.get_self_signed_certificates_with_label", - lambda instance, svc_spec, dspec, label: TLSCredentials(ceph_generated_cert, ceph_generated_key)) + lambda instance, svc_spec, dspec, label, ip: TLSCredentials(ceph_generated_cert, ceph_generated_key)) @patch("cephadm.module.CephadmOrchestrator.get_mgr_ip", lambda _: '::1') @patch('cephadm.cert_mgr.CertMgr.get_root_ca', lambda instance: cephadm_root_ca) @patch("cephadm.services.mgmt_gateway.get_dashboard_endpoints", lambda _: (["ceph-node-2:8443", "ceph-node-2:8443"], "https")) -- 2.39.5