mirror of
https://github.com/mongodb/mongo.git
synced 2024-12-01 09:32:32 +01:00
SERVER-258 add readOnly auth mode
This commit is contained in:
parent
c11297df9a
commit
dcce5e795e
@ -1431,7 +1431,13 @@ namespace mongo {
|
||||
if ( c ){
|
||||
string errmsg;
|
||||
AuthenticationInfo *ai = currentClient.get()->ai;
|
||||
uassert( 10045 , "unauthorized", ai->isAuthorized(cc().database()->name.c_str()) || !c->requiresAuth());
|
||||
if ( c->requiresAuth() ) {
|
||||
if ( c->readOnly() ) {
|
||||
uassert( 12593 , "readOnly unauthorized", ai->isReadOnlyAuthorized(cc().database()->name.c_str()));
|
||||
} else {
|
||||
uassert( 10045 , "unauthorized", ai->isAuthorized(cc().database()->name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
bool admin = c->adminOnly();
|
||||
|
||||
|
@ -562,7 +562,7 @@ namespace mongo {
|
||||
QueryResult* msgdata;
|
||||
try {
|
||||
AuthenticationInfo *ai = currentClient.get()->ai;
|
||||
uassert( 10057 , "unauthorized", ai->isAuthorized(cc().database()->name.c_str()));
|
||||
uassert( 10057 , "unauthorized", ai->isReadOnlyAuthorized(cc().database()->name.c_str()));
|
||||
msgdata = getMore(ns, ntoreturn, cursorid, curop);
|
||||
}
|
||||
catch ( AssertionException& e ) {
|
||||
|
@ -125,7 +125,7 @@ namespace mongo {
|
||||
return say( toSend );
|
||||
}
|
||||
class AlwaysAuthorized : public AuthenticationInfo {
|
||||
virtual bool isAuthorized( const char *dbname ) {
|
||||
virtual bool _isAuthorized( const char *dbname, int level ) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -722,7 +722,7 @@ namespace mongo {
|
||||
/* regular query */
|
||||
|
||||
AuthenticationInfo *ai = currentClient.get()->ai;
|
||||
uassert( 10106 , "unauthorized", ai->isAuthorized(c.database()->name.c_str()));
|
||||
uassert( 10106 , "unauthorized", ai->isReadOnlyAuthorized(c.database()->name.c_str()));
|
||||
|
||||
/* we allow queries to SimpleSlave's -- but not to the slave (nonmaster) member of a replica pair
|
||||
so that queries to a pair are realtime consistent as much as possible. use setSlaveOk() to
|
||||
|
@ -267,7 +267,7 @@ namespace mongo {
|
||||
one is not authenticated for admin db to be safe.
|
||||
*/
|
||||
AuthenticationInfo *ai = currentClient.get()->ai;
|
||||
bool authed = ai->isAuthorized("admin");
|
||||
bool authed = ai->isReadOnlyAuthorized("admin");
|
||||
|
||||
if ( replAllDead ) {
|
||||
result.append("ismaster", 0.0);
|
||||
|
@ -53,11 +53,18 @@ namespace mongo {
|
||||
assertInWriteLock();
|
||||
m[dbname].level = 2;
|
||||
}
|
||||
virtual bool isAuthorized(const char *dbname) {
|
||||
if( m[dbname].level == 2 ) return true;
|
||||
void authorizeReadOnly(const char *dbname) {
|
||||
assertInWriteLock();
|
||||
m[dbname].level = 1;
|
||||
}
|
||||
bool isAuthorized(const char *dbname) { return _isAuthorized( dbname, 2 ); }
|
||||
bool isReadOnlyAuthorized(const char *dbname) { return _isAuthorized( dbname, 1 ); }
|
||||
protected:
|
||||
virtual bool _isAuthorized(const char *dbname, int level) {
|
||||
if( m[dbname].level >= level ) return true;
|
||||
if( noauth ) return true;
|
||||
if( m["admin"].level == 2 ) return true;
|
||||
if( m["local"].level == 2 ) return true;
|
||||
if( m["admin"].level >= level ) return true;
|
||||
if( m["local"].level >= level ) return true;
|
||||
if( isLocalHost ) {
|
||||
readlock l("");
|
||||
Client::Context c("admin.system.users");
|
||||
|
@ -152,7 +152,12 @@ namespace mongo {
|
||||
}
|
||||
|
||||
AuthenticationInfo *ai = currentClient.get()->ai;
|
||||
ai->authorize(cc().database()->name.c_str());
|
||||
|
||||
if ( userObj[ "readOnly" ].isBoolean() && userObj[ "readOnly" ].boolean() ) {
|
||||
ai->authorizeReadOnly( cc().database()->name.c_str() );
|
||||
} else {
|
||||
ai->authorize( cc().database()->name.c_str() );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} cmdAuthenticate;
|
||||
|
38
jstests/auth/auth1.js
Normal file
38
jstests/auth/auth1.js
Normal file
@ -0,0 +1,38 @@
|
||||
// test read/write permissions
|
||||
|
||||
port = allocatePorts( 1 )[ 0 ];
|
||||
baseName = "jstests_auth_auth1";
|
||||
|
||||
m = startMongod( "--auth", "--port", port, "--dbpath", "/data/db/" + baseName, "--nohttpinterface", "--bind_ip", "127.0.0.1" );
|
||||
db = m.getDB( "test" );
|
||||
|
||||
t = db[ baseName ];
|
||||
t.drop();
|
||||
|
||||
users = db.getCollection( "system.users" );
|
||||
users.remove( {} );
|
||||
|
||||
db.addUser( "eliot" , "eliot" );
|
||||
db.addUser( "guest" , "guest", true );
|
||||
db.getSisterDB( "admin" ).addUser( "super", "super" );
|
||||
|
||||
assert.throws( function() { t.findOne() }, [], "read without login" );
|
||||
|
||||
assert( db.auth( "eliot" , "eliot" ) , "auth failed" );
|
||||
|
||||
for( i = 0; i < 1000; ++i ) {
|
||||
t.save( {i:i} );
|
||||
}
|
||||
assert.eq( 1000, t.count() );
|
||||
assert.eq( 1000, t.find().toArray().length );
|
||||
|
||||
assert( db.auth( "guest", "guest" ), "auth failed 2" );
|
||||
|
||||
assert.eq( 1000, t.count() );
|
||||
assert.eq( 1000, t.find().toArray().length ); // make sure we have a getMore in play
|
||||
assert.commandWorked( db.runCommand( {ismaster:1} ) );
|
||||
|
||||
assert( !db.getLastError() );
|
||||
t.save( {} ); // fail
|
||||
assert( db.getLastError() );
|
||||
assert.eq( 1000, t.count() );
|
@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
users = db.getCollection( "system.users" );
|
||||
users.remove( {} );
|
||||
|
||||
|
@ -399,7 +399,6 @@
|
||||
934DD88D0EFAD23B00459CC1 /* unittest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unittest.h; sourceTree = "<group>"; };
|
||||
934DD88E0EFAD23B00459CC1 /* util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = util.cpp; sourceTree = "<group>"; };
|
||||
935C941B1106709800439EB1 /* preallocate.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = preallocate.js; sourceTree = "<group>"; };
|
||||
935C9632110794F500439EB1 /* capped6.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = capped6.js; sourceTree = "<group>"; };
|
||||
936B89590F4C899400934AF2 /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = "<group>"; };
|
||||
936B895A0F4C899400934AF2 /* md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = md5.c; sourceTree = "<group>"; };
|
||||
936B895B0F4C899400934AF2 /* md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = md5.h; sourceTree = "<group>"; };
|
||||
@ -424,6 +423,7 @@
|
||||
938E5EB3110E1ED700A8760A /* repair.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = repair.js; sourceTree = "<group>"; };
|
||||
938E60AB110F721900A8760A /* perdbpath.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = perdbpath.js; sourceTree = "<group>"; };
|
||||
938E60AC110F734800A8760A /* directoryperdb.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = directoryperdb.js; sourceTree = "<group>"; };
|
||||
938E639B110FC66900A8760A /* auth1.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = auth1.js; sourceTree = "<group>"; };
|
||||
93A13A210F4620A500AF1B0D /* commands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = commands.cpp; sourceTree = "<group>"; };
|
||||
93A13A230F4620A500AF1B0D /* config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = config.cpp; sourceTree = "<group>"; };
|
||||
93A13A240F4620A500AF1B0D /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
|
||||
@ -732,7 +732,7 @@
|
||||
934BEB9A10DFFA9600178102 /* jstests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
935C9632110794F500439EB1 /* capped6.js */,
|
||||
938E639A110FC66900A8760A /* auth */,
|
||||
93BCE41810F3AF1B00FA139B /* capped2.js */,
|
||||
93BCE1D310F26CDA00FA139B /* fsync2.js */,
|
||||
93BCE15610F25DFE00FA139B /* arrayfind1.js */,
|
||||
@ -1112,6 +1112,14 @@
|
||||
path = util;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
938E639A110FC66900A8760A /* auth */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
938E639B110FC66900A8760A /* auth1.js */,
|
||||
);
|
||||
path = auth;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
93A13A200F4620A500AF1B0D /* s */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -48,10 +48,12 @@ DB.prototype._adminCommand = function( obj ){
|
||||
return this.getSisterDB( "admin" ).runCommand( obj );
|
||||
}
|
||||
|
||||
DB.prototype.addUser = function( username , pass ){
|
||||
DB.prototype.addUser = function( username , pass, readOnly ){
|
||||
readOnly = readOnly || false;
|
||||
var c = this.getCollection( "system.users" );
|
||||
|
||||
var u = c.findOne( { user : username } ) || { user : username };
|
||||
u.readOnly = readOnly;
|
||||
u.pwd = hex_md5( username + ":mongo:" + pass );
|
||||
print( tojson( u ) );
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user