diff options
author | Jonathan Reams <jbreams@mongodb.com> | 2018-08-16 16:02:16 -0400 |
---|---|---|
committer | Jonathan Reams <jbreams@mongodb.com> | 2018-09-14 11:12:45 -0400 |
commit | 2ea069aa505c750cad6a7ba6ae6d4ac897f396d1 (patch) | |
tree | b8093da62175046189de9fbb876b5ef8b79181b1 /src/mongo/db/auth | |
parent | 7087350d1d5c943520e9972ac1f8b85252c0eceb (diff) | |
download | mongo-2ea069aa505c750cad6a7ba6ae6d4ac897f396d1.tar.gz |
SERVER-5261 Include authentication information in currentOp output
Diffstat (limited to 'src/mongo/db/auth')
-rw-r--r-- | src/mongo/db/auth/SConscript | 31 | ||||
-rw-r--r-- | src/mongo/db/auth/auth_types.idl | 38 | ||||
-rw-r--r-- | src/mongo/db/auth/impersonation_session.cpp | 20 | ||||
-rw-r--r-- | src/mongo/db/auth/impersonation_session.h | 2 | ||||
-rw-r--r-- | src/mongo/db/auth/role_name.cpp | 38 | ||||
-rw-r--r-- | src/mongo/db/auth/role_name.h | 18 | ||||
-rw-r--r-- | src/mongo/db/auth/user_name.cpp | 44 | ||||
-rw-r--r-- | src/mongo/db/auth/user_name.h | 11 |
8 files changed, 164 insertions, 38 deletions
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript index 35c418f448d..a8f89e223b1 100644 --- a/src/mongo/db/auth/SConscript +++ b/src/mongo/db/auth/SConscript @@ -18,16 +18,6 @@ generateActionTypes = env.Command( env.Alias('generated-sources', generateActionTypes) env.Library( - target='auth_rolename', - source=[ - 'role_name.cpp' - ], - LIBDEPS=[ - '$BUILD_DIR/mongo/base', - ], -) - -env.Library( target='authentication_restriction', source=[ 'restriction_environment.cpp', @@ -58,24 +48,12 @@ env.Library( 'authorization_manager.cpp', 'authorization_session.cpp', 'auth_decorations.cpp', - ], - LIBDEPS=[ - 'auth_rolename', - 'user_name', - '$BUILD_DIR/mongo/base', - '$BUILD_DIR/mongo/db/service_context', - '$BUILD_DIR/mongo/rpc/audit_metadata', - ], -) - - -env.Library( - target='user_name', - source=[ 'user_name.cpp', + 'role_name.cpp' ], LIBDEPS=[ '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/db/service_context', ], ) @@ -154,7 +132,6 @@ env.Library( LIBDEPS=[ 'address_restriction', 'auth', - 'auth_rolename', 'authentication_restriction', 'authorization_manager_global', 'authprivilege', @@ -196,6 +173,9 @@ env.Library( '$BUILD_DIR/mongo/bson/mutable/mutable_bson', '$BUILD_DIR/mongo/db/common', ], + LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/rpc/metadata_impersonated_user', + ] ) env.Library( @@ -299,7 +279,6 @@ env.Library( 'authprivilege', 'sasl_options', 'user', - 'user_name', '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/base/secure_allocator', '$BUILD_DIR/mongo/crypto/sha_block_${MONGO_CRYPTO}', diff --git a/src/mongo/db/auth/auth_types.idl b/src/mongo/db/auth/auth_types.idl new file mode 100644 index 00000000000..f035dc7f488 --- /dev/null +++ b/src/mongo/db/auth/auth_types.idl @@ -0,0 +1,38 @@ +# Copyright (C) 2018 MongoDB Inc. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License, version 3, +# as published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +global: + cpp_namespace: "mongo" + cpp_includes: + - "mongo/db/auth/user_name.h" + - "mongo/db/auth/role_name.h" + +imports: + - "mongo/idl/basic_types.idl" + +types: + UserName: + bson_serialization_type: any + description: "A struct representing a UserName" + cpp_type: "UserName" + deserializer: "mongo::UserName::parseFromBSON" + serializer: "mongo::UserName::serializeToBSON" + + RoleName: + bson_serialization_type: any + description: "A struct representing a Role" + cpp_type: "RoleName" + deserializer: "mongo::RoleName::parseFromBSON" + serializer: "mongo::RoleName::serializeToBSON" diff --git a/src/mongo/db/auth/impersonation_session.cpp b/src/mongo/db/auth/impersonation_session.cpp index 8b9a5f09fc7..666522cd043 100644 --- a/src/mongo/db/auth/impersonation_session.cpp +++ b/src/mongo/db/auth/impersonation_session.cpp @@ -39,7 +39,7 @@ #include "mongo/db/auth/resource_pattern.h" #include "mongo/db/client.h" #include "mongo/db/operation_context.h" -#include "mongo/rpc/metadata/audit_metadata.h" +#include "mongo/rpc/metadata/impersonated_user_metadata.h" #include "mongo/util/assert_util.h" #include "mongo/util/destructor_guard.h" @@ -47,28 +47,24 @@ namespace mongo { ImpersonationSessionGuard::ImpersonationSessionGuard(OperationContext* opCtx) : _opCtx(opCtx) { auto authSession = AuthorizationSession::get(_opCtx->getClient()); - - const auto& impersonatedUsersAndRoles = - rpc::AuditMetadata::get(opCtx).getImpersonatedUsersAndRoles(); - - if (impersonatedUsersAndRoles != boost::none) { + const auto impersonatedUsersAndRoles = rpc::getImpersonatedUserMetadata(opCtx); + if (impersonatedUsersAndRoles) { uassert(ErrorCodes::Unauthorized, "Unauthorized use of impersonation metadata.", authSession->isAuthorizedForPrivilege( Privilege(ResourcePattern::forClusterResource(), ActionType::impersonate))); - fassert(ErrorCodes::InternalError, !authSession->isImpersonating()); - - authSession->setImpersonatedUserData(std::get<0>(*impersonatedUsersAndRoles), - std::get<1>(*impersonatedUsersAndRoles)); + authSession->setImpersonatedUserData(impersonatedUsersAndRoles->getUsers(), + impersonatedUsersAndRoles->getRoles()); _active = true; + return; } } ImpersonationSessionGuard::~ImpersonationSessionGuard() { - DESTRUCTOR_GUARD(if (_active) { + if (_active) { AuthorizationSession::get(_opCtx->getClient())->clearImpersonatedUserData(); - }) + } } } // namespace mongo diff --git a/src/mongo/db/auth/impersonation_session.h b/src/mongo/db/auth/impersonation_session.h index a2986cb0e86..e32363be4e9 100644 --- a/src/mongo/db/auth/impersonation_session.h +++ b/src/mongo/db/auth/impersonation_session.h @@ -27,6 +27,7 @@ */ #include "mongo/base/disallow_copying.h" +#include "mongo/rpc/metadata/impersonated_user_metadata.h" namespace mongo { class OperationContext; @@ -43,6 +44,7 @@ public: ~ImpersonationSessionGuard(); private: + rpc::MaybeImpersonatedUserMetadata _oldImpersonationData; OperationContext* _opCtx; bool _active{false}; }; diff --git a/src/mongo/db/auth/role_name.cpp b/src/mongo/db/auth/role_name.cpp index 6c22d03a7c5..a49b80e1fba 100644 --- a/src/mongo/db/auth/role_name.cpp +++ b/src/mongo/db/auth/role_name.cpp @@ -33,6 +33,7 @@ #include <string> #include "mongo/base/string_data.h" +#include "mongo/db/auth/authorization_manager.h" #include "mongo/util/assert_util.h" namespace mongo { @@ -52,4 +53,41 @@ std::ostream& operator<<(std::ostream& os, const RoleName& name) { return os << name.getFullName(); } +RoleName RoleName::parseFromBSON(const BSONElement& elem) { + auto obj = elem.embeddedObjectUserCheck(); + std::array<BSONElement, 2> fields; + obj.getFields( + {AuthorizationManager::ROLE_NAME_FIELD_NAME, AuthorizationManager::ROLE_DB_FIELD_NAME}, + &fields); + const auto& nameField = fields[0]; + uassert(ErrorCodes::BadValue, + str::stream() << "user name must contain a string field named: " + << AuthorizationManager::ROLE_NAME_FIELD_NAME, + nameField.type() == String); + + const auto& dbField = fields[1]; + uassert(ErrorCodes::BadValue, + str::stream() << "role name must contain a string field named: " + << AuthorizationManager::ROLE_DB_FIELD_NAME, + nameField.type() == String); + + return RoleName(nameField.valueStringData(), dbField.valueStringData()); +} + +void RoleName::serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const { + BSONObjBuilder sub(bob->subobjStart(fieldName)); + _serializeToSubObj(&sub); +} + +void RoleName::serializeToBSON(BSONArrayBuilder* bob) const { + BSONObjBuilder sub(bob->subobjStart()); + _serializeToSubObj(&sub); +} + +void RoleName::_serializeToSubObj(BSONObjBuilder* sub) const { + sub->append(AuthorizationManager::ROLE_NAME_FIELD_NAME, getRole()); + sub->append(AuthorizationManager::ROLE_DB_FIELD_NAME, getDB()); +} + + } // namespace mongo diff --git a/src/mongo/db/auth/role_name.h b/src/mongo/db/auth/role_name.h index 5d9981cf9dc..809aa2c4d69 100644 --- a/src/mongo/db/auth/role_name.h +++ b/src/mongo/db/auth/role_name.h @@ -36,6 +36,8 @@ #include "mongo/base/disallow_copying.h" #include "mongo/base/string_data.h" +#include "mongo/bson/bsonelement.h" +#include "mongo/bson/bsonobjbuilder.h" #include "mongo/platform/hash_namespace.h" #include "mongo/util/assert_util.h" @@ -51,6 +53,11 @@ public: RoleName() : _splitPoint(0) {} RoleName(StringData role, StringData dbname); + // Added for IDL support + static RoleName parseFromBSON(const BSONElement& elem); + void serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const; + void serializeToBSON(BSONArrayBuilder* bob) const; + /** * Gets the name of the role excluding the "@dbname" component. */ @@ -88,6 +95,8 @@ public: private: std::string _fullName; // The full name, stored as a string. "role@db". size_t _splitPoint; // The index of the "@" separating the role and db name parts. + + void _serializeToSubObj(BSONObjBuilder* sub) const; }; static inline bool operator==(const RoleName& lhs, const RoleName& rhs) { @@ -213,4 +222,13 @@ RoleNameIterator makeRoleNameIteratorForContainer(const Container& container) { return makeRoleNameIterator(container.begin(), container.end()); } +template <typename Container> +Container roleNameIteratorToContainer(RoleNameIterator it) { + Container container; + while (it.more()) { + container.emplace_back(it.next()); + } + return container; +} + } // namespace mongo diff --git a/src/mongo/db/auth/user_name.cpp b/src/mongo/db/auth/user_name.cpp index 3bcdf3ad813..dd16bc993b3 100644 --- a/src/mongo/db/auth/user_name.cpp +++ b/src/mongo/db/auth/user_name.cpp @@ -32,6 +32,7 @@ #include <string> #include "mongo/base/string_data.h" +#include "mongo/db/auth/authorization_manager.h" #include "mongo/util/assert_util.h" namespace mongo { @@ -62,6 +63,49 @@ StatusWith<UserName> UserName::parse(StringData userNameStr) { return UserName(userNamePortion, userDBPortion); } +UserName UserName::parseFromBSON(const BSONElement& elem) { + if (elem.type() == String) { + return uassertStatusOK(UserName::parse(elem.valueStringData())); + } else if (elem.type() == Object) { + const auto obj = elem.embeddedObject(); + std::array<BSONElement, 2> fields; + obj.getFields( + {AuthorizationManager::USER_NAME_FIELD_NAME, AuthorizationManager::USER_DB_FIELD_NAME}, + &fields); + + const auto& nameField = fields[0]; + uassert(ErrorCodes::BadValue, + str::stream() << "username must contain a string field named: " + << AuthorizationManager::USER_NAME_FIELD_NAME, + nameField.type() == String); + + const auto& dbField = fields[1]; + uassert(ErrorCodes::BadValue, + str::stream() << "username must contain a string field named: " + << AuthorizationManager::USER_DB_FIELD_NAME, + dbField.type() == String); + + return UserName(nameField.valueStringData(), dbField.valueStringData()); + } else { + uasserted(ErrorCodes::BadValue, "username must be either a string or an object"); + } +} + +void UserName::serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const { + BSONObjBuilder sub(bob->subobjStart(fieldName)); + _serializeToSubObj(&sub); +} + +void UserName::serializeToBSON(BSONArrayBuilder* bab) const { + BSONObjBuilder sub(bab->subobjStart()); + _serializeToSubObj(&sub); +} + +void UserName::_serializeToSubObj(BSONObjBuilder* sub) const { + *sub << AuthorizationManager::USER_NAME_FIELD_NAME << getUser() + << AuthorizationManager::USER_DB_FIELD_NAME << getDB(); +} + std::ostream& operator<<(std::ostream& os, const UserName& name) { return os << name.getFullName(); } diff --git a/src/mongo/db/auth/user_name.h b/src/mongo/db/auth/user_name.h index a1b04f010d4..22c62db2d82 100644 --- a/src/mongo/db/auth/user_name.h +++ b/src/mongo/db/auth/user_name.h @@ -36,6 +36,8 @@ #include "mongo/base/disallow_copying.h" #include "mongo/base/status_with.h" #include "mongo/base/string_data.h" +#include "mongo/bson/bsonelement.h" +#include "mongo/bson/bsonobjbuilder.h" namespace mongo { @@ -54,6 +56,13 @@ public: */ static StatusWith<UserName> parse(StringData userNameStr); + /* + * These methods support parsing usernames from IDL + */ + static UserName parseFromBSON(const BSONElement& elem); + void serializeToBSON(StringData fieldName, BSONObjBuilder* bob) const; + void serializeToBSON(BSONArrayBuilder* bob) const; + /** * Gets the user part of a UserName. */ @@ -95,6 +104,8 @@ public: } private: + void _serializeToSubObj(BSONObjBuilder* sub) const; + std::string _fullName; // The full name, stored as a string. "user@db". size_t _splitPoint; // The index of the "@" separating the user and db name parts. }; |