Skip to content

Commit

Permalink
SERVER-7455 x.509 cluster auth tests and expanded use-ssl passthrough
Browse files Browse the repository at this point in the history
  • Loading branch information
agralius committed Sep 30, 2013
1 parent 10870bd commit 625e971
Show file tree
Hide file tree
Showing 13 changed files with 314 additions and 24 deletions.
3 changes: 2 additions & 1 deletion SConscript.smoke
Expand Up @@ -107,7 +107,8 @@ if shellEnv is not None:
addSmoketest( "smokeAggregation", [ add_exe( "mongo" ), add_exe( "mongod" ), add_exe( "mongos" ) ] )
addSmoketest( "smokeMultiVersion", [ add_exe( "mongo" ), add_exe( "mongod" ), add_exe( "mongos" ) ] )
addSmoketest( "smokeFailPoint", [ add_exe( "mongo" ), add_exe( "mongod" ), add_exe( "mongos" ) ] )
addSmoketest( "smokeSsl", [ add_exe("mongo"), add_exe("mongod"), add_exe("mongos") ], ['--use-ssl'] )
addSmoketest( "smokeSsl", [ add_exe("mongo"), add_exe("mongod"), add_exe("mongos") ],
['--use-ssl','--use-x509'] )

addSmoketest( "smokeFailingTests", [ add_exe( "mongo" ), add_exe( "mongod" ) ], ['--only-old-fails', '--continue-on-failure'] )
addSmoketest( "smokeResetFails", [ add_exe( "mongo" ), add_exe( "mongod" ) ], ['--reset-old-fails'] )
Expand Down
42 changes: 33 additions & 9 deletions buildscripts/smoke.py
Expand Up @@ -221,12 +221,13 @@ def start(self):
if authMechanism != 'MONGODB-CR':
argv += ['--setParameter', 'authenticationMechanisms=' + authMechanism]
self.auth = True
if self.kwargs.get('use_ssl'):
if self.kwargs.get('use_ssl') or self.kwargs.get('use_x509'):
argv += ['--sslOnNormalPorts',
'--sslPEMKeyFile', 'jstests/libs/server.pem',
'--sslCAFile', 'jstests/libs/ca.pem',
'--sslWeakCertificateValidation']

if self.kwargs.get('use_x509'):
argv += ['--clusterAuthMode','x509'];
print "running " + " ".join(argv)
self.proc = self._start(buildlogger(argv, is_global=True))

Expand Down Expand Up @@ -384,9 +385,19 @@ def skipTest(path):
if small_oplog: # For tests running in parallel
if basename in ["cursor8.js", "indexh.js", "dropdb.js", "connections_opened.js", "opcounters.js"]:
return True
if auth or keyFile: # For tests running with auth
if use_ssl:
# Skip tests using mongobridge since it does not support SSL
# TODO: Remove when SERVER-10910 has been resolved.
if basename in ["gridfs.js", "initial_sync3.js", "majority.js", "no_chaining.js",
"rollback4.js", "slavedelay3.js", "sync2.js", "tags.js"]:
return True
# TODO: For now skip tests using MongodRunner, remove when SERVER-10909 has been resolved
if basename in ["fastsync.js", "index_retry.js", "ttl_repl_maintenance.js",
"unix_socket1.js"]:
return True;
if auth or keyFile or use_x509: # For tests running with auth
# Skip any tests that run with auth explicitly
if parentDir == "auth" or "auth" in basename:
if parentDir.lower() == "auth" or "auth" in basename.lower():
return True
if parentPath == mongo_repo: # Skip client tests
return True
Expand Down Expand Up @@ -492,7 +503,10 @@ def runTest(test, result):
'TestData.auth = ' + ternary( auth ) + ";" + \
'TestData.keyFile = ' + ternary( keyFile , '"' + str(keyFile) + '"' , 'null' ) + ";" + \
'TestData.keyFileData = ' + ternary( keyFile , '"' + str(keyFileData) + '"' , 'null' ) + ";" + \
'TestData.authMechanism = ' + ternary( authMechanism, '"' + str(authMechanism) + '"', 'null') + ";"
'TestData.authMechanism = ' + ternary( authMechanism,
'"' + str(authMechanism) + '"', 'null') + ";" + \
'TestData.useSSL = ' + ternary( use_ssl ) + ";" + \
'TestData.useX509 = ' + ternary( use_x509 ) + ";"
if os.sys.platform == "win32":
# double quotes in the evalString on windows; this
# prevents the backslashes from being removed when
Expand Down Expand Up @@ -552,6 +566,7 @@ def runTest(test, result):

