0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-24 00:17:37 +01:00
mongodb/jstests/ssl/tlsCATrusts.js
2023-08-06 20:48:04 +00:00

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]);
});