diff options
author | Spencer Jackson <spencer.jackson@mongodb.com> | 2017-07-31 11:21:40 -0400 |
---|---|---|
committer | Spencer Jackson <spencer.jackson@mongodb.com> | 2017-07-31 13:59:59 -0400 |
commit | 0a801f1e152136be8cd0d7c57fda71555042cca1 (patch) | |
tree | 801ca92c11597ec06e30bbad285ba4d6cd0889f8 /src | |
parent | 9096def9687739a40df79efe4e9e4d9b19215201 (diff) | |
download | mongo-0a801f1e152136be8cd0d7c57fda71555042cca1.tar.gz |
SERVER-29182: Add restriction support to the usersInfo command
Diffstat (limited to 'src')
5 files changed, 70 insertions, 29 deletions
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 c391dff44b0..ad8b34fbce5 100644 --- a/src/mongo/db/auth/authz_manager_external_state_local.cpp +++ b/src/mongo/db/auth/authz_manager_external_state_local.cpp @@ -254,12 +254,18 @@ void AuthzManagerExternalStateLocal::resolveUserRoles(mutablebson::Document* use fassert(17158, userDoc->root().pushBack(privilegesElement)); addPrivilegeObjectsOrWarningsToArrayElement(privilegesElement, warningsElement, allPrivileges); - auto authenticationRestrictionsElement = + auto inheritedAuthenticationRestrictionsElement = userDoc->makeElementArray("inheritedAuthenticationRestrictions"); - fassert(40558, userDoc->root().pushBack(authenticationRestrictionsElement)); - addAuthenticationRestrictionObjectsToArrayElement(authenticationRestrictionsElement, + fassert(40558, userDoc->root().pushBack(inheritedAuthenticationRestrictionsElement)); + addAuthenticationRestrictionObjectsToArrayElement(inheritedAuthenticationRestrictionsElement, allAuthenticationRestrictions); + if (!mutablebson::findFirstChildNamed(userDoc->root(), "authenticationRestrictions").ok()) { + auto authenticationRestrictionsElement = + userDoc->makeElementArray("authenticationRestrictions"); + fassert(40572, userDoc->root().pushBack(authenticationRestrictionsElement)); + } + if (!isRoleGraphConsistent) { fassert(17160, warningsElement.appendString( diff --git a/src/mongo/db/auth/authz_manager_external_state_s.cpp b/src/mongo/db/auth/authz_manager_external_state_s.cpp index 852e66fda7a..2fb91f5b8ea 100644 --- a/src/mongo/db/auth/authz_manager_external_state_s.cpp +++ b/src/mongo/db/auth/authz_manager_external_state_s.cpp @@ -130,6 +130,8 @@ Status AuthzManagerExternalStateMongos::getUserDescription(OperationContext* opC << "showPrivileges" << true << "showCredentials" + << true + << "showAuthenticationRestrictions" << true); BSONObjBuilder builder; const bool ok = Grid::get(opCtx)->catalogClient()->runUserManagementReadCommand( diff --git a/src/mongo/db/auth/user_management_commands_parser.cpp b/src/mongo/db/auth/user_management_commands_parser.cpp index f1ab1f40735..ec10ce928f7 100644 --- a/src/mongo/db/auth/user_management_commands_parser.cpp +++ b/src/mongo/db/auth/user_management_commands_parser.cpp @@ -323,6 +323,7 @@ Status parseAndValidateDropAllUsersFromDatabaseCommand(const BSONObj& cmdObj, Status parseUsersInfoCommand(const BSONObj& cmdObj, StringData dbname, UsersInfoArgs* parsedArgs) { unordered_set<std::string> validFieldNames; validFieldNames.insert("usersInfo"); + validFieldNames.insert("showAuthenticationRestrictions"); validFieldNames.insert("showPrivileges"); validFieldNames.insert("showCredentials"); @@ -364,6 +365,20 @@ Status parseUsersInfoCommand(const BSONObj& cmdObj, StringData dbname, UsersInfo return status; } + const auto showAuthenticationRestrictions = cmdObj["showAuthenticationRestrictions"]; + if (showAuthenticationRestrictions.eoo()) { + parsedArgs->authenticationRestrictionsFormat = AuthenticationRestrictionsFormat::kOmit; + } else { + bool show; + status = bsonExtractBooleanField(cmdObj, "showAuthenticationRestrictions", &show); + if (!status.isOK()) { + return status; + } + parsedArgs->authenticationRestrictionsFormat = show + ? AuthenticationRestrictionsFormat::kShow + : AuthenticationRestrictionsFormat::kOmit; + } + return Status::OK(); } diff --git a/src/mongo/db/auth/user_management_commands_parser.h b/src/mongo/db/auth/user_management_commands_parser.h index 2ccd6524ae9..23a19206739 100644 --- a/src/mongo/db/auth/user_management_commands_parser.h +++ b/src/mongo/db/auth/user_management_commands_parser.h @@ -101,10 +101,11 @@ Status parseAndValidateDropAllUsersFromDatabaseCommand(const BSONObj& cmdObj, struct UsersInfoArgs { std::vector<UserName> userNames; - bool allForDB; - bool showPrivileges; - bool showCredentials; - UsersInfoArgs() : allForDB(false), showPrivileges(false), showCredentials(false) {} + bool allForDB = false; + bool showPrivileges = false; + AuthenticationRestrictionsFormat authenticationRestrictionsFormat = + AuthenticationRestrictionsFormat::kOmit; + bool showCredentials = false; }; /** diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp index 533eabefc2e..4e77d630159 100644 --- a/src/mongo/db/commands/user_management_commands.cpp +++ b/src/mongo/db/commands/user_management_commands.cpp @@ -1201,17 +1201,21 @@ public: return appendCommandStatus(result, status); } - if (args.allForDB && args.showPrivileges) { + if (args.allForDB && + (args.showPrivileges || + args.authenticationRestrictionsFormat == AuthenticationRestrictionsFormat::kShow)) { return appendCommandStatus( result, Status(ErrorCodes::IllegalOperation, - "Can only get privilege details on exact-match usersInfo " + "Can only get privilege or restriction details on exact-match usersInfo " "queries.")); } BSONArrayBuilder usersArrayBuilder; - if (args.showPrivileges) { - // If you want privileges you need to call getUserDescription on each user. + if (args.showPrivileges || + args.authenticationRestrictionsFormat == AuthenticationRestrictionsFormat::kShow) { + // If you want privileges or restrictions you need to call getUserDescription on each + // user. for (size_t i = 0; i < args.userNames.size(); ++i) { BSONObj userDetails; status = getGlobalAuthorizationManager()->getUserDescription( @@ -1223,22 +1227,31 @@ public: return appendCommandStatus(result, status); } - if (!args.showCredentials) { - // getUserDescription always includes credentials, need to strip it out - BSONObjBuilder userWithoutCredentials(usersArrayBuilder.subobjStart()); - for (BSONObjIterator it(userDetails); it.more();) { - BSONElement e = it.next(); - if (e.fieldNameStringData() != "credentials" && - e.fieldNameStringData() != AuthorizationManager::USER_ID_FIELD_NAME) - userWithoutCredentials.append(e); + // getUserDescription always includes credentials and restrictions, which may need + // to be stripped out + BSONObjBuilder strippedUser(usersArrayBuilder.subobjStart()); + for (const BSONElement& e : userDetails) { + if (!args.showCredentials && e.fieldNameStringData() == "credentials") { + continue; } - userWithoutCredentials.doneFast(); - } else { - usersArrayBuilder.append(userDetails); + + if (e.fieldNameStringData() == AuthorizationManager::USER_ID_FIELD_NAME) { + continue; + } + + if (e.fieldNameStringData() == "authenticationRestrictions" && + args.authenticationRestrictionsFormat == + AuthenticationRestrictionsFormat::kOmit) { + continue; + } + + strippedUser.append(e); } + strippedUser.doneFast(); } } else { - // If you don't need privileges, you can just do a regular query on system.users + // If you don't need privileges, or authenticationRestrictions, you can just do a + // regular query on system.users BSONObjBuilder queryBuilder; if (args.allForDB) { queryBuilder.append("query", @@ -1257,18 +1270,22 @@ public: queryBuilder.append("orderby", BSON("user" << 1 << "db" << 1)); BSONObjBuilder projection; + projection.append("authenticationRestrictions", 0); if (!args.showCredentials) { projection.append(AuthorizationManager::USER_ID_FIELD_NAME, 0); projection.append("credentials", 0); } const stdx::function<void(const BSONObj&)> function = stdx::bind( appendBSONObjToBSONArrayBuilder, &usersArrayBuilder, stdx::placeholders::_1); - queryAuthzDocument(opCtx, - AuthorizationManager::usersCollectionNamespace, - queryBuilder.done(), - projection.done(), - function) - .transitional_ignore(); + + Status status = queryAuthzDocument(opCtx, + AuthorizationManager::usersCollectionNamespace, + queryBuilder.done(), + projection.done(), + function); + if (!status.isOK()) { + return appendCommandStatus(result, status); + } } result.append("users", usersArrayBuilder.arr()); return true; |