Skip to content

Commit c0d5b9a

Browse files
authored
Merge pull request ceph#59174 from adk3798/cephadm-rgw-generate-cert
mgr/cephadm: add ability for cephadm to generate frontend cert for rgw Reviewed-by: John Mulligan <[email protected]>
2 parents ab8d7ee + ce28c8e commit c0d5b9a

File tree

5 files changed

+33
-8
lines changed

5 files changed

+33
-8
lines changed

src/pybind/mgr/cephadm/cert_mgr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def __init__(self, mgr: "CephadmOrchestrator", ip: str) -> None:
2121
except SSLConfigException:
2222
raise Exception("Cannot load cephadm root CA certificates.")
2323
else:
24-
self.ssl_certs.generate_root_cert(ip)
24+
self.ssl_certs.generate_root_cert(addr=ip)
2525
mgr.cert_key_store.save_cert(self.CEPHADM_ROOT_CA_CERT, self.ssl_certs.get_root_cert())
2626
mgr.cert_key_store.save_key(self.CEPHADM_ROOT_CA_KEY, self.ssl_certs.get_root_key())
2727

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,12 @@ def config(self, spec: RGWSpec) -> None: # type: ignore
10101010
'value': spec.rgw_zone,
10111011
})
10121012

1013+
if spec.generate_cert and not spec.rgw_frontend_ssl_certificate:
1014+
# generate a self-signed cert for the rgw service
1015+
cert, key = self.mgr.cert_mgr.ssl_certs.generate_root_cert(custom_san_list=spec.zonegroup_hostnames)
1016+
spec.rgw_frontend_ssl_certificate = ''.join([key, cert])
1017+
self.mgr.spec_store.save(spec)
1018+
10131019
if spec.rgw_frontend_ssl_certificate:
10141020
if isinstance(spec.rgw_frontend_ssl_certificate, list):
10151021
cert_data = '\n'.join(spec.rgw_frontend_ssl_certificate)

src/pybind/mgr/cephadm/ssl_cert_utils.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
from typing import Any, Tuple, IO, List, Union
2+
from typing import Any, Tuple, IO, List, Union, Optional
33
import ipaddress
44

55
from datetime import datetime, timedelta
@@ -21,7 +21,11 @@ def __init__(self) -> None:
2121
self.key_file: IO[bytes]
2222
self.cert_file: IO[bytes]
2323

24-
def generate_root_cert(self, addr: str) -> Tuple[str, str]:
24+
def generate_root_cert(
25+
self,
26+
addr: Optional[str] = None,
27+
custom_san_list: Optional[List[str]] = None
28+
) -> Tuple[str, str]:
2529
self.root_key = rsa.generate_private_key(
2630
public_exponent=65537, key_size=4096, backend=default_backend())
2731
root_public_key = self.root_key.public_key()
@@ -36,12 +40,19 @@ def generate_root_cert(self, addr: str) -> Tuple[str, str]:
3640
root_builder = root_builder.not_valid_after(datetime.now() + timedelta(days=(365 * 10 + 3)))
3741
root_builder = root_builder.serial_number(x509.random_serial_number())
3842
root_builder = root_builder.public_key(root_public_key)
43+
44+
san_list: List[x509.GeneralName] = []
45+
if addr:
46+
san_list.extend([x509.IPAddress(ipaddress.ip_address(addr))])
47+
if custom_san_list:
48+
san_list.extend([x509.DNSName(n) for n in custom_san_list])
3949
root_builder = root_builder.add_extension(
4050
x509.SubjectAlternativeName(
41-
[x509.IPAddress(ipaddress.ip_address(addr))]
51+
san_list
4252
),
4353
critical=False
4454
)
55+
4556
root_builder = root_builder.add_extension(
4657
x509.BasicConstraints(ca=True, path_length=None), critical=True,
4758
)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def __init__(self) -> None:
3737
self.http_server = MagicMock()
3838
self.http_server.agent = MagicMock()
3939
self.http_server.agent.ssl_certs = SSLCerts()
40-
self.http_server.agent.ssl_certs.generate_root_cert(self.get_mgr_ip())
40+
self.http_server.agent.ssl_certs.generate_root_cert(addr=self.get_mgr_ip())
4141
self.cert_mgr = FakeCertMgr()
4242

4343
def get_mgr_ip(self) -> str:

src/python-common/ceph/deployment/service_spec.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,7 +1208,7 @@ def __init__(self,
12081208
rgw_zonegroup: Optional[str] = None,
12091209
rgw_zone: Optional[str] = None,
12101210
rgw_frontend_port: Optional[int] = None,
1211-
rgw_frontend_ssl_certificate: Optional[List[str]] = None,
1211+
rgw_frontend_ssl_certificate: Optional[Union[str, List[str]]] = None,
12121212
rgw_frontend_type: Optional[str] = None,
12131213
rgw_frontend_extra_args: Optional[List[str]] = None,
12141214
unmanaged: bool = False,
@@ -1223,11 +1223,12 @@ def __init__(self,
12231223
rgw_realm_token: Optional[str] = None,
12241224
update_endpoints: Optional[bool] = False,
12251225
zone_endpoints: Optional[str] = None, # comma separated endpoints list
1226-
zonegroup_hostnames: Optional[str] = None,
1226+
zonegroup_hostnames: Optional[List[str]] = None,
12271227
rgw_user_counters_cache: Optional[bool] = False,
12281228
rgw_user_counters_cache_size: Optional[int] = None,
12291229
rgw_bucket_counters_cache: Optional[bool] = False,
12301230
rgw_bucket_counters_cache_size: Optional[int] = None,
1231+
generate_cert: bool = False,
12311232
):
12321233
assert service_type == 'rgw', service_type
12331234

@@ -1257,7 +1258,8 @@ def __init__(self,
12571258
#: Port of the RGW daemons
12581259
self.rgw_frontend_port: Optional[int] = rgw_frontend_port
12591260
#: List of SSL certificates
1260-
self.rgw_frontend_ssl_certificate: Optional[List[str]] = rgw_frontend_ssl_certificate
1261+
self.rgw_frontend_ssl_certificate: Optional[Union[str, List[str]]] \
1262+
= rgw_frontend_ssl_certificate
12611263
#: civetweb or beast (default: beast). See :ref:`rgw_frontends`
12621264
self.rgw_frontend_type: Optional[str] = rgw_frontend_type
12631265
#: List of extra arguments for rgw_frontend in the form opt=value. See :ref:`rgw_frontends`
@@ -1277,6 +1279,8 @@ def __init__(self,
12771279
self.rgw_bucket_counters_cache = rgw_bucket_counters_cache
12781280
#: Used to set number of entries in each cache of bucket counters
12791281
self.rgw_bucket_counters_cache_size = rgw_bucket_counters_cache_size
1282+
#: Whether we should generate a cert/key for the user if not provided
1283+
self.generate_cert = generate_cert
12801284

12811285
def get_port_start(self) -> List[int]:
12821286
return [self.get_port()]
@@ -1305,6 +1309,10 @@ def validate(self) -> None:
13051309
'Additional rgw type parameters can be passed using rgw_frontend_extra_args.'
13061310
)
13071311

1312+
if self.generate_cert and not self.ssl:
1313+
raise SpecValidationError('"ssl" field must be set to true when "generate_cert" '
1314+
'is set to true')
1315+
13081316

13091317
yaml.add_representer(RGWSpec, ServiceSpec.yaml_representer)
13101318

0 commit comments

Comments
 (0)