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/rpc | |
parent | 7087350d1d5c943520e9972ac1f8b85252c0eceb (diff) | |
download | mongo-2ea069aa505c750cad6a7ba6ae6d4ac897f396d1.tar.gz |
SERVER-5261 Include authentication information in currentOp output
Diffstat (limited to 'src/mongo/rpc')
-rw-r--r-- | src/mongo/rpc/SConscript | 19 | ||||
-rw-r--r-- | src/mongo/rpc/metadata.cpp | 10 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/audit_metadata.cpp | 71 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/audit_metadata.h | 83 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/impersonated_user_metadata.cpp | 93 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/impersonated_user_metadata.h | 73 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/impersonated_user_metadata.idl | 35 |
7 files changed, 216 insertions, 168 deletions
diff --git a/src/mongo/rpc/SConscript b/src/mongo/rpc/SConscript index 53757b9fcb7..f7883dbc9e2 100644 --- a/src/mongo/rpc/SConscript +++ b/src/mongo/rpc/SConscript @@ -80,7 +80,7 @@ env.Library( ], LIBDEPS=[ 'client_metadata', - 'audit_metadata', + 'metadata_impersonated_user', '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/bson/util/bson_extract', '$BUILD_DIR/mongo/client/read_preference', @@ -90,20 +90,21 @@ env.Library( ], ) -env.Clone().InjectModule("enterprise").Library( +env.Library( target=[ - 'audit_metadata', + 'metadata_impersonated_user' ], source=[ - 'metadata/audit_metadata.cpp', - ], - LIBDEPS_PRIVATE=[ - '$BUILD_DIR/mongo/bson/util/bson_extract', - '$BUILD_DIR/mongo/db/auth/auth_rolename', - '$BUILD_DIR/mongo/db/auth/user_name', + 'metadata/impersonated_user_metadata.cpp', + env.Idlc('metadata/impersonated_user_metadata.idl')[0], ], LIBDEPS=[ '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/db/service_context', + ], + LIBDEPS_PRIVATE=[ + '$BUILD_DIR/mongo/db/auth/auth', + '$BUILD_DIR/mongo/db/server_options', ], ) diff --git a/src/mongo/rpc/metadata.cpp b/src/mongo/rpc/metadata.cpp index 74360ead237..6359c9e1952 100644 --- a/src/mongo/rpc/metadata.cpp +++ b/src/mongo/rpc/metadata.cpp @@ -36,9 +36,9 @@ #include "mongo/db/jsobj.h" #include "mongo/db/logical_clock.h" #include "mongo/db/logical_time_validator.h" -#include "mongo/rpc/metadata/audit_metadata.h" #include "mongo/rpc/metadata/client_metadata_ismaster.h" #include "mongo/rpc/metadata/config_server_metadata.h" +#include "mongo/rpc/metadata/impersonated_user_metadata.h" #include "mongo/rpc/metadata/logical_time_metadata.h" #include "mongo/rpc/metadata/sharding_metadata.h" #include "mongo/rpc/metadata/tracking_metadata.h" @@ -53,18 +53,16 @@ BSONObj makeEmptyMetadata() { void readRequestMetadata(OperationContext* opCtx, const BSONObj& metadataObj, bool requiresAuth) { BSONElement readPreferenceElem; - BSONElement auditElem; BSONElement configSvrElem; BSONElement trackingElem; BSONElement clientElem; BSONElement logicalTimeElem; + BSONElement impersonationElem; for (const auto& metadataElem : metadataObj) { auto fieldName = metadataElem.fieldNameStringData(); if (fieldName == "$readPreference") { readPreferenceElem = metadataElem; - } else if (fieldName == AuditMetadata::fieldName()) { - auditElem = metadataElem; } else if (fieldName == ConfigServerMetadata::fieldName()) { configSvrElem = metadataElem; } else if (fieldName == ClientMetadata::fieldName()) { @@ -73,6 +71,8 @@ void readRequestMetadata(OperationContext* opCtx, const BSONObj& metadataObj, bo trackingElem = metadataElem; } else if (fieldName == LogicalTimeMetadata::fieldName()) { logicalTimeElem = metadataElem; + } else if (fieldName == kImpersonationMetadataSectionName) { + impersonationElem = metadataElem; } } @@ -81,7 +81,7 @@ void readRequestMetadata(OperationContext* opCtx, const BSONObj& metadataObj, bo uassertStatusOK(ReadPreferenceSetting::fromInnerBSON(readPreferenceElem)); } - AuditMetadata::get(opCtx) = uassertStatusOK(AuditMetadata::readFromMetadata(auditElem)); + readImpersonatedUserMetadata(impersonationElem, opCtx); uassertStatusOK(ClientMetadataIsMasterState::readFromMetadata(opCtx, clientElem)); diff --git a/src/mongo/rpc/metadata/audit_metadata.cpp b/src/mongo/rpc/metadata/audit_metadata.cpp deleted file mode 100644 index 1dacabd7dc4..00000000000 --- a/src/mongo/rpc/metadata/audit_metadata.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2015 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/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#include "mongo/platform/basic.h" - -#include "mongo/rpc/metadata/audit_metadata.h" - -#include <utility> - -#include "mongo/base/status_with.h" -#include "mongo/bson/util/bson_extract.h" -#include "mongo/db/auth/role_name.h" -#include "mongo/db/auth/user_name.h" - -namespace mongo { -namespace rpc { - -const OperationContext::Decoration<AuditMetadata> AuditMetadata::get = - OperationContext::declareDecoration<AuditMetadata>(); - -AuditMetadata::AuditMetadata(boost::optional<UsersAndRoles> impersonatedUsersAndRoles) - : _impersonatedUsersAndRoles(std::move(impersonatedUsersAndRoles)) {} - -#if !defined(MONGO_ENTERPRISE_VERSION) - -StatusWith<AuditMetadata> AuditMetadata::readFromMetadata(const BSONObj&) { - return AuditMetadata{}; -} - -StatusWith<AuditMetadata> AuditMetadata::readFromMetadata(const BSONElement&) { - return AuditMetadata{}; -} - -Status AuditMetadata::writeToMetadata(BSONObjBuilder*) const { - return Status::OK(); -} - -#endif - -const boost::optional<AuditMetadata::UsersAndRoles>& AuditMetadata::getImpersonatedUsersAndRoles() - const { - return _impersonatedUsersAndRoles; -} - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/metadata/audit_metadata.h b/src/mongo/rpc/metadata/audit_metadata.h deleted file mode 100644 index 0724001d97c..00000000000 --- a/src/mongo/rpc/metadata/audit_metadata.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2015 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/>. - * - * As a special exception, the copyright holders give permission to link the - * code of portions of this program with the OpenSSL library under certain - * conditions as described in each individual source file and distribute - * linked combinations including the program with the OpenSSL library. You - * must comply with the GNU Affero General Public License in all respects for - * all of the code used other than as permitted herein. If you modify file(s) - * with this exception, you may extend this exception to your version of the - * file(s), but you are not obligated to do so. If you do not wish to do so, - * delete this exception statement from your version. If you delete this - * exception statement from all source files in the program, then also delete - * it in the license file. - */ - -#pragma once - -#include <boost/optional.hpp> -#include <vector> - -#include "mongo/base/disallow_copying.h" -#include "mongo/db/auth/role_name.h" -#include "mongo/db/auth/user_name.h" -#include "mongo/db/operation_context.h" - -namespace mongo { -class BSONObj; -class BSONObjBuilder; -class Status; -template <typename T> -class StatusWith; - -namespace rpc { - -/** - * This class comprises the request metadata fields involving auditing. - */ -class AuditMetadata { -public: - static const OperationContext::Decoration<AuditMetadata> get; - - // Decorable requires a default constructor. - AuditMetadata() = default; - - static StatusWith<AuditMetadata> readFromMetadata(const BSONObj& metadataObj); - - /** - * Parses AuditMetadata from a pre-extracted BSONElement. When reading a metadata object, this - * form is more efficient as it permits parsing the metadata in one pass. - */ - static StatusWith<AuditMetadata> readFromMetadata(const BSONElement& metadataElem); - - Status writeToMetadata(BSONObjBuilder* metadataBob) const; - - using UsersAndRoles = std::tuple<std::vector<UserName>, std::vector<RoleName>>; - - const boost::optional<UsersAndRoles>& getImpersonatedUsersAndRoles() const; - - AuditMetadata(boost::optional<UsersAndRoles> impersonatedUsersAndRoles); - - static StringData fieldName() { - return "$audit"; - } - -private: - boost::optional<UsersAndRoles> _impersonatedUsersAndRoles; -}; - -} // namespace rpc -} // namespace mongo diff --git a/src/mongo/rpc/metadata/impersonated_user_metadata.cpp b/src/mongo/rpc/metadata/impersonated_user_metadata.cpp new file mode 100644 index 00000000000..b8e9e77c595 --- /dev/null +++ b/src/mongo/rpc/metadata/impersonated_user_metadata.cpp @@ -0,0 +1,93 @@ +/** + * 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/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/rpc/metadata/impersonated_user_metadata.h" + +#include "mongo/db/auth/authorization_session.h" +#include "mongo/db/server_options.h" + +namespace mongo { +namespace rpc { +namespace { + +static const OperationContext::Decoration<MaybeImpersonatedUserMetadata> getForOpCtx = + OperationContext::declareDecoration<MaybeImpersonatedUserMetadata>(); +} // namespace + +MaybeImpersonatedUserMetadata getImpersonatedUserMetadata(OperationContext* opCtx) { + return opCtx ? getForOpCtx(opCtx) : boost::none; +} + +void readImpersonatedUserMetadata(const BSONElement& elem, OperationContext* opCtx) { + // If we have no opCtx, which does appear to happen, don't do anything. + if (!opCtx) { + return; + } + + // Always reset the current impersonation data to boost::none. + getForOpCtx(opCtx) = boost::none; + if (elem.type() == Object) { + IDLParserErrorContext errCtx(kImpersonationMetadataSectionName); + auto data = ImpersonatedUserMetadata::parse(errCtx, elem.embeddedObject()); + + // Set the impersonation data only if there are actually impersonated + // users/roles. + if ((!data.getUsers().empty()) || (!data.getRoles().empty())) { + getForOpCtx(opCtx) = std::move(data); + } + } +} + +void writeAuthDataToImpersonatedUserMetadata(OperationContext* opCtx, BSONObjBuilder* out) { + // If we have no opCtx, which does appear to happen, don't do anything. + if (!opCtx) { + return; + } + + // Otherwise construct a metadata section from the list of authenticated users/roles + auto authSession = AuthorizationSession::get(opCtx->getClient()); + ImpersonatedUserMetadata metadata; + metadata.setUsers(userNameIteratorToContainer<std::vector<UserName>>( + authSession->getAuthenticatedUserNames())); + + metadata.setRoles(roleNameIteratorToContainer<std::vector<RoleName>>( + authSession->getAuthenticatedRoleNames())); + + // If there are no users/roles being impersonated just exit + if (metadata.getUsers().empty() && metadata.getRoles().empty()) { + return; + } + + BSONObjBuilder section(out->subobjStart(kImpersonationMetadataSectionName)); + metadata.serialize(§ion); +} + +} // namespace rpc +} // namespace mongo diff --git a/src/mongo/rpc/metadata/impersonated_user_metadata.h b/src/mongo/rpc/metadata/impersonated_user_metadata.h new file mode 100644 index 00000000000..f379b509d4c --- /dev/null +++ b/src/mongo/rpc/metadata/impersonated_user_metadata.h @@ -0,0 +1,73 @@ +/** + * 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/>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the GNU Affero General Public License in all respects + * for all of the code used other than as permitted herein. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you do not + * wish to do so, delete this exception statement from your version. If you + * delete this exception statement from all source files in the program, + * then also delete it in the license file. + */ + +#pragma once + +#include "boost/optional.hpp" + +#include "mongo/db/operation_context.h" +#include "mongo/rpc/metadata/impersonated_user_metadata_gen.h" + +namespace mongo { +namespace rpc { + +/* + * The name of the BSON element in message metadata that contains the impersonated user data + * + * This is called "$audit" because in pre-4.2 the enterprise audit subsystem already passed + * the impersonated users info around in metadata for auditing purposes. This has been lifted + * into the community edition and appears in network messages as "$audit" for backwards + * compatibility. + * + * This metadata should only appear in requests from mongos to mongod. + */ +static constexpr auto kImpersonationMetadataSectionName = "$audit"_sd; + +/* + * A type that maybe contains parsed ImpersonationUserMetadata + */ +using MaybeImpersonatedUserMetadata = boost::optional<ImpersonatedUserMetadata>; + +/* + * Gets the current impersonation data from the OpCtx (assumes readImpersonatedUserMetadata + * has already been called) + */ +MaybeImpersonatedUserMetadata getImpersonatedUserMetadata(OperationContext* opCtx); + +/* + * Parses any impersonation data out of a metdata bson obj and into the opCtx + */ +void readImpersonatedUserMetadata(const BSONElement& elem, OperationContext* opCtx); + +/* + * Writes the current impersonation metadata off the opCtx and into a BSONObjBuilder + */ +void writeAuthDataToImpersonatedUserMetadata(OperationContext* opCtx, BSONObjBuilder* out); + +} // namespace rpc +} // namespace mongo diff --git a/src/mongo/rpc/metadata/impersonated_user_metadata.idl b/src/mongo/rpc/metadata/impersonated_user_metadata.idl new file mode 100644 index 00000000000..c2b15e325fc --- /dev/null +++ b/src/mongo/rpc/metadata/impersonated_user_metadata.idl @@ -0,0 +1,35 @@ +# 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::rpc" + +imports: + - "mongo/idl/basic_types.idl" + - "mongo/db/auth/auth_types.idl" + +structs: + # This is the IDL version of the old enterprise-only Audit metadata struct + ImpersonatedUserMetadata: + description: "A struct representing the impersonated users from a mongos" + strict: true + fields: + "$impersonatedUsers": + type: array<UserName> + cpp_name: "users" + "$impersonatedRoles": + type: array<RoleName> + cpp_name: "roles" + |