Skip to content

Commit 4a49393

Browse files
authored
Merge pull request ceph#62561 from rkachach/fix_issue_70359_v2
mgr/cephadm: harmonize mgmt-gateway and oauth2-proxy spec fields Reviewed-by: Adam King <[email protected]> Reviewed-by: Pedro Gonzalez Gomez <[email protected]>
2 parents c94a2f5 + ded9b41 commit 4a49393

File tree

10 files changed

+76
-51
lines changed

10 files changed

+76
-51
lines changed

doc/cephadm/services/mgmt-gateway.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ A ``mgmt-gateway`` service can be applied using a specification. An example in Y
128128
- ceph0
129129
spec:
130130
port: 5000
131+
ssl: True
131132
ssl_protocols:
132133
- TLSv1.2
133134
- TLSv1.3
@@ -136,13 +137,13 @@ A ``mgmt-gateway`` service can be applied using a specification. An example in Y
136137
- AES128-SHA
137138
- AES256-SHA
138139
- ...
139-
ssl_certificate: |
140+
ssl_cert: |
140141
-----BEGIN CERTIFICATE-----
141142
MIIDtTCCAp2gAwIBAgIYMC4xNzc1NDQxNjEzMzc2MjMyXzxvQ7EcMA0GCSqGSIb3
142143
DQEBCwUAMG0xCzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARVdGFoMRcwFQYDVQQHDA5T
143144
[...]
144145
-----END CERTIFICATE-----
145-
ssl_certificate_key: |
146+
ssl_key: |
146147
-----BEGIN PRIVATE KEY-----
147148
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5jdYbjtNTAKW4
148149
/CwQr/7wOiLGzVxChn3mmCIF3DwbL/qvTFTX2d8bDf6LjGwLYloXHscRfxszX/4h

qa/suites/orch/cephadm/workunits/task/test_mgmt_gateway.yaml

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ tasks:
4848
enable_health_check_endpoint: True
4949
EOT
5050
# Add generated certificates to spec file
51-
echo " ssl_certificate: |" >> /tmp/mgmt.spec
51+
echo " ssl_cert: |" >> /tmp/mgmt.spec
5252
while read LINE; do echo $LINE | sed -e "s/^/ /"; done < /tmp/cert.pem >> /tmp/mgmt.spec
53-
echo " ssl_certificate_key: |" >> /tmp/mgmt.spec
53+
echo " ssl_key: |" >> /tmp/mgmt.spec
5454
while read LINE; do echo $LINE | sed -e "s/^/ /"; done < /tmp/key.pem >> /tmp/mgmt.spec
5555
# Apply spec
5656
ceph orch apply -i /tmp/mgmt.spec
@@ -60,18 +60,42 @@ tasks:
6060
host.a:
6161
- |
6262
set -ex
63+
64+
# Function to wait for a service to be healthy and log response on error
65+
wait_for_service() {
66+
local name="$1"
67+
local url="$2"
68+
local jq_filter="$3"
69+
70+
echo "Waiting for service $name to be healthy at $url..."
71+
for i in {1..30}; do
72+
local response
73+
response=$(curl -k -s -u admin:admin "$url")
74+
if echo "$response" | jq -e "$jq_filter" > /dev/null; then
75+
echo "Service $name is healthy."
76+
return 0
77+
fi
78+
echo "Attempt $i: service $name not ready yet"
79+
sleep 10
80+
done
81+
82+
echo "Timeout waiting for $name at $url"
83+
echo "Last HTTP response:"
84+
echo "$response"
85+
echo "jq output:"
86+
echo "$response" | jq "$jq_filter" || echo "(jq parse error or no match)"
87+
return 1
88+
}
89+
6390
# retrieve mgmt hostname and ip
6491
MGMT_GTW_HOST=$(ceph orch ps --daemon-type mgmt-gateway -f json | jq -e '.[]' | jq -r '.hostname')
6592
MGMT_GTW_IP=$(ceph orch host ls -f json | jq -r --arg MGMT_GTW_HOST "$MGMT_GTW_HOST" '.[] | select(.hostname==$MGMT_GTW_HOST) | .addr')
93+
6694
# check mgmt-gateway health
6795
curl -k -s https://${MGMT_GTW_IP}/health
6896
curl -k -s https://${MGMT_GTW_IP}:29443/health
69-
# wait for background services to be reconfigured following mgmt-gateway installation
70-
sleep 180
71-
# check grafana endpoints are responsive and database health is okay
72-
curl -k -s https://${MGMT_GTW_IP}/grafana/api/health | jq -e '.database == "ok"'
73-
# check prometheus endpoints are responsive
74-
curl -k -s -u admin:admin https://${MGMT_GTW_IP}/prometheus/api/v1/status/config | jq -e '.status == "success"'
75-
# check alertmanager endpoints are responsive
76-
curl -k -s -u admin:admin https://${MGMT_GTW_IP}/alertmanager/api/v2/status
7797
98+
# wait for monitoring services
99+
wait_for_service "Grafana" "https://${MGMT_GTW_IP}/grafana/api/health" '.database == "ok"' || exit 1
100+
wait_for_service "Prometheus" "https://${MGMT_GTW_IP}/prometheus/api/v1/status/config" '.status == "success"' || exit 1
101+
wait_for_service "Alertmanager" "https://${MGMT_GTW_IP}/alertmanager/api/v2/status" '.cluster.status == "ready"' || exit 1

