summaryrefslogtreecommitdiff
path: root/src/mongo/db/auth/authorization_session_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/auth/authorization_session_test.cpp')
-rw-r--r--src/mongo/db/auth/authorization_session_test.cpp849
1 files changed, 452 insertions, 397 deletions
diff --git a/src/mongo/db/auth/authorization_session_test.cpp b/src/mongo/db/auth/authorization_session_test.cpp
index 5ce06edb4a7..0f5b4936e9d 100644
--- a/src/mongo/db/auth/authorization_session_test.cpp
+++ b/src/mongo/db/auth/authorization_session_test.cpp
@@ -46,409 +46,464 @@
namespace mongo {
namespace {
- class FailureCapableAuthzManagerExternalStateMock :
- public AuthzManagerExternalStateMock {
- public:
- FailureCapableAuthzManagerExternalStateMock() : _findsShouldFail(false) {}
- virtual ~FailureCapableAuthzManagerExternalStateMock() {}
-
- void setFindsShouldFail(bool enable) { _findsShouldFail = enable; }
-
- virtual Status findOne(OperationContext* txn,
- const NamespaceString& collectionName,
- const BSONObj& query,
- BSONObj* result) {
- if (_findsShouldFail &&
- collectionName == AuthorizationManager::usersCollectionNamespace) {
-
- return Status(ErrorCodes::UnknownError,
- "findOne on admin.system.users set to fail in mock.");
- }
- return AuthzManagerExternalStateMock::findOne(txn, collectionName, query, result);
- }
-
- private:
- bool _findsShouldFail;
- };
-
- class AuthorizationSessionTest : public ::mongo::unittest::Test {
- public:
- FailureCapableAuthzManagerExternalStateMock* managerState;
- OperationContextNoop _txn;
- AuthzSessionExternalStateMock* sessionState;
- std::unique_ptr<AuthorizationManager> authzManager;
- std::unique_ptr<AuthorizationSession> authzSession;
-
- void setUp() {
- auto localManagerState = stdx::make_unique<FailureCapableAuthzManagerExternalStateMock>();
- managerState = localManagerState.get();
- managerState->setAuthzVersion(AuthorizationManager::schemaVersion26Final);
- authzManager = stdx::make_unique<AuthorizationManager>(std::move(localManagerState));
- auto localSessionState = stdx::make_unique<AuthzSessionExternalStateMock>(authzManager.get());
- sessionState = localSessionState.get();
- authzSession = stdx::make_unique<AuthorizationSession>(std::move(localSessionState));
- authzManager->setAuthEnabled(true);
- }
- };
-
- const ResourcePattern testDBResource(ResourcePattern::forDatabaseName("test"));
- const ResourcePattern otherDBResource(ResourcePattern::forDatabaseName("other"));
- const ResourcePattern adminDBResource(ResourcePattern::forDatabaseName("admin"));
- const ResourcePattern testFooCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("test.foo")));
- const ResourcePattern otherFooCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("other.foo")));
- const ResourcePattern thirdFooCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("third.foo")));
- const ResourcePattern adminFooCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("admin.foo")));
- const ResourcePattern testUsersCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("test.system.users")));
- const ResourcePattern otherUsersCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("other.system.users")));
- const ResourcePattern thirdUsersCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("third.system.users")));
- const ResourcePattern testIndexesCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("test.system.indexes")));
- const ResourcePattern otherIndexesCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("other.system.indexes")));
- const ResourcePattern thirdIndexesCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("third.system.indexes")));
- const ResourcePattern testProfileCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("test.system.profile")));
- const ResourcePattern otherProfileCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("other.system.profile")));
- const ResourcePattern thirdProfileCollResource(
- ResourcePattern::forExactNamespace(NamespaceString("third.system.profile")));
-
- TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
- // Check that disabling auth checks works
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
- sessionState->setReturnValueForShouldIgnoreAuthChecks(true);
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
- sessionState->setReturnValueForShouldIgnoreAuthChecks(false);
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
-
- // Check that you can't authorize a user that doesn't exist.
- ASSERT_EQUALS(ErrorCodes::UserNotFound,
- authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
-
- // Add a user with readWrite and dbAdmin on the test DB
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "spencer" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "readWrite" <<
- "db" << "test") <<
- BSON("role" << "dbAdmin" <<
- "db" << "test"))),
- BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
-
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testDBResource, ActionType::dbStats));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
-
- // Add an admin user with readWriteAnyDatabase
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "admin" <<
- "db" << "admin" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "readWriteAnyDatabase" <<
- "db" << "admin"))),
- BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("admin", "admin")));
-
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- ResourcePattern::forExactNamespace(
- NamespaceString("anydb.somecollection")),
- ActionType::insert));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherDBResource, ActionType::insert));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::collMod));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
-
- authzSession->logoutDatabase("test");
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::collMod));
-
- authzSession->logoutDatabase("admin");
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::collMod));
- }
+class FailureCapableAuthzManagerExternalStateMock : public AuthzManagerExternalStateMock {
+public:
+ FailureCapableAuthzManagerExternalStateMock() : _findsShouldFail(false) {}
+ virtual ~FailureCapableAuthzManagerExternalStateMock() {}
- TEST_F(AuthorizationSessionTest, DuplicateRolesOK) {
- // Add a user with doubled-up readWrite and single dbAdmin on the test DB
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "spencer" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "readWrite" <<
- "db" << "test") <<
- BSON("role" << "dbAdmin" <<
- "db" << "test") <<
- BSON("role" << "readWrite" <<
- "db" << "test"))),
- BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
-
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testDBResource, ActionType::dbStats));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherFooCollResource, ActionType::insert));
+ void setFindsShouldFail(bool enable) {
+ _findsShouldFail = enable;
}
- TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "rw" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "readWrite" <<
- "db" << "test") <<
- BSON("role" << "dbAdmin" <<
- "db" << "test"))),
- BSONObj()));
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "useradmin" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "userAdmin" <<
- "db" << "test"))),
- BSONObj()));
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "rwany" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "readWriteAnyDatabase" <<
- "db" << "admin") <<
- BSON("role" << "dbAdminAnyDatabase" <<
- "db" << "admin"))),
- BSONObj()));
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "useradminany" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "userAdminAnyDatabase" <<
- "db" << "admin"))),
- BSONObj()));
-
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("rwany", "test")));
-
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testIndexesCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testProfileCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherIndexesCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherProfileCollResource, ActionType::find));
-
- // Logging in as useradminany@test implicitly logs out rwany@test.
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("useradminany", "test")));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::insert));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::insert));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testIndexesCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testProfileCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherIndexesCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherProfileCollResource, ActionType::find));
-
- // Logging in as rw@test implicitly logs out useradminany@test.
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("rw", "test")));
-
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testIndexesCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testProfileCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherIndexesCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherProfileCollResource, ActionType::find));
-
-
- // Logging in as useradmin@test implicitly logs out rw@test.
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("useradmin", "test")));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testUsersCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherUsersCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testIndexesCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testProfileCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherIndexesCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- otherProfileCollResource, ActionType::find));
- }
-
- TEST_F(AuthorizationSessionTest, InvalidateUser) {
- // Add a readWrite user
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "spencer" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "readWrite" <<
- "db" << "test"))),
- BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
-
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
-
- User* user = authzSession->lookupUser(UserName("spencer", "test"));
- ASSERT(user->isValid());
-
- // Change the user to be read-only
- int ignored;
- managerState->remove(
- &_txn,
- AuthorizationManager::usersCollectionNamespace,
- BSONObj(),
- BSONObj(),
- &ignored);
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "spencer" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "read" <<
- "db" << "test"))),
- BSONObj()));
-
- // Make sure that invalidating the user causes the session to reload its privileges.
- authzManager->invalidateUserByName(user->getName());
- authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
-
- user = authzSession->lookupUser(UserName("spencer", "test"));
- ASSERT(user->isValid());
-
- // Delete the user.
- managerState->remove(
- &_txn,
- AuthorizationManager::usersCollectionNamespace,
- BSONObj(),
- BSONObj(),
- &ignored);
- // Make sure that invalidating the user causes the session to reload its privileges.
- authzManager->invalidateUserByName(user->getName());
- authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
- ASSERT_FALSE(authzSession->lookupUser(UserName("spencer", "test")));
+ virtual Status findOne(OperationContext* txn,
+ const NamespaceString& collectionName,
+ const BSONObj& query,
+ BSONObj* result) {
+ if (_findsShouldFail && collectionName == AuthorizationManager::usersCollectionNamespace) {
+ return Status(ErrorCodes::UnknownError,
+ "findOne on admin.system.users set to fail in mock.");
+ }
+ return AuthzManagerExternalStateMock::findOne(txn, collectionName, query, result);
}
- TEST_F(AuthorizationSessionTest, UseOldUserInfoInFaceOfConnectivityProblems) {
- // Add a readWrite user
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "spencer" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "readWrite" <<
- "db" << "test"))),
- BSONObj()));
- ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
-
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
-
- User* user = authzSession->lookupUser(UserName("spencer", "test"));
- ASSERT(user->isValid());
-
- // Change the user to be read-only
- int ignored;
- managerState->setFindsShouldFail(true);
- managerState->remove(
- &_txn,
- AuthorizationManager::usersCollectionNamespace,
- BSONObj(),
- BSONObj(),
- &ignored);
- ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
- BSON("user" << "spencer" <<
- "db" << "test" <<
- "credentials" << BSON("MONGODB-CR" << "a") <<
- "roles" << BSON_ARRAY(BSON("role" << "read" <<
- "db" << "test"))),
- BSONObj()));
-
- // Even though the user's privileges have been reduced, since we've configured user
- // document lookup to fail, the authz session should continue to use its known out-of-date
- // privilege data.
- authzManager->invalidateUserByName(user->getName());
- authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
-
- // Once we configure document lookup to succeed again, authorization checks should
- // observe the new values.
- managerState->setFindsShouldFail(false);
- authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
- ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::find));
- ASSERT_FALSE(authzSession->isAuthorizedForActionsOnResource(
- testFooCollResource, ActionType::insert));
+private:
+ bool _findsShouldFail;
+};
+
+class AuthorizationSessionTest : public ::mongo::unittest::Test {
+public:
+ FailureCapableAuthzManagerExternalStateMock* managerState;
+ OperationContextNoop _txn;
+ AuthzSessionExternalStateMock* sessionState;
+ std::unique_ptr<AuthorizationManager> authzManager;
+ std::unique_ptr<AuthorizationSession> authzSession;
+
+ void setUp() {
+ auto localManagerState = stdx::make_unique<FailureCapableAuthzManagerExternalStateMock>();
+ managerState = localManagerState.get();
+ managerState->setAuthzVersion(AuthorizationManager::schemaVersion26Final);
+ authzManager = stdx::make_unique<AuthorizationManager>(std::move(localManagerState));
+ auto localSessionState =
+ stdx::make_unique<AuthzSessionExternalStateMock>(authzManager.get());
+ sessionState = localSessionState.get();
+ authzSession = stdx::make_unique<AuthorizationSession>(std::move(localSessionState));
+ authzManager->setAuthEnabled(true);
}
+};
+
+const ResourcePattern testDBResource(ResourcePattern::forDatabaseName("test"));
+const ResourcePattern otherDBResource(ResourcePattern::forDatabaseName("other"));
+const ResourcePattern adminDBResource(ResourcePattern::forDatabaseName("admin"));
+const ResourcePattern testFooCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("test.foo")));
+const ResourcePattern otherFooCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("other.foo")));
+const ResourcePattern thirdFooCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("third.foo")));
+const ResourcePattern adminFooCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("admin.foo")));
+const ResourcePattern testUsersCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("test.system.users")));
+const ResourcePattern otherUsersCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("other.system.users")));
+const ResourcePattern thirdUsersCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("third.system.users")));
+const ResourcePattern testIndexesCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("test.system.indexes")));
+const ResourcePattern otherIndexesCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("other.system.indexes")));
+const ResourcePattern thirdIndexesCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("third.system.indexes")));
+const ResourcePattern testProfileCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("test.system.profile")));
+const ResourcePattern otherProfileCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("other.system.profile")));
+const ResourcePattern thirdProfileCollResource(
+ ResourcePattern::forExactNamespace(NamespaceString("third.system.profile")));
+
+TEST_F(AuthorizationSessionTest, AddUserAndCheckAuthorization) {
+ // Check that disabling auth checks works
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+ sessionState->setReturnValueForShouldIgnoreAuthChecks(true);
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+ sessionState->setReturnValueForShouldIgnoreAuthChecks(false);
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+
+ // Check that you can't authorize a user that doesn't exist.
+ ASSERT_EQUALS(ErrorCodes::UserNotFound,
+ authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
+
+ // Add a user with readWrite and dbAdmin on the test DB
+ ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "spencer"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "readWrite"
+ << "db"
+ << "test")
+ << BSON("role"
+ << "dbAdmin"
+ << "db"
+ << "test"))),
+ BSONObj()));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
+
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testDBResource, ActionType::dbStats));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::insert));
+
+ // Add an admin user with readWriteAnyDatabase
+ ASSERT_OK(
+ managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "admin"
+ << "db"
+ << "admin"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "readWriteAnyDatabase"
+ << "db"
+ << "admin"))),
+ BSONObj()));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("admin", "admin")));
+
+ ASSERT_TRUE(authzSession->isAuthorizedForActionsOnResource(
+ ResourcePattern::forExactNamespace(NamespaceString("anydb.somecollection")),
+ ActionType::insert));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(otherDBResource, ActionType::insert));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::collMod));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+
+ authzSession->logoutDatabase("test");
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::insert));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::collMod));
+
+ authzSession->logoutDatabase("admin");
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::collMod));
+}
+
+TEST_F(AuthorizationSessionTest, DuplicateRolesOK) {
+ // Add a user with doubled-up readWrite and single dbAdmin on the test DB
+ ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "spencer"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "readWrite"
+ << "db"
+ << "test")
+ << BSON("role"
+ << "dbAdmin"
+ << "db"
+ << "test")
+ << BSON("role"
+ << "readWrite"
+ << "db"
+ << "test"))),
+ BSONObj()));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
+
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testDBResource, ActionType::dbStats));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherFooCollResource, ActionType::insert));
+}
+
+TEST_F(AuthorizationSessionTest, SystemCollectionsAccessControl) {
+ ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "rw"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "readWrite"
+ << "db"
+ << "test")
+ << BSON("role"
+ << "dbAdmin"
+ << "db"
+ << "test"))),
+ BSONObj()));
+ ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "useradmin"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "userAdmin"
+ << "db"
+ << "test"))),
+ BSONObj()));
+ ASSERT_OK(
+ managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "rwany"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "readWriteAnyDatabase"
+ << "db"
+ << "admin")
+ << BSON("role"
+ << "dbAdminAnyDatabase"
+ << "db"
+ << "admin"))),
+ BSONObj()));
+ ASSERT_OK(
+ managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "useradminany"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "userAdminAnyDatabase"
+ << "db"
+ << "admin"))),
+ BSONObj()));
+
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("rwany", "test")));
+
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherUsersCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherUsersCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testIndexesCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testProfileCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(otherIndexesCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
+
+ // Logging in as useradminany@test implicitly logs out rwany@test.
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("useradminany", "test")));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherUsersCollResource, ActionType::insert));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(otherUsersCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testIndexesCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testProfileCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherIndexesCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
+
+ // Logging in as rw@test implicitly logs out useradminany@test.
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("rw", "test")));
+
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherUsersCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherUsersCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testIndexesCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testProfileCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherIndexesCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
+
+
+ // Logging in as useradmin@test implicitly logs out rw@test.
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("useradmin", "test")));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testUsersCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherUsersCollResource, ActionType::insert));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherUsersCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testIndexesCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testProfileCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherIndexesCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(otherProfileCollResource, ActionType::find));
+}
+
+TEST_F(AuthorizationSessionTest, InvalidateUser) {
+ // Add a readWrite user
+ ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "spencer"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "readWrite"
+ << "db"
+ << "test"))),
+ BSONObj()));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
+
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+
+ User* user = authzSession->lookupUser(UserName("spencer", "test"));
+ ASSERT(user->isValid());
+
+ // Change the user to be read-only
+ int ignored;
+ managerState->remove(
+ &_txn, AuthorizationManager::usersCollectionNamespace, BSONObj(), BSONObj(), &ignored);
+ ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "spencer"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "read"
+ << "db"
+ << "test"))),
+ BSONObj()));
+
+ // Make sure that invalidating the user causes the session to reload its privileges.
+ authzManager->invalidateUserByName(user->getName());
+ authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+
+ user = authzSession->lookupUser(UserName("spencer", "test"));
+ ASSERT(user->isValid());
+
+ // Delete the user.
+ managerState->remove(
+ &_txn, AuthorizationManager::usersCollectionNamespace, BSONObj(), BSONObj(), &ignored);
+ // Make sure that invalidating the user causes the session to reload its privileges.
+ authzManager->invalidateUserByName(user->getName());
+ authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+ ASSERT_FALSE(authzSession->lookupUser(UserName("spencer", "test")));
+}
+
+TEST_F(AuthorizationSessionTest, UseOldUserInfoInFaceOfConnectivityProblems) {
+ // Add a readWrite user
+ ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "spencer"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "readWrite"
+ << "db"
+ << "test"))),
+ BSONObj()));
+ ASSERT_OK(authzSession->addAndAuthorizeUser(&_txn, UserName("spencer", "test")));
+
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+
+ User* user = authzSession->lookupUser(UserName("spencer", "test"));
+ ASSERT(user->isValid());
+
+ // Change the user to be read-only
+ int ignored;
+ managerState->setFindsShouldFail(true);
+ managerState->remove(
+ &_txn, AuthorizationManager::usersCollectionNamespace, BSONObj(), BSONObj(), &ignored);
+ ASSERT_OK(managerState->insertPrivilegeDocument(&_txn,
+ BSON("user"
+ << "spencer"
+ << "db"
+ << "test"
+ << "credentials" << BSON("MONGODB-CR"
+ << "a") << "roles"
+ << BSON_ARRAY(BSON("role"
+ << "read"
+ << "db"
+ << "test"))),
+ BSONObj()));
+
+ // Even though the user's privileges have been reduced, since we've configured user
+ // document lookup to fail, the authz session should continue to use its known out-of-date
+ // privilege data.
+ authzManager->invalidateUserByName(user->getName());
+ authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+
+ // Once we configure document lookup to succeed again, authorization checks should
+ // observe the new values.
+ managerState->setFindsShouldFail(false);
+ authzSession->startRequest(&_txn); // Refreshes cached data for invalid users
+ ASSERT_TRUE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::find));
+ ASSERT_FALSE(
+ authzSession->isAuthorizedForActionsOnResource(testFooCollResource, ActionType::insert));
+}
} // namespace
} // namespace mongo