diff options
Diffstat (limited to 'jstests/auth/repl.js')
| -rw-r--r-- | jstests/auth/repl.js | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/jstests/auth/repl.js b/jstests/auth/repl.js new file mode 100644 index 00000000000..3dfd01df6f5 --- /dev/null +++ b/jstests/auth/repl.js @@ -0,0 +1,249 @@ +// Test that authorization information gets propogated correctly to secondaries and slaves. + +var baseName = "jstests_auth_repl"; +var rsName = baseName + "_rs"; +var rtName = baseName + "_rt"; +var mongoOptions = {auth: null, keyFile: "jstests/libs/key1"}; +var authErrCode = 13; + +var AuthReplTest = function(spec) { + var that = {}; + + // argument validation + assert("primaryConn" in spec); + assert("secondaryConn" in spec); + + // private vars + var primaryConn, secondaryConn; + var adminPri, adminSec; + var testUser = "testUser", testRole = "testRole", testRole2 = "testRole2"; + + primaryConn = spec.primaryConn; + secondaryConn = spec.secondaryConn; + + adminPri = primaryConn.getDB("admin"); + adminPri.addUser({user: "super", pwd: "super", roles: ["__system"]}); + assert(adminPri.auth("super", "super"), "could not authenticate as superuser"); + + if (secondaryConn != null) { + secondaryConn.setSlaveOk(true); + adminSec = secondaryConn.getDB("admin"); + } + + /* --- private functions --- */ + + var authOnSecondary = function() { + assert(adminSec.auth(testUser, testUser), "could not authenticate as test user"); + }; + + /** + * Use the rolesInfo command to check that the test + * role is as expected on the secondary/slave + */ + var confirmRolesInfo = function(actionType) { + var role = adminSec.getRole(testRole, {showPrivileges: true}); + assert.eq(1, role.privileges.length); + assert.eq(role.privileges[0].actions[0], actionType); + }; + + /** + * Use the usersInfo command to check that the test + * user is as expected on the secondary/slave + */ + var confirmUsersInfo = function(roleName) { + var user = adminSec.getUser(testUser); + assert.eq(1, user.roles.length); + assert.eq(user.roles[0].role, roleName); + }; + + /** + * Ensure that the test user has the proper privileges + * on the secondary/slave + */ + var confirmPrivilegeBeforeUpdate = function() { + // can run hostInfo + var res = adminSec.runCommand({hostInfo: 1}); + assert.commandWorked(res); + + // but cannot run listDatabases + res = adminSec.runCommand({listDatabases: 1}); + assert.commandFailedWithCode(res, authErrCode); + }; + + var updateRole = function() { + var res = adminPri.runCommand({ + updateRole: testRole, + privileges: [ + { resource: {cluster: true}, actions: ["listDatabases"] } + ], + writeConcern: {w: 2, wtimeout: 5000} + }); + assert.commandWorked(res); + }; + + var updateUser = function() { + var res = adminPri.runCommand({ + updateUser: testUser, + roles: [testRole2], + writeConcern: {w: 2, wtimeout: 5000} + }); + assert.commandWorked(res); + }; + + /** + * Ensure that the auth changes have taken effect + * properly on the secondary/slave + */ + var confirmPrivilegeAfterUpdate = function() { + // cannot run hostInfo + var res = adminSec.runCommand({hostInfo: 1}); + assert.commandFailedWithCode(res, authErrCode); + + // but can run listDatabases + res = adminSec.runCommand({listDatabases: 1}); + assert.commandWorked(res); + }; + + /** + * Remove test users and roles + */ + var cleanup = function() { + var res = adminPri.runCommand({dropUser: testUser, + writeConcern: {w: 2, wtimeout: 5000}}); + assert.commandWorked(res); + res = adminPri.runCommand({dropAllRolesFromDatabase: 1, + writeConcern: {w: 2, wtimeout: 5000}}); + assert.commandWorked(res); + }; + + /* --- public functions --- */ + + /** + * Set the secondary for the test + */ + that.setSecondary = function(secondary) { + secondaryConn = secondary; + secondaryConn.setSlaveOk(true); + adminSec = secondaryConn.getDB("admin"); + } + + /** + * Create user and roles in preparation + * for the test. + */ + that.createUserAndRoles = function(numNodes) { + var roles = [testRole, testRole2]; + var actions = ["hostInfo", "listDatabases"]; + for (var i = 0; i < roles.length; i++) { + var res = adminPri.runCommand({ + createRole: roles[i], + privileges: [ + { resource: {cluster: true}, actions: [ actions[i] ] } + ], + roles: [ ], + writeConcern: {w: numNodes, wtimeout: 5000} + }); + assert.commandWorked(res); + } + + var res = adminPri.runCommand({ + createUser: testUser, + pwd: testUser, + roles: [testRole], + writeConcern: {w: numNodes, wtimeout: 5000} + }); + assert.commandWorked(res); + }; + + /** + * Top-level test for updating users and roles and ensuring that the update + * has the correct effect on the secondary/slave + */ + that.testAll = function() { + authOnSecondary(); + confirmPrivilegeBeforeUpdate(); + confirmUsersInfo(testRole); + confirmRolesInfo("hostInfo"); + + updateRole(); + confirmPrivilegeAfterUpdate(); + confirmRolesInfo("listDatabases"); + + updateUser(); + confirmPrivilegeAfterUpdate(); + confirmUsersInfo(testRole2); + + cleanup(); + }; + + return that; +} + +jsTest.log("1 test replica sets"); +var rs = new ReplSetTest({name: rsName, nodes: 2}); +var nodes = rs.startSet(mongoOptions); +rs.initiate(); +rs.awaitReplication(); + +var primary = rs.getPrimary(); +var secondary = rs.getSecondary(); + +var authReplTest = AuthReplTest({ + primaryConn: primary, + secondaryConn: secondary +}); +authReplTest.createUserAndRoles(2); +authReplTest.testAll(); +rs.stopSet(); + +jsTest.log("2 test initial sync"); +rs = new ReplSetTest({name: rsName, nodes: 1, nodeOptions: mongoOptions}); +nodes = rs.startSet(); +rs.initiate(); +rs.awaitReplication(); + +primary = rs.getPrimary(); + +var authReplTest = AuthReplTest({ + primaryConn: primary, + secondaryConn: null +}); +authReplTest.createUserAndRoles(1); + +// Add a secondary and wait for initial sync +rs.add(mongoOptions); +rs.reInitiate(); +rs.awaitSecondaryNodes(); +secondary = rs.getSecondary(); + +authReplTest.setSecondary(secondary); +authReplTest.testAll(); +rs.stopSet(); + +jsTest.log("3 test master/slave"); +var rt = new ReplTest(rtName); + +// start and stop without auth in order to ensure +// existence of the correct dbpath +var master = rt.start(true, {}, false, true); +rt.stop(true); +var slave = rt.start(false, {}, false, true); +rt.stop(false); + +// start master/slave with auth +master = rt.start(true, mongoOptions, true); +slave = rt.start(false, mongoOptions, true); +var masterDB = master.getDB("admin"); + +// ensure that master/slave replication is up and running +masterDB.foo.save({}, { writeConcern: { w: 2, wtimeout: 5000 }}); +masterDB.foo.drop(); + +authReplTest = AuthReplTest({ + primaryConn: master, + secondaryConn: slave +}); +authReplTest.createUserAndRoles(2); +authReplTest.testAll(); +rt.stop(); + |
