diff options
-rw-r--r-- | src/mongo/base/error_codes.yml | 2 | ||||
-rw-r--r-- | src/mongo/crypto/SConscript | 6 | ||||
-rw-r--r-- | src/mongo/crypto/jwk_manager.cpp | 22 | ||||
-rw-r--r-- | src/mongo/crypto/jwk_manager.h | 25 | ||||
-rw-r--r-- | src/mongo/crypto/jwt_test.cpp | 2 |
5 files changed, 38 insertions, 19 deletions
diff --git a/src/mongo/base/error_codes.yml b/src/mongo/base/error_codes.yml index e1054f1b471..cec467176fb 100644 --- a/src/mongo/base/error_codes.yml +++ b/src/mongo/base/error_codes.yml @@ -511,8 +511,8 @@ error_codes: - {code: 389, name: LibmongocryptError} - {code: 390, name: InvalidSignature} - - {code: 391, name: ReauthenticationRequired} + - {code: 392, name: InvalidJWT} # Error codes 4000-8999 are reserved. # Non-sequential error codes for compatibility only) diff --git a/src/mongo/crypto/SConscript b/src/mongo/crypto/SConscript index 0bcf8da8b0a..3e1211051b8 100644 --- a/src/mongo/crypto/SConscript +++ b/src/mongo/crypto/SConscript @@ -152,6 +152,7 @@ env.CppUnitTest( '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/base/secure_allocator', '$BUILD_DIR/mongo/shell/kms_idl', + '$BUILD_DIR/mongo/util/net/http_client_impl', '$BUILD_DIR/mongo/util/net/openssl_init' if ssl_provider == 'openssl' else [], 'aead_encryption', 'encrypted_field_config', @@ -171,11 +172,12 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/base', - '$BUILD_DIR/mongo/client/sasl_client', - '$BUILD_DIR/mongo/util/net/http_client_impl', ], LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/client/sasl_client', + '$BUILD_DIR/mongo/db/commands/test_commands_enabled', '$BUILD_DIR/mongo/idl/idl_parser', + '$BUILD_DIR/mongo/util/net/http_client_impl', ], ) diff --git a/src/mongo/crypto/jwk_manager.cpp b/src/mongo/crypto/jwk_manager.cpp index 71e2619f33e..29ee470517d 100644 --- a/src/mongo/crypto/jwk_manager.cpp +++ b/src/mongo/crypto/jwk_manager.cpp @@ -32,6 +32,7 @@ #include "mongo/bson/json.h" #include "mongo/crypto/jws_validator.h" #include "mongo/crypto/jwt_types_gen.h" +#include "mongo/db/commands/test_commands_enabled.h" #include "mongo/logv2/log.h" #include "mongo/util/base64.h" #include "mongo/util/net/http_client.h" @@ -58,8 +59,9 @@ StringData reduceInt(StringData value) { JWKManager::JWKManager(StringData source) : _keyURI(source) { auto httpClient = HttpClient::createWithoutConnectionPool(); httpClient->setHeaders({"Accept: */*"}); + httpClient->allowInsecureHTTP(getTestCommandsEnabled()); - DataBuilder getJWKs = httpClient->get(source); + auto getJWKs = httpClient->get(source); ConstDataRange cdr = getJWKs.getCursor(); StringData str; @@ -73,11 +75,11 @@ JWKManager::JWKManager(BSONObj keys) { _setAndValidateKeys(keys); } -const BSONObj& JWKManager::getKey(StringData keyId) const { +StatusWith<BSONObj> JWKManager::getKey(StringData keyId) const { auto it = _keyMaterial.find(keyId.toString()); - uassert(ErrorCodes::NoSuchKey, - str::stream() << "Unknown key '" << keyId << "'", - it != _keyMaterial.end()); + if (it == _keyMaterial.end()) { + return {ErrorCodes::NoSuchKey, str::stream() << "Unknown key '" << keyId << "'"}; + } return it->second; } @@ -132,7 +134,17 @@ void JWKManager::_setAndValidateKeys(const BSONObj& keys) { SharedValidator shValidator = std::move(swValidator.getValue()); _validators->insert({keyId, shValidator}); + LOGV2_DEBUG(7070202, 3, "Loaded JWK key", "kid"_attr = keyId, "typ"_attr = JWK.getType()); } } +std::vector<std::string> JWKManager::getKeyIds() const { + std::vector<std::string> ids; + std::transform(_validators->cbegin(), + _validators->cend(), + std::back_inserter(ids), + [](const auto& it) { return it.first; }); + return ids; +} + } // namespace mongo::crypto diff --git a/src/mongo/crypto/jwk_manager.h b/src/mongo/crypto/jwk_manager.h index 47aa8fc753a..bba9a276388 100644 --- a/src/mongo/crypto/jwk_manager.h +++ b/src/mongo/crypto/jwk_manager.h @@ -44,22 +44,22 @@ public: using SharedValidator = std::shared_ptr<JWSValidator>; /** - Fetch a JWKS file from the specified URL, parse them as keys, - and instantiate JWSValidator instances. - */ + * Fetch a JWKS file from the specified URL, parse them as keys, + * and instantiate JWSValidator instances. + */ explicit JWKManager(StringData source); /** - Parse a BSONObj array of keys, and instantiate JWSValidator instances. - This was added for testing purposes. - */ + * Parse a BSONObj array of keys, and instantiate JWSValidator instances. + * This was added for testing purposes. + */ explicit JWKManager(BSONObj keys); /** - Given a unique keyId it will return the matching JWK. - If no key is found for the given keyId, a uassert will be thrown. - */ - const BSONObj& getKey(StringData keyId) const; + * Given a unique keyId it will return the matching JWK. + * If no key is found for the given keyId, a + */ + StatusWith<BSONObj> getKey(StringData keyId) const; /** * Fetch a specific JWSValidator from the JWKManager by keyId. @@ -74,6 +74,11 @@ public: return _validators->size(); } + /** + * Get the list of keyIds held by this key manager. + */ + std::vector<std::string> getKeyIds() const; + private: void _setAndValidateKeys(const BSONObj& keys); diff --git a/src/mongo/crypto/jwt_test.cpp b/src/mongo/crypto/jwt_test.cpp index 41e8059bbfe..b43b929b08a 100644 --- a/src/mongo/crypto/jwt_test.cpp +++ b/src/mongo/crypto/jwt_test.cpp @@ -54,7 +54,7 @@ TEST(JWKManager, parseJWKSetBasicFromSource) { JWKManager manager(source); for (const auto& key : data["keys"_sd].Obj()) { - auto keyFromKid = manager.getKey(key["kid"_sd].str()); + auto keyFromKid = uassertStatusOK(manager.getKey(key["kid"_sd].str())); ASSERT_BSONOBJ_EQ(key.Obj(), keyFromKid); } |