diff options
author | Spencer T Brody <spencer@10gen.com> | 2013-08-12 18:18:08 -0400 |
---|---|---|
committer | Spencer T Brody <spencer@10gen.com> | 2013-08-19 17:03:51 -0400 |
commit | e8a98c47fcf80829adae349c09efa1f6e2e1d9af (patch) | |
tree | d84947d9f8dd2acc90fbf3a819b39d84e8921916 /src/mongo | |
parent | 4140e3743026af40d83b29f10cfbc6d7cd8505fa (diff) | |
download | mongo-e8a98c47fcf80829adae349c09efa1f6e2e1d9af.tar.gz |
SERVER-9518 Reload User if User has been invalidated
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/db/auth/authorization_manager.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager.h | 5 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session.cpp | 16 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_session_test.cpp | 27 |
4 files changed, 63 insertions, 1 deletions
diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp index b4903730b45..102ac60bed6 100644 --- a/src/mongo/db/auth/authorization_manager.cpp +++ b/src/mongo/db/auth/authorization_manager.cpp @@ -731,6 +731,22 @@ namespace { } } + void AuthorizationManager::invalidateUser(User* user) { + boost::lock_guard<boost::mutex> lk(_lock); + if (!user->isValid()) { + return; + } + + unordered_map<UserName, User*>::iterator it = _userCache.find(user->getName()); + massert(17052, + mongoutils::str::stream() << + "Invalidating cache for user " << user->getName().toString() << + " failed as it is not present in the user cache", + it != _userCache.end() && it->second == user); + _userCache.erase(it); + user->invalidate(); + } + void AuthorizationManager::addInternalUser(User* user) { boost::lock_guard<boost::mutex> lk(_lock); _userCache.insert(make_pair(user->getName(), user)); diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h index c206f0299e0..7f00c0d902d 100644 --- a/src/mongo/db/auth/authorization_manager.h +++ b/src/mongo/db/auth/authorization_manager.h @@ -146,6 +146,11 @@ namespace mongo { void releaseUser(User* user); /** + * Marks the given user as invalid and removes it from the user cache. + */ + void invalidateUser(User* user); + + /** * Inserts the given user directly into the _userCache. Used to add the internalSecurity * user into the cache at process startup. */ diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp index 6c89fbbef84..5358d5c90f0 100644 --- a/src/mongo/db/auth/authorization_session.cpp +++ b/src/mongo/db/auth/authorization_session.cpp @@ -356,7 +356,21 @@ namespace { it != _authenticatedUsers.end(); ++it) { User* user = *it; - // TODO(spencer): Handle if the user has been invalidated. + if (!user->isValid()) { + // Need to release and re-acquire user if it's been invalidated. + UserName name = user->getName(); + + _authenticatedUsers.removeByDBName(name.getDB()); + getAuthorizationManager().releaseUser(user); + + Status status = getAuthorizationManager().acquireUser(name, &user); + if (!status.isOK()) { + return Status(ErrorCodes::Unauthorized, + mongoutils::str::stream() << "Re-acquiring invalidated user " + "failed due to: " << status.reason()); + } + _authenticatedUsers.add(user); + } for (int i = 0; i < static_cast<int>(boost::size(resourceSearchList)); ++i) { ActionSet userActions = user->getActionsForResource(resourceSearchList[i]); diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp index 6a473091729..6000e616368 100644 --- a/src/mongo/db/auth/authorization_session_test.cpp +++ b/src/mongo/db/auth/authorization_session_test.cpp @@ -101,6 +101,33 @@ namespace { ASSERT_FALSE(authzSession->checkAuthorization("test.foo", ActionType::collMod)); } + TEST_F(AuthorizationSessionTest, InvalidateUser) { + // Add a readWrite user + ASSERT_OK(managerState->insertPrivilegeDocument("test", + BSON("user" << "spencer" << + "pwd" << "a" << + "roles" << BSON_ARRAY("readWrite")))); + ASSERT_OK(authzSession->addAndAuthorizeUser(UserName("spencer", "test"))); + + ASSERT_TRUE(authzSession->checkAuthorization("test", ActionType::find)); + ASSERT_TRUE(authzSession->checkAuthorization("test", ActionType::insert)); + + User* user = authzSession->lookupUser(UserName("spencer", "test")); + ASSERT(user->isValid()); + + // Change the user to be read-only + managerState->clearPrivilegeDocuments(); + ASSERT_OK(managerState->insertPrivilegeDocument("test", + BSON("user" << "spencer" << + "pwd" << "a" << + "roles" << BSON_ARRAY("read")))); + + // Make sure that invalidating the user causes the session to reload its privileges. + authzManager->invalidateUser(user); + ASSERT_TRUE(authzSession->checkAuthorization("test", ActionType::find)); + ASSERT_FALSE(authzSession->checkAuthorization("test", ActionType::insert)); + } + TEST_F(AuthorizationSessionTest, ImplicitAcquireFromSomeDatabasesWithV1Users) { managerState->insertPrivilegeDocument("test", |