if start_mongod:
try:
# The purpose of this Connection is to verify that the smoke.py mongod is still up
c = Connection(host="127.0.0.1", port=int(mongod_port), ssl=use_ssl)
except Exception,e:
print "Exception from pymongo: ", e
Expand All @@ -576,7 +591,8 @@ def run_tests(tests):
no_preallocj=no_preallocj,
auth=auth,
authMechanism=authMechanism,
use_ssl=use_ssl).__enter__()
use_ssl=use_ssl,
use_x509=use_x509).__enter__()
else:
master = Nothing()
try:
Expand All @@ -592,7 +608,8 @@ def run_tests(tests):
no_preallocj=no_preallocj,
auth=auth,
authMechanism=authMechanism,
use_ssl=use_ssl).__enter__()
use_ssl=use_ssl,
use_x509=use_x509).__enter__()
primary = Connection(port=master.port, slave_okay=True);

primary.admin.command({'replSetInitiate' : {'_id' : 'foo', 'members' : [
Expand Down Expand Up @@ -645,7 +662,8 @@ def run_tests(tests):
no_preallocj=no_preallocj,
auth=auth,
authMechanism=authMechanism,
use_ssl=use_ssl).__enter__()
use_ssl=use_ssl,
use_x509=use_x509).__enter__()

except TestFailure, f:
test_result["end"] = time.time()
Expand Down Expand Up @@ -807,12 +825,15 @@ def add_exe(e):
def set_globals(options, tests):
global mongod_executable, mongod_port, shell_executable, continue_on_failure, small_oplog, small_oplog_rs
global no_journal, set_parameters, no_preallocj, auth, authMechanism, keyFile, smoke_db_prefix, test_path, start_mongod
global use_ssl
global use_ssl, use_x509
global file_of_commands_mode
global report_file
start_mongod = options.start_mongod
if hasattr(options, 'use_ssl'):
use_ssl = options.use_ssl
if hasattr(options, 'use_x509'):
use_x509 = options.use_x509
use_ssl = use_ssl or use_x509
#Careful, this can be called multiple times
test_path = options.test_path

Expand Down Expand Up @@ -975,6 +996,9 @@ def main():
parser.add_option('--auth', dest='auth', default=False,
action="store_true",
help='Run standalone mongods in tests with authentication enabled')
parser.add_option('--use-x509', dest='use_x509', default=False,
action="store_true",
help='Use x509 auth for internal cluster authentication')
parser.add_option('--authMechanism', dest='authMechanism', default='MONGODB-CR',
help='Use the given authentication mechanism, when --auth is used.')
parser.add_option('--keyFile', dest='keyFile', default=None,
Expand Down
101 changes: 101 additions & 0 deletions jstests/libs/cluster-cert.pem
@@ -0,0 +1,101 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 5 (0x5)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=US, ST=New York, L=New York City, O=10Gen, OU=Kernel, CN=My Cert Authority/emailAddress=root@lazarus
Validity
Not Before: Aug 7 17:19:17 2013 GMT
Not After : Dec 22 17:19:17 2040 GMT
Subject: C=US, ST=New York, L=New York City, O=10Gen, OU=Kernel, CN=clustertest
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:98:ec:01:6e:f4:ae:8e:16:c8:87:a2:44:86:a0:
45:5c:ca:82:56:ba:0d:a9:60:bf:07:40:da:db:70:
33:a6:c2:ec:9d:e1:f0:da:fe:b9:f9:ac:23:33:64:
e6:63:71:cc:a2:0d:eb:86:bc:31:32:aa:30:e6:1d:
5d:6d:fd:45:f4:2f:dc:72:93:bc:92:27:f7:6a:5a:
18:04:f7:64:d0:6a:3c:a9:14:f6:9e:9d:58:26:f4:
16:93:7e:3d:2e:3c:9e:54:41:4d:1a:e1:bd:b4:cf:
d0:05:4c:4d:15:fb:5c:70:1e:0c:32:6d:d7:67:5b:
ec:b2:61:83:e3:f0:b1:78:aa:30:45:86:f9:6d:f5:
48:1f:f1:90:06:25:db:71:ed:af:d7:0d:65:65:70:
89:d4:c8:c8:23:a0:67:22:de:d9:6e:1d:44:38:cf:
0f:eb:2c:fe:79:01:d7:98:15:5f:22:42:3f:ee:c9:
16:eb:b9:25:08:9a:2a:11:74:47:e0:51:75:8c:ae:
eb:8d:b5:30:fe:48:98:0a:9e:ba:6e:a4:60:08:81:
c6:05:a0:97:38:70:c0:1f:b4:27:96:8e:c3:d2:c1:
14:5f:34:16:91:7d:ad:4c:e9:23:07:f0:42:86:78:
11:a1:1e:9d:f3:d0:41:09:06:7d:5c:89:ef:d2:0d:
6c:d5
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
C9:00:3A:28:CC:6A:75:57:82:81:00:A6:25:48:6C:CE:0A:A0:4A:59
X509v3 Authority Key Identifier:
keyid:07:41:19:3A:9F:7E:C5:B7:22:4E:B7:BC:D5:DF:E4:FC:09:B8:64:16

Signature Algorithm: sha1WithRSAEncryption
d1:55:e3:5c:43:8c:4f:d3:29:8d:74:4a:1d:23:50:17:27:b3:
30:6f:c6:d7:4c:6c:96:7e:52:a0:2f:91:92:b3:f5:4c:a1:ca:
88:62:31:e4:d6:64:ac:40:17:47:00:24:e8:0d:3b:7b:c7:d4:
7f:3a:76:45:27:fd:9b:ae:9d:44:71:8f:ab:62:60:e5:9d:e8:
59:dd:0e:25:17:14:f8:83:b0:b6:fc:5f:27:8b:69:a2:dc:31:
b9:17:a1:27:92:96:c1:73:bf:a3:f0:b8:97:b9:e2:fb:97:6d:
44:01:b0:68:68:47:4b:84:56:3b:19:66:f8:0b:6c:1b:f5:44:
a9:ae
-----BEGIN CERTIFICATE-----
MIIDdzCCAuCgAwIBAgIBBTANBgkqhkiG9w0BAQUFADCBkjELMAkGA1UEBhMCVVMx
ETAPBgNVBAgMCE5ldyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MQ4wDAYD
VQQKDAUxMEdlbjEPMA0GA1UECwwGS2VybmVsMRowGAYDVQQDDBFNeSBDZXJ0IEF1
dGhvcml0eTEbMBkGCSqGSIb3DQEJARYMcm9vdEBsYXphcnVzMB4XDTEzMDgwNzE3
MTkxN1oXDTQwMTIyMjE3MTkxN1owbzELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE5l
dyBZb3JrMRYwFAYDVQQHDA1OZXcgWW9yayBDaXR5MQ4wDAYDVQQKDAUxMEdlbjEP
MA0GA1UECwwGS2VybmVsMRQwEgYDVQQDDAtjbHVzdGVydGVzdDCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJjsAW70ro4WyIeiRIagRVzKgla6DalgvwdA
2ttwM6bC7J3h8Nr+ufmsIzNk5mNxzKIN64a8MTKqMOYdXW39RfQv3HKTvJIn92pa
GAT3ZNBqPKkU9p6dWCb0FpN+PS48nlRBTRrhvbTP0AVMTRX7XHAeDDJt12db7LJh
g+PwsXiqMEWG+W31SB/xkAYl23Htr9cNZWVwidTIyCOgZyLe2W4dRDjPD+ss/nkB
15gVXyJCP+7JFuu5JQiaKhF0R+BRdYyu6421MP5ImAqeum6kYAiBxgWglzhwwB+0
J5aOw9LBFF80FpF9rUzpIwfwQoZ4EaEenfPQQQkGfVyJ79INbNUCAwEAAaN7MHkw
CQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2Vy
dGlmaWNhdGUwHQYDVR0OBBYEFMkAOijManVXgoEApiVIbM4KoEpZMB8GA1UdIwQY
MBaAFAdBGTqffsW3Ik63vNXf5PwJuGQWMA0GCSqGSIb3DQEBBQUAA4GBANFV41xD
jE/TKY10Sh0jUBcnszBvxtdMbJZ+UqAvkZKz9UyhyohiMeTWZKxAF0cAJOgNO3vH
1H86dkUn/ZuunURxj6tiYOWd6FndDiUXFPiDsLb8XyeLaaLcMbkXoSeSlsFzv6Pw
uJe54vuXbUQBsGhoR0uEVjsZZvgLbBv1RKmu
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCY7AFu9K6OFsiH
okSGoEVcyoJWug2pYL8HQNrbcDOmwuyd4fDa/rn5rCMzZOZjccyiDeuGvDEyqjDm
HV1t/UX0L9xyk7ySJ/dqWhgE92TQajypFPaenVgm9BaTfj0uPJ5UQU0a4b20z9AF
TE0V+1xwHgwybddnW+yyYYPj8LF4qjBFhvlt9Ugf8ZAGJdtx7a/XDWVlcInUyMgj
oGci3tluHUQ4zw/rLP55AdeYFV8iQj/uyRbruSUImioRdEfgUXWMruuNtTD+SJgK
nrpupGAIgcYFoJc4cMAftCeWjsPSwRRfNBaRfa1M6SMH8EKGeBGhHp3z0EEJBn1c
ie/SDWzVAgMBAAECggEAfogRK5Dz+gfqByiCEO7+VagOrtolwbeWeNb2AEpXwq1Z
Ac5Y76uDkI4ZVkYvx6r6ykBAWOzQvH5MFavIieDeiA0uF/QcPMcrFmnTpBBb74No
C/OXmGjS7vBa2dHDp8VqsIaT2SFeSgUFt8yJoB2rP+3s47E1YYWTVYoQioO3JQJN
f0mSuvTnvJO9lbTWiW+yWGVkQvIciCCnHkCEwU0fHht8IoFBGNFlpWZcGiMeietr
16GdRcmAq95q8TTCeQxkgmmL+0ZJ1BrF7llG2pGYdacawXj1eVRqOHQaFIlcKe05
RITpuXVYOWBpBpfbQsBZaCGLe7WxHJedrFxdbqm0ZQKBgQDLUQrmIl2wz43t3sI+
WjW6y1GwMPG9EjXUT1Boq6PNHKgw04/32QNn5IMmz4cp2Mgyz7Hc0ABDU/ZATujd
yCkxVErPbKRDKSxSl6nLXtLpLbHFmVPfKPbNKIuyFMBsOFOtoFoVbo33wI5dI7aO
i7sTGB3ngbq4pzCJ9dVt/t81QwKBgQDAjAtBXS8WB69l9w35tx+MgYG0LJ+ykAug
d91pwiWqSt02fZ0nr/S/76G6B4C8eqeOnYh1RzF5isLD246rLD2Y+uuFrgasvSiS
4qSKbpG2kk02R/DRTAglAyXI0rhYIDrYKCQPWqNMWpawT/FQQwbFjTuhmz10FyXS
hmVztZWoBwKBgQCBdnptLibghllGxViEoaai6gJ7Ib9ceHMEXPjDnb+wxPWoGZ8L
4AjWJ+EHXpAfqmVYTX5hL6VrOdSNAHIxftoUCiuUxwYVqesKMH6y/A9q4WjYfRi1
+fyliJLjc2lPv9IwtfGGwh3uS5ObZTlCrWES+IFaP/YozHUQ9BPSdb+lxwKBgB35
Lv9b3CqXw6why2EmKpkax/AeSjXnyoeOYT9HY8mgodMLtt0ovPbr/McSx+2PQmon
B8kJ7h+3hB4tHYZz+prH5MYIky1svNYwxeBu2ewL1k0u4cQTC+mHFeivNNczHTXs
+cASIf2O1IpZx3zxEirKk4/StLxPpimhlkVu7P8dAoGBAJVw2U70+PagVBPtvheu
ZDEvxSEzrn90ivIh7Y6ZIwdSOSLW04sOVL2JAzO155u4g77jdmcxV3urr1vD9LbF
qkBGLXx7FFC/Mn/H42qerxr16Bt6RtvVpms71UIQLYxA7caab9cqoyt0wkgqJFKX
fj0TVODnIf+zPMDCu+frpLbA
-----END PRIVATE KEY-----
2 changes: 1 addition & 1 deletion jstests/replsets/cloneDb.js
Expand Up @@ -53,7 +53,7 @@ doTest = function( signal ) {
repset.stopSet( signal )
}

if (jsTest.options().keyFile) {
if (jsTest.options().keyFile || jsTest.options().useX509) {
print("Skipping test because clone command doesn't work with authentication enabled: SERVER-4245")
} else {
doTest( 15 );
Expand Down
8 changes: 6 additions & 2 deletions jstests/replsets/initial_sync1.js
Expand Up @@ -16,9 +16,13 @@
load("jstests/replsets/rslib.js");
var basename = "jstests_initsync1";


print("1. Bring up set");
var replTest = new ReplSetTest( {name: basename, nodes: 2} );
// SERVER-7455, this test is called from ssl/auth_x509.js
var x509_options1;
var x509_options2;
var replTest = new ReplSetTest({name: basename,
nodes : {node0 : x509_options1, node1 : x509_options2}});

var conns = replTest.startSet();
replTest.initiate();

Expand Down
37 changes: 37 additions & 0 deletions jstests/ssl/auth_x509.js
@@ -0,0 +1,37 @@
// Basic tests for cluster authentication using x509
// This test is launching replsets/initial_sync1.js with different
// values for clusterAuthMode to emulate an upgrade process.

var common_options = {sslOnNormalPorts : "",
sslPEMKeyFile : "jstests/libs/server.pem",
sslCAFile: "jstests/libs/ca.pem",
keyFile : "jstests/libs/key1"};

// Standard case, clusterAuthMode: x509
x509_options1 = Object.merge(common_options,
{sslClusterFile: "jstests/libs/cluster-cert.pem",
clusterAuthMode: "x509"});
var x509_options2 = x509_options1;
load("jstests/replsets/initial_sync_1.js");

// Mixed clusterAuthMode: sendX509 and sendKeyfile and try adding --auth
x509_options1 = Object.merge(common_options,
{sslClusterFile: "jstests/libs/cluster-cert.pem",
clusterAuthMode: "x509",
auth: ""});
x509_options2 = Object.merge(common_options, {clusterAuthMode: "sendKeyfile"});
load("jstests/replsets/initial_sync1.js");

// Mixed clusterAuthMode: x509 and sendX509, use the PEMKeyFile for outgoing connections
x509_options1 = Object.merge(common_options, {clusterAuthMode: "x509"});
x509_options2 = Object.merge(common_options, {clusterAuthMode: "sendX509"});
load("jstests/replsets/initial_sync1.js");

//verify that replset initiate fails if using an invalid cert
x509_options1 = Object.merge(common_options, {clusterAuthMode: "x509"});
x509_options2 = Object.merge(common_options,
{sslClusterFile: "jstests/libs/smoke.pem",
clusterAuthMode: "x509"});
var replTest = new ReplSetTest({nodes : {node0 : x509_options1, node1 : x509_options2}});
var conns = replTest.startSet();
assert.throws( function() { replTest.initiate() } );
67 changes: 67 additions & 0 deletions jstests/ssl/sharding_with_x509.js
@@ -0,0 +1,67 @@
// Tests basic sharding with x509 cluster auth
// The purpose is to verify the connectivity between mongos and the shards

var x509_options = {sslOnNormalPorts : "",
sslPEMKeyFile : "jstests/libs/server.pem",
sslCAFile: "jstests/libs/ca.pem",
sslClusterFile: "jstests/libs/cluster-cert.pem",
clusterAuthMode: "x509"};

var st = new ShardingTest({ name : "sharding_with_x509" ,
shards : 2,
mongos : 1,
keyFile : "jstests/libs/key1",
other: {
configOptions : x509_options,
mongosOptions : x509_options,
rsOptions : x509_options,
shardOptions : x509_options
}});

var mongos = new Mongo( "localhost:" + st.s0.port )
var coll = mongos.getCollection( "test.foo" )

st.shardColl( coll, { _id : 1 }, false )

// Create an index so we can find by num later
coll.ensureIndex({ insert : 1 })

// For more logging
// mongos.getDB("admin").runCommand({ setParameter : 1, logLevel : 3 })

print( "INSERT!" )

// Insert a bunch of data
var toInsert = 2000
for( var i = 0; i < toInsert; i++ ){
coll.insert({ my : "test", data : "to", insert : i })
}

assert.eq( coll.getDB().getLastError(), null )

print( "UPDATE!" )

// Update a bunch of data
var toUpdate = toInsert
for( var i = 0; i < toUpdate; i++ ){
var id = coll.findOne({ insert : i })._id
coll.update({ insert : i, _id : id }, { $inc : { counter : 1 } })
}

assert.eq( coll.getDB().getLastError(), null )

print( "DELETE" )

// Remove a bunch of data
var toDelete = toInsert / 2
for( var i = 0; i < toDelete; i++ ){
coll.remove({ insert : i })
}

assert.eq( coll.getDB().getLastError(), null )

// Make sure the right amount of data is there
assert.eq( coll.find().count(), toInsert / 2 )

// Finish
st.stop()
3 changes: 2 additions & 1 deletion src/mongo/shell/mongo.js
Expand Up @@ -34,7 +34,8 @@ Mongo.prototype.getSlaveOk = function() {
}

Mongo.prototype.getDB = function( name ){
if (jsTest.options().keyFile && ((typeof this.authenticated == 'undefined') || !this.authenticated)) {
if ((jsTest.options().keyFile || jsTest.options().useX509) &&
((typeof this.authenticated == 'undefined') || !this.authenticated)) {
jsTest.authenticate(this)
}
return new DB( this , name );
Expand Down
3 changes: 2 additions & 1 deletion src/mongo/shell/replsettest.js
Expand Up @@ -487,7 +487,8 @@ ReplSetTest.prototype.initiate = function( cfg , initCmd , timeout ) {
this.awaitSecondaryNodes();

// Setup authentication if running test with authentication
if (jsTestOptions().keyFile && !this.keyFile && cmdKey == 'replSetInitiate') {
if ((jsTestOptions().keyFile || jsTestOptions().useX509) &&
cmdKey == 'replSetInitiate') {
master = this.getMaster();
jsTest.addAuth(master);
jsTest.authenticateNodes(this.nodes);
Expand Down

0 comments on commit 625e971

Please sign in to comment.