diff options
Diffstat (limited to 'src/mongo/db/auth')
| -rw-r--r-- | src/mongo/db/auth/auth_index_d.cpp | 31 | ||||
| -rw-r--r-- | src/mongo/db/auth/authorization_manager_test.cpp | 13 | ||||
| -rw-r--r-- | src/mongo/db/auth/authorization_session.cpp | 7 | ||||
| -rw-r--r-- | src/mongo/db/auth/authz_manager_external_state.cpp | 16 |
4 files changed, 52 insertions, 15 deletions
diff --git a/src/mongo/db/auth/auth_index_d.cpp b/src/mongo/db/auth/auth_index_d.cpp index 47987ac40c4..9944a582f5c 100644 --- a/src/mongo/db/auth/auth_index_d.cpp +++ b/src/mongo/db/auth/auth_index_d.cpp @@ -47,6 +47,7 @@ #include "mongo/db/db_raii.h" #include "mongo/db/index/index_descriptor.h" #include "mongo/db/jsobj.h" +#include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/storage/storage_options.h" #include "mongo/util/assert_util.h" #include "mongo/util/log.h" @@ -105,6 +106,15 @@ void generateSystemIndexForExistingCollection(OperationContext* opCtx, return; } + // Do not try to generate any system indexes on a secondary. + auto replCoord = repl::ReplicationCoordinator::get(opCtx); + uassert(ErrorCodes::NotMaster, + "Not primary while creating authorization index", + replCoord->getReplicationMode() != repl::ReplicationCoordinator::modeReplSet || + replCoord->canAcceptWritesForDatabase(ns.db())); + + invariant(!opCtx->lockState()->inAWriteUnitOfWork()); + try { auto indexSpecStatus = index_key_validate::validateIndexSpec( spec.toBSON(), ns, serverGlobalParams.featureCompatibility); @@ -115,8 +125,10 @@ void generateSystemIndexForExistingCollection(OperationContext* opCtx, MultiIndexBlock indexer(opCtx, collection); + std::vector<BSONObj> indexInfoObjs; MONGO_WRITE_CONFLICT_RETRY_LOOP_BEGIN { - fassertStatusOK(40453, indexer.init(indexSpec)); + indexInfoObjs = fassertStatusOK(40453, indexer.init(indexSpec)); + invariant(indexInfoObjs.size() == 1); } MONGO_WRITE_CONFLICT_RETRY_LOOP_END(opCtx, "authorization index regeneration", ns.ns()); @@ -126,6 +138,8 @@ void generateSystemIndexForExistingCollection(OperationContext* opCtx, WriteUnitOfWork wunit(opCtx); indexer.commit(); + opCtx->getServiceContext()->getOpObserver()->onCreateIndex( + opCtx, ns.getSystemIndexesCollection(), indexInfoObjs[0], false /* fromMigrate */); wunit.commit(); } @@ -205,22 +219,23 @@ Status verifySystemIndexes(OperationContext* txn) { void createSystemIndexes(OperationContext* txn, Collection* collection) { invariant(collection); const NamespaceString& ns = collection->ns(); + BSONObj indexSpec; if (ns == AuthorizationManager::usersCollectionNamespace) { - auto indexSpec = fassertStatusOK( + indexSpec = fassertStatusOK( 40455, index_key_validate::validateIndexSpec( v3SystemUsersIndexSpec.toBSON(), ns, serverGlobalParams.featureCompatibility)); - - fassertStatusOK( - 40456, collection->getIndexCatalog()->createIndexOnEmptyCollection(txn, indexSpec)); } else if (ns == AuthorizationManager::rolesCollectionNamespace) { - auto indexSpec = fassertStatusOK( + indexSpec = fassertStatusOK( 40457, index_key_validate::validateIndexSpec( v3SystemRolesIndexSpec.toBSON(), ns, serverGlobalParams.featureCompatibility)); - + } + if (!indexSpec.isEmpty()) { + txn->getServiceContext()->getOpObserver()->onCreateIndex( + txn, ns.getSystemIndexesCollection(), indexSpec, false /* fromMigrate */); fassertStatusOK( - 40458, collection->getIndexCatalog()->createIndexOnEmptyCollection(txn, indexSpec)); + 40456, collection->getIndexCatalog()->createIndexOnEmptyCollection(txn, indexSpec)); } } diff --git a/src/mongo/db/auth/authorization_manager_test.cpp b/src/mongo/db/auth/authorization_manager_test.cpp index 50f823f014a..ea39d0834a7 100644 --- a/src/mongo/db/auth/authorization_manager_test.cpp +++ b/src/mongo/db/auth/authorization_manager_test.cpp @@ -32,6 +32,7 @@ */ #include "mongo/base/status.h" #include "mongo/bson/mutable/document.h" +#include "mongo/config.h" #include "mongo/db/auth/action_set.h" #include "mongo/db/auth/action_type.h" #include "mongo/db/auth/authorization_manager.h" @@ -55,6 +56,12 @@ namespace mongo { namespace { +// Construct a simple, structured X509 name equivalent to "CN=mongodb.com" +SSLX509Name buildX509Name() { + return SSLX509Name(std::vector<std::vector<SSLX509Name::Entry>>( + {{{kOID_CommonName.toString(), 19 /* Printable String */, "mongodb.com"}}})); +} + using std::vector; TEST(RoleParsingTest, BuildRoleBSON) { @@ -241,13 +248,14 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) { authzManager->releaseUser(v2cluster); } +#ifdef MONGO_CONFIG_SSL TEST_F(AuthorizationManagerTest, testLocalX509Authorization) { ServiceContextNoop serviceContext; transport::TransportLayerMock transportLayer{}; transport::SessionHandle session = transportLayer.createSession(); transportLayer.setX509PeerInfo( session, - SSLPeerInfo("CN=mongodb.com", {RoleName("read", "test"), RoleName("readWrite", "test")})); + SSLPeerInfo(buildX509Name(), {RoleName("read", "test"), RoleName("readWrite", "test")})); ServiceContext::UniqueClient client = serviceContext.makeClient("testClient", session); ServiceContext::UniqueOperationContext txn = client->makeOperationContext(); @@ -274,6 +282,7 @@ TEST_F(AuthorizationManagerTest, testLocalX509Authorization) { authzManager->releaseUser(x509User); } +#endif TEST_F(AuthorizationManagerTest, testLocalX509AuthorizationInvalidUser) { ServiceContextNoop serviceContext; @@ -281,7 +290,7 @@ TEST_F(AuthorizationManagerTest, testLocalX509AuthorizationInvalidUser) { transport::SessionHandle session = transportLayer.createSession(); transportLayer.setX509PeerInfo( session, - SSLPeerInfo("CN=mongodb.com", {RoleName("read", "test"), RoleName("write", "test")})); + SSLPeerInfo(buildX509Name(), {RoleName("read", "test"), RoleName("write", "test")})); ServiceContext::UniqueClient client = serviceContext.makeClient("testClient", session); ServiceContext::UniqueOperationContext txn = client->makeOperationContext(); diff --git a/src/mongo/db/auth/authorization_session.cpp b/src/mongo/db/auth/authorization_session.cpp index a91f350e24d..c4f219c15de 100644 --- a/src/mongo/db/auth/authorization_session.cpp +++ b/src/mongo/db/auth/authorization_session.cpp @@ -679,7 +679,12 @@ static int buildResourceSearchList(const ResourcePattern& target, // Some databases should not be matchable with ResourcePattern::forAnyNormalResource. // 'local' and 'config' are used to store special system collections, which user level // administrators should not be able to manipulate. - if (target.ns().db() != "local" && target.ns().db() != "config") { + // '$setFeatureCompatibilityVersion' is a virtual database that + // setFeatureCompatibilityVersion performs auth checks against. When this command was + // first written, there was a moratorium on creating new ActionTypes. SERVER-31983 + // introduced the ActionType after the moratorium expired. + if (target.ns().db() != "local" && target.ns().db() != "config" && + target.ns().db() != "$setFeatureCompatibilityVersion") { resourceSearchList[size++] = ResourcePattern::forAnyNormalResource(); } resourceSearchList[size++] = ResourcePattern::forDatabaseName(target.ns().db()); diff --git a/src/mongo/db/auth/authz_manager_external_state.cpp b/src/mongo/db/auth/authz_manager_external_state.cpp index ed5f0fe6bfd..0403af8e256 100644 --- a/src/mongo/db/auth/authz_manager_external_state.cpp +++ b/src/mongo/db/auth/authz_manager_external_state.cpp @@ -28,6 +28,7 @@ #include "mongo/platform/basic.h" +#include "mongo/config.h" #include "mongo/db/auth/authz_manager_external_state.h" #include "mongo/db/auth/user_name.h" #include "mongo/db/operation_context.h" @@ -42,10 +43,17 @@ AuthzManagerExternalState::~AuthzManagerExternalState() = default; bool AuthzManagerExternalState::shouldUseRolesFromConnection(OperationContext* txn, const UserName& userName) { - return txn && txn->getClient() && txn->getClient()->session() && - txn->getClient()->session()->getX509PeerInfo().subjectName == userName.getUser() && - userName.getDB() == "$external" && - !txn->getClient()->session()->getX509PeerInfo().roles.empty(); +#ifdef MONGO_CONFIG_SSL + if (!txn || !txn->getClient() || !txn->getClient()->session()) { + return false; + } + + auto sslPeerInfo = txn->getClient()->session()->getX509PeerInfo(); + return sslPeerInfo.subjectName.toString() == userName.getUser() && + userName.getDB() == "$external" && !sslPeerInfo.roles.empty(); +#else + return false; +#endif } |
