mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-24 00:17:37 +01:00
188 lines
7.3 KiB
JavaScript
188 lines
7.3 KiB
JavaScript
// Test restricting role authorization via X509 extensions.
|
|
import {requireSSLProvider} from "jstests/ssl/libs/ssl_helpers.js";
|
|
|
|
requireSSLProvider('openssl', function() {
|
|
const SERVER_CERT = 'jstests/libs/server.pem';
|
|
const COMBINED_CA_CERT = 'jstests/ssl/x509/root-and-trusted-ca.pem';
|
|
const CA_HASH = cat('jstests/libs/ca.pem.digest.sha256');
|
|
const TRUSTED_CA_HASH = cat('jstests/libs/trusted-ca.pem.digest.sha256');
|
|
|
|
// Common suffix, keep the lines short.
|
|
const RDN_SUFFIX = ',O=MongoDB,L=New York City,ST=New York,C=US';
|
|
const USERS = [];
|
|
|
|
const CLIENT = {
|
|
cert: 'jstests/libs/client.pem',
|
|
roles: [],
|
|
};
|
|
USERS.push('CN=client,OU=KernelUser');
|
|
|
|
const CLIENT_ROLES = {
|
|
cert: 'jstests/libs/client_roles.pem',
|
|
roles: [{role: 'backup', db: 'admin'}, {role: 'readAnyDatabase', db: 'admin'}],
|
|
};
|
|
USERS.push('CN=Kernel Client Peer Role,OU=Kernel Users');
|
|
|
|
const TRUSTED_CLIENT_TESTDB_ROLES = {
|
|
cert: 'jstests/ssl/x509/trusted-client-testdb-roles.pem',
|
|
roles: [{role: 'role1', db: 'testDB'}, {role: 'role2', db: 'testDB'}],
|
|
};
|
|
USERS.push('CN=Trusted Kernel Test Client With Roles,OU=Kernel Users');
|
|
|
|
function test(tlsCATrusts, success, failure) {
|
|
const options = {
|
|
auth: '',
|
|
tlsMode: 'requireTLS',
|
|
tlsCertificateKeyFile: SERVER_CERT,
|
|
tlsCAFile: COMBINED_CA_CERT,
|
|
};
|
|
|
|
if (tlsCATrusts !== null) {
|
|
options.setParameter = {
|
|
tlsCATrusts: tojson(tlsCATrusts),
|
|
};
|
|
}
|
|
|
|
const mongod = MongoRunner.runMongod(options);
|
|
|
|
const admin = mongod.getDB('admin');
|
|
admin.createUser({user: 'admin', pwd: 'pwd', roles: ['root']});
|
|
admin.auth({user: 'admin', pwd: 'pwd'});
|
|
|
|
const external = mongod.getDB('$external');
|
|
USERS.forEach((u) => external.createUser({user: u + RDN_SUFFIX, roles: []}));
|
|
|
|
const testDB = mongod.getDB('test');
|
|
testDB.createRole({role: 'role1', privileges: [], roles: []});
|
|
testDB.createRole({role: 'role2', privileges: [], roles: []});
|
|
|
|
// Sorting JS arrays of objects with arbitrary order is... complex.
|
|
const serverTrusts =
|
|
assert.commandWorked(admin.runCommand({getParameter: 1, tlsCATrusts: 1})).tlsCATrusts;
|
|
function sortAndNormalizeRoles(roles) {
|
|
return roles.map((r) => r.role + '.' + r.db).sort().join('/');
|
|
}
|
|
function sortAndNormalizeTrusts(trusts) {
|
|
if (trusts === null) {
|
|
return "(unconfigured)";
|
|
}
|
|
return trusts.map((t) => t.sha256 + '/' + sortAndNormalizeRoles(t.roles)).sort();
|
|
}
|
|
assert.eq(sortAndNormalizeTrusts(tlsCATrusts), sortAndNormalizeTrusts(serverTrusts));
|
|
|
|
function impl(user, expect) {
|
|
const snRoles = tojson(sortAndNormalizeRoles(user.roles));
|
|
const uri = 'mongodb://localhost:' + mongod.port + '/admin';
|
|
const script = tojson(sortAndNormalizeRoles) +
|
|
'assert(db.getSiblingDB("$external").auth({mechanism: "MONGODB-X509"}));' +
|
|
'const status = assert.commandWorked(db.runCommand({connectionStatus: 1}));' +
|
|
'const roles = status.authInfo.authenticatedUserRoles;' +
|
|
'assert.eq(' + snRoles + ', sortAndNormalizeRoles(roles));';
|
|
const mongo = runMongoProgram('mongo',
|
|
'--tls',
|
|
'--tlsCertificateKeyFile',
|
|
user.cert,
|
|
'--tlsCAFile',
|
|
COMBINED_CA_CERT,
|
|
uri,
|
|
'--eval',
|
|
script);
|
|
expect(mongo, 0);
|
|
}
|
|
|
|
success.forEach((u) => impl(u, assert.eq));
|
|
failure.forEach((u) => impl(u, assert.neq));
|
|
|
|
MongoRunner.stopMongod(mongod);
|
|
}
|
|
|
|
// Positive tests.
|
|
const unconfigured = null;
|
|
test(unconfigured, [CLIENT, CLIENT_ROLES, TRUSTED_CLIENT_TESTDB_ROLES], []);
|
|
|
|
const allRoles = [
|
|
{sha256: CA_HASH, roles: [{role: '', db: ''}]},
|
|
{sha256: TRUSTED_CA_HASH, roles: [{role: '', db: ''}]}
|
|
];
|
|
test(allRoles, [CLIENT, CLIENT_ROLES, TRUSTED_CLIENT_TESTDB_ROLES], []);
|
|
|
|
const allRolesOnAdmin = [{sha256: CA_HASH, roles: [{role: '', db: 'admin'}]}];
|
|
test(allRolesOnAdmin, [CLIENT, CLIENT_ROLES], [TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const specificRolesOnAnyDB =
|
|
[{sha256: CA_HASH, roles: [{role: 'backup', db: ''}, {role: 'readAnyDatabase', db: ''}]}];
|
|
test(specificRolesOnAnyDB, [CLIENT, CLIENT_ROLES], [TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const exactRoles = [{
|
|
sha256: CA_HASH,
|
|
roles: [{role: 'backup', db: 'admin'}, {role: 'readAnyDatabase', db: 'admin'}]
|
|
}];
|
|
test(exactRoles, [CLIENT, CLIENT_ROLES], [TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const extraRoles = [{
|
|
sha256: CA_HASH,
|
|
roles: [
|
|
{role: 'backup', db: 'admin'},
|
|
{role: 'readAnyDatabase', db: 'admin'},
|
|
{role: 'readWrite', db: 'admin'}
|
|
]
|
|
}];
|
|
test(extraRoles, [CLIENT, CLIENT_ROLES], [TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const similarRoles = [
|
|
{
|
|
sha256: CA_HASH,
|
|
roles: [
|
|
{role: 'backup', db: 'test'},
|
|
{role: 'readAnyDatabase', db: ''},
|
|
{role: 'backup', db: 'admin'}
|
|
]
|
|
},
|
|
{
|
|
sha256: TRUSTED_CA_HASH,
|
|
roles: [
|
|
{role: 'role1', db: 'admin'},
|
|
{role: 'role2', db: 'testDB'},
|
|
{role: 'role1', db: 'testDB'},
|
|
]
|
|
}
|
|
];
|
|
test(similarRoles, [CLIENT, CLIENT_ROLES, TRUSTED_CLIENT_TESTDB_ROLES], []);
|
|
|
|
const withUntrusted =
|
|
[{sha256: CA_HASH, roles: [{role: '', db: ''}]}, {sha256: TRUSTED_CA_HASH, roles: []}];
|
|
test(withUntrusted, [CLIENT, CLIENT_ROLES], [TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const customRoles = [{
|
|
sha256: TRUSTED_CA_HASH,
|
|
roles: [
|
|
{role: 'role1', db: 'testDB'},
|
|
{role: 'role2', db: 'testDB'},
|
|
]
|
|
}];
|
|
test(customRoles, [CLIENT, TRUSTED_CLIENT_TESTDB_ROLES], [CLIENT_ROLES]);
|
|
|
|
// Negative tests. CLIENT_CERT is okay because it doesn't ask for roles.
|
|
const noTrustedCAs = [];
|
|
test(noTrustedCAs, [CLIENT], [CLIENT_ROLES, TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const noRoles = [{sha256: CA_HASH, roles: []}];
|
|
test(noRoles, [CLIENT], [CLIENT_ROLES, TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const insufficientRoles1 = [
|
|
{sha256: CA_HASH, roles: [{role: 'backup', db: ''}]},
|
|
{sha256: TRUSTED_CA_HASH, roles: [{role: 'role1', db: 'testDB'}]}
|
|
];
|
|
test(insufficientRoles1, [CLIENT], [CLIENT_ROLES, TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const insufficientRoles2 = [
|
|
{sha256: CA_HASH, roles: [{role: 'readWriteAnyDatabase', db: ''}]},
|
|
{sha256: TRUSTED_CA_HASH, roles: [{role: 'role2', db: 'testDB'}]}
|
|
];
|
|
test(insufficientRoles2, [CLIENT], [CLIENT_ROLES, TRUSTED_CLIENT_TESTDB_ROLES]);
|
|
|
|
const withTrusted =
|
|
[{sha256: CA_HASH, roles: []}, {sha256: TRUSTED_CA_HASH, roles: [{role: '', db: ''}]}];
|
|
test(withTrusted, [CLIENT, TRUSTED_CLIENT_TESTDB_ROLES], [CLIENT_ROLES]);
|
|
});
|