summaryrefslogtreecommitdiff
path: root/src/mongo/db/auth/user_document_parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/auth/user_document_parser.cpp')
-rw-r--r--src/mongo/db/auth/user_document_parser.cpp787
1 files changed, 379 insertions, 408 deletions
diff --git a/src/mongo/db/auth/user_document_parser.cpp b/src/mongo/db/auth/user_document_parser.cpp
index d4a095c661d..058829622f5 100644
--- a/src/mongo/db/auth/user_document_parser.cpp
+++ b/src/mongo/db/auth/user_document_parser.cpp
@@ -44,142 +44,135 @@
namespace mongo {
namespace {
- const std::string ADMIN_DBNAME = "admin";
-
- const std::string ROLES_FIELD_NAME = "roles";
- const std::string PRIVILEGES_FIELD_NAME = "inheritedPrivileges";
- const std::string INHERITED_ROLES_FIELD_NAME = "inheritedRoles";
- const std::string OTHER_DB_ROLES_FIELD_NAME = "otherDBRoles";
- const std::string READONLY_FIELD_NAME = "readOnly";
- const std::string CREDENTIALS_FIELD_NAME = "credentials";
- const std::string ROLE_NAME_FIELD_NAME = "role";
- const std::string ROLE_DB_FIELD_NAME = "db";
- const std::string MONGODB_CR_CREDENTIAL_FIELD_NAME = "MONGODB-CR";
- const std::string SCRAM_CREDENTIAL_FIELD_NAME = "SCRAM-SHA-1";
- const std::string MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME = "external";
-
- inline Status _badValue(const char* reason, int location) {
- return Status(ErrorCodes::BadValue, reason, location);
+const std::string ADMIN_DBNAME = "admin";
+
+const std::string ROLES_FIELD_NAME = "roles";
+const std::string PRIVILEGES_FIELD_NAME = "inheritedPrivileges";
+const std::string INHERITED_ROLES_FIELD_NAME = "inheritedRoles";
+const std::string OTHER_DB_ROLES_FIELD_NAME = "otherDBRoles";
+const std::string READONLY_FIELD_NAME = "readOnly";
+const std::string CREDENTIALS_FIELD_NAME = "credentials";
+const std::string ROLE_NAME_FIELD_NAME = "role";
+const std::string ROLE_DB_FIELD_NAME = "db";
+const std::string MONGODB_CR_CREDENTIAL_FIELD_NAME = "MONGODB-CR";
+const std::string SCRAM_CREDENTIAL_FIELD_NAME = "SCRAM-SHA-1";
+const std::string MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME = "external";
+
+inline Status _badValue(const char* reason, int location) {
+ return Status(ErrorCodes::BadValue, reason, location);
+}
+
+inline Status _badValue(const std::string& reason, int location) {
+ return Status(ErrorCodes::BadValue, reason, location);
+}
+
+Status _checkV1RolesArray(const BSONElement& rolesElement) {
+ if (rolesElement.type() != Array) {
+ return _badValue("Role fields must be an array when present in system.users entries", 0);
}
-
- inline Status _badValue(const std::string& reason, int location) {
- return Status(ErrorCodes::BadValue, reason, location);
- }
-
- Status _checkV1RolesArray(const BSONElement& rolesElement) {
- if (rolesElement.type() != Array) {
- return _badValue("Role fields must be an array when present in system.users entries",
- 0);
- }
- for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
- BSONElement element = *iter;
- if (element.type() != String || element.valueStringData().empty()) {
- return _badValue("Roles must be non-empty strings.", 0);
- }
+ for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
+ BSONElement element = *iter;
+ if (element.type() != String || element.valueStringData().empty()) {
+ return _badValue("Roles must be non-empty strings.", 0);
}
- return Status::OK();
}
+ return Status::OK();
+}
} // namespace
- std::string V1UserDocumentParser::extractUserNameFromUserDocument(
- const BSONObj& doc) const {
- return doc[AuthorizationManager::V1_USER_NAME_FIELD_NAME].str();
- }
-
- Status V1UserDocumentParser::initializeUserCredentialsFromUserDocument(
- User* user, const BSONObj& privDoc) const {
- User::CredentialData credentials;
- if (privDoc.hasField(AuthorizationManager::PASSWORD_FIELD_NAME)) {
- credentials.password = privDoc[AuthorizationManager::PASSWORD_FIELD_NAME].String();
- credentials.isExternal = false;
- }
- else if (privDoc.hasField(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME)) {
- std::string userSource = privDoc[AuthorizationManager::V1_USER_SOURCE_FIELD_NAME].String();
- if (userSource != "$external") {
- return Status(ErrorCodes::UnsupportedFormat,
- "Cannot extract credentials from user documents without a password "
- "and with userSource != \"$external\"");
- } else {
- credentials.isExternal = true;
- }
- }
- else {
+std::string V1UserDocumentParser::extractUserNameFromUserDocument(const BSONObj& doc) const {
+ return doc[AuthorizationManager::V1_USER_NAME_FIELD_NAME].str();
+}
+
+Status V1UserDocumentParser::initializeUserCredentialsFromUserDocument(
+ User* user, const BSONObj& privDoc) const {
+ User::CredentialData credentials;
+ if (privDoc.hasField(AuthorizationManager::PASSWORD_FIELD_NAME)) {
+ credentials.password = privDoc[AuthorizationManager::PASSWORD_FIELD_NAME].String();
+ credentials.isExternal = false;
+ } else if (privDoc.hasField(AuthorizationManager::V1_USER_SOURCE_FIELD_NAME)) {
+ std::string userSource = privDoc[AuthorizationManager::V1_USER_SOURCE_FIELD_NAME].String();
+ if (userSource != "$external") {
return Status(ErrorCodes::UnsupportedFormat,
- "Invalid user document: must have one of \"pwd\" and \"userSource\"");
+ "Cannot extract credentials from user documents without a password "
+ "and with userSource != \"$external\"");
+ } else {
+ credentials.isExternal = true;
}
-
- user->setCredentials(credentials);
- return Status::OK();
+ } else {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "Invalid user document: must have one of \"pwd\" and \"userSource\"");
}
- static void _initializeUserRolesFromV0UserDocument(
- User* user, const BSONObj& privDoc, StringData dbname) {
- bool readOnly = privDoc["readOnly"].trueValue();
- if (dbname == "admin") {
- if (readOnly) {
- user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_ADMIN_READ, "admin"));
- } else {
- user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_ADMIN_READ_WRITE, "admin"));
- }
+ user->setCredentials(credentials);
+ return Status::OK();
+}
+
+static void _initializeUserRolesFromV0UserDocument(User* user,
+ const BSONObj& privDoc,
+ StringData dbname) {
+ bool readOnly = privDoc["readOnly"].trueValue();
+ if (dbname == "admin") {
+ if (readOnly) {
+ user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_ADMIN_READ, "admin"));
} else {
- if (readOnly) {
- user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_READ, dbname));
- } else {
- user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_READ_WRITE, dbname));
- }
+ user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_ADMIN_READ_WRITE, "admin"));
+ }
+ } else {
+ if (readOnly) {
+ user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_READ, dbname));
+ } else {
+ user->addRole(RoleName(RoleGraph::BUILTIN_ROLE_V0_READ_WRITE, dbname));
}
}
+}
- Status _initializeUserRolesFromV1RolesArray(User* user,
- const BSONElement& rolesElement,
- StringData dbname) {
- static const char privilegesTypeMismatchMessage[] =
- "Roles in V1 user documents must be enumerated in an array of strings.";
+Status _initializeUserRolesFromV1RolesArray(User* user,
+ const BSONElement& rolesElement,
+ StringData dbname) {
+ static const char privilegesTypeMismatchMessage[] =
+ "Roles in V1 user documents must be enumerated in an array of strings.";
- if (rolesElement.type() != Array)
- return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);
+ if (rolesElement.type() != Array)
+ return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);
- for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
- BSONElement roleElement = *iter;
- if (roleElement.type() != String)
- return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);
+ for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
+ BSONElement roleElement = *iter;
+ if (roleElement.type() != String)
+ return Status(ErrorCodes::TypeMismatch, privilegesTypeMismatchMessage);
- user->addRole(RoleName(roleElement.String(), dbname));
- }
- return Status::OK();
+ user->addRole(RoleName(roleElement.String(), dbname));
+ }
+ return Status::OK();
+}
+
+static Status _initializeUserRolesFromV1UserDocument(User* user,
+ const BSONObj& privDoc,
+ StringData dbname) {
+ if (!privDoc[READONLY_FIELD_NAME].eoo()) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "User documents may not contain both \"readonly\" and "
+ "\"roles\" fields");
}
- static Status _initializeUserRolesFromV1UserDocument(
- User* user, const BSONObj& privDoc, StringData dbname) {
-
- if (!privDoc[READONLY_FIELD_NAME].eoo()) {
- return Status(ErrorCodes::UnsupportedFormat,
- "User documents may not contain both \"readonly\" and "
- "\"roles\" fields");
- }
-
- Status status = _initializeUserRolesFromV1RolesArray(user,
- privDoc[ROLES_FIELD_NAME],
- dbname);
- if (!status.isOK()) {
- return status;
- }
+ Status status = _initializeUserRolesFromV1RolesArray(user, privDoc[ROLES_FIELD_NAME], dbname);
+ if (!status.isOK()) {
+ return status;
+ }
- // If "dbname" is the admin database, handle the otherDBPrivileges field, which
- // grants privileges on databases other than "dbname".
- BSONElement otherDbPrivileges = privDoc[OTHER_DB_ROLES_FIELD_NAME];
- if (dbname == ADMIN_DBNAME) {
- switch (otherDbPrivileges.type()) {
+ // If "dbname" is the admin database, handle the otherDBPrivileges field, which
+ // grants privileges on databases other than "dbname".
+ BSONElement otherDbPrivileges = privDoc[OTHER_DB_ROLES_FIELD_NAME];
+ if (dbname == ADMIN_DBNAME) {
+ switch (otherDbPrivileges.type()) {
case EOO:
break;
case Object: {
- for (BSONObjIterator iter(otherDbPrivileges.embeddedObject());
- iter.more(); iter.next()) {
-
+ for (BSONObjIterator iter(otherDbPrivileges.embeddedObject()); iter.more();
+ iter.next()) {
BSONElement rolesElement = *iter;
- status = _initializeUserRolesFromV1RolesArray(user,
- rolesElement,
- rolesElement.fieldName());
+ status = _initializeUserRolesFromV1RolesArray(
+ user, rolesElement, rolesElement.fieldName());
if (!status.isOK())
return status;
}
@@ -188,359 +181,337 @@ namespace {
default:
return Status(ErrorCodes::TypeMismatch,
"Field \"otherDBRoles\" must be an object, if present.");
- }
- }
- else if (!otherDbPrivileges.eoo()) {
- return Status(ErrorCodes::UnsupportedFormat,
- "Only the admin database may contain a field called \"otherDBRoles\"");
}
+ } else if (!otherDbPrivileges.eoo()) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "Only the admin database may contain a field called \"otherDBRoles\"");
+ }
- return Status::OK();
+ return Status::OK();
+}
+
+Status V1UserDocumentParser::initializeUserRolesFromUserDocument(User* user,
+ const BSONObj& privDoc,
+ StringData dbname) const {
+ if (!privDoc.hasField("roles")) {
+ _initializeUserRolesFromV0UserDocument(user, privDoc, dbname);
+ } else {
+ return _initializeUserRolesFromV1UserDocument(user, privDoc, dbname);
}
+ return Status::OK();
+}
- Status V1UserDocumentParser::initializeUserRolesFromUserDocument(
- User* user, const BSONObj& privDoc, StringData dbname) const {
- if (!privDoc.hasField("roles")) {
- _initializeUserRolesFromV0UserDocument(user, privDoc, dbname);
- } else {
- return _initializeUserRolesFromV1UserDocument(user, privDoc, dbname);
+
+Status _checkV2RolesArray(const BSONElement& rolesElement) {
+ if (rolesElement.eoo()) {
+ return _badValue("User document needs 'roles' field to be provided", 0);
+ }
+ if (rolesElement.type() != Array) {
+ return _badValue("'roles' field must be an array", 0);
+ }
+ for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
+ if ((*iter).type() != Object) {
+ return _badValue("Elements in 'roles' array must objects", 0);
}
- return Status::OK();
+ Status status = V2UserDocumentParser::checkValidRoleObject((*iter).Obj());
+ if (!status.isOK())
+ return status;
+ }
+ return Status::OK();
+}
+
+Status V2UserDocumentParser::checkValidUserDocument(const BSONObj& doc) const {
+ BSONElement userElement = doc[AuthorizationManager::USER_NAME_FIELD_NAME];
+ BSONElement userDBElement = doc[AuthorizationManager::USER_DB_FIELD_NAME];
+ BSONElement credentialsElement = doc[CREDENTIALS_FIELD_NAME];
+ BSONElement rolesElement = doc[ROLES_FIELD_NAME];
+
+ // Validate the "user" element.
+ if (userElement.type() != String)
+ return _badValue("User document needs 'user' field to be a string", 0);
+ if (userElement.valueStringData().empty())
+ return _badValue("User document needs 'user' field to be non-empty", 0);
+
+ // Validate the "db" element
+ if (userDBElement.type() != String || userDBElement.valueStringData().empty()) {
+ return _badValue("User document needs 'db' field to be a non-empty string", 0);
+ }
+ StringData userDBStr = userDBElement.valueStringData();
+ if (!NamespaceString::validDBName(userDBStr) && userDBStr != "$external") {
+ return _badValue(mongoutils::str::stream() << "'" << userDBStr
+ << "' is not a valid value for the db field.",
+ 0);
}
+ // Validate the "credentials" element
+ if (credentialsElement.eoo()) {
+ return _badValue("User document needs 'credentials' object", 0);
+ }
+ if (credentialsElement.type() != Object) {
+ return _badValue("User document needs 'credentials' field to be an object", 0);
+ }
- Status _checkV2RolesArray(const BSONElement& rolesElement) {
- if (rolesElement.eoo()) {
- return _badValue("User document needs 'roles' field to be provided", 0);
- }
- if (rolesElement.type() != Array) {
- return _badValue("'roles' field must be an array", 0);
+ BSONObj credentialsObj = credentialsElement.Obj();
+ if (credentialsObj.isEmpty()) {
+ return _badValue("User document needs 'credentials' field to be a non-empty object", 0);
+ }
+ if (userDBStr == "$external") {
+ BSONElement externalElement = credentialsObj[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME];
+ if (externalElement.eoo() || externalElement.type() != Bool || !externalElement.Bool()) {
+ return _badValue(
+ "User documents for users defined on '$external' must have "
+ "'credentials' field set to {external: true}",
+ 0);
}
- for (BSONObjIterator iter(rolesElement.embeddedObject()); iter.more(); iter.next()) {
- if ((*iter).type() != Object) {
- return _badValue("Elements in 'roles' array must objects", 0);
+ } else {
+ BSONElement scramElement = credentialsObj[SCRAM_CREDENTIAL_FIELD_NAME];
+ BSONElement mongoCRElement = credentialsObj[MONGODB_CR_CREDENTIAL_FIELD_NAME];
+
+ if (!mongoCRElement.eoo()) {
+ if (mongoCRElement.type() != String || mongoCRElement.valueStringData().empty()) {
+ return _badValue(
+ "MONGODB-CR credential must to be a non-empty string"
+ ", if present",
+ 0);
+ }
+ } else if (!scramElement.eoo()) {
+ if (scramElement.type() != Object) {
+ return _badValue("SCRAM credential must be an object, if present", 0);
}
- Status status = V2UserDocumentParser::checkValidRoleObject((*iter).Obj());
- if (!status.isOK())
- return status;
+ } else {
+ return _badValue(
+ "User document must provide credentials for all "
+ "non-external users",
+ 0);
}
- return Status::OK();
}
- Status V2UserDocumentParser::checkValidUserDocument(const BSONObj& doc) const {
- BSONElement userElement = doc[AuthorizationManager::USER_NAME_FIELD_NAME];
- BSONElement userDBElement = doc[AuthorizationManager::USER_DB_FIELD_NAME];
- BSONElement credentialsElement = doc[CREDENTIALS_FIELD_NAME];
- BSONElement rolesElement = doc[ROLES_FIELD_NAME];
-
- // Validate the "user" element.
- if (userElement.type() != String)
- return _badValue("User document needs 'user' field to be a string", 0);
- if (userElement.valueStringData().empty())
- return _badValue("User document needs 'user' field to be non-empty", 0);
-
- // Validate the "db" element
- if (userDBElement.type() != String || userDBElement.valueStringData().empty()) {
- return _badValue("User document needs 'db' field to be a non-empty string", 0);
- }
- StringData userDBStr = userDBElement.valueStringData();
- if (!NamespaceString::validDBName(userDBStr) && userDBStr != "$external") {
- return _badValue(mongoutils::str::stream() << "'" << userDBStr <<
- "' is not a valid value for the db field.",
- 0);
- }
+ // Validate the "roles" element.
+ Status status = _checkV2RolesArray(rolesElement);
+ if (!status.isOK())
+ return status;
- // Validate the "credentials" element
- if (credentialsElement.eoo()) {
- return _badValue("User document needs 'credentials' object",
- 0);
- }
- if (credentialsElement.type() != Object) {
- return _badValue("User document needs 'credentials' field to be an object", 0);
- }
+ return Status::OK();
+}
+
+std::string V2UserDocumentParser::extractUserNameFromUserDocument(const BSONObj& doc) const {
+ return doc[AuthorizationManager::USER_NAME_FIELD_NAME].str();
+}
- BSONObj credentialsObj = credentialsElement.Obj();
- if (credentialsObj.isEmpty()) {
- return _badValue("User document needs 'credentials' field to be a non-empty object",
- 0);
+Status V2UserDocumentParser::initializeUserCredentialsFromUserDocument(
+ User* user, const BSONObj& privDoc) const {
+ User::CredentialData credentials;
+ std::string userDB = privDoc[AuthorizationManager::USER_DB_FIELD_NAME].String();
+ BSONElement credentialsElement = privDoc[CREDENTIALS_FIELD_NAME];
+ if (!credentialsElement.eoo()) {
+ if (credentialsElement.type() != Object) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "'credentials' field in user documents must be an object");
}
- if (userDBStr == "$external") {
- BSONElement externalElement = credentialsObj[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME];
- if (externalElement.eoo() || externalElement.type() != Bool ||
- !externalElement.Bool()) {
- return _badValue("User documents for users defined on '$external' must have "
- "'credentials' field set to {external: true}", 0);
- }
- }
- else {
- BSONElement scramElement = credentialsObj[SCRAM_CREDENTIAL_FIELD_NAME];
- BSONElement mongoCRElement = credentialsObj[MONGODB_CR_CREDENTIAL_FIELD_NAME];
-
- if (!mongoCRElement.eoo()) {
- if (mongoCRElement.type() != String || mongoCRElement.valueStringData().empty()) {
- return _badValue("MONGODB-CR credential must to be a non-empty string"
- ", if present", 0);
- }
- }
- else if (!scramElement.eoo()) {
- if (scramElement.type() != Object) {
- return _badValue("SCRAM credential must be an object, if present", 0);
+ if (userDB == "$external") {
+ BSONElement externalCredentialElement =
+ credentialsElement.Obj()[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME];
+ if (!externalCredentialElement.eoo()) {
+ if (externalCredentialElement.type() != Bool || !externalCredentialElement.Bool()) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "'external' field in credentials object must be set to true");
+ } else {
+ credentials.isExternal = true;
}
+ } else {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "User documents defined on '$external' must provide set "
+ "credentials to {external:true}");
}
- else {
- return _badValue("User document must provide credentials for all "
- "non-external users", 0);
+ } else {
+ BSONElement scramElement = credentialsElement.Obj()[SCRAM_CREDENTIAL_FIELD_NAME];
+ BSONElement mongoCRCredentialElement =
+ credentialsElement.Obj()[MONGODB_CR_CREDENTIAL_FIELD_NAME];
+
+ if (scramElement.eoo() && mongoCRCredentialElement.eoo()) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "User documents must provide credentials for SCRAM-SHA-1 "
+ "or MONGODB-CR authentication");
}
- }
- // Validate the "roles" element.
- Status status = _checkV2RolesArray(rolesElement);
- if (!status.isOK())
- return status;
+ if (!scramElement.eoo()) {
+ // We are asserting rather then returning errors since these
+ // fields should have been prepopulated by the calling code.
+ credentials.scram.iterationCount = scramElement.Obj()["iterationCount"].numberInt();
+ uassert(17501,
+ "Invalid or missing SCRAM iteration count",
+ credentials.scram.iterationCount > 0);
- return Status::OK();
- }
+ credentials.scram.salt = scramElement.Obj()["salt"].str();
+ uassert(17502, "Missing SCRAM salt", !credentials.scram.salt.empty());
- std::string V2UserDocumentParser::extractUserNameFromUserDocument(
- const BSONObj& doc) const {
- return doc[AuthorizationManager::USER_NAME_FIELD_NAME].str();
- }
+ credentials.scram.serverKey = scramElement["serverKey"].str();
+ uassert(17503, "Missing SCRAM serverKey", !credentials.scram.serverKey.empty());
- Status V2UserDocumentParser::initializeUserCredentialsFromUserDocument(
- User* user, const BSONObj& privDoc) const {
- User::CredentialData credentials;
- std::string userDB = privDoc[AuthorizationManager::USER_DB_FIELD_NAME].String();
- BSONElement credentialsElement = privDoc[CREDENTIALS_FIELD_NAME];
- if (!credentialsElement.eoo()) {
- if (credentialsElement.type() != Object) {
- return Status(ErrorCodes::UnsupportedFormat,
- "'credentials' field in user documents must be an object");
+ credentials.scram.storedKey = scramElement["storedKey"].str();
+ uassert(17504, "Missing SCRAM storedKey", !credentials.scram.storedKey.empty());
}
- if (userDB == "$external") {
- BSONElement externalCredentialElement =
- credentialsElement.Obj()[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME];
- if (!externalCredentialElement.eoo()) {
- if (externalCredentialElement.type() != Bool ||
- !externalCredentialElement.Bool()) {
- return Status(ErrorCodes::UnsupportedFormat,
- "'external' field in credentials object must be set to true");
- } else {
- credentials.isExternal = true;
- }
- } else {
- return Status(ErrorCodes::UnsupportedFormat,
- "User documents defined on '$external' must provide set "
- "credentials to {external:true}");
- }
- } else {
-
- BSONElement scramElement =
- credentialsElement.Obj()[SCRAM_CREDENTIAL_FIELD_NAME];
- BSONElement mongoCRCredentialElement =
- credentialsElement.Obj()[MONGODB_CR_CREDENTIAL_FIELD_NAME];
-
- if (scramElement.eoo() && mongoCRCredentialElement.eoo()) {
- return Status(ErrorCodes::UnsupportedFormat,
- "User documents must provide credentials for SCRAM-SHA-1 "
- "or MONGODB-CR authentication");
- }
- if (!scramElement.eoo()) {
- // We are asserting rather then returning errors since these
- // fields should have been prepopulated by the calling code.
- credentials.scram.iterationCount =
- scramElement.Obj()["iterationCount"].numberInt();
- uassert(17501, "Invalid or missing SCRAM iteration count",
- credentials.scram.iterationCount > 0);
-
- credentials.scram.salt =
- scramElement.Obj()["salt"].str();
- uassert(17502, "Missing SCRAM salt",
- !credentials.scram.salt.empty());
-
- credentials.scram.serverKey =
- scramElement["serverKey"].str();
- uassert(17503, "Missing SCRAM serverKey",
- !credentials.scram.serverKey.empty());
-
- credentials.scram.storedKey =
- scramElement["storedKey"].str();
- uassert(17504, "Missing SCRAM storedKey",
- !credentials.scram.storedKey.empty());
- }
-
- if (!mongoCRCredentialElement.eoo()) {
- if (mongoCRCredentialElement.type() != String ||
- mongoCRCredentialElement.valueStringData().empty()) {
+ if (!mongoCRCredentialElement.eoo()) {
+ if (mongoCRCredentialElement.type() != String ||
+ mongoCRCredentialElement.valueStringData().empty()) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "MONGODB-CR credentials must be non-empty strings");
+ } else {
+ credentials.password = mongoCRCredentialElement.String();
+ if (credentials.password.empty()) {
return Status(ErrorCodes::UnsupportedFormat,
- "MONGODB-CR credentials must be non-empty strings");
- } else {
- credentials.password = mongoCRCredentialElement.String();
- if (credentials.password.empty()) {
- return Status(ErrorCodes::UnsupportedFormat,
- "User documents must provide authentication credentials");
- }
+ "User documents must provide authentication credentials");
}
}
- credentials.isExternal = false;
}
- } else {
- return Status(ErrorCodes::UnsupportedFormat,
- "Cannot extract credentials from user documents without a "
- "'credentials' field");
+ credentials.isExternal = false;
}
-
- user->setCredentials(credentials);
- return Status::OK();
+ } else {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "Cannot extract credentials from user documents without a "
+ "'credentials' field");
}
- static Status _extractRoleDocumentElements(
- const BSONObj& roleObject,
- BSONElement* roleNameElement,
- BSONElement* roleSourceElement) {
+ user->setCredentials(credentials);
+ return Status::OK();
+}
- *roleNameElement = roleObject[ROLE_NAME_FIELD_NAME];
- *roleSourceElement = roleObject[ROLE_DB_FIELD_NAME];
-
- if (roleNameElement->type() != String || roleNameElement->valueStringData().empty()) {
- return Status(ErrorCodes::UnsupportedFormat,
- "Role names must be non-empty strings");
- }
- if (roleSourceElement->type() != String || roleSourceElement->valueStringData().empty()) {
- return Status(ErrorCodes::UnsupportedFormat, "Role db must be non-empty strings");
- }
+static Status _extractRoleDocumentElements(const BSONObj& roleObject,
+ BSONElement* roleNameElement,
+ BSONElement* roleSourceElement) {
+ *roleNameElement = roleObject[ROLE_NAME_FIELD_NAME];
+ *roleSourceElement = roleObject[ROLE_DB_FIELD_NAME];
- return Status::OK();
+ if (roleNameElement->type() != String || roleNameElement->valueStringData().empty()) {
+ return Status(ErrorCodes::UnsupportedFormat, "Role names must be non-empty strings");
}
-
- Status V2UserDocumentParser::checkValidRoleObject(const BSONObj& roleObject) {
- BSONElement roleNameElement;
- BSONElement roleSourceElement;
- return _extractRoleDocumentElements(
- roleObject,
- &roleNameElement,
- &roleSourceElement);
+ if (roleSourceElement->type() != String || roleSourceElement->valueStringData().empty()) {
+ return Status(ErrorCodes::UnsupportedFormat, "Role db must be non-empty strings");
}
- Status V2UserDocumentParser::parseRoleName(const BSONObj& roleObject, RoleName* result) {
- BSONElement roleNameElement;
- BSONElement roleSourceElement;
- Status status = _extractRoleDocumentElements(
- roleObject,
- &roleNameElement,
- &roleSourceElement);
- if (!status.isOK())
- return status;
- *result = RoleName(roleNameElement.str(), roleSourceElement.str());
- return status;
- }
+ return Status::OK();
+}
- Status V2UserDocumentParser::parseRoleVector(const BSONArray& rolesArray,
- std::vector<RoleName>* result) {
- std::vector<RoleName> roles;
- for (BSONObjIterator it(rolesArray); it.more(); it.next()) {
- if ((*it).type() != Object) {
- return Status(ErrorCodes::TypeMismatch, "Roles must be objects.");
- }
- RoleName role;
- Status status = parseRoleName((*it).Obj(), &role);
- if (!status.isOK())
- return status;
- roles.push_back(role);
+Status V2UserDocumentParser::checkValidRoleObject(const BSONObj& roleObject) {
+ BSONElement roleNameElement;
+ BSONElement roleSourceElement;
+ return _extractRoleDocumentElements(roleObject, &roleNameElement, &roleSourceElement);
+}
+
+Status V2UserDocumentParser::parseRoleName(const BSONObj& roleObject, RoleName* result) {
+ BSONElement roleNameElement;
+ BSONElement roleSourceElement;
+ Status status = _extractRoleDocumentElements(roleObject, &roleNameElement, &roleSourceElement);
+ if (!status.isOK())
+ return status;
+ *result = RoleName(roleNameElement.str(), roleSourceElement.str());
+ return status;
+}
+
+Status V2UserDocumentParser::parseRoleVector(const BSONArray& rolesArray,
+ std::vector<RoleName>* result) {
+ std::vector<RoleName> roles;
+ for (BSONObjIterator it(rolesArray); it.more(); it.next()) {
+ if ((*it).type() != Object) {
+ return Status(ErrorCodes::TypeMismatch, "Roles must be objects.");
}
- std::swap(*result, roles);
- return Status::OK();
+ RoleName role;
+ Status status = parseRoleName((*it).Obj(), &role);
+ if (!status.isOK())
+ return status;
+ roles.push_back(role);
}
+ std::swap(*result, roles);
+ return Status::OK();
+}
- Status V2UserDocumentParser::initializeUserRolesFromUserDocument(
- const BSONObj& privDoc, User* user) const {
+Status V2UserDocumentParser::initializeUserRolesFromUserDocument(const BSONObj& privDoc,
+ User* user) const {
+ BSONElement rolesElement = privDoc[ROLES_FIELD_NAME];
- BSONElement rolesElement = privDoc[ROLES_FIELD_NAME];
+ if (rolesElement.type() != Array) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "User document needs 'roles' field to be an array");
+ }
- if (rolesElement.type() != Array) {
+ std::vector<RoleName> roles;
+ for (BSONObjIterator it(rolesElement.Obj()); it.more(); it.next()) {
+ if ((*it).type() != Object) {
return Status(ErrorCodes::UnsupportedFormat,
- "User document needs 'roles' field to be an array");
+ "User document needs values in 'roles' array to be a sub-documents");
}
+ BSONObj roleObject = (*it).Obj();
- std::vector<RoleName> roles;
- for (BSONObjIterator it(rolesElement.Obj()); it.more(); it.next()) {
- if ((*it).type() != Object) {
- return Status(ErrorCodes::UnsupportedFormat,
- "User document needs values in 'roles' array to be a sub-documents");
- }
- BSONObj roleObject = (*it).Obj();
-
- RoleName role;
- Status status = parseRoleName(roleObject, &role);
- if (!status.isOK()) {
- return status;
- }
- roles.push_back(role);
+ RoleName role;
+ Status status = parseRoleName(roleObject, &role);
+ if (!status.isOK()) {
+ return status;
}
- user->setRoles(makeRoleNameIteratorForContainer(roles));
- return Status::OK();
+ roles.push_back(role);
}
+ user->setRoles(makeRoleNameIteratorForContainer(roles));
+ return Status::OK();
+}
- Status V2UserDocumentParser::initializeUserIndirectRolesFromUserDocument(
- const BSONObj& privDoc, User* user) const {
+Status V2UserDocumentParser::initializeUserIndirectRolesFromUserDocument(const BSONObj& privDoc,
+ User* user) const {
+ BSONElement indirectRolesElement = privDoc[INHERITED_ROLES_FIELD_NAME];
- BSONElement indirectRolesElement = privDoc[INHERITED_ROLES_FIELD_NAME];
+ if (indirectRolesElement.type() != Array) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "User document needs 'inheritedRoles' field to be an array");
+ }
- if (indirectRolesElement.type() != Array) {
+ std::vector<RoleName> indirectRoles;
+ for (BSONObjIterator it(indirectRolesElement.Obj()); it.more(); it.next()) {
+ if ((*it).type() != Object) {
return Status(ErrorCodes::UnsupportedFormat,
- "User document needs 'inheritedRoles' field to be an array");
+ "User document needs values in 'inheritedRoles'"
+ " array to be a sub-documents");
}
+ BSONObj indirectRoleObject = (*it).Obj();
- std::vector<RoleName> indirectRoles;
- for (BSONObjIterator it(indirectRolesElement.Obj()); it.more(); it.next()) {
- if ((*it).type() != Object) {
- return Status(ErrorCodes::UnsupportedFormat,
- "User document needs values in 'inheritedRoles'"
- " array to be a sub-documents");
- }
- BSONObj indirectRoleObject = (*it).Obj();
-
- RoleName indirectRole;
- Status status = parseRoleName(indirectRoleObject, &indirectRole);
- if (!status.isOK()) {
- return status;
- }
- indirectRoles.push_back(indirectRole);
+ RoleName indirectRole;
+ Status status = parseRoleName(indirectRoleObject, &indirectRole);
+ if (!status.isOK()) {
+ return status;
}
- user->setIndirectRoles(makeRoleNameIteratorForContainer(indirectRoles));
+ indirectRoles.push_back(indirectRole);
+ }
+ user->setIndirectRoles(makeRoleNameIteratorForContainer(indirectRoles));
+ return Status::OK();
+}
+
+Status V2UserDocumentParser::initializeUserPrivilegesFromUserDocument(const BSONObj& doc,
+ User* user) const {
+ BSONElement privilegesElement = doc[PRIVILEGES_FIELD_NAME];
+ if (privilegesElement.eoo())
return Status::OK();
+ if (privilegesElement.type() != Array) {
+ return Status(ErrorCodes::UnsupportedFormat,
+ "User document 'inheritedPrivileges' element must be Array if present.");
}
-
- Status V2UserDocumentParser::initializeUserPrivilegesFromUserDocument(const BSONObj& doc,
- User* user) const {
- BSONElement privilegesElement = doc[PRIVILEGES_FIELD_NAME];
- if (privilegesElement.eoo())
- return Status::OK();
- if (privilegesElement.type() != Array) {
- return Status(ErrorCodes::UnsupportedFormat,
- "User document 'inheritedPrivileges' element must be Array if present.");
+ PrivilegeVector privileges;
+ std::string errmsg;
+ for (BSONObjIterator it(privilegesElement.Obj()); it.more(); it.next()) {
+ if ((*it).type() != Object) {
+ warning() << "Wrong type of element in inheritedPrivileges array for "
+ << user->getName() << ": " << *it;
+ continue;
}
- PrivilegeVector privileges;
- std::string errmsg;
- for (BSONObjIterator it(privilegesElement.Obj()); it.more(); it.next()) {
- if ((*it).type() != Object) {
- warning() << "Wrong type of element in inheritedPrivileges array for " <<
- user->getName() << ": " << *it;
- continue;
- }
- Privilege privilege;
- ParsedPrivilege pp;
- if (!pp.parseBSON((*it).Obj(), &errmsg) ||
- !ParsedPrivilege::parsedPrivilegeToPrivilege(pp, &privilege, &errmsg)) {
-
- warning() << "Could not parse privilege element in user document for " <<
- user->getName() << ": " << errmsg;
- continue;
- }
- privileges.push_back(privilege);
+ Privilege privilege;
+ ParsedPrivilege pp;
+ if (!pp.parseBSON((*it).Obj(), &errmsg) ||
+ !ParsedPrivilege::parsedPrivilegeToPrivilege(pp, &privilege, &errmsg)) {
+ warning() << "Could not parse privilege element in user document for "
+ << user->getName() << ": " << errmsg;
+ continue;
}
- user->setPrivileges(privileges);
- return Status::OK();
+ privileges.push_back(privilege);
}
+ user->setPrivileges(privileges);
+ return Status::OK();
+}
-} // namespace mongo
+} // namespace mongo