mirror of https://github.com/mongodb/mongo
224 lines
7.0 KiB
JavaScript
224 lines
7.0 KiB
JavaScript
// Check if this build supports the authenticationMechanisms startup parameter.
|
|
|
|
import {ShardingTest} from "jstests/libs/shardingtest.js";
|
|
|
|
const SERVER_CERT = "jstests/libs/server.pem";
|
|
const SERVER_SAN_CERT = "jstests/libs/server_SAN.pem";
|
|
const CLIENT_CERT = "jstests/libs/client.pem";
|
|
const CA_CERT = "jstests/libs/ca.pem";
|
|
|
|
const SERVER_USER = "CN=server,OU=Kernel,O=MongoDB,L=New York City,ST=New York,C=US";
|
|
const SERVER_SAN_USER = "CN=Kernel Client Peer Role,OU=Kernel,O=MongoDB,L=New York City,ST=New York,C=US";
|
|
const CLIENT_USER = "CN=client,OU=KernelUser,O=MongoDB,L=New York City,ST=New York,C=US";
|
|
|
|
function authAndTest(cert, user) {
|
|
const INVALID_USER = "C=US,ST=New York,L=New York City,O=MongoDB,OU=KernelUser,CN=invalid";
|
|
|
|
let external = db.getSiblingDB("$external");
|
|
let test = db.getSiblingDB("test");
|
|
|
|
assert(
|
|
!external.auth({user: INVALID_USER, mechanism: "MONGODB-X509"}),
|
|
"authentication with invalid user should fail",
|
|
);
|
|
assert(external.auth({user: user, mechanism: "MONGODB-X509"}), "authentication with valid user failed");
|
|
assert(external.auth({mechanism: "MONGODB-X509"}), "authentication with valid cert and no user field failed");
|
|
assert(
|
|
external.runCommand({authenticate: 1, mechanism: "MONGODB-X509", user: user}).ok,
|
|
"runCommand authentication with valid cert and user field failed",
|
|
);
|
|
assert(
|
|
external.runCommand({authenticate: 1, mechanism: "MONGODB-X509"}).ok,
|
|
"runCommand authentication with valid cert and no user field failed",
|
|
);
|
|
// Smoke our current user with a find.
|
|
test.foo.findOne();
|
|
|
|
// Check that we can add a user and read data.
|
|
test.createUser({user: "test", pwd: "test", roles: [{"role": "readWriteAnyDatabase", "db": "admin"}]});
|
|
test.foo.findOne();
|
|
|
|
// Reads are not allowed after logout.
|
|
external.logout();
|
|
assert.throws(
|
|
function () {
|
|
test.foo.findOne();
|
|
},
|
|
[],
|
|
"read after logout",
|
|
);
|
|
}
|
|
|
|
function runSubShell(conn, cert, user, func) {
|
|
const args = [
|
|
"mongo",
|
|
"--tls",
|
|
`--tlsCAFile=${CA_CERT}`,
|
|
`--tlsCertificateKeyFile=${cert}`,
|
|
"--tlsAllowInvalidHostnames",
|
|
"--authenticationDatabase=$external",
|
|
"--authenticationMechanism=MONGODB-X509",
|
|
`mongodb://${conn.host}`,
|
|
"--eval",
|
|
`(${func.toString()})('${cert}', '${user}');`,
|
|
];
|
|
const ret = _runMongoProgram(...args);
|
|
assert(ret == ErrorCodes.OK, "subshell did not succeed");
|
|
}
|
|
|
|
function initUser(conn, user) {
|
|
const external = conn.getDB("$external");
|
|
external.createUser({
|
|
user: user,
|
|
roles: [
|
|
{"role": "userAdminAnyDatabase", "db": "admin"},
|
|
{"role": "readWriteAnyDatabase", "db": "admin"},
|
|
{"role": "clusterMonitor", "db": "admin"},
|
|
],
|
|
});
|
|
|
|
// Localhost exception should not be in place anymore
|
|
const test = conn.getDB("test");
|
|
assert.throws(
|
|
function () {
|
|
test.foo.findOne();
|
|
},
|
|
[],
|
|
"read without login",
|
|
);
|
|
}
|
|
|
|
const x509_options = {
|
|
tlsMode: "requireTLS",
|
|
tlsCertificateKeyFile: SERVER_CERT,
|
|
tlsCAFile: CA_CERT,
|
|
};
|
|
|
|
const mongodOptions = Object.merge(x509_options, {auth: "", setParameter: {enforceUserClusterSeparation: false}});
|
|
|
|
const mongosOptions = Object.merge(x509_options, {setParameter: {enforceUserClusterSeparation: false}});
|
|
|
|
function runMongodTest(desc, func) {
|
|
print(desc);
|
|
const mongo = MongoRunner.runMongod(mongodOptions);
|
|
func(mongo);
|
|
|
|
MongoRunner.stopMongod(mongo);
|
|
}
|
|
|
|
function runMongodFailTest(desc, options) {
|
|
print(desc);
|
|
assert.throws(
|
|
() => MongoRunner.runMongod(Object.merge(mongodOptions, options)),
|
|
[],
|
|
"MongoD started successfully with bad options",
|
|
);
|
|
}
|
|
|
|
function runMongosTest(desc, func) {
|
|
print(desc);
|
|
const st = new ShardingTest({
|
|
shards: 1,
|
|
mongos: 1,
|
|
other: {
|
|
keyFile: "jstests/libs/key1",
|
|
configOptions: mongodOptions,
|
|
mongosOptions: mongosOptions,
|
|
rsOptions: x509_options,
|
|
useHostname: false,
|
|
},
|
|
});
|
|
|
|
const mongo = new Mongo(`localhost:${st.s0.port}`);
|
|
func(mongo);
|
|
st.stop();
|
|
}
|
|
|
|
function runMongosFailTest(desc, options) {
|
|
print(desc);
|
|
// We start the ShardingTest cleanly first because it throws and fails to clean up after itself.
|
|
const st = new ShardingTest({
|
|
config: 1,
|
|
shards: 1,
|
|
mongos: 1,
|
|
other: {
|
|
keyFile: "jstests/libs/key1",
|
|
configOptions: mongodOptions,
|
|
mongosOptions: mongosOptions,
|
|
rsOptions: x509_options,
|
|
useHostname: false,
|
|
},
|
|
});
|
|
|
|
const failOptions = Object.merge(mongosOptions, options);
|
|
print(`Fail options: ${tojson(failOptions)}`);
|
|
|
|
assert.throws(
|
|
function () {
|
|
// Start a new mongos with bad options.
|
|
st.restartMongos(0, failOptions);
|
|
},
|
|
[],
|
|
"MongoS restarted successfully with bad options",
|
|
);
|
|
|
|
// Avoid st.stop() because it will throw when it attempts to stop the second mongos.
|
|
st.stopAllShards();
|
|
st.stopAllConfigServers();
|
|
}
|
|
|
|
runMongodTest("1a. Testing x.509 auth to mongod with a client user/cert", function (conn) {
|
|
initUser(conn, CLIENT_USER);
|
|
|
|
runSubShell(conn, CLIENT_CERT, CLIENT_USER, authAndTest);
|
|
});
|
|
|
|
runMongodTest("1b. Testing x.509 auth to mongod with the server user/cert", function (conn) {
|
|
initUser(conn, SERVER_USER);
|
|
|
|
runSubShell(conn, SERVER_CERT, SERVER_USER, authAndTest);
|
|
});
|
|
|
|
runMongodTest("1c. Testing x.509 auth to mongod with a cluster user/cert", function (conn) {
|
|
initUser(conn, SERVER_SAN_USER);
|
|
|
|
runSubShell(conn, SERVER_SAN_CERT, SERVER_SAN_USER, authAndTest);
|
|
});
|
|
|
|
runMongodFailTest('1d. Testing x.509 cluster auth on mongod with "x509" option', {clusterAuthMode: "x509"});
|
|
|
|
runMongodFailTest('1e. Testing x.509 cluster auth on mongod with "sendX509" option', {clusterAuthMode: "sendX509"});
|
|
|
|
runMongodFailTest('1e. Testing x.509 cluster auth on mongod with "sendKeyFile" option', {
|
|
clusterAuthMode: "sendKeyFile",
|
|
});
|
|
|
|
runMongosTest("2a. Testing x.509 auth to mongos with a client user/cert", function (conn) {
|
|
initUser(conn, CLIENT_USER);
|
|
|
|
runSubShell(conn, CLIENT_CERT, CLIENT_USER, authAndTest);
|
|
});
|
|
|
|
runMongosTest("2b. Testing x.509 auth to mongos with the server user/cert", function (conn) {
|
|
initUser(conn, SERVER_USER);
|
|
|
|
runSubShell(conn, SERVER_CERT, SERVER_USER, authAndTest);
|
|
});
|
|
|
|
runMongosTest("2c. Testing x.509 auth to mongos with a cluster user/cert", function (conn) {
|
|
initUser(conn, SERVER_SAN_USER);
|
|
|
|
runSubShell(conn, SERVER_SAN_CERT, SERVER_SAN_USER, authAndTest);
|
|
});
|
|
|
|
runMongosFailTest('2d. Testing x.509 cluster auth on mongos with "x509" option', {
|
|
restart: true,
|
|
clusterAuthMode: "x509",
|
|
});
|
|
|
|
runMongosFailTest('2e. Testing x.509 cluster auth on mongos with "sendX509" option', {clusterAuthMode: "sendX509"});
|
|
|
|
runMongosFailTest('2f. Testing x.509 cluster auth on mongos with "sendKeyFile" option', {
|
|
clusterAuthMode: "sendKeyFile",
|
|
});
|