]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/sts: fix to pick jwk which is of type
authorPritha Srivastava <prsrivas@redhat.com>
Wed, 12 Feb 2025 08:06:20 +0000 (13:36 +0530)
committerPritha Srivastava <prsrivas@redhat.com>
Wed, 30 Apr 2025 06:03:34 +0000 (11:33 +0530)
'sig' for signature validation of the token.

Fixes: https://tracker.ceph.com/issues/54562
Signed-off-by: Pritha Srivastava <prsrivas@redhat.com>
(cherry picked from commit 4c08b48a655f549c0375b2ce728737647ec5cb31)

src/rgw/rgw_rest_sts.cc

index b9308b5cf941bf91b42ac794b9d32cfd7f0445b9..c2c979ca9ce8f518e20dc5479f682a3b73227818 100644 (file)
@@ -389,115 +389,133 @@ WebTokenEngine::validate_signature(const DoutPrefixProvider* dpp, const jwt::dec
 
     JSONParser parser;
     if (parser.parse(cert_resp.c_str(), cert_resp.length())) {
-      JSONObj::data_val val;
-      if (parser.get_data("keys", &val)) {
-        if (val.str[0] == '[') {
-          val.str.erase(0, 1);
-        }
-        if (val.str[val.str.size() - 1] == ']') {
-          val.str = val.str.erase(val.str.size() - 1, 1);
-        }
-        if (parser.parse(val.str.c_str(), val.str.size())) {
+      JSONObj* val = parser.find_obj("keys");
+      if (val && val->is_array()) {
+        vector<string> keys = val->get_array_elements();
+        for (auto &key : keys) {
+          JSONParser k_parser;
           vector<string> x5c;
-          if (JSONDecoder::decode_json("x5c", x5c, &parser)) {
-            string cert;
-            bool found_valid_cert = false;
-            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)) {
-               found_valid_cert = true;
-               break;
+          std::string use;
+          bool skip{false};
+          if (k_parser.parse(key.c_str(), key.size())) {
+            if (JSONDecoder::decode_json("use", use, &k_parser)) {
+              if (use == "enc") { //if key is for encryption then don't use x5c or n and e for signature validation
+                skip = true;
+              } else if (use == "sig") {
+                skip = false;
               }
             }
-            if (! found_valid_cert) {
-              ldpp_dout(dpp, 0) << "Cert doesn't match that with the thumbprints registered with oidc provider: " << cert.c_str() << dendl;
-              throw -EINVAL;
-            }
-            try {
-              //verify method takes care of expired tokens also
-              if (algorithm == "RS256") {
-                auto verifier = jwt::verify()
-                            .allow_algorithm(jwt::algorithm::rs256{cert});
-
-                verifier.verify(decoded);
-              } else if (algorithm == "RS384") {
-                auto verifier = jwt::verify()
-                            .allow_algorithm(jwt::algorithm::rs384{cert});
-
-                verifier.verify(decoded);
-              } else if (algorithm == "RS512") {
-                auto verifier = jwt::verify()
-                            .allow_algorithm(jwt::algorithm::rs512{cert});
-
-                verifier.verify(decoded);
-              } else if (algorithm == "ES256") {
-                auto verifier = jwt::verify()
-                            .allow_algorithm(jwt::algorithm::es256{cert});
-
-                verifier.verify(decoded);
-              } else if (algorithm == "ES384") {
-                auto verifier = jwt::verify()
-                            .allow_algorithm(jwt::algorithm::es384{cert});
-
-                verifier.verify(decoded);
-              } else if (algorithm == "ES512") {
-                auto verifier = jwt::verify()
-                              .allow_algorithm(jwt::algorithm::es512{cert});
-
-                verifier.verify(decoded);
-              } else if (algorithm == "PS256") {
-                auto verifier = jwt::verify()
-                              .allow_algorithm(jwt::algorithm::ps256{cert});
-
-                verifier.verify(decoded);
-              } else if (algorithm == "PS384") {
-                auto verifier = jwt::verify()
-                              .allow_algorithm(jwt::algorithm::ps384{cert});
-
-                verifier.verify(decoded);
-              } else if (algorithm == "PS512") {
-                auto verifier = jwt::verify()
-                              .allow_algorithm(jwt::algorithm::ps512{cert});
-
-                verifier.verify(decoded);
-              } else {
-                ldpp_dout(dpp, 0) << "Unsupported algorithm: " << algorithm << dendl;
+            if (JSONDecoder::decode_json("x5c", x5c, &k_parser)) {
+              if (skip == true) {
+                continue;
+              }
+              string cert;
+              bool found_valid_cert = false;
+              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)) {
+                  found_valid_cert = true;
+                  break;
+                }
+              }
+              if (! found_valid_cert) {
+                ldpp_dout(dpp, 0) << "Cert doesn't match that with the thumbprints registered with oidc provider: " << cert.c_str() << dendl;
                 throw -EINVAL;
               }
-            } catch (std::runtime_error& e) {
-              ldpp_dout(dpp, 0) << "Signature validation failed: " << e.what() << dendl;
-              throw;
-            }
-            catch (...) {
-              ldpp_dout(dpp, 0) << "Signature validation failed" << dendl;
-              throw;
-            }
-          } else {
-            if (algorithm == "RS256" || algorithm == "RS384" || algorithm == "RS512") {
-              string n, e; //modulus and exponent
-              if (JSONDecoder::decode_json("n", n, &parser) && JSONDecoder::decode_json("e", e, &parser)) {
-                validate_signature_using_n_e(dpp, decoded, algorithm, n, e);
-                return;
+              try {
+                //verify method takes care of expired tokens also
+                if (algorithm == "RS256") {
+                  auto verifier = jwt::verify()
+                              .allow_algorithm(jwt::algorithm::rs256{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else if (algorithm == "RS384") {
+                  auto verifier = jwt::verify()
+                              .allow_algorithm(jwt::algorithm::rs384{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else if (algorithm == "RS512") {
+                  auto verifier = jwt::verify()
+                              .allow_algorithm(jwt::algorithm::rs512{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else if (algorithm == "ES256") {
+                  auto verifier = jwt::verify()
+                              .allow_algorithm(jwt::algorithm::es256{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else if (algorithm == "ES384") {
+                  auto verifier = jwt::verify()
+                              .allow_algorithm(jwt::algorithm::es384{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else if (algorithm == "ES512") {
+                  auto verifier = jwt::verify()
+                                .allow_algorithm(jwt::algorithm::es512{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else if (algorithm == "PS256") {
+                  auto verifier = jwt::verify()
+                                .allow_algorithm(jwt::algorithm::ps256{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else if (algorithm == "PS384") {
+                  auto verifier = jwt::verify()
+                                .allow_algorithm(jwt::algorithm::ps384{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else if (algorithm == "PS512") {
+                  auto verifier = jwt::verify()
+                                .allow_algorithm(jwt::algorithm::ps512{cert});
+
+                  verifier.verify(decoded);
+                  return;
+                } else {
+                  ldpp_dout(dpp, 0) << "Unsupported algorithm: " << algorithm << dendl;
+                  throw -EINVAL;
+                }
+              } catch (std::runtime_error& e) {
+                ldpp_dout(dpp, 0) << "Signature validation failed: " << e.what() << dendl;
+                throw;
+              }
+              catch (...) {
+                ldpp_dout(dpp, 0) << "Signature validation failed" << dendl;
+                throw;
               }
-              ldpp_dout(dpp, 0) << "x5c not present or n, e not present" << dendl;
-              throw std::system_error(EINVAL, std::system_category());
             } else {
-              throw std::system_error(EINVAL, std::system_category(), "Invalid algorithm: " + algorithm);
+              if (algorithm == "RS256" || algorithm == "RS384" || algorithm == "RS512") {
+                string n, e; //modulus and exponent
+                if (JSONDecoder::decode_json("n", n, &parser) && JSONDecoder::decode_json("e", e, &parser)) {
+                  validate_signature_using_n_e(dpp, decoded, algorithm, n, e);
+                  return;
+                }
+                ldpp_dout(dpp, 0) << "x5c not present or n, e not present" << dendl;
+                throw -EINVAL;
+              } else {
+                throw std::system_error(EINVAL, std::system_category(), "Invalid algorithm: " + algorithm);
+              }
             }
-          }
-        } else {
-          ldpp_dout(dpp, 0) << "Malformed JSON object for keys" << dendl;
-          throw -EINVAL;
-        }
-      } else {
+            ldpp_dout(dpp, 0) << "Signature can not be validated with the input given in keys: "<< dendl;
+            throw -EINVAL;
+          } //end k_parser.parse
+        }//end for iterate through keys
+      } else { //end val->is_array
         ldpp_dout(dpp, 0) << "keys not present in JSON" << dendl;
         throw -EINVAL;
-      } //if-else get-data
+      }
     } else {
       ldpp_dout(dpp, 0) << "Malformed json returned while fetching cert" << dendl;
       throw -EINVAL;
-    } //if-else parser cert_resp
+    } //if-else get-data
   } else {
     ldpp_dout(dpp, 0) << "JWT signed by HMAC algos are currently not supported" << dendl;
     throw -EINVAL;