src/pybind/mgr/cephadm/module.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ def _get_mgmt_gw_endpoint(self, is_internal: bool) -> Optional[str]:
751751
endpoint_suffix = '/internal'
752752
else:
753753
mgmt_gw_port = dd.ports[0] if dd.ports else None
754-
protocol = 'http' if mgmt_gw_spec.disable_https else 'https'
754+
protocol = 'https' if mgmt_gw_spec.ssl else 'http'
755755
endpoint_suffix = ''
756756

757757
mgmt_gw_endpoint = build_url(scheme=protocol, host=mgmt_gw_addr, port=mgmt_gw_port)

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ def get_external_certificates(self, svc_spec: MgmtGatewaySpec, daemon_spec: Ceph
5757
user_made = False
5858
if not (cert and key):
5959
# not available on store, check if provided on the spec
60-
if svc_spec.ssl_certificate and svc_spec.ssl_certificate_key:
60+
if svc_spec.ssl_cert and svc_spec.ssl_key:
6161
user_made = True
62-
cert = svc_spec.ssl_certificate
63-
key = svc_spec.ssl_certificate_key
62+
cert = svc_spec.ssl_cert
63+
key = svc_spec.ssl_key
6464
else:
6565
# not provided on the spec, let's generate self-sigend certificates
6666
ip = self.get_mgmt_gw_ip(svc_spec, daemon_spec)
@@ -147,7 +147,6 @@ def generate_config(self, daemon_spec: CephadmDaemonDeploySpec) -> Tuple[Dict[st
147147
'enable_oauth2_proxy': bool(oauth2_proxy_endpoints),
148148
}
149149

150-
cert, key = self.get_external_certificates(svc_spec, daemon_spec)
151150
internal_cert, internal_pkey = self.get_internal_certificates(svc_spec, daemon_spec)
152151
daemon_config = {
153152
"files": {
@@ -159,7 +158,8 @@ def generate_config(self, daemon_spec: CephadmDaemonDeploySpec) -> Tuple[Dict[st
159158
"ca.crt": self.mgr.cert_mgr.get_root_ca()
160159
}
161160
}
162-
if not svc_spec.disable_https:
161+
if svc_spec.ssl:
162+
cert, key = self.get_external_certificates(svc_spec, daemon_spec)
163163
daemon_config["files"]["nginx.crt"] = cert
164164
daemon_config["files"]["nginx.key"] = key
165165

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ def get_certificates(self, svc_spec: OAuth2ProxySpec, daemon_spec: CephadmDaemon
6464
user_made = False
6565
if not (cert and key):
6666
# not available on store, check if provided on the spec
67-
if svc_spec.ssl_certificate and svc_spec.ssl_certificate_key:
67+
if svc_spec.ssl_cert and svc_spec.ssl_key:
6868
user_made = True
69-
cert = svc_spec.ssl_certificate
70-
key = svc_spec.ssl_certificate_key
69+
cert = svc_spec.ssl_cert
70+
key = svc_spec.ssl_key
7171
else:
7272
# not provided on the spec, let's generate self-sigend certificates
7373
addr = self.mgr.inventory.get_addr(daemon_spec.host)

src/pybind/mgr/cephadm/templates/services/mgmt-gateway/external_server.conf.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
server {
3-
{% if spec.disable_https %}
3+
{% if not spec.ssl %}
44
listen {{ spec.port or 80 }};
55
{% else %}
66
listen {{ spec.port or 443 }} ssl;

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

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,8 +1596,8 @@ def inline_certificate(multi_line_cert):
15961596
client_secret='my_client_secret',
15971597
oidc_issuer_url='http://192.168.10.10:8888/dex',
15981598
cookie_secret='kbAEM9opAmuHskQvt0AW8oeJRaOM2BYy5Loba0kZ0SQ=',
1599-
ssl_certificate=ceph_generated_cert,
1600-
ssl_certificate_key=ceph_generated_key)
1599+
ssl_cert=ceph_generated_cert,
1600+
ssl_key=ceph_generated_key)
16011601

16021602
with with_host(cephadm_module, "test"):
16031603
cephadm_module.cert_mgr.save_cert('grafana_cert', ceph_generated_cert, host='test')
@@ -4013,8 +4013,8 @@ def get_services_endpoints(name):
40134013

40144014
server_port = 5555
40154015
spec = MgmtGatewaySpec(port=server_port,
4016-
ssl_certificate=ceph_generated_cert,
4017-
ssl_certificate_key=ceph_generated_key)
4016+
ssl_cert=ceph_generated_cert,
4017+
ssl_key=ceph_generated_key)
40184018

40194019
expected = {
40204020
"fsid": "fsid",
@@ -4261,8 +4261,8 @@ def get_services_endpoints(name):
42614261

42624262
server_port = 5555
42634263
spec = MgmtGatewaySpec(port=server_port,
4264-
ssl_certificate=ceph_generated_cert,
4265-
ssl_certificate_key=ceph_generated_key,
4264+
ssl_cert=ceph_generated_cert,
4265+
ssl_key=ceph_generated_key,
42664266
enable_auth=True)
42674267

42684268
expected = {
@@ -4611,8 +4611,8 @@ def get_services_endpoints(name):
46114611

46124612
server_port = 5555
46134613
mgmt_gw_spec = MgmtGatewaySpec(port=server_port,
4614-
ssl_certificate=ceph_generated_cert,
4615-
ssl_certificate_key=ceph_generated_key,
4614+
ssl_cert=ceph_generated_cert,
4615+
ssl_key=ceph_generated_key,
46164616
enable_auth=True,
46174617
virtual_ip=virtual_ip)
46184618

@@ -4622,8 +4622,8 @@ def get_services_endpoints(name):
46224622
client_secret='my_client_secret',
46234623
oidc_issuer_url='http://192.168.10.10:8888/dex',
46244624
cookie_secret='kbAEM9opAmuHskQvt0AW8oeJRaOM2BYy5Loba0kZ0SQ=',
4625-
ssl_certificate=ceph_generated_cert,
4626-
ssl_certificate_key=ceph_generated_key,
4625+
ssl_cert=ceph_generated_cert,
4626+
ssl_key=ceph_generated_key,
46274627
allowlist_domains=[allowed_domain])
46284628

46294629
whitelist_domains = f"{allowed_domain},1::4,ceph-node" if virtual_ip is None else f"{allowed_domain},{virtual_ip},1::4,ceph-node"

src/pybind/mgr/dashboard/frontend/src/app/ceph/cluster/services/service-form/service-form.component.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -752,10 +752,10 @@ export class ServiceFormComponent extends CdForm implements OnInit {
752752
.setValue(response[0].spec?.ssl_ciphers.join(':'));
753753
}
754754
if (response[0].spec?.ssl_cert) {
755-
this.serviceForm.get('ssl_cert').setValue(response[0].spec.ssl_certificate);
755+
this.serviceForm.get('ssl_cert').setValue(response[0].spec.ssl_cert);
756756
}
757757
if (response[0].spec?.ssl_key) {
758-
this.serviceForm.get('ssl_key').setValue(response[0].spec.ssl_certificate_key);
758+
this.serviceForm.get('ssl_key').setValue(response[0].spec.ssl_key);
759759
}
760760
if (response[0].spec?.enable_auth) {
761761
this.serviceForm.get('enable_auth').setValue(response[0].spec.enable_auth);
@@ -1284,8 +1284,8 @@ export class ServiceFormComponent extends CdForm implements OnInit {
12841284
serviceSpec['virtual_interface_networks'] = values['virtual_interface_networks'];
12851285
break;
12861286
case 'mgmt-gateway':
1287-
serviceSpec['ssl_certificate'] = values['ssl_cert']?.trim();
1288-
serviceSpec['ssl_certificate_key'] = values['ssl_key']?.trim();
1287+
serviceSpec['ssl_cert'] = values['ssl_cert']?.trim();
1288+
serviceSpec['ssl_key'] = values['ssl_key']?.trim();
12891289
serviceSpec['enable_auth'] = values['enable_auth'];
12901290
serviceSpec['port'] = values['port'];
12911291
if (serviceSpec['port'] === (443 || 80)) {

src/pybind/mgr/orchestrator/module.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,7 +2048,7 @@ def _apply_iscsi(self,
20482048
@_cli_write_command('orch apply mgmt-gateway')
20492049
def _apply_mgmt_gateway(self,
20502050
port: Optional[int] = None,
2051-
disable_https: Optional[bool] = False,
2051+
ssl: Optional[bool] = True,
20522052
enable_auth: Optional[bool] = False,
20532053
virtual_ip: Optional[str] = None,
20542054
placement: Optional[str] = None,
@@ -2066,7 +2066,7 @@ def _apply_mgmt_gateway(self,
20662066
unmanaged=unmanaged,
20672067
port=port,
20682068
virtual_ip=virtual_ip,
2069-
disable_https=disable_https,
2069+
ssl=ssl,
20702070
enable_auth=enable_auth,
20712071
preview_only=dry_run
20722072
)

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,11 +1935,11 @@ def __init__(self,
19351935
config: Optional[Dict[str, str]] = None,
19361936
networks: Optional[List[str]] = None,
19371937
placement: Optional[PlacementSpec] = None,
1938-
disable_https: Optional[bool] = False,
1938+
ssl: Optional[bool] = True,
19391939
enable_auth: Optional[bool] = False,
19401940
port: Optional[int] = None,
1941-
ssl_certificate: Optional[str] = None,
1942-
ssl_certificate_key: Optional[str] = None,
1941+
ssl_cert: Optional[str] = None,
1942+
ssl_key: Optional[str] = None,
19431943
ssl_prefer_server_ciphers: Optional[str] = None,
19441944
ssl_session_tickets: Optional[str] = None,
19451945
ssl_session_timeout: Optional[str] = None,
@@ -1968,16 +1968,16 @@ def __init__(self,
19681968
extra_entrypoint_args=extra_entrypoint_args,
19691969
custom_configs=custom_configs
19701970
)
1971-
#: Is a flag to disable HTTPS. If True, the server will use unsecure HTTP
1972-
self.disable_https = disable_https
1971+
#: Is a flag to enable/disable HTTPS. By default set to True.
1972+
self.ssl = ssl
19731973
#: Is a flag to enable SSO auth. Requires oauth2-proxy to be active for SSO authentication.
19741974
self.enable_auth = enable_auth
19751975
#: The port number on which the server will listen
19761976
self.port = port
19771977
#: A multi-line string that contains the SSL certificate
1978-
self.ssl_certificate = ssl_certificate
1978+
self.ssl_cert = ssl_cert
19791979
#: A multi-line string that contains the SSL key
1980-
self.ssl_certificate_key = ssl_certificate_key
1980+
self.ssl_key = ssl_key
19811981
#: Prefer server ciphers over client ciphers: on | off
19821982
self.ssl_prefer_server_ciphers = ssl_prefer_server_ciphers
19831983
#: A multioption flag to control session tickets: on | off
@@ -2009,8 +2009,8 @@ def get_port_start(self) -> List[int]:
20092009
def validate(self) -> None:
20102010
super(MgmtGatewaySpec, self).validate()
20112011
self._validate_port(self.port)
2012-
self._validate_certificate(self.ssl_certificate, "ssl_certificate")
2013-
self._validate_private_key(self.ssl_certificate_key, "ssl_certificate_key")
2012+
self._validate_certificate(self.ssl_cert, "ssl_cert")
2013+
self._validate_private_key(self.ssl_key, "ssl_key")
20142014
self._validate_boolean_switch(self.ssl_prefer_server_ciphers, "ssl_prefer_server_ciphers")
20152015
self._validate_boolean_switch(self.ssl_session_tickets, "ssl_session_tickets")
20162016
self._validate_session_timeout(self.ssl_session_timeout)
@@ -2079,8 +2079,8 @@ def __init__(self,
20792079
oidc_issuer_url: Optional[str] = None,
20802080
redirect_url: Optional[str] = None,
20812081
cookie_secret: Optional[str] = None,
2082-
ssl_certificate: Optional[str] = None,
2083-
ssl_certificate_key: Optional[str] = None,
2082+
ssl_cert: Optional[str] = None,
2083+
ssl_key: Optional[str] = None,
20842084
allowlist_domains: Optional[List[str]] = None,
20852085
unmanaged: bool = False,
20862086
extra_container_args: Optional[GeneralArgList] = None,
@@ -2114,9 +2114,9 @@ def __init__(self,
21142114
# 24, or 32 bytes to create an AES cipher.
21152115
self.cookie_secret = cookie_secret or self.generate_random_secret()
21162116
#: The multi-line SSL certificate for encrypting communications.
2117-
self.ssl_certificate = ssl_certificate
2117+
self.ssl_cert = ssl_cert
21182118
#: The multi-line SSL certificate private key for decrypting communications.
2119-
self.ssl_certificate_key = ssl_certificate_key
2119+
self.ssl_key = ssl_key
21202120
#: List of allowed domains for safe redirection after login or logout,
21212121
# preventing unauthorized redirects.
21222122
self.allowlist_domains = allowlist_domains

0 commit comments

Comments
 (0)