Skip to content

Commit 7c9cdae

Browse files
author
Andy Schwerin
committed
Replace CmdAuthenticate::getUserObj() with AuthorizationManager::getPrivilegeDocument().
The new getPrivilegeDocument() returns a Status, and does not have a "pwd" out parameter. More importantly, by moving the implementation into the AuthExternalState interface, we eliminate a symbol conflict between mongod and mongos. This implementation reduces code duplication, and meets the needs of the enterprise SASL authentication module. Once there is a mongod/mongos-agnostic way to obtain a connection-like object for issuing queries, the code may be futher simplified.
1 parent 962cbe0 commit 7c9cdae

19 files changed

+332
-157
lines changed

src/mongo/SConscript

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,7 @@ env.StaticLibrary("coredb", [
242242
"db/stats/top.cpp",
243243
"s/shardconnection.cpp",
244244
],
245-
LIBDEPS=['db/auth/auth',
246-
'db/auth/serverauth',
245+
LIBDEPS=['db/auth/serverauth',
247246
'server_parameters'])
248247

249248
coreServerFiles = [ "db/common.cpp",
@@ -439,7 +438,7 @@ mongosLibraryFiles = [
439438
"s/security.cpp",
440439
]
441440

442-
env.Library( "mongoscore" , mongosLibraryFiles )
441+
env.Library( "mongoscore" , mongosLibraryFiles, LIBDEPS=['db/auth/authmongos'] )
443442

444443
env.CppUnitTest( "balancer_policy_test" , [ "s/balancer_policy_tests.cpp" ] ,
445444
LIBDEPS=["mongoscore", "coreshard","mongocommon","coreserver","coredb","dbcmdline","mongodandmongos"] ,
@@ -505,6 +504,7 @@ env.CppUnitTest("geojsonparser_test", [ "db/geo/geojsonparser_test.cpp" ], LIBDE
505504

506505
env.StaticLibrary("serveronly", serverOnlyFiles,
507506
LIBDEPS=["coreshard",
507+
"db/auth/authmongod",
508508
"dbcmdline",
509509
"defaultversion",
510510
"geojson",

src/mongo/db/auth/SConscript

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,25 @@ env.Command(['action_type.h', 'action_type.cpp'], ['generate_action_types.py', '
1010
# Just the data structures used
1111
env.StaticLibrary('authcore', ['action_set.cpp',
1212
'action_type.cpp',
13+
'auth_external_state.cpp',
1314
'authorization_manager.cpp',
1415
'principal.cpp',
1516
'principal_set.cpp',
1617
'privilege.cpp',
1718
'privilege_set.cpp'],
1819
LIBDEPS=['$BUILD_DIR/mongo/base/base', '$BUILD_DIR/mongo/stringutils'])
1920

20-
env.StaticLibrary('auth', ['auth_external_state.cpp'], LIBDEPS=['authcore'])
21+
env.StaticLibrary('authservercommon',
22+
['auth_external_state_server_common.cpp'],
23+
LIBDEPS=['authcore'])
24+
25+
env.StaticLibrary('authmongod',
26+
['auth_external_state_d.cpp'],
27+
LIBDEPS=['authservercommon'])
28+
29+
env.StaticLibrary('authmongos',
30+
['auth_external_state_s.cpp'],
31+
LIBDEPS=['authservercommon'])
2132

2233
env.CppUnitTest('action_set_test', 'action_set_test.cpp', LIBDEPS=['authcore'])
2334
env.CppUnitTest('principal_set_test', 'principal_set_test.cpp', LIBDEPS=['authcore'])

src/mongo/db/auth/auth_external_state.cpp

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,41 +14,43 @@
1414
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1515
*/
1616

17-
#include "mongo/db/auth/auth_external_state_impl.h"
17+
#include "mongo/db/auth/auth_external_state.h"
1818

19-
#include "mongo/base/status.h"
20-
#include "mongo/client/dbclientinterface.h"
2119
#include "mongo/db/auth/authorization_manager.h"
22-
#include "mongo/db/client.h"
23-
#include "mongo/util/debug_util.h"
2420

2521
namespace mongo {
2622

27-
Status AuthExternalStateImpl::initialize(DBClientBase* adminDBConnection) {
28-
if (noauth) {
23+
AuthExternalState::AuthExternalState() {}
24+
AuthExternalState::~AuthExternalState() {}
25+
26+
Status AuthExternalState::getPrivilegeDocumentOverConnection(DBClientBase* conn,
27+
const std::string& dbname,
28+
const std::string& principalName,
29+
BSONObj* result) {
30+
if (principalName == internalSecurity.user) {
31+
if (internalSecurity.pwd.empty()) {
32+
return Status(ErrorCodes::UserNotFound,
33+
"key file must be used to log in with internal user",
34+
15889);
35+
}
36+
*result = BSON("user" << principalName << "pwd" << internalSecurity.pwd).getOwned();
2937
return Status::OK();
3038
}
3139

32-
try {
33-
_adminUserExists = AuthorizationManager::hasPrivilegeDocument(adminDBConnection,
34-
"admin");
35-
} catch (DBException& e) {
36-
return Status(ErrorCodes::InternalError,
37-
mongoutils::str::stream() << "An error occurred while checking for the "
38-
"existence of an admin user: " << e.what(),
40+
std::string usersNamespace = dbname + ".system.users";
41+
42+
BSONObj userBSONObj;
43+
BSONObj query = BSON("user" << principalName);
44+
userBSONObj = conn->findOne(usersNamespace, query, 0, QueryOption_SlaveOk);
45+
if (userBSONObj.isEmpty()) {
46+
return Status(ErrorCodes::UserNotFound,
47+
mongoutils::str::stream() << "auth: couldn't find user " << principalName
48+
<< ", " << usersNamespace,
3949
0);
4050
}
41-
ONCE {
42-
if (!_adminUserExists) {
43-
log() << "note: no users configured in admin.system.users, allowing localhost access"
44-
<< endl;
45-
}
46-
}
47-
return Status::OK();
48-
}
4951

50-
bool AuthExternalStateImpl::shouldIgnoreAuthChecks() const {
51-
return noauth || (!_adminUserExists && cc().getIsLocalHostConnection()) || cc().isGod();
52+
*result = userBSONObj.getOwned();
53+
return Status::OK();
5254
}
5355

54-
} // namespace mongo
56+
} // namespace mongo

src/mongo/db/auth/auth_external_state.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#pragma once
1818

19+
#include <string>
20+
1921
#include "mongo/base/disallow_copying.h"
2022
#include "mongo/base/status.h"
2123
#include "mongo/client/dbclientinterface.h"
@@ -33,7 +35,7 @@ namespace mongo {
3335

3436
public:
3537

36-
virtual ~AuthExternalState() {};
38+
virtual ~AuthExternalState();
3739

3840
// Returns true if this connection should be treated as if it has full access to do
3941
// anything, regardless of the current auth state. Currently the reasons why this could be
@@ -48,8 +50,24 @@ namespace mongo {
4850
// before any other methods are called on the AuthExternalState.
4951
virtual Status initialize(DBClientBase* adminDBConnection) = 0;
5052

53+
// Gets the privilege information document for "principalName" on "dbname".
54+
//
55+
// On success, returns Status::OK() and stores a shared-ownership copy of the document into
56+
// "result".
57+
virtual Status getPrivilegeDocument(const std::string& dbname,
58+
const std::string& principalName,
59+
BSONObj* result) = 0;
60+
61+
5162
protected:
52-
AuthExternalState() {}; // This class should never be instantiated directly.
63+
// Look up the privilege document for "principalName" in database "dbname", over "conn".
64+
static Status getPrivilegeDocumentOverConnection(DBClientBase* conn,
65+
const std::string& dbname,
66+
const std::string& userName,
67+
BSONObj* result);
68+
69+
70+
AuthExternalState(); // This class should never be instantiated directly.
5371
};
5472

5573
} // namespace mongo
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Copyright (C) 2012 10gen Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Affero General Public License, version 3,
6+
* as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU Affero General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU Affero General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#include "mongo/db/auth/auth_external_state_d.h"
18+
19+
#include "mongo/base/status.h"
20+
#include "mongo/client/dbclientinterface.h"
21+
#include "mongo/db/auth/authorization_manager.h"
22+
#include "mongo/db/client.h"
23+
#include "mongo/db/instance.h"
24+
#include "mongo/util/debug_util.h"
25+
26+
namespace mongo {
27+
28+
AuthExternalStateMongod::AuthExternalStateMongod() {}
29+
AuthExternalStateMongod::~AuthExternalStateMongod() {}
30+
31+
Status AuthExternalStateMongod::getPrivilegeDocument(const string& dbname,
32+
const string& principalName,
33+
BSONObj* result) {
34+
Client::GodScope gs;
35+
DBDirectClient conn;
36+
return getPrivilegeDocumentOverConnection(&conn, dbname, principalName, result);
37+
}
38+
39+
} // namespace mongo
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* Copyright (C) 2012 10gen Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Affero General Public License, version 3,
6+
* as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU Affero General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU Affero General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#pragma once
18+
19+
#include "mongo/base/disallow_copying.h"
20+
#include "mongo/base/status.h"
21+
#include "mongo/client/dbclientinterface.h"
22+
#include "mongo/db/auth/auth_external_state_server_common.h"
23+
24+
namespace mongo {
25+
26+
/**
27+
* The implementation of AuthExternalState functionality for mongod.
28+
*/
29+
class AuthExternalStateMongod : public AuthExternalStateServerCommon {
30+
MONGO_DISALLOW_COPYING(AuthExternalStateMongod);
31+
32+
public:
33+
AuthExternalStateMongod();
34+
virtual ~AuthExternalStateMongod();
35+
36+
virtual Status getPrivilegeDocument(const string& dbname,
37+
const string& principalName,
38+
BSONObj* result);
39+
};
40+
41+
} // namespace mongo

src/mongo/db/auth/auth_external_state_mock.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ namespace mongo {
4343
// This is a no-op for the mock
4444
virtual Status initialize(DBClientBase* adminDBConnection) { return Status::OK(); }
4545

46+
virtual Status getPrivilegeDocument(const string& dbname,
47+
const string& user,
48+
BSONObj* result) {
49+
return Status(ErrorCodes::InternalError, "Not Implemented!");
50+
}
51+
4652
private:
4753
bool _returnValue;
4854
};
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* Copyright (C) 2012 10gen Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Affero General Public License, version 3,
6+
* as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU Affero General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU Affero General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#include "mongo/db/auth/auth_external_state_s.h"
18+
19+
#include "mongo/base/status.h"
20+
#include "mongo/client/dbclientinterface.h"
21+
#include "mongo/db/auth/authorization_manager.h"
22+
#include "mongo/s/grid.h"
23+
24+
namespace mongo {
25+
26+
AuthExternalStateMongos::AuthExternalStateMongos() {}
27+
AuthExternalStateMongos::~AuthExternalStateMongos() {}
28+
29+
Status AuthExternalStateMongos::getPrivilegeDocument(const string& dbname,
30+
const string& principalName,
31+
BSONObj* result) {
32+
33+
//
34+
// Note: The connection mechanism here is *not* ideal, and should not be used elsewhere.
35+
// If the primary for the collection moves, this approach may throw rather than handle
36+
// version exceptions.
37+
//
38+
39+
std::string systemUsers = dbname + ".system.users";
40+
DBConfigPtr config = grid.getDBConfig(systemUsers);
41+
Shard s = config->getShard(systemUsers);
42+
43+
scoped_ptr<ScopedDbConnection> conn(
44+
ScopedDbConnection::getInternalScopedDbConnection(s.getConnString(), 30.0));
45+
Status status = getPrivilegeDocumentOverConnection(
46+
conn->get(), dbname, principalName, result);
47+
conn->done();
48+
return status;
49+
}
50+
51+
} // namespace mongo
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* Copyright (C) 2012 10gen Inc.
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU Affero General Public License, version 3,
6+
* as published by the Free Software Foundation.
7+
*
8+
* This program is distributed in the hope that it will be useful,
9+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
* GNU Affero General Public License for more details.
12+
*
13+
* You should have received a copy of the GNU Affero General Public License
14+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15+
*/
16+
17+
#pragma once
18+
19+
#include "mongo/base/disallow_copying.h"
20+
#include "mongo/base/status.h"
21+
#include "mongo/client/dbclientinterface.h"
22+
#include "mongo/db/auth/auth_external_state_server_common.h"
23+
24+
namespace mongo {
25+
26+
/**
27+
* The implementation of AuthExternalState functionality for mongos.
28+
*/
29+
class AuthExternalStateMongos : public AuthExternalStateServerCommon {
30+
MONGO_DISALLOW_COPYING(AuthExternalStateMongos);
31+
32+
public:
33+
AuthExternalStateMongos();
34+
virtual ~AuthExternalStateMongos();
35+
36+
virtual Status getPrivilegeDocument(const string& dbname,
37+
const string& principalName,
38+
BSONObj* result);
39+
};
40+
41+
} // namespace mongo

0 commit comments

Comments
 (0)