// 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.createUser({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: 15000} }); assert.commandWorked(res); }; var updateUser = function() { var res = adminPri.runCommand( {updateUser: testUser, roles: [testRole2], writeConcern: {w: 2, wtimeout: 15000}}); 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: 15000}}); assert.commandWorked(res); res = adminPri.runCommand( {dropAllRolesFromDatabase: 1, writeConcern: {w: 2, wtimeout: 15000}}); 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: 15000} }); assert.commandWorked(res); } var res = adminPri.runCommand({ createUser: testUser, pwd: testUser, roles: [testRole], writeConcern: {w: numNodes, wtimeout: 15000} }); 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(); authutil.asCluster(nodes, "jstests/libs/key1", function() { 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(); authutil.asCluster(nodes, "jstests/libs/key1", function() { 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();