diff options
author | ADAM David Alan Martin <adam.martin@10gen.com> | 2017-07-11 12:41:24 -0400 |
---|---|---|
committer | Spencer Jackson <spencer.jackson@mongodb.com> | 2017-07-12 11:15:35 -0400 |
commit | cddf5ed098ea4eb8df1d946d750edd4280e022e3 (patch) | |
tree | b18e5a4ebdf3e130b35479d724b5590ef75944b2 | |
parent | 1d1b6ba0a7387b36d8ad0e47b77121e6c6c156f1 (diff) | |
download | mongo-cddf5ed098ea4eb8df1d946d750edd4280e022e3.tar.gz |
SERVER-29176: Implement --clusterIpSourceWhitelist
-rw-r--r-- | src/mongo/db/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/db/auth/SConscript | 75 | ||||
-rw-r--r-- | src/mongo/db/auth/address_restriction.h | 28 | ||||
-rw-r--r-- | src/mongo/db/auth/address_restriction_test.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/auth/authorization_manager.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/auth/restriction_set.h | 16 | ||||
-rw-r--r-- | src/mongo/db/mongod_options.cpp | 23 | ||||
-rw-r--r-- | src/mongo/db/mongod_options.h | 6 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/SConscript | 8 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/mmap_v1_engine.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/storage/mmap_v1/mmap_v1_options.cpp | 31 |
11 files changed, 154 insertions, 73 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index 70b7fa064a1..d3728542f69 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -411,11 +411,11 @@ env.Library( "mongod_options.cpp", ], LIBDEPS=[ + '$BUILD_DIR/mongo/db/storage/mmap_v1/mmap_v1_options', '$BUILD_DIR/mongo/util/options_parser/options_parser_init', 'diag_log', 'repl/repl_settings', 'server_options', - "storage/mmap_v1/storage_mmapv1", 'storage/storage_options', ], ) diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript index 8eab9b9c948..596c75d7f8b 100644 --- a/src/mongo/db/auth/SConscript +++ b/src/mongo/db/auth/SConscript @@ -52,39 +52,48 @@ env.CppUnitTest( # Just the data structures used -env.Library('authcore', ['action_set.cpp', - 'action_type.cpp', - 'authorization_manager.cpp', - 'authorization_session.cpp', - 'auth_decorations.cpp', - 'authz_manager_external_state.cpp', - 'authz_manager_external_state_local.cpp', - 'authz_session_external_state.cpp', - 'privilege.cpp', - 'privilege_parser.cpp', - 'resource_pattern.cpp', - 'role_graph.cpp', - 'role_graph_update.cpp', - 'role_graph_builtin_roles.cpp', - 'user.cpp', - 'user_document_parser.cpp', - 'user_management_commands_parser.cpp', - 'user_set.cpp'], - LIBDEPS=['auth_rolename', - 'authentication_restriction', - 'sasl_options', - 'user_name', - '$BUILD_DIR/mongo/base', - '$BUILD_DIR/mongo/bson/mutable/mutable_bson', - '$BUILD_DIR/mongo/bson/util/bson_extract', - '$BUILD_DIR/mongo/crypto/scramauth', - '$BUILD_DIR/mongo/db/catalog/document_validation', - '$BUILD_DIR/mongo/db/common', - '$BUILD_DIR/mongo/db/namespace_string', - '$BUILD_DIR/mongo/db/service_context', - '$BUILD_DIR/mongo/db/update/update_driver', - '$BUILD_DIR/mongo/util/md5', - '$BUILD_DIR/mongo/util/net/network']) +env.Library( + target='authcore', + source=[ + 'action_set.cpp', + 'action_type.cpp', + 'authorization_manager.cpp', + 'authorization_session.cpp', + 'auth_decorations.cpp', + 'authz_manager_external_state.cpp', + 'authz_manager_external_state_local.cpp', + 'authz_session_external_state.cpp', + 'privilege.cpp', + 'privilege_parser.cpp', + 'resource_pattern.cpp', + 'role_graph.cpp', + 'role_graph_update.cpp', + 'role_graph_builtin_roles.cpp', + 'user.cpp', + 'user_document_parser.cpp', + 'user_management_commands_parser.cpp', + 'user_set.cpp', + ], + LIBDEPS=[ + 'address_restriction', + 'auth_rolename', + 'authentication_restriction', + 'sasl_options', + 'user_name', + '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/bson/mutable/mutable_bson', + '$BUILD_DIR/mongo/bson/util/bson_extract', + '$BUILD_DIR/mongo/crypto/scramauth', + '$BUILD_DIR/mongo/db/catalog/document_validation', + '$BUILD_DIR/mongo/db/common', + '$BUILD_DIR/mongo/db/mongod_options', + '$BUILD_DIR/mongo/db/namespace_string', + '$BUILD_DIR/mongo/db/service_context', + '$BUILD_DIR/mongo/db/update/update_driver', + '$BUILD_DIR/mongo/util/md5', + '$BUILD_DIR/mongo/util/net/network', + ], +) env.Library('authcommon', ['internal_user_auth.cpp'], diff --git a/src/mongo/db/auth/address_restriction.h b/src/mongo/db/auth/address_restriction.h index 0f993ef117a..27fd2c8259e 100644 --- a/src/mongo/db/auth/address_restriction.h +++ b/src/mongo/db/auth/address_restriction.h @@ -75,39 +75,13 @@ public: /** * Construct an AddressRestriction based on several human readable subnet specs */ - explicit AddressRestriction(const std::vector<StringData>& ranges) { + explicit AddressRestriction(const std::vector<std::string>& ranges) { for (auto const& range : ranges) { _ranges.emplace_back(range); } } /** - * If the given BSONElement represents a valid CIDR range, - * constructs and returns the AddressRestriction. - * Otherwise returns an error. - */ - static StatusWith<AddressRestriction<T>> parse(BSONElement from) noexcept { - auto cidr = CIDR::parse(from); - if (cidr.isOK()) { - return AddressRestriction<T>(std::move(cidr.getValue())); - } - return cidr.getStatus(); - } - - /** - * If the given string represents a valid CIDR range, - * constructs and returns the AddressRestriction. - * Otherwise returns an error. - */ - static StatusWith<AddressRestriction<T>> parse(StringData from) noexcept { - auto cidr = CIDR::parse(from); - if (cidr.isOK()) { - return AddressRestriction<T>(std::move(cidr.getValue())); - } - return cidr.getStatus(); - } - - /** * Returns true if the Environment's client/server's address * satisfies this restriction set. */ diff --git a/src/mongo/db/auth/address_restriction_test.cpp b/src/mongo/db/auth/address_restriction_test.cpp index 88b803cc284..abfcc34b01b 100644 --- a/src/mongo/db/auth/address_restriction_test.cpp +++ b/src/mongo/db/auth/address_restriction_test.cpp @@ -71,7 +71,7 @@ TEST(AddressRestrictionTest, toAndFromStringSingle) { TEST(AddressRestrictionTest, toAndFromStringVector) { const struct { - std::vector<StringData> input; + std::vector<std::string> input; std::string output; } tests[] = { {{"127.0.0.1", "169.254.0.0/16", "::1"}, @@ -101,7 +101,7 @@ TEST(AddressRestrictionTest, toAndFromStringVector) { TEST(AddressRestrictionTest, contains) { enableIPv6(true); const struct { - std::vector<StringData> range; + std::vector<std::string> range; std::string address; bool valid; } contains[] = { diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp index 1bcebbc502f..4bf0ae2ba4a 100644 --- a/src/mongo/db/auth/authorization_manager.cpp +++ b/src/mongo/db/auth/authorization_manager.cpp @@ -43,6 +43,7 @@ #include "mongo/bson/util/bson_extract.h" #include "mongo/crypto/mechanism_scram.h" #include "mongo/db/auth/action_set.h" +#include "mongo/db/auth/address_restriction.h" #include "mongo/db/auth/authorization_session.h" #include "mongo/db/auth/authz_manager_external_state.h" #include "mongo/db/auth/privilege.h" @@ -53,6 +54,7 @@ #include "mongo/db/auth/user_name.h" #include "mongo/db/auth/user_name_hash.h" #include "mongo/db/jsobj.h" +#include "mongo/db/mongod_options.h" #include "mongo/platform/compiler.h" #include "mongo/platform/unordered_map.h" #include "mongo/stdx/memory.h" @@ -63,14 +65,17 @@ namespace mongo { +using std::begin; +using std::end; using std::endl; +using std::back_inserter; using std::string; using std::vector; AuthInfo internalSecurity; -MONGO_INITIALIZER_WITH_PREREQUISITES(SetupInternalSecurityUser, MONGO_NO_PREREQUISITES) -(InitializerContext* context) { +MONGO_INITIALIZER_WITH_PREREQUISITES(SetupInternalSecurityUser, ("EndStartupOptionStorage")) +(InitializerContext* const context) try { User* user = new User(UserName("__system", "local")); user->incrementRefCount(); // Pin this user so the ref count never drops below 1. @@ -79,9 +84,26 @@ MONGO_INITIALIZER_WITH_PREREQUISITES(SetupInternalSecurityUser, MONGO_NO_PREREQU PrivilegeVector privileges; RoleGraph::generateUniversalPrivileges(&privileges); user->addPrivileges(privileges); + + if (mongodGlobalParams.whitelistedClusterNetwork) { + const auto& whitelist = *mongodGlobalParams.whitelistedClusterNetwork; + + auto restriction = stdx::make_unique<ClientSourceRestriction>(whitelist); + auto restrictionSet = stdx::make_unique<RestrictionSet<>>(std::move(restriction)); + auto restrictionDocument = + stdx::make_unique<RestrictionDocument<>>(std::move(restrictionSet)); + + RestrictionDocuments clusterWhiteList(std::move(restrictionDocument)); + + user->setRestrictions(std::move(clusterWhiteList)); + } + + internalSecurity.user = user; return Status::OK(); +} catch (...) { + return exceptionToStatus(); } const std::string AuthorizationManager::USER_NAME_FIELD_NAME = "user"; @@ -581,7 +603,7 @@ Status AuthorizationManager::_fetchUserV2(OperationContext* opCtx, // Put the new user into an unique_ptr temporarily in case there's an error while // initializing the user. - std::unique_ptr<User> user(new User(userName)); + auto user = stdx::make_unique<User>(userName); status = _initializeUserFromPrivilegeDocument(user.get(), userObj); if (!status.isOK()) { diff --git a/src/mongo/db/auth/restriction_set.h b/src/mongo/db/auth/restriction_set.h index a6e48e3d0a9..8731b105d03 100644 --- a/src/mongo/db/auth/restriction_set.h +++ b/src/mongo/db/auth/restriction_set.h @@ -54,6 +54,11 @@ public: noexcept(Sequence<Pointer<T>>(std::move(std::declval<Sequence<Pointer<T>>>())))) : _restrictions(std::move(restrictions)) {} + template <typename U> + explicit RestrictionSetAny(std::unique_ptr<U> restriction) { + _restrictions.push_back(std::move(restriction)); + } + Status validate(const RestrictionEnvironment& environment) const final { if (_restrictions.empty()) { return Status::OK(); @@ -97,6 +102,17 @@ public: explicit RestrictionSetAll(Sequence<Pointer<T>> restrictions) : _restrictions(std::move(restrictions)) {} + template <typename U> + explicit RestrictionSetAll(std::unique_ptr<U> restriction) { + _restrictions.push_back(std::move(restriction)); + } + + template <typename R> + explicit RestrictionSetAll(const R& restriction) { + static_assert(std::is_base_of<Restriction, R>::value, "Must pass a Restriction type."); + _restrictions.push_back(stdx::make_unique<R>(restriction)); + } + Status validate(const RestrictionEnvironment& environment) const final { for (const Pointer<T>& restriction : _restrictions) { Status status = restriction->validate(environment); diff --git a/src/mongo/db/mongod_options.cpp b/src/mongo/db/mongod_options.cpp index cb801830e55..ae7407bbd6a 100644 --- a/src/mongo/db/mongod_options.cpp +++ b/src/mongo/db/mongod_options.cpp @@ -50,6 +50,7 @@ #include "mongo/util/mongoutils/str.h" #include "mongo/util/net/ssl_options.h" #include "mongo/util/options_parser/startup_options.h" +#include "mongo/util/stringutils.h" #include "mongo/util/version.h" namespace mongo { @@ -99,6 +100,15 @@ Status addMongodOptions(moe::OptionSection* options) { .setSources(moe::SourceAllLegacy) .incompatibleWith("noauth"); + // IP Whitelisting Options + general_options + .addOptionChaining("security.clusterIpSourceWhitelist", + "clusterIpSourceWhitelist", + moe::StringVector, + "Network CIDR specification of permitted origin for `__system` access.") + .composing(); + + // Way to enable or disable auth in JSON Config general_options .addOptionChaining( @@ -1046,6 +1056,19 @@ Status storeMongodOptions(const moe::Environment& params) { if (params.count("security.javascriptEnabled")) { mongodGlobalParams.scriptingEnabled = params["security.javascriptEnabled"].as<bool>(); } + + if (params.count("security.clusterIpSourceWhitelist")) { + mongodGlobalParams.whitelistedClusterNetwork = std::vector<std::string>(); + for (const std::string& whitelistEntry : + params["security.clusterIpSourceWhitelist"].as<std::vector<std::string>>()) { + std::vector<std::string> intermediates; + splitStringDelim(whitelistEntry, &intermediates, ','); + std::copy(intermediates.begin(), + intermediates.end(), + std::back_inserter(*mongodGlobalParams.whitelistedClusterNetwork)); + } + } + if (params.count("storage.mmapv1.preallocDataFiles")) { mmapv1GlobalOptions.prealloc = params["storage.mmapv1.preallocDataFiles"].as<bool>(); cout << "note: noprealloc may hurt performance in many applications" << endl; diff --git a/src/mongo/db/mongod_options.h b/src/mongo/db/mongod_options.h index 27fb778cfdf..05bb6d8d5a5 100644 --- a/src/mongo/db/mongod_options.h +++ b/src/mongo/db/mongod_options.h @@ -28,6 +28,8 @@ #pragma once +#include <boost/optional.hpp> + #include "mongo/base/status.h" #include "mongo/db/repl/repl_settings.h" #include "mongo/db/server_options.h" @@ -45,9 +47,9 @@ class Environment; namespace moe = mongo::optionenvironment; struct MongodGlobalParams { - bool scriptingEnabled; // --noscripting + bool scriptingEnabled = true; // --noscripting - MongodGlobalParams() : scriptingEnabled(true) {} + boost::optional<std::vector<std::string>> whitelistedClusterNetwork; }; extern MongodGlobalParams mongodGlobalParams; diff --git a/src/mongo/db/storage/mmap_v1/SConscript b/src/mongo/db/storage/mmap_v1/SConscript index f569c2a6bd5..e3eb4a43ba6 100644 --- a/src/mongo/db/storage/mmap_v1/SConscript +++ b/src/mongo/db/storage/mmap_v1/SConscript @@ -16,6 +16,13 @@ env.Library( ) env.Library( + target='mmap_v1_options', + source=[ + 'mmap_v1_options.cpp', + ], +) + +env.Library( target = 'storage_mmapv1', source = [ "aligned_builder.cpp", "catalog/hashtab.cpp", @@ -52,6 +59,7 @@ env.Library( 'logfile', 'compress', 'paths', + 'mmap_v1_options', '$BUILD_DIR/mongo/db/catalog/collection_options', '$BUILD_DIR/mongo/db/catalog/database', '$BUILD_DIR/mongo/db/catalog/database_holder', diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_engine.cpp b/src/mongo/db/storage/mmap_v1/mmap_v1_engine.cpp index c43e148d3f4..1dd2c2e8cc3 100644 --- a/src/mongo/db/storage/mmap_v1/mmap_v1_engine.cpp +++ b/src/mongo/db/storage/mmap_v1/mmap_v1_engine.cpp @@ -1,5 +1,3 @@ -// mmap_v1_engine.cpp - /** * Copyright (C) 2014 MongoDB Inc. * @@ -66,8 +64,6 @@ using std::string; using std::stringstream; using std::vector; -MMAPV1Options mmapv1GlobalOptions; - namespace { #if !defined(__sun) @@ -411,4 +407,4 @@ void MMAPV1Engine::cleanShutdown() { void MMAPV1Engine::setJournalListener(JournalListener* jl) { dur::setJournalListener(jl); } -} // namespace +} // namespace mongo diff --git a/src/mongo/db/storage/mmap_v1/mmap_v1_options.cpp b/src/mongo/db/storage/mmap_v1/mmap_v1_options.cpp new file mode 100644 index 00000000000..87986746d93 --- /dev/null +++ b/src/mongo/db/storage/mmap_v1/mmap_v1_options.cpp @@ -0,0 +1,31 @@ +/** + * Copyright (C) 2017 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/db/storage/mmap_v1/mmap_v1_options.h" + +mongo::MMAPV1Options mongo::mmapv1GlobalOptions; |