summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer T Brody <spencer@mongodb.com>2015-11-25 14:40:17 -0500
committerSpencer T Brody <spencer@mongodb.com>2015-11-30 10:44:18 -0500
commit16b5070833b20c73f87fc37df1f6a21afca825ba (patch)
tree56d814c448c3f85fed7c708395796de9136875c0
parent909b13f0ac6ed6d0de5a37ae3b833494f9a12218 (diff)
downloadmongo-16b5070833b20c73f87fc37df1f6a21afca825ba.tar.gz
SERVER-21659 Move logic for redacting 'bypassDocumentValidation' privilege for backwards compatibility up to the usersInfo command
-rw-r--r--src/mongo/db/auth/SConscript1
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.cpp22
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.h15
-rw-r--r--src/mongo/db/commands/user_management_commands.cpp46
4 files changed, 49 insertions, 35 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index fc535d9033f..f8935e8d588 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -38,7 +38,6 @@ env.Library('authcore', ['action_set.cpp',
'$BUILD_DIR/mongo/db/common',
'$BUILD_DIR/mongo/db/ops/update_driver',
'$BUILD_DIR/mongo/db/namespace_string',
- '$BUILD_DIR/mongo/rpc/protocol',
'$BUILD_DIR/mongo/util/md5'])
env.Library('authcommon',
diff --git a/src/mongo/db/auth/authz_manager_external_state_local.cpp b/src/mongo/db/auth/authz_manager_external_state_local.cpp
index 10576b5380f..674a06cfb6b 100644
--- a/src/mongo/db/auth/authz_manager_external_state_local.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_local.cpp
@@ -37,7 +37,6 @@
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/user_document_parser.h"
#include "mongo/db/operation_context.h"
-#include "mongo/rpc/protocol.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
@@ -157,14 +156,13 @@ Status AuthzManagerExternalStateLocal::getUserDescription(OperationContext* txn,
return status;
mutablebson::Document resultDoc(*result, mutablebson::Document::kInPlaceDisabled);
- _resolveUserRoles(txn, &resultDoc, directRoles);
+ _resolveUserRoles(&resultDoc, directRoles);
*result = resultDoc.getObject();
return Status::OK();
}
-void AuthzManagerExternalStateLocal::_resolveUserRoles(OperationContext* txn,
- mutablebson::Document* userDoc,
+void AuthzManagerExternalStateLocal::_resolveUserRoles(mutablebson::Document* userDoc,
const std::vector<RoleName>& directRoles) {
unordered_set<RoleName> indirectRoles;
PrivilegeVector allPrivileges;
@@ -194,8 +192,6 @@ void AuthzManagerExternalStateLocal::_resolveUserRoles(OperationContext* txn,
}
}
- _redactPrivilegesForBackwardsCompatibilityIfNeeded(txn, &allPrivileges);
-
mutablebson::Element inheritedRolesElement = userDoc->makeElementArray("inheritedRoles");
mutablebson::Element privilegesElement = userDoc->makeElementArray("inheritedPrivileges");
mutablebson::Element warningsElement = userDoc->makeElementArray("warnings");
@@ -214,20 +210,6 @@ void AuthzManagerExternalStateLocal::_resolveUserRoles(OperationContext* txn,
}
}
-void AuthzManagerExternalStateLocal::_redactPrivilegesForBackwardsCompatibilityIfNeeded(
- OperationContext* txn, PrivilegeVector* privileges) {
- auto protocol = rpc::getOperationProtocol(txn);
- if (protocol == rpc::Protocol::kOpCommandV1) {
- return;
- }
-
- for (auto& privilege : *privileges) {
- ActionSet toRedact;
- toRedact.addAction(ActionType::bypassDocumentValidation);
- privilege.removeActions(toRedact);
- }
-}
-
Status AuthzManagerExternalStateLocal::_getUserDocument(OperationContext* txn,
const UserName& userName,
BSONObj* userDoc) {
diff --git a/src/mongo/db/auth/authz_manager_external_state_local.h b/src/mongo/db/auth/authz_manager_external_state_local.h
index 2a43cacd630..954374cf961 100644
--- a/src/mongo/db/auth/authz_manager_external_state_local.h
+++ b/src/mongo/db/auth/authz_manager_external_state_local.h
@@ -131,23 +131,10 @@ private:
* resolve roles and add the 'inheritedRoles', 'inheritedPrivileges',
* and 'warnings' fields.
*/
- void _resolveUserRoles(OperationContext* txn,
- mutablebson::Document* userDoc,
+ void _resolveUserRoles(mutablebson::Document* userDoc,
const std::vector<RoleName>& directRoles);
/**
- * Gets the Protocol from 'txn' of the operation being run to determine if it was from
- * OP_COMMAND or OP_QUERY. If OP_COMMAND, does nothing. If OP_QUERY, assumes that means it is
- * a 3.0 mongos talking to us, and modifies the input PrivilegeVector to remove all references
- * to any ActionTypes that didn't exist 3.0. This is because when a 3.0 mongos parses the
- * privileges from a user document at authentication time, it skips any privileges containing
- * any actions it doesn't know about. See SERVER-2146 for more details.
- * TODO(SERVER-21561): Remove this after 3.2
- */
- void _redactPrivilegesForBackwardsCompatibilityIfNeeded(OperationContext* txn,
- PrivilegeVector* privileges);
-
- /**
* Eventually consistent, in-memory representation of all roles in the system (both
* user-defined and built-in). Synchronized via _roleGraphMutex.
*/
diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp
index 30387107ff4..9a48de6d74e 100644
--- a/src/mongo/db/commands/user_management_commands.cpp
+++ b/src/mongo/db/commands/user_management_commands.cpp
@@ -62,6 +62,7 @@
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
#include "mongo/platform/unordered_set.h"
+#include "mongo/rpc/protocol.h"
#include "mongo/stdx/functional.h"
#include "mongo/stdx/mutex.h"
#include "mongo/util/log.h"
@@ -1209,6 +1210,9 @@ public:
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
+
+ userDetails = _redactPrivilegesForBackwardsCompabilityIfNeeded(txn, userDetails);
+
if (!args.showCredentials) {
// getUserDescription always includes credentials, need to strip it out
BSONObjBuilder userWithoutCredentials(usersArrayBuilder.subobjStart());
@@ -1254,6 +1258,48 @@ public:
return true;
}
+private:
+ /**
+ * Gets the Protocol from 'txn' of the operation being run to determine if it was from
+ * OP_COMMAND or OP_QUERY. If OP_COMMAND, returns the input user document unmodified.
+ * If OP_QUERY, assumes that means it is a 3.0 mongos talking to us, and returns a modified
+ * version of the input user doc, with all privileges containing the 'bypassDocumentValidation'
+ * modified to remove that action. This is because when a 3.0 mongos parses the privileges from
+ * a user document at authentication time, it skips any privileges containing any actions it
+ * doesn't know about, and 'bypassDocumentValidation' was added for 3.2 so a 3.0 mongos will not
+ * recognize it.
+ * NOTE: This means that if a user connects directly to mongod with a driver that doesn't use
+ * OP_COMMAND and runs usersInfo with 'showPrivileges':true, they won't see any privileges
+ * containing 'bypassDocumentValidation', even if the user in question actually does possess
+ * that action.
+ * See SERVER-21486 and SERVER-21659 for more details.
+ * TODO(SERVER-21561): Remove this after 3.2
+ */
+ BSONObj _redactPrivilegesForBackwardsCompabilityIfNeeded(OperationContext* txn,
+ BSONObj userDoc) {
+ if (rpc::getOperationProtocol(txn) != rpc::Protocol::kOpQuery) {
+ return userDoc;
+ }
+
+ namespace mmb = mutablebson;
+ bool changed = false;
+ mmb::Document redacted(userDoc, mmb::Document::kInPlaceDisabled);
+ mmb::Element privilegesArray =
+ mmb::findFirstChildNamed(redacted.root(), "inheritedPrivileges");
+ for (auto privilegeElement = privilegesArray.leftChild(); privilegeElement.ok();
+ privilegeElement = privilegeElement.rightSibling()) {
+ auto actionsArray = mmb::findFirstChildNamed(privilegeElement, "actions");
+ for (auto actionElement = actionsArray.leftChild(); actionElement.ok();) {
+ auto nextActionElement = actionElement.rightSibling();
+ if (actionElement.getValueString() == "bypassDocumentValidation") {
+ invariantOK(actionElement.remove());
+ changed = true;
+ }
+ actionElement = nextActionElement;
+ }
+ }
+ return changed ? redacted.getObject().getOwned() : userDoc;
+ }
} cmdUsersInfo;
class CmdCreateRole : public Command {