From: Alex Wojno Date: Tue, 20 May 2025 16:03:56 +0000 (+0000) Subject: rgw: make jwks url verification configurable X-Git-Tag: testing/wip-jcollin-testing-20250911.040549-tentacle~8^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3ab88a030509764a1dcffe001896fa5964a2f064;p=ceph-ci.git rgw: make jwks url verification configurable Added `rgw_enable_jwks_url_verification` to control verification. Signed-off-by: Alex Wojno (cherry picked from commit 759fb7f116014353fed98996ab76761e451453f4) --- diff --git a/src/common/options/rgw.yaml.in b/src/common/options/rgw.yaml.in index 701d09067d3..ec7e6fbbb9f 100644 --- a/src/common/options/rgw.yaml.in +++ b/src/common/options/rgw.yaml.in @@ -1215,6 +1215,17 @@ options: see_also: - rgw_keystone_verify_ssl with_legacy: true +- name: rgw_enable_jwks_url_verification + type: bool + level: advanced + desc: Enable JWKS url verification for AWS compliance + long_desc: + Verifies the security of the JWKS url endpoint using the client provided thumbprints + for AWS compliance. If turned on, the legacy verification option of using thumbprints + to verify JWT x5c certs is disabled. + default: false + services: + - rgw # The following are tunables for caches of RGW NFS (and other file # client) objects. # diff --git a/src/rgw/rgw_rest_sts.cc b/src/rgw/rgw_rest_sts.cc index 071372822bb..862c4b81a2a 100644 --- a/src/rgw/rgw_rest_sts.cc +++ b/src/rgw/rgw_rest_sts.cc @@ -577,9 +577,14 @@ WebTokenEngine::validate_signature_using_n_e(const DoutPrefixProvider* dpp, cons return true; } -bool WebTokenEngine::validate_cert_url(const DoutPrefixProvider* dpp, const std::string& cert_url, +bool WebTokenEngine::verify_oidc_thumbprint(const DoutPrefixProvider* dpp, const std::string& cert_url, const std::vector& thumbprints) const { + if (!cct->_conf.get_val("rgw_enable_jwks_url_verification")) { + ldpp_dout(dpp, 5) << "Verification of JWKS endpoint is turned off." << dendl; + return true; + } + // Fetch and verify cert according to https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc_verify-thumbprint.html const auto hostname = get_top_level_domain_from_host(dpp, cert_url); ldpp_dout(dpp, 20) << "Validating hostname: " << hostname << dendl; @@ -606,7 +611,7 @@ WebTokenEngine::validate_signature(const DoutPrefixProvider* dpp, const jwt::dec { if (algorithm != "HS256" && algorithm != "HS384" && algorithm != "HS512") { const auto cert_url = get_cert_url(iss, dpp, y); - if (cert_url.empty() || !validate_cert_url(dpp, cert_url, thumbprints)) { + if (cert_url.empty() || !verify_oidc_thumbprint(dpp, cert_url, thumbprints)) { ldpp_dout(dpp, 5) << "Not able to validate JWKS url with registered thumbprints" << dendl; throw std::system_error(EINVAL, std::system_category()); } @@ -646,10 +651,11 @@ WebTokenEngine::validate_signature(const DoutPrefixProvider* dpp, const jwt::dec if (JSONDecoder::decode_json("x5c", x5c, &k_parser)) { string cert; bool found_valid_cert = false; + bool skip_thumbprint_verification = cct->_conf.get_val("rgw_enable_jwks_url_verification"); for (auto& it : x5c) { cert = "-----BEGIN CERTIFICATE-----\n" + it + "\n-----END CERTIFICATE-----"; ldpp_dout(dpp, 20) << "Certificate is: " << cert.c_str() << dendl; - if (is_cert_valid(thumbprints, cert)) { + if (skip_thumbprint_verification || is_cert_valid(thumbprints, cert)) { found_valid_cert = true; break; } @@ -737,7 +743,7 @@ WebTokenEngine::validate_signature(const DoutPrefixProvider* dpp, const jwt::dec return; } } - ldpp_dout(dpp, 10) << "Bare key parameters are not present for key" << dendl; + ldpp_dout(dpp, 10) << "Bare key parameters (n&e) are not present for key" << dendl; } } } //end k_parser.parse diff --git a/src/rgw/rgw_rest_sts.h b/src/rgw/rgw_rest_sts.h index 0f3f8c00070..f00e66493c5 100644 --- a/src/rgw/rgw_rest_sts.h +++ b/src/rgw/rgw_rest_sts.h @@ -69,7 +69,7 @@ class WebTokenEngine : public rgw::auth::Engine { std::string connect_to_host_get_cert_chain(const DoutPrefixProvider* dpp, const std::string& hostname, int port = 443) const; std::string get_top_level_domain_from_host(const DoutPrefixProvider* dpp, const std::string& hostname) const; std::string extract_last_certificate(const DoutPrefixProvider* dpp, const std::string& pem_chain) const; - bool validate_cert_url(const DoutPrefixProvider* dpp, const std::string& cert_url, + bool verify_oidc_thumbprint(const DoutPrefixProvider* dpp, const std::string& cert_url, const std::vector& thumbprints) const; void shutdown_ssl(const DoutPrefixProvider* dpp, SSL* ssl, SSL_CTX* ctx) const;