summaryrefslogtreecommitdiff
path: root/src/mongo/db/auth
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/auth')
-rw-r--r--src/mongo/db/auth/auth_index_d.cpp31
-rw-r--r--src/mongo/db/auth/authorization_manager_test.cpp13
-rw-r--r--src/mongo/db/auth/authorization_session.cpp7
-rw-r--r--src/mongo/db/auth/authz_manager_external_state.cpp16
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
}