summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSpencer Jackson <spencer.jackson@mongodb.com>2016-08-10 14:39:34 -0400
committerSpencer Jackson <spencer.jackson@mongodb.com>2016-08-10 14:39:34 -0400
commitf6bb7b0a3bff0495db6be1e04ff72d95862cbb6f (patch)
treef8b9cc8250552dc7d2602451c7f84e64ba84d25e
parentdf2dacb8a92ac0a5f42b7e40a848c8074940ef2d (diff)
downloadmongo-f6bb7b0a3bff0495db6be1e04ff72d95862cbb6f.tar.gz
Revert "SERVER-22826 Support X509 Authorization"
This reverts commit d930f4832631eca7092ada4328d780f2b8d19d31.
-rw-r--r--jstests/auth/role_management_commands_lib.js21
-rw-r--r--src/mongo/db/auth/SConscript17
-rw-r--r--src/mongo/db/auth/authorization_manager.cpp16
-rw-r--r--src/mongo/db/auth/authorization_manager.h45
-rw-r--r--src/mongo/db/auth/authorization_manager_test.cpp63
-rw-r--r--src/mongo/db/auth/authz_manager_external_state.cpp12
-rw-r--r--src/mongo/db/auth/authz_manager_external_state.h75
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.cpp81
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_local.h10
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_s.cpp211
-rw-r--r--src/mongo/db/auth/authz_manager_external_state_s.h8
-rw-r--r--src/mongo/db/auth/privilege_format.h42
-rw-r--r--src/mongo/db/auth/sasl_authentication_session.cpp1
-rw-r--r--src/mongo/db/auth/user_management_commands_parser.cpp18
-rw-r--r--src/mongo/db/auth/user_management_commands_parser.h6
-rw-r--r--src/mongo/db/commands/authentication_commands.cpp2
-rw-r--r--src/mongo/db/commands/user_management_commands.cpp91
-rw-r--r--src/mongo/transport/service_entry_point_test_suite.cpp6
-rw-r--r--src/mongo/transport/service_entry_point_test_suite.h3
-rw-r--r--src/mongo/transport/session.cpp5
-rw-r--r--src/mongo/transport/session.h7
-rw-r--r--src/mongo/transport/transport_layer.h6
-rw-r--r--src/mongo/transport/transport_layer_legacy.cpp14
-rw-r--r--src/mongo/transport/transport_layer_legacy.h6
-rw-r--r--src/mongo/transport/transport_layer_manager.cpp5
-rw-r--r--src/mongo/transport/transport_layer_manager.h2
-rw-r--r--src/mongo/transport/transport_layer_mock.cpp17
-rw-r--r--src/mongo/transport/transport_layer_mock.h10
-rw-r--r--src/mongo/util/net/SConscript1
-rw-r--r--src/mongo/util/net/abstract_message_port.h9
-rw-r--r--src/mongo/util/net/asio_message_port.cpp29
-rw-r--r--src/mongo/util/net/asio_message_port.h6
-rw-r--r--src/mongo/util/net/message_port.cpp13
-rw-r--r--src/mongo/util/net/message_port.h6
-rw-r--r--src/mongo/util/net/message_port_mock.cpp8
-rw-r--r--src/mongo/util/net/message_port_mock.h5
-rw-r--r--src/mongo/util/net/sock.cpp4
-rw-r--r--src/mongo/util/net/sock.h3
-rw-r--r--src/mongo/util/net/ssl_manager.cpp148
-rw-r--r--src/mongo/util/net/ssl_manager.h26
-rw-r--r--src/mongo/util/net/ssl_types.h50
41 files changed, 236 insertions, 872 deletions
diff --git a/jstests/auth/role_management_commands_lib.js b/jstests/auth/role_management_commands_lib.js
index 4da8d4bac49..e1ff7860950 100644
--- a/jstests/auth/role_management_commands_lib.js
+++ b/jstests/auth/role_management_commands_lib.js
@@ -278,27 +278,6 @@ function runAllRoleManagementCommandsTests(conn, writeConcern) {
res = testUserAdmin.runCommand({rolesInfo: 1, showBuiltinRoles: 1});
assert.eq(10, res.roles.length);
-
- res = testUserAdmin.runCommand({rolesInfo: "testRole1", showPrivileges: 'asUserFragment'});
- assert(res.userFragment);
- assert.eq(1, res.userFragment.roles.length);
- assert.eq([{role: "testRole1", db: "test"}], res.userFragment.roles);
- assert.eq(2, res.userFragment.inheritedRoles.length);
- assert.contains({role: "testRole1", db: "test"}, res.userFragment.inheritedRoles);
- assert.contains({role: "read", db: "test"}, res.userFragment.inheritedRoles);
- assert.gt(res.userFragment.inheritedPrivileges.length, 0);
-
- res = testUserAdmin.runCommand(
- {rolesInfo: ['testRole1', 'testRole2'], showPrivileges: 'asUserFragment'});
- assert(res.userFragment);
- assert.eq(2, res.userFragment.roles.length);
- assert.contains({role: "testRole1", db: "test"}, res.userFragment.roles);
- assert.contains({role: "testRole2", db: "test"}, res.userFragment.roles);
- assert.eq(3, res.userFragment.inheritedRoles.length);
- assert.contains({role: "testRole1", db: "test"}, res.userFragment.inheritedRoles);
- assert.contains({role: "testRole2", db: "test"}, res.userFragment.inheritedRoles);
- assert.contains({role: "read", db: "test"}, res.userFragment.inheritedRoles);
- assert.gt(res.userFragment.inheritedPrivileges.length, 0);
})();
(function testDropRole() {
diff --git a/src/mongo/db/auth/SConscript b/src/mongo/db/auth/SConscript
index 555d21845ea..93a2091e343 100644
--- a/src/mongo/db/auth/SConscript
+++ b/src/mongo/db/auth/SConscript
@@ -10,12 +10,6 @@ generateActionTypes = env.Command(
action='$PYTHON $SOURCES $TARGETS')
env.Alias('generated-sources', generateActionTypes)
-env.Library('auth_rolename', ['role_name.cpp'],
- LIBDEPS=[
- '$BUILD_DIR/mongo/base',
- ]
-)
-
# Just the data structures used
env.Library('authcore', ['action_set.cpp',
'action_type.cpp',
@@ -30,14 +24,14 @@ env.Library('authcore', ['action_set.cpp',
'resource_pattern.cpp',
'role_graph.cpp',
'role_graph_update.cpp',
+ 'role_name.cpp',
'role_graph_builtin_roles.cpp',
'user.cpp',
'user_document_parser.cpp',
'user_management_commands_parser.cpp',
'user_name.cpp',
'user_set.cpp'],
- LIBDEPS=['auth_rolename',
- 'sasl_options',
+ LIBDEPS=['sasl_options',
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/bson/mutable/mutable_bson',
'$BUILD_DIR/mongo/bson/util/bson_extract',
@@ -180,11 +174,6 @@ env.CppUnitTest('user_document_parser_test', 'user_document_parser_test.cpp',
env.CppUnitTest('user_set_test', 'user_set_test.cpp',
LIBDEPS=['authcore', 'authmocks', 'saslauth'])
env.CppUnitTest('authorization_manager_test', 'authorization_manager_test.cpp',
- LIBDEPS=[
- '$BUILD_DIR/mongo/transport/transport_layer_common',
- '$BUILD_DIR/mongo/transport/transport_layer_mock',
- 'authcore',
- 'authmocks',
- 'saslauth'])
+ LIBDEPS=['authcore', 'authmocks', 'saslauth'])
env.CppUnitTest('authorization_session_test', 'authorization_session_test.cpp',
LIBDEPS=['authcore', 'authmocks', 'saslauth'])
diff --git a/src/mongo/db/auth/authorization_manager.cpp b/src/mongo/db/auth/authorization_manager.cpp
index 8f404e7ed8c..131eeda34c6 100644
--- a/src/mongo/db/auth/authorization_manager.cpp
+++ b/src/mongo/db/auth/authorization_manager.cpp
@@ -422,26 +422,18 @@ Status AuthorizationManager::getUserDescription(OperationContext* txn,
Status AuthorizationManager::getRoleDescription(OperationContext* txn,
const RoleName& roleName,
- PrivilegeFormat privileges,
+ bool showPrivileges,
BSONObj* result) {
- return _externalState->getRoleDescription(txn, roleName, privileges, result);
+ return _externalState->getRoleDescription(txn, roleName, showPrivileges, result);
}
-Status AuthorizationManager::getRolesDescription(OperationContext* txn,
- const std::vector<RoleName>& roleName,
- PrivilegeFormat privileges,
- BSONObj* result) {
- return _externalState->getRolesDescription(txn, roleName, privileges, result);
-}
-
-
Status AuthorizationManager::getRoleDescriptionsForDB(OperationContext* txn,
const std::string dbname,
- PrivilegeFormat privileges,
+ bool showPrivileges,
bool showBuiltinRoles,
vector<BSONObj>* result) {
return _externalState->getRoleDescriptionsForDB(
- txn, dbname, privileges, showBuiltinRoles, result);
+ txn, dbname, showPrivileges, showBuiltinRoles, result);
}
Status AuthorizationManager::acquireUser(OperationContext* txn,
diff --git a/src/mongo/db/auth/authorization_manager.h b/src/mongo/db/auth/authorization_manager.h
index b12abccad40..43b1741841b 100644
--- a/src/mongo/db/auth/authorization_manager.h
+++ b/src/mongo/db/auth/authorization_manager.h
@@ -36,7 +36,6 @@
#include "mongo/bson/mutable/element.h"
#include "mongo/bson/oid.h"
#include "mongo/db/auth/action_set.h"
-#include "mongo/db/auth/privilege_format.h"
#include "mongo/db/auth/resource_pattern.h"
#include "mongo/db/auth/role_graph.h"
#include "mongo/db/auth/user.h"
@@ -220,32 +219,50 @@ public:
ActionSet getActionsForOldStyleUser(const std::string& dbname, bool readOnly) const;
/**
- * Delegates method call to the underlying AuthzManagerExternalState.
+ * Writes into "result" a document describing the named user and returns Status::OK(). The
+ * description includes the user credentials and customData, if present, the user's role
+ * membership and delegation information, a full list of the user's privileges, and a full
+ * list of the user's roles, including those roles held implicitly through other roles
+ * (indirect roles). In the event that some of this information is inconsistent, the
+ * document will contain a "warnings" array, with std::string messages describing
+ * inconsistencies.
+ *
+ * If the user does not exist, returns ErrorCodes::UserNotFound.
*/
Status getUserDescription(OperationContext* txn, const UserName& userName, BSONObj* result);
/**
- * Delegates method call to the underlying AuthzManagerExternalState.
+ * Writes into "result" a document describing the named role and returns Status::OK(). The
+ * description includes the roles in which the named role has membership and a full list of
+ * the roles of which the named role is a member, including those roles memberships held
+ * implicitly through other roles (indirect roles). If "showPrivileges" is true, then the
+ * description documents will also include a full list of the role's privileges.
+ * In the event that some of this information is inconsistent, the document will contain a
+ * "warnings" array, with std::string messages describing inconsistencies.
+ *
+ * If the role does not exist, returns ErrorCodes::RoleNotFound.
*/
Status getRoleDescription(OperationContext* txn,
const RoleName& roleName,
- PrivilegeFormat privilegeFormat,
+ bool showPrivileges,
BSONObj* result);
/**
- * Delegates method call to the underlying AuthzManagerExternalState.
- */
- Status getRolesDescription(OperationContext* txn,
- const std::vector<RoleName>& roleName,
- PrivilegeFormat privilegeFormat,
- BSONObj* result);
-
- /**
- * Delegates method call to the underlying AuthzManagerExternalState.
+ * Writes into "result" documents describing the roles that are defined on the given
+ * database. Each role description document includes the other roles in which the role has
+ * membership and a full list of the roles of which the named role is a member,
+ * including those roles memberships held implicitly through other roles (indirect roles).
+ * If showPrivileges is true, then the description documents will also include a full list
+ * of the role's privileges. If showBuiltinRoles is true, then the result array will
+ * contain description documents for all the builtin roles for the given database, if it
+ * is false the result will just include user defined roles.
+ * In the event that some of the information in a given role description is inconsistent,
+ * the document will contain a "warnings" array, with std::string messages describing
+ * inconsistencies.
*/
Status getRoleDescriptionsForDB(OperationContext* txn,
const std::string dbname,
- PrivilegeFormat privilegeFormat,
+ bool showPrivileges,
bool showBuiltinRoles,
std::vector<BSONObj>* result);
diff --git a/src/mongo/db/auth/authorization_manager_test.cpp b/src/mongo/db/auth/authorization_manager_test.cpp
index 56afbd26d40..cd2b83fa6b1 100644
--- a/src/mongo/db/auth/authorization_manager_test.cpp
+++ b/src/mongo/db/auth/authorization_manager_test.cpp
@@ -41,13 +41,9 @@
#include "mongo/db/jsobj.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context_noop.h"
-#include "mongo/db/service_context_noop.h"
#include "mongo/stdx/memory.h"
-#include "mongo/transport/session.h"
-#include "mongo/transport/transport_layer_mock.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/map_util.h"
-#include "mongo/util/net/message_port.h"
#define ASSERT_NULL(EXPR) ASSERT_FALSE(EXPR)
#define ASSERT_NON_NULL(EXPR) ASSERT_TRUE(EXPR)
@@ -241,65 +237,6 @@ TEST_F(AuthorizationManagerTest, testAcquireV2User) {
authzManager->releaseUser(v2cluster);
}
-TEST_F(AuthorizationManagerTest, testLocalX509Authorization) {
- ServiceContextNoop serviceContext;
- transport::TransportLayerMock transportLayer{};
- transport::Session* session = transportLayer.createSession();
- transportLayer.setX509PeerInfo(
- *session,
- SSLPeerInfo("CN=mongodb.com", {RoleName("read", "test"), RoleName("readWrite", "test")}));
- ServiceContext::UniqueClient client = serviceContext.makeClient("testClient", session);
- ServiceContext::UniqueOperationContext txn = client->makeOperationContext();
-
- User* x509User;
- ASSERT_OK(
- authzManager->acquireUser(txn.get(), UserName("CN=mongodb.com", "$external"), &x509User));
- ASSERT(x509User->isValid());
-
- RoleNameIterator roles = x509User->getRoles();
- ASSERT_EQUALS(RoleName("read", "test"), roles.next());
- ASSERT_EQUALS(RoleName("readWrite", "test"), roles.next());
- ASSERT_FALSE(roles.more());
-
-
- const User::ResourcePrivilegeMap& privileges = x509User->getPrivileges();
- ASSERT_FALSE(privileges.empty());
- auto privilegeIt = privileges.find(ResourcePattern::forDatabaseName("test"));
- ASSERT(privilegeIt != privileges.end());
- ASSERT(privilegeIt->second.includesAction(ActionType::insert));
-
-
- authzManager->releaseUser(x509User);
-}
-
-TEST_F(AuthorizationManagerTest, testLocalX509AuthorizationInvalidUser) {
- ServiceContextNoop serviceContext;
- transport::TransportLayerMock transportLayer{};
- transport::Session* session = transportLayer.createSession();
- transportLayer.setX509PeerInfo(
- *session,
- SSLPeerInfo("CN=mongodb.com", {RoleName("read", "test"), RoleName("write", "test")}));
- ServiceContext::UniqueClient client = serviceContext.makeClient("testClient", session);
- ServiceContext::UniqueOperationContext txn = client->makeOperationContext();
-
- User* x509User;
- ASSERT_NOT_OK(
- authzManager->acquireUser(txn.get(), UserName("CN=10gen.com", "$external"), &x509User));
-}
-
-TEST_F(AuthorizationManagerTest, testLocalX509AuthenticationNoAuthorization) {
- ServiceContextNoop serviceContext;
- transport::TransportLayerMock transportLayer{};
- transport::Session* session = transportLayer.createSession();
- transportLayer.setX509PeerInfo(*session, {});
- ServiceContext::UniqueClient client = serviceContext.makeClient("testClient", session);
- ServiceContext::UniqueOperationContext txn = client->makeOperationContext();
-
- User* x509User;
- ASSERT_NOT_OK(
- authzManager->acquireUser(txn.get(), UserName("CN=mongodb.com", "$external"), &x509User));
-}
-
/**
* An implementation of AuthzManagerExternalStateMock that overrides the getUserDescription method
* to return the user document unmodified from how it was inserted. When using this insert user
diff --git a/src/mongo/db/auth/authz_manager_external_state.cpp b/src/mongo/db/auth/authz_manager_external_state.cpp
index ed5f0fe6bfd..fae54cbf5e9 100644
--- a/src/mongo/db/auth/authz_manager_external_state.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state.cpp
@@ -29,9 +29,6 @@
#include "mongo/platform/basic.h"
#include "mongo/db/auth/authz_manager_external_state.h"
-#include "mongo/db/auth/user_name.h"
-#include "mongo/db/operation_context.h"
-#include "mongo/util/net/ssl_types.h"
namespace mongo {
@@ -40,13 +37,4 @@ stdx::function<std::unique_ptr<AuthzManagerExternalState>()> AuthzManagerExterna
AuthzManagerExternalState::AuthzManagerExternalState() = default;
AuthzManagerExternalState::~AuthzManagerExternalState() = default;
-bool AuthzManagerExternalState::shouldUseRolesFromConnection(OperationContext* txn,
- const UserName& userName) {
- return txn && txn->getClient() && txn->getClient()->session() &&
- txn->getClient()->session()->getX509PeerInfo().subjectName == userName.getUser() &&
- userName.getDB() == "$external" &&
- !txn->getClient()->session()->getX509PeerInfo().roles.empty();
-}
-
-
} // namespace mongo
diff --git a/src/mongo/db/auth/authz_manager_external_state.h b/src/mongo/db/auth/authz_manager_external_state.h
index f3d2cc721c6..78aac5ea832 100644
--- a/src/mongo/db/auth/authz_manager_external_state.h
+++ b/src/mongo/db/auth/authz_manager_external_state.h
@@ -34,9 +34,7 @@
#include "mongo/base/disallow_copying.h"
#include "mongo/base/status.h"
-#include "mongo/db/auth/privilege_format.h"
#include "mongo/db/auth/role_name.h"
-#include "mongo/db/auth/user.h"
#include "mongo/db/auth/user_name.h"
#include "mongo/db/jsobj.h"
#include "mongo/stdx/functional.h"
@@ -82,12 +80,11 @@ public:
/**
* Writes into "result" a document describing the named user and returns Status::OK(). The
- * description includes the user credentials and customData, if present, the user's role
- * membership and delegation information, a full list of the user's privileges, and a full
- * list of the user's roles, including those roles held implicitly through other roles
- * (indirect roles). In the event that some of this information is inconsistent, the
- * document will contain a "warnings" array, with std::string messages describing
- * inconsistencies.
+ * description includes the user credentials, if present, the user's role membership and
+ * delegation information, a full list of the user's privileges, and a full list of the
+ * user's roles, including those roles held implicitly through other roles (indirect roles).
+ * In the event that some of this information is inconsistent, the document will contain a
+ * "warnings" array, with std::string messages describing inconsistencies.
*
* If the user does not exist, returns ErrorCodes::UserNotFound.
*/
@@ -96,57 +93,37 @@ public:
BSONObj* result) = 0;
/**
- * Writes into "result" a document describing the named role and returns Status::OK(). If
- * showPrivileges is kOmit or kShowPrivileges, the description includes the roles which the
- * named role is a member of, including those memberships held implicitly through other roles
- * (indirect roles). If "showPrivileges" is kShowPrivileges, then the description documents
- * will also include a full list of the role's privileges. If "showPrivileges" is
- * kShowAsUserFragment, then the description returned will take the form of a partial user
- * document, describing a hypothetical user which possesses the provided and implicit roles,
- * and all inherited privileges. In the event that some of this information is inconsistent,
- * the document will contain a "warnings" array, with std::string messages describing
- * inconsistencies.
+ * Writes into "result" a document describing the named role and returns Status::OK(). The
+ * description includes the roles in which the named role has membership and a full list of
+ * the roles of which the named role is a member, including those roles memberships held
+ * implicitly through other roles (indirect roles). If "showPrivileges" is true, then the
+ * description documents will also include a full list of the role's privileges.
+ * In the event that some of this information is inconsistent, the document will contain a
+ * "warnings" array, with std::string messages describing inconsistencies.
*
* If the role does not exist, returns ErrorCodes::RoleNotFound.
*/
virtual Status getRoleDescription(OperationContext* txn,
const RoleName& roleName,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
BSONObj* result) = 0;
/**
- * Writes into "result" a document describing the named role is and returns Status::OK(). If
- * showPrivileges is kOmit or kShowPrivileges, the description includes the roles which the
- * named roles are a member of, including those memberships held implicitly through other roles
- * (indirect roles). If "showPrivileges" is kShowPrivileges, then the description documents
- * will also include a full list of the roles' privileges. If "showPrivileges" is
- * kShowAsUserFragment, then the description returned will take the form of a partial user
- * document, describing a hypothetical user which possesses the provided and implicit roles,
- * and all inherited privileges. In the event that some of this information is inconsistent,
+ * Writes into "result" documents describing the roles that are defined on the given
+ * database. Each role description document includes the other roles in which the role has
+ * membership and a full list of the roles of which the named role is a member,
+ * including those roles memberships held implicitly through other roles (indirect roles).
+ * If showPrivileges is true, then the description documents will also include a full list
+ * of the role's privileges. If showBuiltinRoles is true, then the result array will
+ * contain description documents for all the builtin roles for the given database, if it
+ * is false the result will just include user defined roles.
+ * In the event that some of the information in a given role description is inconsistent,
* the document will contain a "warnings" array, with std::string messages describing
* inconsistencies.
*/
-
- virtual Status getRolesDescription(OperationContext* txn,
- const std::vector<RoleName>& roles,
- PrivilegeFormat showPrivileges,
- BSONObj* result) = 0;
-
- /**
- * Writes into "result" documents describing the roles that are defined on the given
- * database. If showPrivileges is kOmit or kShowPrivileges, then a vector of BSON documents are
- * returned, where each document includes the other roles a particular role is a
- * member of, including those role memberships held implicitly through other roles
- * (indirect roles). If showPrivileges is kShowPrivileges, then the description documents
- * will also include a full list of the roles' privileges. If showBuiltinRoles is true, then
- * the result array will contain description documents for all the builtin roles for the given
- * database, if it is false the result will just include user defined roles. In the event that
- * some of the information in a given role description is inconsistent, the document will
- * contain a "warnings" array, with std::string messages describing inconsistencies.
- */
virtual Status getRoleDescriptionsForDB(OperationContext* txn,
const std::string dbname,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
bool showBuiltinRoles,
std::vector<BSONObj>* result) = 0;
@@ -164,12 +141,6 @@ public:
protected:
AuthzManagerExternalState(); // This class should never be instantiated directly.
-
- /**
- * Returns true if roles for this user were provided by the client, and can be obtained from
- * the connection.
- */
- bool shouldUseRolesFromConnection(OperationContext* txn, const UserName& username);
};
} // namespace mongo
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 d4f814baae5..82bd5c29440 100644
--- a/src/mongo/db/auth/authz_manager_external_state_local.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_local.cpp
@@ -152,25 +152,9 @@ bool AuthzManagerExternalStateLocal::hasAnyPrivilegeDocuments(OperationContext*
Status AuthzManagerExternalStateLocal::getUserDescription(OperationContext* txn,
const UserName& userName,
BSONObj* result) {
- Status status = Status::OK();
-
- if (!shouldUseRolesFromConnection(txn, userName)) {
- status = _getUserDocument(txn, userName, result);
- if (!status.isOK())
- return status;
- } else {
- // We are able to artifically construct the external user from the request
- BSONArrayBuilder userRoles;
- for (const RoleName& role : txn->getClient()->session()->getX509PeerInfo().roles) {
- userRoles << BSON("role" << role.getRole() << "db" << role.getDB());
- }
- *result = BSON("_id" << userName.getUser() << "user" << userName.getUser() << "db"
- << userName.getDB()
- << "credentials"
- << BSON("external" << true)
- << "roles"
- << userRoles.arr());
- }
+ Status status = _getUserDocument(txn, userName, result);
+ if (!status.isOK())
+ return status;
BSONElement directRolesElement;
status = bsonExtractTypedField(*result, "roles", Array, &directRolesElement);
@@ -257,55 +241,14 @@ Status AuthzManagerExternalStateLocal::_getUserDocument(OperationContext* txn,
Status AuthzManagerExternalStateLocal::getRoleDescription(OperationContext* txn,
const RoleName& roleName,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
BSONObj* result) {
- if (showPrivileges == PrivilegeFormat::kShowAsUserFragment) {
- mutablebson::Document resultDoc;
- mutablebson::Element rolesElement = resultDoc.makeElementArray("roles");
- fassert(40271, resultDoc.root().pushBack(rolesElement));
- addRoleNameObjectsToArrayElement(
- rolesElement, makeRoleNameIteratorForContainer(std::vector<RoleName>{roleName}));
- resolveUserRoles(&resultDoc, {roleName});
- *result = resultDoc.getObject();
- return Status::OK();
- }
stdx::lock_guard<stdx::mutex> lk(_roleGraphMutex);
return _getRoleDescription_inlock(roleName, showPrivileges, result);
}
-Status AuthzManagerExternalStateLocal::getRolesDescription(OperationContext* txn,
- const std::vector<RoleName>& roles,
- PrivilegeFormat showPrivileges,
- BSONObj* result) {
- if (showPrivileges == PrivilegeFormat::kShowAsUserFragment) {
- mutablebson::Document resultDoc;
- mutablebson::Element rolesElement = resultDoc.makeElementArray("roles");
- fassert(40272, resultDoc.root().pushBack(rolesElement));
- addRoleNameObjectsToArrayElement(rolesElement, makeRoleNameIteratorForContainer(roles));
- resolveUserRoles(&resultDoc, roles);
- *result = resultDoc.getObject();
- return Status::OK();
- }
-
- stdx::lock_guard<stdx::mutex> lk(_roleGraphMutex);
- BSONArrayBuilder resultBuilder;
- for (const RoleName& role : roles) {
- BSONObj roleDoc;
- Status status = _getRoleDescription_inlock(role, showPrivileges, &roleDoc);
- if (!status.isOK()) {
- if (status.code() == ErrorCodes::RoleNotFound) {
- continue;
- }
- return status;
- }
- resultBuilder << roleDoc;
- }
- *result = resultBuilder.arr();
- return Status::OK();
-}
-
Status AuthzManagerExternalStateLocal::_getRoleDescription_inlock(const RoleName& roleName,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
BSONObj* result) {
if (!_roleGraph.roleExists(roleName))
return Status(ErrorCodes::RoleNotFound, "No role named " + roleName.toString());
@@ -325,7 +268,7 @@ Status AuthzManagerExternalStateLocal::_getRoleDescription_inlock(const RoleName
mutablebson::Element privilegesElement = resultDoc.makeElementArray("privileges");
mutablebson::Element inheritedPrivilegesElement =
resultDoc.makeElementArray("inheritedPrivileges");
- if (showPrivileges == PrivilegeFormat::kShowSeparate) {
+ if (showPrivileges) {
fassert(17166, resultDoc.root().pushBack(privilegesElement));
}
mutablebson::Element warningsElement = resultDoc.makeElementArray("warnings");
@@ -334,7 +277,7 @@ Status AuthzManagerExternalStateLocal::_getRoleDescription_inlock(const RoleName
if (_roleGraphState == roleGraphStateConsistent) {
addRoleNameObjectsToArrayElement(inheritedRolesElement,
_roleGraph.getIndirectSubordinates(roleName));
- if (showPrivileges == PrivilegeFormat::kShowSeparate) {
+ if (showPrivileges) {
addPrivilegeObjectsOrWarningsToArrayElement(
privilegesElement, warningsElement, _roleGraph.getDirectPrivileges(roleName));
@@ -343,7 +286,7 @@ Status AuthzManagerExternalStateLocal::_getRoleDescription_inlock(const RoleName
fassert(17323, resultDoc.root().pushBack(inheritedPrivilegesElement));
}
- } else if (showPrivileges == PrivilegeFormat::kShowSeparate) {
+ } else if (showPrivileges) {
warningsElement.appendString(
"", "Role graph state inconsistent; only direct privileges available.");
addPrivilegeObjectsOrWarningsToArrayElement(
@@ -358,15 +301,11 @@ Status AuthzManagerExternalStateLocal::_getRoleDescription_inlock(const RoleName
Status AuthzManagerExternalStateLocal::getRoleDescriptionsForDB(OperationContext* txn,
const std::string dbname,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
bool showBuiltinRoles,
vector<BSONObj>* result) {
- if (showPrivileges == PrivilegeFormat::kShowAsUserFragment) {
- return Status(ErrorCodes::IllegalOperation,
- "Cannot get user fragment for all roles in a database");
- }
-
stdx::lock_guard<stdx::mutex> lk(_roleGraphMutex);
+
for (RoleNameIterator it = _roleGraph.getRolesForDatabase(dbname); it.more(); it.next()) {
if (!showBuiltinRoles && _roleGraph.isBuiltinRole(it.get())) {
continue;
diff --git a/src/mongo/db/auth/authz_manager_external_state_local.h b/src/mongo/db/auth/authz_manager_external_state_local.h
index e1e2cbdc1e2..c9646686b03 100644
--- a/src/mongo/db/auth/authz_manager_external_state_local.h
+++ b/src/mongo/db/auth/authz_manager_external_state_local.h
@@ -63,15 +63,11 @@ public:
BSONObj* result);
virtual Status getRoleDescription(OperationContext* txn,
const RoleName& roleName,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
BSONObj* result);
- virtual Status getRolesDescription(OperationContext* txn,
- const std::vector<RoleName>& roles,
- PrivilegeFormat showPrivileges,
- BSONObj* result);
virtual Status getRoleDescriptionsForDB(OperationContext* txn,
const std::string dbname,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
bool showBuiltinRoles,
std::vector<BSONObj>* result);
@@ -135,7 +131,7 @@ private:
Status _getUserDocument(OperationContext* txn, const UserName& userName, BSONObj* result);
Status _getRoleDescription_inlock(const RoleName& roleName,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
BSONObj* result);
/**
* Eventually consistent, in-memory representation of all roles in the system (both
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 06831cf9a58..500cc85c70a 100644
--- a/src/mongo/db/auth/authz_manager_external_state_s.cpp
+++ b/src/mongo/db/auth/authz_manager_external_state_s.cpp
@@ -38,47 +38,16 @@
#include "mongo/db/auth/authorization_manager.h"
#include "mongo/db/auth/authorization_manager_global.h"
#include "mongo/db/auth/authz_session_external_state_s.h"
-#include "mongo/db/auth/user_document_parser.h"
-#include "mongo/db/auth/user_management_commands_parser.h"
#include "mongo/db/auth/user_name.h"
#include "mongo/db/jsobj.h"
-#include "mongo/db/operation_context.h"
#include "mongo/rpc/get_status_from_command_result.h"
#include "mongo/s/catalog/sharding_catalog_client.h"
#include "mongo/s/grid.h"
#include "mongo/stdx/memory.h"
#include "mongo/util/mongoutils/str.h"
-#include "mongo/util/stringutils.h"
namespace mongo {
-namespace {
-
-/**
- * Returns the top level field which is expected to be returned by rolesInfo.
- */
-std::string rolesFieldName(PrivilegeFormat showPrivileges) {
- if (showPrivileges == PrivilegeFormat::kShowAsUserFragment) {
- return "userFragment";
- }
- return "roles";
-}
-
-/**
- * Attches a string representation of a PrivilegeFormat to the provided BSONObjBuilder.
- */
-void addShowPrivilegesToBuilder(BSONObjBuilder* builder, PrivilegeFormat showPrivileges) {
- if (showPrivileges == PrivilegeFormat::kShowSeparate) {
- builder->append("showPrivileges", true);
- } else if (showPrivileges == PrivilegeFormat::kShowAsUserFragment) {
- builder->append("showPrivileges", "asUserfragment");
- } else {
- builder->append("showPrivileges", false);
- }
-}
-
-} // namespace
-
AuthzManagerExternalStateMongos::AuthzManagerExternalStateMongos() = default;
AuthzManagerExternalStateMongos::~AuthzManagerExternalStateMongos() = default;
@@ -119,111 +88,59 @@ Status AuthzManagerExternalStateMongos::getStoredAuthorizationVersion(OperationC
Status AuthzManagerExternalStateMongos::getUserDescription(OperationContext* txn,
const UserName& userName,
BSONObj* result) {
- if (!shouldUseRolesFromConnection(txn, userName)) {
- BSONObj usersInfoCmd =
- BSON("usersInfo" << BSON_ARRAY(BSON(AuthorizationManager::USER_NAME_FIELD_NAME
- << userName.getUser()
- << AuthorizationManager::USER_DB_FIELD_NAME
- << userName.getDB()))
- << "showPrivileges"
- << true
- << "showCredentials"
- << true);
- BSONObjBuilder builder;
- const bool ok = grid.catalogClient(txn)->runUserManagementReadCommand(
- txn, "admin", usersInfoCmd, &builder);
- BSONObj cmdResult = builder.obj();
- if (!ok) {
- return getStatusFromCommandResult(cmdResult);
- }
-
- std::vector<BSONElement> foundUsers = cmdResult["users"].Array();
- if (foundUsers.size() == 0) {
- return Status(ErrorCodes::UserNotFound,
- "User \"" + userName.toString() + "\" not found");
- }
-
- if (foundUsers.size() > 1) {
- return Status(ErrorCodes::UserDataInconsistent,
- str::stream() << "Found multiple users on the \"" << userName.getDB()
- << "\" database with name \""
- << userName.getUser()
- << "\"");
- }
- *result = foundUsers[0].Obj().getOwned();
- return Status::OK();
- } else {
- // Obtain privilege information from the config servers for all roles acquired from the X509
- // certificate.
- BSONArrayBuilder userRolesBuilder;
- for (const RoleName& role : txn->getClient()->session()->getX509PeerInfo().roles) {
- userRolesBuilder.append(BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
- << role.getRole()
- << AuthorizationManager::ROLE_DB_FIELD_NAME
- << role.getDB()));
- }
- BSONArray providedRoles = userRolesBuilder.arr();
-
- BSONObj rolesInfoCmd = BSON("rolesInfo" << providedRoles << "showPrivileges"
- << "asUserFragment");
-
- BSONObjBuilder cmdResultBuilder;
- const bool cmdOk = grid.catalogClient(txn)->runUserManagementReadCommand(
- txn, "admin", rolesInfoCmd, &cmdResultBuilder);
- BSONObj cmdResult = cmdResultBuilder.obj();
- if (!cmdOk || !cmdResult["userFragment"].ok()) {
- return Status(ErrorCodes::FailedToParse,
- "Unable to get resolved X509 roles from config server: " +
- getStatusFromCommandResult(cmdResult).toString());
- }
- cmdResult = cmdResult["userFragment"].Obj().getOwned();
- BSONElement userRoles = cmdResult["roles"];
- BSONElement userInheritedRoles = cmdResult["inheritedRoles"];
- BSONElement userInheritedPrivileges = cmdResult["inheritedPrivileges"];
+ BSONObj usersInfoCmd =
+ BSON("usersInfo" << BSON_ARRAY(BSON(AuthorizationManager::USER_NAME_FIELD_NAME
+ << userName.getUser()
+ << AuthorizationManager::USER_DB_FIELD_NAME
+ << userName.getDB()))
+ << "showPrivileges"
+ << true
+ << "showCredentials"
+ << true);
+ BSONObjBuilder builder;
+ const bool ok =
+ grid.catalogClient(txn)->runUserManagementReadCommand(txn, "admin", usersInfoCmd, &builder);
+ BSONObj cmdResult = builder.obj();
+ if (!ok) {
+ return getStatusFromCommandResult(cmdResult);
+ }
- if (userRoles.eoo() || userInheritedRoles.eoo() || userInheritedPrivileges.eoo() ||
- !userRoles.isABSONObj() || !userInheritedRoles.isABSONObj() ||
- !userInheritedPrivileges.isABSONObj()) {
- return Status(
- ErrorCodes::UserDataInconsistent,
- "Recieved malformed response to request for X509 roles from config server");
- }
+ std::vector<BSONElement> foundUsers = cmdResult["users"].Array();
+ if (foundUsers.size() == 0) {
+ return Status(ErrorCodes::UserNotFound, "User \"" + userName.toString() + "\" not found");
+ }
- *result = BSON("_id" << userName.getUser() << "user" << userName.getUser() << "db"
- << userName.getDB()
- << "credentials"
- << BSON("external" << true)
- << "roles"
- << BSONArray(cmdResult["roles"].Obj())
- << "inheritedRoles"
- << BSONArray(cmdResult["inheritedRoles"].Obj())
- << "inheritedPrivileges"
- << BSONArray(cmdResult["inheritedPrivileges"].Obj()));
- return Status::OK();
+ if (foundUsers.size() > 1) {
+ return Status(ErrorCodes::UserDataInconsistent,
+ str::stream() << "Found multiple users on the \"" << userName.getDB()
+ << "\" database with name \""
+ << userName.getUser()
+ << "\"");
}
+ *result = foundUsers[0].Obj().getOwned();
+ return Status::OK();
}
Status AuthzManagerExternalStateMongos::getRoleDescription(OperationContext* txn,
const RoleName& roleName,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
BSONObj* result) {
- BSONObjBuilder rolesInfoCmd;
- rolesInfoCmd.append("rolesInfo",
- BSON_ARRAY(BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
- << roleName.getRole()
- << AuthorizationManager::ROLE_DB_FIELD_NAME
- << roleName.getDB())));
- addShowPrivilegesToBuilder(&rolesInfoCmd, showPrivileges);
-
+ BSONObj rolesInfoCmd =
+ BSON("rolesInfo" << BSON_ARRAY(BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
+ << roleName.getRole()
+ << AuthorizationManager::ROLE_DB_FIELD_NAME
+ << roleName.getDB()))
+ << "showPrivileges"
+ << showPrivileges);
BSONObjBuilder builder;
- const bool ok = grid.catalogClient(txn)->runUserManagementReadCommand(
- txn, "admin", rolesInfoCmd.obj(), &builder);
+ const bool ok =
+ grid.catalogClient(txn)->runUserManagementReadCommand(txn, "admin", rolesInfoCmd, &builder);
BSONObj cmdResult = builder.obj();
if (!ok) {
return getStatusFromCommandResult(cmdResult);
}
- std::vector<BSONElement> foundRoles = cmdResult[rolesFieldName(showPrivileges)].Array();
+ std::vector<BSONElement> foundRoles = cmdResult["roles"].Array();
if (foundRoles.size() == 0) {
return Status(ErrorCodes::RoleNotFound, "Role \"" + roleName.toString() + "\" not found");
}
@@ -238,59 +155,23 @@ Status AuthzManagerExternalStateMongos::getRoleDescription(OperationContext* txn
*result = foundRoles[0].Obj().getOwned();
return Status::OK();
}
-Status AuthzManagerExternalStateMongos::getRolesDescription(OperationContext* txn,
- const std::vector<RoleName>& roles,
- PrivilegeFormat showPrivileges,
- BSONObj* result) {
- BSONArrayBuilder rolesInfoCmdArray;
-
- for (const RoleName& roleName : roles) {
- rolesInfoCmdArray << BSON(AuthorizationManager::ROLE_NAME_FIELD_NAME
- << roleName.getRole()
- << AuthorizationManager::ROLE_DB_FIELD_NAME
- << roleName.getDB());
- }
-
- BSONObjBuilder rolesInfoCmd;
- rolesInfoCmd.append("rolesInfo", rolesInfoCmdArray.arr());
- addShowPrivilegesToBuilder(&rolesInfoCmd, showPrivileges);
- BSONObjBuilder builder;
- const bool ok = grid.catalogClient(txn)->runUserManagementReadCommand(
- txn, "admin", rolesInfoCmd.obj(), &builder);
- BSONObj cmdResult = builder.obj();
- if (!ok) {
- return getStatusFromCommandResult(cmdResult);
- }
-
- std::vector<BSONElement> foundRoles = cmdResult[rolesFieldName(showPrivileges)].Array();
- if (foundRoles.size() == 0) {
- return Status(ErrorCodes::RoleNotFound, "Roles not found");
- }
-
- *result = foundRoles[0].Obj().getOwned();
-
- return Status::OK();
-}
Status AuthzManagerExternalStateMongos::getRoleDescriptionsForDB(OperationContext* txn,
const std::string dbname,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
bool showBuiltinRoles,
std::vector<BSONObj>* result) {
- BSONObjBuilder rolesInfoCmd;
- rolesInfoCmd << "rolesInfo" << 1 << "showBuiltinRoles" << showBuiltinRoles;
- addShowPrivilegesToBuilder(&rolesInfoCmd, showPrivileges);
-
+ BSONObj rolesInfoCmd =
+ BSON("rolesInfo" << 1 << "showPrivileges" << showPrivileges << "showBuiltinRoles"
+ << showBuiltinRoles);
BSONObjBuilder builder;
- const bool ok = grid.catalogClient(txn)->runUserManagementReadCommand(
- txn, dbname, rolesInfoCmd.obj(), &builder);
+ const bool ok =
+ grid.catalogClient(txn)->runUserManagementReadCommand(txn, dbname, rolesInfoCmd, &builder);
BSONObj cmdResult = builder.obj();
if (!ok) {
return getStatusFromCommandResult(cmdResult);
}
-
- for (BSONObjIterator it(cmdResult[rolesFieldName(showPrivileges)].Obj()); it.more();
- it.next()) {
+ for (BSONObjIterator it(cmdResult["roles"].Obj()); it.more(); it.next()) {
result->push_back((*it).Obj().getOwned());
}
return Status::OK();
diff --git a/src/mongo/db/auth/authz_manager_external_state_s.h b/src/mongo/db/auth/authz_manager_external_state_s.h
index 9f9c5c12d2b..bf9ca876c43 100644
--- a/src/mongo/db/auth/authz_manager_external_state_s.h
+++ b/src/mongo/db/auth/authz_manager_external_state_s.h
@@ -59,15 +59,11 @@ public:
BSONObj* result);
virtual Status getRoleDescription(OperationContext* txn,
const RoleName& roleName,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
BSONObj* result);
- virtual Status getRolesDescription(OperationContext* txn,
- const std::vector<RoleName>& roles,
- PrivilegeFormat showPrivileges,
- BSONObj* result);
virtual Status getRoleDescriptionsForDB(OperationContext* txn,
const std::string dbname,
- PrivilegeFormat showPrivileges,
+ bool showPrivileges,
bool showBuiltinRoles,
std::vector<BSONObj>* result);
diff --git a/src/mongo/db/auth/privilege_format.h b/src/mongo/db/auth/privilege_format.h
deleted file mode 100644
index 2f452a3ae84..00000000000
--- a/src/mongo/db/auth/privilege_format.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
-* Copyright (C) 2016 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
-
-
-namespace mongo {
-/**
- * How user management functions should structure the BSON representation of privileges and roles.
- */
-enum class PrivilegeFormat {
- kOmit, // Privileges should not be included in the BSON representation.
- kShowSeparate, // Privileges should be included, each as a separate entry.
- kShowAsUserFragment // Privileges and roles should all be collapsed together, and presented as
- // a fragment of a user document.
-};
-} // namespace mongo
diff --git a/src/mongo/db/auth/sasl_authentication_session.cpp b/src/mongo/db/auth/sasl_authentication_session.cpp
index fdb7f024929..c64e4be8100 100644
--- a/src/mongo/db/auth/sasl_authentication_session.cpp
+++ b/src/mongo/db/auth/sasl_authentication_session.cpp
@@ -69,7 +69,6 @@ bool isAuthorizedCommon(SaslAuthenticationSession* session,
SaslAuthenticationSession::SaslAuthenticationSession(AuthorizationSession* authzSession)
: AuthenticationSession(AuthenticationSession::SESSION_TYPE_SASL),
- _txn(nullptr),
_authzSession(authzSession),
_saslStep(0),
_conversationId(0),
diff --git a/src/mongo/db/auth/user_management_commands_parser.cpp b/src/mongo/db/auth/user_management_commands_parser.cpp
index aee95bbbdef..090ca7e0246 100644
--- a/src/mongo/db/auth/user_management_commands_parser.cpp
+++ b/src/mongo/db/auth/user_management_commands_parser.cpp
@@ -414,20 +414,10 @@ Status parseRolesInfoCommand(const BSONObj& cmdObj, StringData dbname, RolesInfo
parsedArgs->roleNames.push_back(name);
}
- BSONElement showPrivileges = cmdObj["showPrivileges"];
- if (showPrivileges.eoo()) {
- parsedArgs->privilegeFormat = PrivilegeFormat::kOmit;
- } else if (showPrivileges.isNumber() || showPrivileges.isBoolean()) {
- parsedArgs->privilegeFormat =
- showPrivileges.trueValue() ? PrivilegeFormat::kShowSeparate : PrivilegeFormat::kOmit;
- } else if (showPrivileges.type() == BSONType::String &&
- showPrivileges.String() == "asUserFragment") {
- parsedArgs->privilegeFormat = PrivilegeFormat::kShowAsUserFragment;
- } else {
- return Status(ErrorCodes::FailedToParse,
- str::stream() << "Failed to parse 'showPrivileges'. 'showPrivileges' should "
- "either be a boolean or the string 'asUserFragment', given: "
- << showPrivileges.toString());
+ status = bsonExtractBooleanFieldWithDefault(
+ cmdObj, "showPrivileges", false, &parsedArgs->showPrivileges);
+ if (!status.isOK()) {
+ return status;
}
status = bsonExtractBooleanFieldWithDefault(
diff --git a/src/mongo/db/auth/user_management_commands_parser.h b/src/mongo/db/auth/user_management_commands_parser.h
index 720c4c1d9d7..94dc3b7b2ae 100644
--- a/src/mongo/db/auth/user_management_commands_parser.h
+++ b/src/mongo/db/auth/user_management_commands_parser.h
@@ -35,7 +35,6 @@
#include "mongo/base/status.h"
#include "mongo/base/string_data.h"
#include "mongo/db/auth/privilege.h"
-#include "mongo/db/auth/privilege_format.h"
#include "mongo/db/auth/role_name.h"
#include "mongo/db/auth/user.h"
#include "mongo/db/auth/user_name.h"
@@ -115,10 +114,9 @@ Status parseUsersInfoCommand(const BSONObj& cmdObj, StringData dbname, UsersInfo
struct RolesInfoArgs {
std::vector<RoleName> roleNames;
bool allForDB;
- PrivilegeFormat privilegeFormat;
+ bool showPrivileges;
bool showBuiltinRoles;
- RolesInfoArgs()
- : allForDB(false), privilegeFormat(PrivilegeFormat::kOmit), showBuiltinRoles(false) {}
+ RolesInfoArgs() : allForDB(false), showPrivileges(false), showBuiltinRoles(false) {}
};
/**
diff --git a/src/mongo/db/commands/authentication_commands.cpp b/src/mongo/db/commands/authentication_commands.cpp
index a6a9a6f4508..e5b50fec80d 100644
--- a/src/mongo/db/commands/authentication_commands.cpp
+++ b/src/mongo/db/commands/authentication_commands.cpp
@@ -314,7 +314,7 @@ Status CmdAuthenticate::_authenticateX509(OperationContext* txn,
Client* client = Client::getCurrent();
AuthorizationSession* authorizationSession = AuthorizationSession::get(client);
- auto clientName = client->session()->getX509PeerInfo().subjectName;
+ auto clientName = client->session()->getX509SubjectName();
if (!getSSLManager()->getSSLConfiguration().hasCA) {
return Status(ErrorCodes::AuthenticationFailed,
diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp
index 2238383d960..5dc5bba8138 100644
--- a/src/mongo/db/commands/user_management_commands.cpp
+++ b/src/mongo/db/commands/user_management_commands.cpp
@@ -180,8 +180,7 @@ Status checkOkayToGrantRolesToRole(OperationContext* txn,
}
BSONObj roleToAddDoc;
- Status status =
- authzManager->getRoleDescription(txn, roleToAdd, PrivilegeFormat::kOmit, &roleToAddDoc);
+ Status status = authzManager->getRoleDescription(txn, roleToAdd, false, &roleToAddDoc);
if (status == ErrorCodes::RoleNotFound) {
return Status(ErrorCodes::RoleNotFound,
"Cannot grant nonexistent role " + roleToAdd.toString());
@@ -716,8 +715,7 @@ public:
// Role existence has to be checked after acquiring the update lock
for (size_t i = 0; i < args.roles.size(); ++i) {
BSONObj ignored;
- status = authzManager->getRoleDescription(
- txn, args.roles[i], PrivilegeFormat::kOmit, &ignored);
+ status = authzManager->getRoleDescription(txn, args.roles[i], false, &ignored);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -829,8 +827,7 @@ public:
if (args.hasRoles) {
for (size_t i = 0; i < args.roles.size(); ++i) {
BSONObj ignored;
- status = authzManager->getRoleDescription(
- txn, args.roles[i], PrivilegeFormat::kOmit, &ignored);
+ status = authzManager->getRoleDescription(txn, args.roles[i], false, &ignored);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1038,8 +1035,7 @@ public:
for (vector<RoleName>::iterator it = roles.begin(); it != roles.end(); ++it) {
RoleName& roleName = *it;
BSONObj roleDoc;
- status =
- authzManager->getRoleDescription(txn, roleName, PrivilegeFormat::kOmit, &roleDoc);
+ status = authzManager->getRoleDescription(txn, roleName, false, &roleDoc);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1113,8 +1109,7 @@ public:
for (vector<RoleName>::iterator it = roles.begin(); it != roles.end(); ++it) {
RoleName& roleName = *it;
BSONObj roleDoc;
- status =
- authzManager->getRoleDescription(txn, roleName, PrivilegeFormat::kOmit, &roleDoc);
+ status = authzManager->getRoleDescription(txn, roleName, false, &roleDoc);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1429,8 +1424,7 @@ public:
// Role existence has to be checked after acquiring the update lock
BSONObj ignored;
- status =
- authzManager->getRoleDescription(txn, args.roleName, PrivilegeFormat::kOmit, &ignored);
+ status = authzManager->getRoleDescription(txn, args.roleName, false, &ignored);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1489,7 +1483,6 @@ public:
int options,
string& errmsg,
BSONObjBuilder& result) {
-
RoleName roleName;
PrivilegeVector privilegesToAdd;
Status status = auth::parseAndValidateRolePrivilegeManipulationCommands(
@@ -1521,8 +1514,7 @@ public:
}
BSONObj roleDoc;
- status = authzManager->getRoleDescription(
- txn, roleName, PrivilegeFormat::kShowSeparate, &roleDoc);
+ status = authzManager->getRoleDescription(txn, roleName, true, &roleDoc);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1624,8 +1616,7 @@ public:
}
BSONObj roleDoc;
- status = authzManager->getRoleDescription(
- txn, roleName, PrivilegeFormat::kShowSeparate, &roleDoc);
+ status = authzManager->getRoleDescription(txn, roleName, true, &roleDoc);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1737,7 +1728,7 @@ public:
// Role existence has to be checked after acquiring the update lock
BSONObj roleDoc;
- status = authzManager->getRoleDescription(txn, roleName, PrivilegeFormat::kOmit, &roleDoc);
+ status = authzManager->getRoleDescription(txn, roleName, false, &roleDoc);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1827,7 +1818,7 @@ public:
}
BSONObj roleDoc;
- status = authzManager->getRoleDescription(txn, roleName, PrivilegeFormat::kOmit, &roleDoc);
+ status = authzManager->getRoleDescription(txn, roleName, false, &roleDoc);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -1914,7 +1905,7 @@ public:
}
BSONObj roleDoc;
- status = authzManager->getRoleDescription(txn, roleName, PrivilegeFormat::kOmit, &roleDoc);
+ status = authzManager->getRoleDescription(txn, roleName, false, &roleDoc);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
@@ -2133,29 +2124,6 @@ public:
} cmdDropAllRolesFromDatabase;
-/**
- * Provides information about one or more roles, the indirect roles they are members of, and
- * optionally the privileges they provide.
- *
- * This command accepts the following arguments:
- * rolesInfo:
- * (String) Returns information about a single role on the current database.
- * {role: (String), db: (String)} Returns information about a specified role, on a specific db
- * (BooleanTrue) Returns information about all roles in this database
- * [ //Zero or more of
- * {role: (String), db: (String) ] Returns information about all specified roles
- *
- * showBuiltinRoles:
- * (Boolean) If true, and rolesInfo == (BooleanTrue), include built-in roles from the database
- *
- * showPrivileges:
- * (BooleanFalse) Do not show information about privileges
- * (BooleanTrue) Attach all privileges inherited from roles to role descriptions
- * "asUserFragment" Render results as a partial user document as-if a user existed which possessed
- * these roles. This format may change over time with changes to the auth
- * schema.
- */
-
class CmdRolesInfo : public Command {
public:
virtual bool slaveOk() const {
@@ -2199,40 +2167,33 @@ public:
return appendCommandStatus(result, status);
}
+ BSONArrayBuilder rolesArrayBuilder;
if (args.allForDB) {
std::vector<BSONObj> rolesDocs;
status = getGlobalAuthorizationManager()->getRoleDescriptionsForDB(
- txn, dbname, args.privilegeFormat, args.showBuiltinRoles, &rolesDocs);
+ txn, dbname, args.showPrivileges, args.showBuiltinRoles, &rolesDocs);
if (!status.isOK()) {
return appendCommandStatus(result, status);
}
- if (args.privilegeFormat == PrivilegeFormat::kShowAsUserFragment) {
- return appendCommandStatus(
- result,
- Status(ErrorCodes::IllegalOperation,
- "Cannot get user fragment for all roles in a database"));
- }
- BSONArrayBuilder rolesArrayBuilder;
for (size_t i = 0; i < rolesDocs.size(); ++i) {
rolesArrayBuilder.append(rolesDocs[i]);
}
- result.append("roles", rolesArrayBuilder.arr());
- }
-
- BSONObj roleDetails;
- status = getGlobalAuthorizationManager()->getRolesDescription(
- txn, args.roleNames, args.privilegeFormat, &roleDetails);
- if (!status.isOK()) {
- return appendCommandStatus(result, status);
- }
-
- if (args.privilegeFormat == PrivilegeFormat::kShowAsUserFragment) {
- result.append("userFragment", roleDetails);
} else {
- result.append("roles", BSONArray(roleDetails));
+ for (size_t i = 0; i < args.roleNames.size(); ++i) {
+ BSONObj roleDetails;
+ status = getGlobalAuthorizationManager()->getRoleDescription(
+ txn, args.roleNames[i], args.showPrivileges, &roleDetails);
+ if (status.code() == ErrorCodes::RoleNotFound) {
+ continue;
+ }
+ if (!status.isOK()) {
+ return appendCommandStatus(result, status);
+ }
+ rolesArrayBuilder.append(roleDetails);
+ }
}
-
+ result.append("roles", rolesArrayBuilder.arr());
return true;
}
diff --git a/src/mongo/transport/service_entry_point_test_suite.cpp b/src/mongo/transport/service_entry_point_test_suite.cpp
index c3814accc47..841851d5ccd 100644
--- a/src/mongo/transport/service_entry_point_test_suite.cpp
+++ b/src/mongo/transport/service_entry_point_test_suite.cpp
@@ -51,7 +51,6 @@
#include "mongo/transport/transport_layer.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/net/message.h"
-#include "mongo/util/net/ssl_types.h"
namespace mongo {
@@ -149,9 +148,8 @@ void ServiceEntryPointTestSuite::MockTLHarness::asyncWait(Ticket&& ticket,
return _asyncWait(std::move(ticket), std::move(callback));
}
-SSLPeerInfo ServiceEntryPointTestSuite::MockTLHarness::getX509PeerInfo(
- const Session& session) const {
- return SSLPeerInfo("mock", {});
+std::string ServiceEntryPointTestSuite::MockTLHarness::getX509SubjectName(const Session& session) {
+ return "mock";
}
void ServiceEntryPointTestSuite::MockTLHarness::registerTags(const Session& session) {}
diff --git a/src/mongo/transport/service_entry_point_test_suite.h b/src/mongo/transport/service_entry_point_test_suite.h
index 7f15d4723eb..2249c86b9bd 100644
--- a/src/mongo/transport/service_entry_point_test_suite.h
+++ b/src/mongo/transport/service_entry_point_test_suite.h
@@ -39,7 +39,6 @@
namespace mongo {
class ServiceEntryPoint;
-struct SSLPeerInfo;
/**
* Test class. Uses a mock TransportLayer to test that the ServiceEntryPoint
@@ -130,7 +129,7 @@ private:
Date_t expiration = transport::Ticket::kNoExpirationDate) override;
Status wait(transport::Ticket&& ticket) override;
void asyncWait(transport::Ticket&& ticket, TicketCallback callback) override;
- SSLPeerInfo getX509PeerInfo(const transport::Session& session) const override;
+ std::string getX509SubjectName(const transport::Session& session) override;
void registerTags(const transport::Session& session) override;
Stats sessionStats() override;
void end(transport::Session& session) override;
diff --git a/src/mongo/transport/session.cpp b/src/mongo/transport/session.cpp
index 851f348edc0..b341cd97630 100644
--- a/src/mongo/transport/session.cpp
+++ b/src/mongo/transport/session.cpp
@@ -32,7 +32,6 @@
#include "mongo/platform/atomic_word.h"
#include "mongo/transport/transport_layer.h"
-#include "mongo/util/net/ssl_types.h"
namespace mongo {
namespace transport {
@@ -96,8 +95,8 @@ Ticket Session::sinkMessage(const Message& message, Date_t expiration) {
return _tl->sinkMessage(*this, message, expiration);
}
-SSLPeerInfo Session::getX509PeerInfo() const {
- return _tl->getX509PeerInfo(*this);
+std::string Session::getX509SubjectName() const {
+ return _tl->getX509SubjectName(*this);
}
void Session::end() {
diff --git a/src/mongo/transport/session.h b/src/mongo/transport/session.h
index 76c2a975478..c7ec5cd28f0 100644
--- a/src/mongo/transport/session.h
+++ b/src/mongo/transport/session.h
@@ -37,9 +37,6 @@
#include "mongo/util/time_support.h"
namespace mongo {
-
-struct SSLPeerInfo;
-
namespace transport {
class TransportLayer;
@@ -105,9 +102,9 @@ public:
}
/**
- * Return the X509 peer information for this connection (SSL only).
+ * Return the X509 subject name for this connection (SSL only).
*/
- SSLPeerInfo getX509PeerInfo() const;
+ std::string getX509SubjectName() const;
/**
* Set this session's tags. This Session will register
diff --git a/src/mongo/transport/transport_layer.h b/src/mongo/transport/transport_layer.h
index c407eef1f0d..3634ec68de5 100644
--- a/src/mongo/transport/transport_layer.h
+++ b/src/mongo/transport/transport_layer.h
@@ -154,10 +154,10 @@ public:
virtual void registerTags(const Session& session) = 0;
/**
- * Return the stored X509 peer information for this session. If the session does not
- * exist in this TransportLayer, returns a default constructed object.
+ * Return the stored X509 subject name for this session. If the session does not
+ * exist in this TransportLayer, returns "".
*/
- virtual SSLPeerInfo getX509PeerInfo(const Session& session) const = 0;
+ virtual std::string getX509SubjectName(const Session& session) = 0;
/**
* Returns the number of sessions currently open in the transport layer.
diff --git a/src/mongo/transport/transport_layer_legacy.cpp b/src/mongo/transport/transport_layer_legacy.cpp
index 1a719d66e93..3c004eb793f 100644
--- a/src/mongo/transport/transport_layer_legacy.cpp
+++ b/src/mongo/transport/transport_layer_legacy.cpp
@@ -117,16 +117,16 @@ Ticket TransportLayerLegacy::sourceMessage(Session& session, Message* message, D
return Ticket(this, stdx::make_unique<LegacyTicket>(session, expiration, std::move(sourceCb)));
}
-SSLPeerInfo TransportLayerLegacy::getX509PeerInfo(const Session& session) const {
+std::string TransportLayerLegacy::getX509SubjectName(const Session& session) {
{
stdx::lock_guard<stdx::mutex> lk(_connectionsMutex);
auto conn = _connections.find(session.id());
if (conn == _connections.end()) {
// Return empty string if the session is not found
- return SSLPeerInfo();
+ return "";
}
- return conn->second.sslPeerInfo.value_or(SSLPeerInfo());
+ return conn->second.x509SubjectName.value_or("");
}
}
@@ -274,10 +274,10 @@ Status TransportLayerLegacy::_runTicket(Ticket ticket) {
#ifdef MONGO_CONFIG_SSL
// If we didn't have an X509 subject name, see if we have one now
- if (!conn->second.sslPeerInfo) {
- auto info = amp->getX509PeerInfo();
- if (info.subjectName != "") {
- conn->second.sslPeerInfo = info;
+ if (!conn->second.x509SubjectName) {
+ auto name = amp->getX509SubjectName();
+ if (name != "") {
+ conn->second.x509SubjectName = name;
}
}
#endif
diff --git a/src/mongo/transport/transport_layer_legacy.h b/src/mongo/transport/transport_layer_legacy.h
index 873da5a2123..7472212ffc9 100644
--- a/src/mongo/transport/transport_layer_legacy.h
+++ b/src/mongo/transport/transport_layer_legacy.h
@@ -79,7 +79,7 @@ public:
void asyncWait(Ticket&& ticket, TicketCallback callback) override;
void registerTags(const Session& session) override;
- SSLPeerInfo getX509PeerInfo(const Session& session) const override;
+ std::string getX509SubjectName(const Session& session) override;
Stats sessionStats() override;
@@ -150,7 +150,7 @@ private:
const long long connectionId;
- boost::optional<SSLPeerInfo> sslPeerInfo;
+ boost::optional<std::string> x509SubjectName;
Session::TagMask tags;
bool inUse;
bool ended;
@@ -161,7 +161,7 @@ private:
std::unique_ptr<Listener> _listener;
stdx::thread _listenerThread;
- mutable stdx::mutex _connectionsMutex;
+ stdx::mutex _connectionsMutex;
std::unordered_map<Session::Id, Connection> _connections;
void _endSession_inlock(decltype(_connections.begin()) conn);
diff --git a/src/mongo/transport/transport_layer_manager.cpp b/src/mongo/transport/transport_layer_manager.cpp
index 6fc191bf49f..e513155e5cd 100644
--- a/src/mongo/transport/transport_layer_manager.cpp
+++ b/src/mongo/transport/transport_layer_manager.cpp
@@ -33,7 +33,6 @@
#include "mongo/base/status.h"
#include "mongo/stdx/memory.h"
#include "mongo/transport/session.h"
-#include "mongo/util/net/ssl_types.h"
#include "mongo/util/time_support.h"
#include <limits>
@@ -62,8 +61,8 @@ void TransportLayerManager::asyncWait(Ticket&& ticket, TicketCallback callback)
return getTicketTransportLayer(ticket)->asyncWait(std::move(ticket), std::move(callback));
}
-SSLPeerInfo TransportLayerManager::getX509PeerInfo(const Session& session) const {
- return session.getX509PeerInfo();
+std::string TransportLayerManager::getX509SubjectName(const Session& session) {
+ return session.getX509SubjectName();
}
template <typename Callable>
diff --git a/src/mongo/transport/transport_layer_manager.h b/src/mongo/transport/transport_layer_manager.h
index 9648a0859f2..20d27d6571c 100644
--- a/src/mongo/transport/transport_layer_manager.h
+++ b/src/mongo/transport/transport_layer_manager.h
@@ -64,7 +64,7 @@ public:
Status wait(Ticket&& ticket) override;
void asyncWait(Ticket&& ticket, TicketCallback callback) override;
- SSLPeerInfo getX509PeerInfo(const Session& session) const override;
+ std::string getX509SubjectName(const Session& session) override;
void registerTags(const Session& session) override;
Stats sessionStats() override;
diff --git a/src/mongo/transport/transport_layer_mock.cpp b/src/mongo/transport/transport_layer_mock.cpp
index 5b66c00bf91..e7fa76d2e9b 100644
--- a/src/mongo/transport/transport_layer_mock.cpp
+++ b/src/mongo/transport/transport_layer_mock.cpp
@@ -109,13 +109,8 @@ void TransportLayerMock::asyncWait(Ticket&& ticket, TicketCallback callback) {
callback(Status::OK());
}
-SSLPeerInfo TransportLayerMock::getX509PeerInfo(const Session& session) const {
- return _sessions.at(session.id()).peerInfo;
-}
-
-
-void TransportLayerMock::setX509PeerInfo(const Session& session, SSLPeerInfo peerInfo) {
- _sessions[session.id()].peerInfo = std::move(peerInfo);
+std::string TransportLayerMock::getX509SubjectName(const Session& session) {
+ return session.getX509SubjectName();
}
TransportLayer::Stats TransportLayerMock::sessionStats() {
@@ -129,16 +124,16 @@ Session* TransportLayerMock::createSession() {
stdx::make_unique<Session>(HostAndPort(), HostAndPort(), this);
Session::Id sessionId = session->id();
- _sessions[sessionId] = Connection{std::move(session), SSLPeerInfo()};
+ _sessions[sessionId] = std::move(session);
- return _sessions[sessionId].session.get();
+ return _sessions[sessionId].get();
}
Session* TransportLayerMock::get(Session::Id id) {
if (!owns(id))
return nullptr;
- return _sessions[id].session.get();
+ return _sessions[id].get();
}
bool TransportLayerMock::owns(Session::Id id) {
@@ -152,7 +147,7 @@ void TransportLayerMock::end(Session& session) {
void TransportLayerMock::endAllSessions(Session::TagMask tags) {
auto it = _sessions.begin();
while (it != _sessions.end()) {
- end(*it->second.session.get());
+ end(*it->second.get());
it++;
}
}
diff --git a/src/mongo/transport/transport_layer_mock.h b/src/mongo/transport/transport_layer_mock.h
index 10913f0cf96..38ab3eed0f1 100644
--- a/src/mongo/transport/transport_layer_mock.h
+++ b/src/mongo/transport/transport_layer_mock.h
@@ -36,7 +36,6 @@
#include "mongo/transport/ticket_impl.h"
#include "mongo/transport/transport_layer.h"
#include "mongo/util/net/message.h"
-#include "mongo/util/net/ssl_types.h"
#include "mongo/util/time_support.h"
namespace mongo {
@@ -87,8 +86,7 @@ public:
Status wait(Ticket&& ticket) override;
void asyncWait(Ticket&& ticket, TicketCallback callback) override;
- SSLPeerInfo getX509PeerInfo(const Session& session) const override;
- void setX509PeerInfo(const Session& session, SSLPeerInfo peerInfo);
+ std::string getX509SubjectName(const Session& session) override;
void registerTags(const Session& session) override;
Stats sessionStats() override;
@@ -104,11 +102,7 @@ public:
bool inShutdown() const;
private:
- struct Connection {
- std::unique_ptr<Session> session;
- SSLPeerInfo peerInfo;
- };
- std::unordered_map<Session::Id, Connection> _sessions;
+ std::unordered_map<Session::Id, std::unique_ptr<Session>> _sessions;
bool _shutdown;
};
diff --git a/src/mongo/util/net/SConscript b/src/mongo/util/net/SConscript
index c9da1751462..34105547ab6 100644
--- a/src/mongo/util/net/SConscript
+++ b/src/mongo/util/net/SConscript
@@ -49,7 +49,6 @@ networkEnv.Library(
"thread_idle_callback.cpp",
],
LIBDEPS=[
- '$BUILD_DIR/mongo/db/auth/auth_rolename',
'$BUILD_DIR/mongo/db/server_options_core',
'$BUILD_DIR/mongo/db/server_parameters',
'$BUILD_DIR/mongo/util/background_job',
diff --git a/src/mongo/util/net/abstract_message_port.h b/src/mongo/util/net/abstract_message_port.h
index 99ffce63977..10860552a7d 100644
--- a/src/mongo/util/net/abstract_message_port.h
+++ b/src/mongo/util/net/abstract_message_port.h
@@ -35,7 +35,6 @@
#include "mongo/stdx/functional.h"
#include "mongo/util/net/message.h"
#include "mongo/util/net/sockaddr.h"
-#include "mongo/util/net/ssl_types.h"
#include "mongo/util/time_support.h"
namespace mongo {
@@ -156,14 +155,14 @@ public:
virtual long long getBytesOut() const = 0;
/**
- * Set the x509 peer information (used for SSL).
+ * Set the x509 subject name (used for SSL).
*/
- virtual void setX509PeerInfo(SSLPeerInfo x509PeerInfo) = 0;
+ virtual void setX509SubjectName(const std::string& x509SubjectName) = 0;
/**
- * Get the current x509 peer information (used for SSL).
+ * Get the current x509 subject name (used for SSL).
*/
- virtual const SSLPeerInfo& getX509PeerInfo() const = 0;
+ virtual std::string getX509SubjectName() const = 0;
/**
* Set the connection ID.
diff --git a/src/mongo/util/net/asio_message_port.cpp b/src/mongo/util/net/asio_message_port.cpp
index d883a474ab0..d5378f8b756 100644
--- a/src/mongo/util/net/asio_message_port.cpp
+++ b/src/mongo/util/net/asio_message_port.cpp
@@ -83,7 +83,7 @@ ASIOMessagingPort::ASIOMessagingPort(int fd, SockAddr farEnd)
_remote(),
_isEncrypted(false),
_awaitingHandshake(true),
- _x509PeerInfo(),
+ _x509SubjectName(),
_bytesIn(0),
_bytesOut(0),
_logLevel(logger::LogSeverity::Log()),
@@ -121,7 +121,7 @@ ASIOMessagingPort::ASIOMessagingPort(Milliseconds timeout, logger::LogSeverity l
_remote(),
_isEncrypted(false),
_awaitingHandshake(true),
- _x509PeerInfo(),
+ _x509SubjectName(),
_bytesIn(0),
_bytesOut(0),
_logLevel(logLevel),
@@ -383,13 +383,13 @@ bool ASIOMessagingPort::recv(Message& m) {
throw asio::system_error(ec);
}
- auto swPeerInfo =
+ auto swPeerSubjectName =
getSSLManager()->parseAndValidatePeerCertificate(_sslSock.native_handle(), "");
- if (!swPeerInfo.isOK()) {
+ if (!swPeerSubjectName.isOK()) {
throw SocketException(SocketException::CONNECT_ERROR,
- swPeerInfo.getStatus().reason());
+ swPeerSubjectName.getStatus().reason());
}
- setX509PeerInfo(swPeerInfo.getValue().get_value_or(SSLPeerInfo()));
+ setX509SubjectName(swPeerSubjectName.getValue().get_value_or(""));
_isEncrypted = true;
_awaitingHandshake = false;
@@ -590,12 +590,13 @@ bool ASIOMessagingPort::secure(SSLManagerInterface* ssl, const std::string& remo
return false;
}
- auto swPeerInfo =
+ auto swPeerSubjectName =
getSSLManager()->parseAndValidatePeerCertificate(_sslSock.native_handle(), remoteHost);
- if (!swPeerInfo.isOK()) {
- throw SocketException(SocketException::CONNECT_ERROR, swPeerInfo.getStatus().reason());
+ if (!swPeerSubjectName.isOK()) {
+ throw SocketException(SocketException::CONNECT_ERROR,
+ swPeerSubjectName.getStatus().reason());
}
- setX509PeerInfo(swPeerInfo.getValue().get_value_or(SSLPeerInfo()));
+ setX509SubjectName(swPeerSubjectName.getValue().get_value_or(""));
_isEncrypted = true;
return true;
@@ -629,12 +630,12 @@ long long ASIOMessagingPort::getBytesOut() const {
return _bytesOut;
}
-void ASIOMessagingPort::setX509PeerInfo(SSLPeerInfo x509PeerInfo) {
- _x509PeerInfo = std::move(x509PeerInfo);
+void ASIOMessagingPort::setX509SubjectName(const std::string& x509SubjectName) {
+ _x509SubjectName = x509SubjectName;
}
-const SSLPeerInfo& ASIOMessagingPort::getX509PeerInfo() const {
- return _x509PeerInfo;
+std::string ASIOMessagingPort::getX509SubjectName() const {
+ return _x509SubjectName;
}
void ASIOMessagingPort::setConnectionId(const long long connectionId) {
diff --git a/src/mongo/util/net/asio_message_port.h b/src/mongo/util/net/asio_message_port.h
index 37280b0b714..d3e5fc33b1c 100644
--- a/src/mongo/util/net/asio_message_port.h
+++ b/src/mongo/util/net/asio_message_port.h
@@ -105,9 +105,9 @@ public:
long long getBytesOut() const override;
- void setX509PeerInfo(SSLPeerInfo x509PeerInfo) override;
+ void setX509SubjectName(const std::string& x509SubjectName) override;
- const SSLPeerInfo& getX509PeerInfo() const override;
+ std::string getX509SubjectName() const override;
void setConnectionId(const long long connectionId) override;
@@ -140,7 +140,7 @@ private:
bool _isEncrypted;
bool _awaitingHandshake;
- SSLPeerInfo _x509PeerInfo;
+ std::string _x509SubjectName;
long long _bytesIn;
long long _bytesOut;
diff --git a/src/mongo/util/net/message_port.cpp b/src/mongo/util/net/message_port.cpp
index 22031c71e93..137d494c4ac 100644
--- a/src/mongo/util/net/message_port.cpp
+++ b/src/mongo/util/net/message_port.cpp
@@ -70,7 +70,7 @@ MessagingPort::MessagingPort(double timeout, logger::LogSeverity ll)
: MessagingPort(std::make_shared<Socket>(timeout, ll)) {}
MessagingPort::MessagingPort(std::shared_ptr<Socket> sock)
- : _x509PeerInfo(), _connectionId(), _tag(), _psock(std::move(sock)) {
+ : _x509SubjectName(), _connectionId(), _tag(), _psock(std::move(sock)) {
SockAddr sa = _psock->remoteAddr();
_remoteParsed = HostAndPort(sa.getAddr(), sa.getPort());
}
@@ -127,10 +127,9 @@ bool MessagingPort::recv(Message& m) {
uassert(17132,
"SSL handshake received but server is started without SSL support",
sslGlobalParams.sslMode.load() != SSLParams::SSLMode_disabled);
- setX509PeerInfo(
+ setX509SubjectName(
_psock->doSSLHandshake(reinterpret_cast<const char*>(&header), sizeof(header)));
_psock->setHandshakeReceived();
-
goto again;
}
uassert(17189,
@@ -217,12 +216,12 @@ SockAddr MessagingPort::localAddr() const {
return _psock->localAddr();
}
-void MessagingPort::setX509PeerInfo(SSLPeerInfo x509PeerInfo) {
- _x509PeerInfo = std::move(x509PeerInfo);
+void MessagingPort::setX509SubjectName(const std::string& x509SubjectName) {
+ _x509SubjectName = x509SubjectName;
}
-const SSLPeerInfo& MessagingPort::getX509PeerInfo() const {
- return _x509PeerInfo;
+std::string MessagingPort::getX509SubjectName() const {
+ return _x509SubjectName;
}
void MessagingPort::setConnectionId(const long long connectionId) {
diff --git a/src/mongo/util/net/message_port.h b/src/mongo/util/net/message_port.h
index 6163e84fe3c..41ecc2fce3b 100644
--- a/src/mongo/util/net/message_port.h
+++ b/src/mongo/util/net/message_port.h
@@ -101,9 +101,9 @@ public:
return _psock->getBytesOut();
}
- void setX509PeerInfo(SSLPeerInfo x509PeerInfo) override;
+ void setX509SubjectName(const std::string& x509SubjectName) override;
- const SSLPeerInfo& getX509PeerInfo() const override;
+ std::string getX509SubjectName() const override;
void setConnectionId(const long long connectionId) override;
@@ -139,7 +139,7 @@ public:
private:
// this is the parsed version of remote
HostAndPort _remoteParsed;
- SSLPeerInfo _x509PeerInfo;
+ std::string _x509SubjectName;
long long _connectionId;
AbstractMessagingPort::Tag _tag;
std::shared_ptr<Socket> _psock;
diff --git a/src/mongo/util/net/message_port_mock.cpp b/src/mongo/util/net/message_port_mock.cpp
index c09d69f2bba..de07ba032ae 100644
--- a/src/mongo/util/net/message_port_mock.cpp
+++ b/src/mongo/util/net/message_port_mock.cpp
@@ -36,7 +36,7 @@ namespace mongo {
using std::string;
-MessagingPortMock::MessagingPortMock() : AbstractMessagingPort(), _x509PeerInfo() {}
+MessagingPortMock::MessagingPortMock() : AbstractMessagingPort() {}
MessagingPortMock::~MessagingPortMock() {}
void MessagingPortMock::setTimeout(Milliseconds millis) {}
@@ -101,10 +101,10 @@ uint64_t MessagingPortMock::getSockCreationMicroSec() const {
return 0;
}
-void MessagingPortMock::setX509PeerInfo(SSLPeerInfo x509PeerInfo) {}
+void MessagingPortMock::setX509SubjectName(const std::string& x509SubjectName) {}
-const SSLPeerInfo& MessagingPortMock::getX509PeerInfo() const {
- return _x509PeerInfo;
+std::string MessagingPortMock::getX509SubjectName() const {
+ return "mock";
}
void MessagingPortMock::setConnectionId(const long long connectionId) {}
diff --git a/src/mongo/util/net/message_port_mock.h b/src/mongo/util/net/message_port_mock.h
index bb7e8b678d7..721998f81f3 100644
--- a/src/mongo/util/net/message_port_mock.h
+++ b/src/mongo/util/net/message_port_mock.h
@@ -79,9 +79,9 @@ public:
uint64_t getSockCreationMicroSec() const override;
- void setX509PeerInfo(SSLPeerInfo x509PeerInfo) override;
+ void setX509SubjectName(const std::string& x509SubjectName) override;
- const SSLPeerInfo& getX509PeerInfo() const override;
+ std::string getX509SubjectName() const override;
void setConnectionId(const long long connectionId) override;
@@ -97,7 +97,6 @@ public:
private:
HostAndPort _remote;
- SSLPeerInfo _x509PeerInfo;
};
} // namespace mongo
diff --git a/src/mongo/util/net/sock.cpp b/src/mongo/util/net/sock.cpp
index ed4092bbac1..5466c21dd4b 100644
--- a/src/mongo/util/net/sock.cpp
+++ b/src/mongo/util/net/sock.cpp
@@ -306,9 +306,9 @@ void Socket::secureAccepted(SSLManagerInterface* ssl) {
_sslManager = ssl;
}
-SSLPeerInfo Socket::doSSLHandshake(const char* firstBytes, int len) {
+std::string Socket::doSSLHandshake(const char* firstBytes, int len) {
if (!_sslManager)
- return SSLPeerInfo();
+ return "";
fassert(16506, _fd != INVALID_SOCKET);
if (_sslConnection.get()) {
throw SocketException(SocketException::RECV_ERROR,
diff --git a/src/mongo/util/net/sock.h b/src/mongo/util/net/sock.h
index 9828ddcf1f5..a9da4bdbbfb 100644
--- a/src/mongo/util/net/sock.h
+++ b/src/mongo/util/net/sock.h
@@ -63,7 +63,6 @@ namespace mongo {
class SSLManagerInterface;
class SSLConnection;
#endif
-struct SSLPeerInfo;
extern const int portSendFlags;
extern const int portRecvFlags;
@@ -222,7 +221,7 @@ public:
*
* This function may throw SocketException.
*/
- SSLPeerInfo doSSLHandshake(const char* firstBytes = NULL, int len = 0);
+ std::string doSSLHandshake(const char* firstBytes = NULL, int len = 0);
/**
* @return the time when the socket was opened.
diff --git a/src/mongo/util/net/ssl_manager.cpp b/src/mongo/util/net/ssl_manager.cpp
index 9769dd62262..77fc732e918 100644
--- a/src/mongo/util/net/ssl_manager.cpp
+++ b/src/mongo/util/net/ssl_manager.cpp
@@ -195,10 +195,10 @@ public:
virtual SSLConnection* accept(Socket* socket, const char* initialBytes, int len);
- virtual SSLPeerInfo parseAndValidatePeerCertificateDeprecated(const SSLConnection* conn,
+ virtual std::string parseAndValidatePeerCertificateDeprecated(const SSLConnection* conn,
const std::string& remoteHost);
- StatusWith<boost::optional<SSLPeerInfo>> parseAndValidatePeerCertificate(
+ StatusWith<boost::optional<std::string>> parseAndValidatePeerCertificate(
SSL* conn, const std::string& remoteHost) final;
virtual const SSLConfiguration& getSSLConfiguration() const {
@@ -220,9 +220,6 @@ public:
virtual void SSL_free(SSLConnection* conn);
private:
- const int _rolesNid = OBJ_create(mongodbRolesOID.identifier.c_str(),
- mongodbRolesOID.shortDescription.c_str(),
- mongodbRolesOID.longDescription.c_str());
UniqueSSLContext _serverContext; // SSL context for incoming connections
UniqueSSLContext _clientContext; // SSL context for outgoing connections
std::string _password;
@@ -271,9 +268,6 @@ private:
std::string* subjectName,
Date_t* serverNotAfter);
-
- StatusWith<std::unordered_set<RoleName>> _parsePeerRoles(X509* peerCert) const;
-
/** @return true if was successful, otherwise false */
bool _setupPEM(SSL_CTX* context, const std::string& keyFile, const std::string& password);
@@ -1095,7 +1089,7 @@ bool SSLManager::_hostNameMatch(const char* nameToMatch, const char* certHostNam
}
}
-StatusWith<boost::optional<SSLPeerInfo>> SSLManager::parseAndValidatePeerCertificate(
+StatusWith<boost::optional<std::string>> SSLManager::parseAndValidatePeerCertificate(
SSL* conn, const std::string& remoteHost) {
if (!_sslConfiguration.hasCA && isSSLServer)
return {boost::none};
@@ -1133,16 +1127,10 @@ StatusWith<boost::optional<SSLPeerInfo>> SSLManager::parseAndValidatePeerCertifi
std::string peerSubjectName = getCertificateSubjectName(peerCert);
LOG(2) << "Accepted TLS connection from peer: " << peerSubjectName;
- StatusWith<std::unordered_set<RoleName>> swPeerCertificateRoles = _parsePeerRoles(peerCert);
- if (!swPeerCertificateRoles.isOK()) {
- return swPeerCertificateRoles.getStatus();
- }
-
// If this is an SSL client context (on a MongoDB server or client)
// perform hostname validation of the remote server
if (remoteHost.empty()) {
- return boost::make_optional(
- SSLPeerInfo(peerSubjectName, std::move(swPeerCertificateRoles.getValue())));
+ return boost::make_optional(peerSubjectName);
}
// Try to match using the Subject Alternate Name, if it exists.
@@ -1200,11 +1188,10 @@ StatusWith<boost::optional<SSLPeerInfo>> SSLManager::parseAndValidatePeerCertifi
}
}
- return boost::make_optional(SSLPeerInfo(peerSubjectName, std::unordered_set<RoleName>()));
+ return boost::make_optional(peerSubjectName);
}
-
-SSLPeerInfo SSLManager::parseAndValidatePeerCertificateDeprecated(const SSLConnection* conn,
+std::string SSLManager::parseAndValidatePeerCertificateDeprecated(const SSLConnection* conn,
const std::string& remoteHost) {
auto swPeerSubjectName = parseAndValidatePeerCertificate(conn->ssl, remoteHost);
// We can't use uassertStatusOK here because we need to throw a SocketException.
@@ -1212,128 +1199,7 @@ SSLPeerInfo SSLManager::parseAndValidatePeerCertificateDeprecated(const SSLConne
throw SocketException(SocketException::CONNECT_ERROR,
swPeerSubjectName.getStatus().reason());
}
- return swPeerSubjectName.getValue().get_value_or(SSLPeerInfo());
-}
-
-StatusWith<std::unordered_set<RoleName>> SSLManager::_parsePeerRoles(X509* peerCert) const {
- // exts is owned by the peerCert
- STACK_OF(X509_EXTENSION)* exts = peerCert->cert_info->extensions;
-
- int extCount = 0;
- if (exts) {
- extCount = sk_X509_EXTENSION_num(exts);
- }
-
- ASN1_OBJECT* rolesObj = OBJ_nid2obj(_rolesNid);
-
- // Search all certificate extensions for our own
- std::unordered_set<RoleName> roles;
- for (int i = 0; i < extCount; i++) {
- X509_EXTENSION* ex = sk_X509_EXTENSION_value(exts, i);
- ASN1_OBJECT* obj = X509_EXTENSION_get_object(ex);
-
- if (!OBJ_cmp(obj, rolesObj)) {
- // We've found an extension which has our roles OID
- ASN1_OCTET_STRING* data = X509_EXTENSION_get_data(ex);
-
- /*
- * MongoDBAuthorizationGrant ::= CHOICE {
- * MongoDBRole,
- * ...!UTF8String:"Unrecognized entity in MongoDBAuthorizationGrant"
- * }
- * MongoDBAuthorizationGrants ::= SET OF MongoDBAuthorizationGrant
- */
- // Extract the set of roles from our extension, and load them into an OpenSSL stack.
- STACK_OF(ASN1_TYPE)* mongoDBAuthorizationGrants = nullptr;
-
- // OpenSSL's parsing function will try and manipulate the pointer it's passed. If we
- // passed it 'data->data' directly, it would modify structures owned by peerCert.
- const unsigned char* dataBytes = data->data;
- mongoDBAuthorizationGrants =
- d2i_ASN1_SET_ANY(&mongoDBAuthorizationGrants, &dataBytes, data->length);
- if (!mongoDBAuthorizationGrants) {
- return Status(ErrorCodes::FailedToParse,
- "Failed to parse x509 authorization grants");
- }
- const auto grantGuard = MakeGuard([&mongoDBAuthorizationGrants]() {
- sk_ASN1_TYPE_pop_free(mongoDBAuthorizationGrants, ASN1_TYPE_free);
- });
-
- /*
- * MongoDBRole ::= SEQUENCE {
- * role UTF8String,
- * database UTF8String
- * }
- */
- // Loop through every role in the stack.
- ASN1_TYPE* MongoDBRoleWrapped = nullptr;
- while ((MongoDBRoleWrapped = sk_ASN1_TYPE_pop(mongoDBAuthorizationGrants))) {
- const auto roleWrappedGuard =
- MakeGuard([MongoDBRoleWrapped]() { ASN1_TYPE_free(MongoDBRoleWrapped); });
-
- if (MongoDBRoleWrapped->type == V_ASN1_SEQUENCE) {
- // Unwrap the ASN1Type into a STACK_OF(ASN1_TYPE)
- unsigned char* roleBytes = ASN1_STRING_data(MongoDBRoleWrapped->value.sequence);
- int roleBytesLength = ASN1_STRING_length(MongoDBRoleWrapped->value.sequence);
- ASN1_SEQUENCE_ANY* MongoDBRole = nullptr;
- MongoDBRole = d2i_ASN1_SEQUENCE_ANY(
- &MongoDBRole, (const unsigned char**)&roleBytes, roleBytesLength);
- if (!MongoDBRole) {
- return Status(ErrorCodes::FailedToParse,
- "Failed to parse role in x509 authorization grant");
- }
- const auto roleGuard = MakeGuard(
- [&MongoDBRole]() { sk_ASN1_TYPE_pop_free(MongoDBRole, ASN1_TYPE_free); });
-
- if (sk_ASN1_TYPE_num(MongoDBRole) != 2) {
- return Status(ErrorCodes::FailedToParse,
- "Role entity in MongoDBAuthorizationGrant must have exactly "
- "2 sequence elements");
- }
- // Extract the subcomponents of the sequence, which are popped off the stack in
- // reverse order. Here, parse the role's database.
- ASN1_TYPE* roleComponent = sk_ASN1_TYPE_pop(MongoDBRole);
- const auto roleDBGuard =
- MakeGuard([roleComponent]() { ASN1_TYPE_free(roleComponent); });
- if (roleComponent->type != V_ASN1_UTF8STRING) {
- return Status(ErrorCodes::FailedToParse,
- "database in MongoDBRole must be a UTF8 string");
- }
- std::string roleDB(
- reinterpret_cast<char*>(ASN1_STRING_data(roleComponent->value.utf8string)));
-
- // Parse the role's name.
- roleComponent = sk_ASN1_TYPE_pop(MongoDBRole);
- const auto roleNameGuard =
- MakeGuard([roleComponent]() { ASN1_TYPE_free(roleComponent); });
- if (roleComponent->type != V_ASN1_UTF8STRING) {
- return Status(ErrorCodes::FailedToParse,
- "role in MongoDBRole must be a UTF8 string");
- }
- std::string roleName(
- reinterpret_cast<char*>(ASN1_STRING_data(roleComponent->value.utf8string)));
-
- // Construct a RoleName from the subcomponents
- roles.emplace(RoleName(roleName, roleDB));
-
- } else {
- return Status(ErrorCodes::FailedToParse,
- "Unrecognized entity in MongoDBAuthorizationGrant");
- }
- }
- }
- }
-
- LOG(1) << "MONGODB-X509 authorization parsed the following roles from peer certificate: "
- << [&roles]() {
- StringBuilder sb;
- std::for_each(roles.begin(), roles.end(), [&sb](const RoleName& role) {
- sb << role.toString();
- });
- return sb.str();
- }();
-
- return roles;
+ return swPeerSubjectName.getValue().get_value_or("");
}
std::string SSLManagerInterface::getSSLErrorMessage(int code) {
diff --git a/src/mongo/util/net/ssl_manager.h b/src/mongo/util/net/ssl_manager.h
index ef7ad5c403b..ecc393070a8 100644
--- a/src/mongo/util/net/ssl_manager.h
+++ b/src/mongo/util/net/ssl_manager.h
@@ -40,7 +40,6 @@
#include "mongo/bson/bsonobj.h"
#include "mongo/util/decorable.h"
#include "mongo/util/net/sock.h"
-#include "mongo/util/net/ssl_types.h"
#include "mongo/util/time_support.h"
#include <openssl/err.h>
@@ -88,24 +87,6 @@ struct SSLConfiguration {
bool hasCA = false;
};
-/**
- * Stores information about a globally unique OID.
- */
-class ASN1OID {
-public:
- ASN1OID(std::string identifier, std::string shortDescription, std::string longDescription)
- : identifier(std::move(identifier)),
- shortDescription(std::move(shortDescription)),
- longDescription(std::move(longDescription)) {}
-
- std::string identifier; // An OID
- std::string shortDescription; // A brief description of the entity associated with the OID
- std::string longDescription; // A long form description of the entity associated with the OID
-};
-const ASN1OID mongodbRolesOID("1.3.6.1.4.1.34601.2.1.1",
- "MongoRoles",
- "Sequence of MongoDB Database Roles");
-
class SSLManagerInterface : public Decorable<SSLManagerInterface> {
public:
static std::unique_ptr<SSLManagerInterface> create(const SSLParams& params, bool isServer);
@@ -135,7 +116,7 @@ public:
* SocketException upon failure. New code should prefer the version that returns
* a StatusWith instead.
*/
- virtual SSLPeerInfo parseAndValidatePeerCertificateDeprecated(
+ virtual std::string parseAndValidatePeerCertificateDeprecated(
const SSLConnection* conn, const std::string& remoteHost) = 0;
/**
@@ -181,10 +162,9 @@ public:
* Fetches a peer certificate and validates it if it exists. If validation fails, but weak
* validation is enabled, boost::none will be returned. If validation fails, and invalid
* certificates are not allowed, a non-OK status will be returned. If validation is successful,
- * an engaged optional containing the certificate's subject name, and any roles acquired by
- * X509 authorization will be returned.
+ * an engaged optional containing the certificate's subject name will be returned.
*/
- virtual StatusWith<boost::optional<SSLPeerInfo>> parseAndValidatePeerCertificate(
+ virtual StatusWith<boost::optional<std::string>> parseAndValidatePeerCertificate(
SSL* ssl, const std::string& remoteHost) = 0;
};
diff --git a/src/mongo/util/net/ssl_types.h b/src/mongo/util/net/ssl_types.h
deleted file mode 100644
index 87fe6eca59a..00000000000
--- a/src/mongo/util/net/ssl_types.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2016 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 <string>
-#include <unordered_set>
-
-#include "mongo/db/auth/role_name.h"
-
-namespace mongo {
-
-/**
- * Contains information extracted from the peer certificate which is consumed by subsystems
- * outside of the networking stack.
- */
-struct SSLPeerInfo {
- SSLPeerInfo(std::string subjectName, std::unordered_set<RoleName> roles)
- : subjectName(std::move(subjectName)), roles(std::move(roles)) {}
- SSLPeerInfo() = default;
-
- std::string subjectName;
- std::unordered_set<RoleName> roles;
-};
-
-} // namespace mongo