0
0
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:
Aaron 2010-01-26 17:04:09 -08:00
parent c11297df9a
commit dcce5e795e
11 changed files with 79 additions and 15 deletions

View File

@ -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();

View File

@ -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 ) {

View File

@ -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;
}
};

View File

@ -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

View File

@ -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);

View File

@ -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");

View File

@ -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
View 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() );

View File

@ -1,5 +1,3 @@
users = db.getCollection( "system.users" );
users.remove( {} );

View File

@ -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 = (

View File

@ -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 ) );