diff options
author | Sara Golemon <sara.golemon@mongodb.com> | 2017-07-21 14:48:00 -0400 |
---|---|---|
committer | Sara Golemon <sara.golemon@mongodb.com> | 2017-07-24 21:46:43 -0400 |
commit | 090d9cf938b5825cf4ae7eb0a2642be10e53b81a (patch) | |
tree | 795349f61807953f85e1f2fd1c52860fa7e6a794 /src/mongo/db | |
parent | d8094ad9be285cb5bf588faff20af785bb76ce4b (diff) | |
download | mongo-090d9cf938b5825cf4ae7eb0a2642be10e53b81a.tar.gz |
SERVER-29180 Add restriction support to the createRole
Diffstat (limited to 'src/mongo/db')
-rw-r--r-- | src/mongo/db/auth/address_restriction.cpp | 39 | ||||
-rw-r--r-- | src/mongo/db/auth/address_restriction.h | 7 | ||||
-rw-r--r-- | src/mongo/db/auth/user_management_commands_parser.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/auth/user_management_commands_parser.h | 1 | ||||
-rw-r--r-- | src/mongo/db/commands/user_management_commands.cpp | 5 |
5 files changed, 70 insertions, 0 deletions
diff --git a/src/mongo/db/auth/address_restriction.cpp b/src/mongo/db/auth/address_restriction.cpp index e8b5c64a881..607aa3056e9 100644 --- a/src/mongo/db/auth/address_restriction.cpp +++ b/src/mongo/db/auth/address_restriction.cpp @@ -98,3 +98,42 @@ mongo::StatusWith<mongo::SharedRestrictionDocument> mongo::parseAuthenticationRe return std::make_shared<document_type>(std::move(doc)); } + +mongo::StatusWith<mongo::BSONArray> mongo::getRawAuthenticationRestrictions( + const BSONArray& arr) noexcept try { + BSONArrayBuilder builder; + + if (serverGlobalParams.featureCompatibility.version.load() < + ServerGlobalParams::FeatureCompatibility::Version::k36) { + return Status(ErrorCodes::UnsupportedFormat, + "'authenticationRestrictions' requires 3.6 feature compatibility version"); + } + + for (auto const& elem : arr) { + if (elem.type() != Object) { + return Status(ErrorCodes::UnsupportedFormat, + "'authenticationRestrictions' array sub-documents must be address " + "restriction objects"); + } + IDLParserErrorContext ctx("address restriction"); + auto const ar = Address_restriction::parse(ctx, elem.Obj()); + if (auto const&& client = ar.getClientSource()) { + // Validate + ClientSourceRestriction(client.get()); + } + if (auto const&& server = ar.getServerAddress()) { + // Validate + ServerAddressRestriction(server.get()); + } + if (!ar.getClientSource() && !ar.getServerAddress()) { + return Status(ErrorCodes::CollectionIsEmpty, + "At least one of 'clientSource' and/or 'serverAddress' must be set"); + } + builder.append(ar.toBSON()); + } + return builder.arr(); +} catch (const DBException& e) { + return Status(ErrorCodes::BadValue, e.what()); +} catch (const std::exception& e) { + return Status(ErrorCodes::InternalError, e.what()); +} diff --git a/src/mongo/db/auth/address_restriction.h b/src/mongo/db/auth/address_restriction.h index 73881651024..05930e7340d 100644 --- a/src/mongo/db/auth/address_restriction.h +++ b/src/mongo/db/auth/address_restriction.h @@ -190,6 +190,13 @@ StatusWith<RestrictionSet<>> parseAddressRestrictionSet(const BSONObj& obj); */ StatusWith<SharedRestrictionDocument> parseAuthenticationRestriction(const BSONArray& arr); +/** + * Parse and validate a BSONArray containing AuthenticationRestrictions + * and return a new BSONArray representing a sanitized portion thereof. + */ +StatusWith<BSONArray> getRawAuthenticationRestrictions(const BSONArray& arr) noexcept; + + template <> inline BSONObjBuilder& BSONObjBuilderValueStream::operator<<<ClientSourceRestriction>( ClientSourceRestriction value) { diff --git a/src/mongo/db/auth/user_management_commands_parser.cpp b/src/mongo/db/auth/user_management_commands_parser.cpp index e712ad27cba..9a7742d14a4 100644 --- a/src/mongo/db/auth/user_management_commands_parser.cpp +++ b/src/mongo/db/auth/user_management_commands_parser.cpp @@ -37,6 +37,7 @@ #include "mongo/base/status.h" #include "mongo/bson/util/bson_extract.h" #include "mongo/db/auth/action_type.h" +#include "mongo/db/auth/address_restriction.h" #include "mongo/db/auth/authorization_manager.h" #include "mongo/db/auth/privilege.h" #include "mongo/db/auth/privilege_parser.h" @@ -489,6 +490,7 @@ Status parseCreateOrUpdateRoleCommands(const BSONObj& cmdObj, validFieldNames.insert(cmdName.toString()); validFieldNames.insert("privileges"); validFieldNames.insert("roles"); + validFieldNames.insert("authenticationRestrictions"); Status status = _checkNoExtraFields(cmdObj, cmdName, validFieldNames); if (!status.isOK()) { @@ -536,6 +538,22 @@ Status parseCreateOrUpdateRoleCommands(const BSONObj& cmdObj, } parsedArgs->hasRoles = true; } + + // Parse restrictions + if (cmdObj.hasField("authenticationRestrictions")) { + BSONElement restrictionsElement; + status = bsonExtractTypedField( + cmdObj, "authenticationRestrictions", Array, &restrictionsElement); + if (!status.isOK()) { + return status; + } + auto restrictions = getRawAuthenticationRestrictions(BSONArray(restrictionsElement.Obj())); + if (!restrictions.isOK()) { + return restrictions.getStatus(); + } + parsedArgs->authenticationRestrictions = restrictions.getValue(); + } + 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 5c942a97a09..2ccd6524ae9 100644 --- a/src/mongo/db/auth/user_management_commands_parser.h +++ b/src/mongo/db/auth/user_management_commands_parser.h @@ -134,6 +134,7 @@ struct CreateOrUpdateRoleArgs { std::vector<RoleName> roles; bool hasPrivileges = false; PrivilegeVector privileges; + boost::optional<BSONArray> authenticationRestrictions; }; /** diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp index 293c6d83fd4..016d44ed577 100644 --- a/src/mongo/db/commands/user_management_commands.cpp +++ b/src/mongo/db/commands/user_management_commands.cpp @@ -1357,6 +1357,11 @@ public: roleObjBuilder.append("roles", rolesVectorToBSONArray(args.roles)); + if (args.authenticationRestrictions && !args.authenticationRestrictions->isEmpty()) { + roleObjBuilder.append("authenticationRestrictions", + args.authenticationRestrictions.get()); + } + ServiceContext* serviceContext = opCtx->getClient()->getServiceContext(); stdx::lock_guard<stdx::mutex> lk(getAuthzDataMutex(serviceContext)); |