From c0e18ccca77484ce7b879044c05f9daea62769f5 Mon Sep 17 00:00:00 2001 From: Alex Wojno Date: Tue, 20 May 2025 16:03:56 +0000 Subject: [PATCH] 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) --- src/common/options/rgw.yaml.in | 11 +++++++++++ src/rgw/rgw_rest_sts.cc | 14 ++++++++++---- src/rgw/rgw_rest_sts.h | 2 +- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/common/options/rgw.yaml.in b/src/common/options/rgw.yaml.in index e601291626e..d2f5a59e2b9 100644 --- a/src/common/options/rgw.yaml.in +++ b/src/common/options/rgw.yaml.in @@ -1141,6 +1141,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 b0e55f1c2d4..5d2ab9e05cf 100644 --- a/src/rgw/rgw_rest_sts.cc +++ b/src/rgw/rgw_rest_sts.cc @@ -573,9 +573,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; @@ -602,7 +607,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()); } @@ -642,10 +647,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; } @@ -733,7 +739,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; -- 2.47.3