summaryrefslogtreecommitdiff
path: root/jstests/replsets/advance_cluster_time.js
blob: 2e4fdf74b153a14195db5ffd41bbb288a86ea4bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
 * Test that the client cannot gossip clusterTime from one replica set to another if it doesn't
 * have the advanceClusterTime privilege.
 *
 * @tags: [
 * ]
 */

(function() {
"use strict";

// Multiple users cannot be authenticated on one connection within a session.
TestData.disableImplicitSessions = true;

const kDbName = "testDb";
const kCollName = "testColl";

const kAdminUser = {
    name: "admin",
    pwd: "admin",
};

const kUserWithoutAdvanceClusterTimePrivilege = {
    name: "cannotAdvanceClusterTime",
    pwd: "pwd"
};
const kUserWithAdvanceClusterTimePrivilege = {
    name: "canAdvanceClusterTime",
    pwd: "pwd"
};

function createUsers(primary) {
    // Create the admin user and advanceClusterTimeRole.
    const adminDB = primary.getDB("admin");
    assert.commandWorked(
        adminDB.runCommand({createUser: kAdminUser.name, pwd: kAdminUser.pwd, roles: ["root"]}));
    assert.eq(1, adminDB.auth(kAdminUser.name, kAdminUser.pwd));
    assert.commandWorked(adminDB.runCommand({
        createRole: "advanceClusterTimeRole",
        privileges: [{resource: {cluster: true}, actions: ["advanceClusterTime"]}],
        roles: []
    }));

    // Create one user without advanceClusterTime privilege, and one with advanceClusterTime
    // privilege.
    const testDB = primary.getDB(kDbName);
    assert.commandWorked(testDB.runCommand({
        createUser: kUserWithoutAdvanceClusterTimePrivilege.name,
        pwd: kUserWithoutAdvanceClusterTimePrivilege.pwd,
        roles: ["readWrite"]
    }));
    assert.commandWorked(testDB.runCommand({
        createUser: kUserWithAdvanceClusterTimePrivilege.name,
        pwd: kUserWithAdvanceClusterTimePrivilege.pwd,
        roles: [{role: "advanceClusterTimeRole", db: "admin"}, "readWrite"]
    }));
    adminDB.logout();
}

const rst1 = new ReplSetTest({
    nodes: [
        {setParameter: {"failpoint.alwaysValidateClientsClusterTime": tojson({mode: "alwaysOn"})}}
    ],
    name: "rst1",
    keyFile: "jstests/libs/key1"
});
const rst2 = new ReplSetTest({nodes: 1, name: "rst2", keyFile: "jstests/libs/key2"});

rst1.startSet();
rst1.initiate();

rst2.startSet();
rst2.initiate();

const rst1Primary = rst1.getPrimary();
const rst2Primary = rst2.getPrimary();

createUsers(rst1Primary);
createUsers(rst2Primary);

const rst1TestDB = rst1Primary.getDB(kDbName);
const rst2TestDB = rst2Primary.getDB(kDbName);

// Test clusterTime gossip when the client does not have advanceClusterTime privilege.
(() => {
    assert.eq(1,
              rst1TestDB.auth(kUserWithoutAdvanceClusterTimePrivilege.name,
                              kUserWithoutAdvanceClusterTimePrivilege.pwd));
    assert.eq(1,
              rst2TestDB.auth(kUserWithoutAdvanceClusterTimePrivilege.name,
                              kUserWithoutAdvanceClusterTimePrivilege.pwd));

    const rst1ClusterTime =
        assert.commandWorked(rst1TestDB.runCommand({find: kCollName})).$clusterTime;
    const rst2ClusterTime =
        assert.commandWorked(rst2TestDB.runCommand({insert: kCollName, documents: [{_id: 0}]}))
            .$clusterTime;
    jsTest.log("rst1's clusterTime " + tojson(rst1ClusterTime));
    jsTest.log("rst2's clusterTime " + tojson(rst2ClusterTime));

    // A key's keyId is generated as the node's current clusterTime's Timestamp so it is possible
    // for the keyId for rst2ClusterTime to match the key on rst1, and in that case the command
    // would fail with TimeProofMismatch instead of KeyNotFound.
    assert.commandFailedWithCode(
        rst1TestDB.runCommand({find: kCollName, $clusterTime: rst2ClusterTime}),
        [ErrorCodes.TimeProofMismatch, ErrorCodes.KeyNotFound]);

    rst1TestDB.logout();
    rst2TestDB.logout();
})();

// Test clusterTime gossip when the client does have advanceClusterTime privilege.
(() => {
    assert.eq(1,
              rst1TestDB.auth(kUserWithAdvanceClusterTimePrivilege.name,
                              kUserWithAdvanceClusterTimePrivilege.pwd));
    assert.eq(1,
              rst2TestDB.auth(kUserWithoutAdvanceClusterTimePrivilege.name,
                              kUserWithoutAdvanceClusterTimePrivilege.pwd));

    const rst1ClusterTime =
        assert.commandWorked(rst1TestDB.runCommand({find: kCollName})).$clusterTime;
    const rst2ClusterTime =
        assert.commandWorked(rst2TestDB.runCommand({insert: kCollName, documents: [{_id: 1}]}))
            .$clusterTime;
    jsTest.log("rst1's clusterTime " + tojson(rst1ClusterTime));
    jsTest.log("rst2's clusterTime " + tojson(rst2ClusterTime));

    assert.commandWorked(rst1TestDB.runCommand({find: kCollName, $clusterTime: rst2ClusterTime}));

    rst1TestDB.logout();
    rst2TestDB.logout();
})();

rst1.stopSet();
rst2.stopSet();
})();