summaryrefslogtreecommitdiff
path: root/jstests/auth/cluster_ip_allowlist.js
blob: 76ac47593d956de303bc94802819e2b5382bef77 (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
138
139
140
141
142
143
144
145
146
147
148
/**
 * This test checks that cluster IP allowlists can be set and respected.
 */

(function() {
'use strict';

print("When allowlist is empty, the server does not start.");
assert.throws(() => MongoRunner.runMongod(
                  {auth: null, keyFile: "jstests/libs/key1", clusterIpSourceAllowlist: ""}),
              [],
              "The server unexpectedly started");
// Check that the same behavior is seen with the deprecated 'clusterIpSourceWhiteList' flag.
assert.throws(() => MongoRunner.runMongod(
                  {auth: null, keyFile: "jstests/libs/key1", clusterIpSourceWhitelist: ""}),
              [],
              "The server unexpectedly started");

function emitWarningAuthErrorIsExpected(authResult) {
    if (!authResult) {
        print("***** NOTE: an authentication error is expected");
    }
}

function testIpAllowlistStartup(description, allowlistString, authResult) {
    print("Startup: " + description);

    let conn = MongoRunner.runMongod(
        {auth: null, keyFile: "jstests/libs/key1", clusterIpSourceAllowlist: allowlistString});
    assert.eq(authResult, conn.getDB("local").auth("__system", "foopdedoop"));
    emitWarningAuthErrorIsExpected(authResult);
    MongoRunner.stopMongod(conn);

    // Verify that the deprecated 'clusterIpSourceWhitelist' flag still exhibits the same behavior.
    conn = MongoRunner.runMongod(
        {auth: null, keyFile: "jstests/libs/key1", clusterIpSourceWhitelist: allowlistString});
    assert.eq(authResult, conn.getDB("local").auth("__system", "foopdedoop"));
    emitWarningAuthErrorIsExpected(authResult);
    MongoRunner.stopMongod(conn);
}

function testIpAllowlistRuntime(description, allowlistString, authResult) {
    print("Runtime: " + description);

    const conn = MongoRunner.runMongod({keyFile: "jstests/libs/key1"});

    // Must create a user to verify that we don't fallback to localhost exception for auth.
    assert.commandWorked(
        conn.getDB('admin').runCommand({createUser: 'admin', pwd: 'admin', roles: ['root']}));

    assert.eq(true, conn.getDB("local").auth("__system", "foopdedoop"));

    print("Testing whether __system can login after set to: " + allowlistString);
    assert.commandWorked(conn.adminCommand(
        {setParameter: 1, "clusterIpSourceAllowlist": allowlistString.split(",")}));
    if (!authResult) {
        // At this time we have no valid authentication, and existing session should reset.
        // We should expect admin commands to fail.
        print("Verifying that there is no longer authenticated session and admin commands fail");
        assert.commandFailed(conn.adminCommand({fsync: 1}));
    }

    assert.eq(authResult, conn.getDB("local").auth("__system", "foopdedoop"));
    emitWarningAuthErrorIsExpected(authResult);

    if (!authResult) {
        print("Authenticating with admin user since __system is barred");
        conn.getDB('admin').auth('admin', 'admin');
    }

    print("Testing that __system can login after reset to null");
    assert.commandWorked(conn.adminCommand({setParameter: 1, "clusterIpSourceAllowlist": null}));
    conn.getDB("local").logout();
    assert.eq(true, conn.getDB("local").auth("__system", "foopdedoop"));
    MongoRunner.stopMongod(conn);
}

function testIpAllowlist(description, allowlistString, authResult) {
    testIpAllowlistStartup(description, allowlistString, authResult);
    testIpAllowlistRuntime(description, allowlistString, authResult);
}

function testIpAllowlistRuntimeGarbage() {
    print("Testing that garbage input is handled");

    const conn = MongoRunner.runMongod({auth: null, keyFile: "jstests/libs/key1"});
    assert.eq(true, conn.getDB("local").auth("__system", "foopdedoop"));

    const BAD_INPUTS = [
        [""],
        ["abcxyz"],
        ["1.1.1.1", "abcxyz"],
        ["1.1.1.1/abcxyz"],
        "1.1.1.1",
        1,
        {"something": "something else"},
        ["1.1.1.1", {"something": "something else"}],
    ];

    for (let bi in BAD_INPUTS) {
        print(bi);
        assert.commandFailed(conn.adminCommand({setParameter: 1, "clusterIpSourceAllowlist": bi}));
    }

    print("Testing that __system can login after reset to null");
    assert.commandWorked(conn.adminCommand({setParameter: 1, "clusterIpSourceAllowlist": null}));
    conn.getDB("local").logout();
    assert.eq(true, conn.getDB("local").auth("__system", "foopdedoop"));
    MongoRunner.stopMongod(conn);
}

testIpAllowlist(
    "When 127.0.0.1 is allowlisted, a client connected via localhost may auth as __system.",
    "127.0.0.1",
    true);

testIpAllowlist(
    "When 127.0.0.0 is allowlisted as a 24-bit CIDR block, a client connected via localhost may auth as __system.",
    "127.0.0.0/24",
    true);

testIpAllowlist(
    "When 127.0.0.5 is allowlisted as a 24-bit CIDR block, a client connected via localhost may auth as __system.",
    "127.0.0.5/24",
    true);

testIpAllowlist(
    "When 127.0.0.0 is allowlisted as a 8-bit CIDR block, a client connected via localhost may auth as __system.",
    "127.0.0.0/8",
    true);

testIpAllowlist(
    "When the IP block reserved for documentation and the 127.0.0.0/8 block are both allowlisted, a client connected via localhost may auth as __system.",
    "192.0.2.0/24,127.0.0.0/8",
    true);

testIpAllowlist(
    "When 127.0.0.0/8 and the IP block reserved for documentation are both allowlisted, a client connected via localhost may auth as __system.",
    "127.0.0.0/8,192.0.2.0/24",
    true);

testIpAllowlist(
    "When the IP block reserved for documentation and examples is allowlisted, a client connected via localhost may not auth as __system.",
    "192.0.2.0/24",
    false);

testIpAllowlistRuntimeGarbage();
}());