2525from pymongo import MongoClient , MongoReplicaSetClient
2626from pymongo .common import HAS_SSL
2727from pymongo .errors import ConfigurationError , ConnectionFailure
28+ from test import host , port , pair
2829
29- if HAS_SSL :
30- import ssl
3130
3231CERT_PATH = os .path .join (os .path .dirname (os .path .realpath (__file__ )),
3332 'certificates' )
3433CLIENT_PEM = os .path .join (CERT_PATH , 'client.pem' )
3534CA_PEM = os .path .join (CERT_PATH , 'ca.pem' )
35+ SIMPLE_SSL = False
36+ CERT_SSL = False
37+ SERVER_IS_RESOLVABLE = False
38+
39+ # To fully test this start a mongod instance (built with SSL support) like so:
40+ # mongod --dbpath /path/to/data/directory --sslOnNormalPorts \
41+ # --sslPEMKeyFile /path/to/mongo/jstests/libs/server.pem \
42+ # --sslCAFile /path/to/mongo/jstests/libs/ca.pem \
43+ # --sslWeakCertificateValidation
44+ # Also, make sure you have 'server' as an alias for localhost in /etc/hosts
45+ #
46+ # Note: For all tests to pass with MongoReplicaSetConnection the replica
47+ # set configuration must use 'server' for the hostname of all hosts.
3648
37-
38- def has_server_host_entry ():
49+ def is_server_resolvable ():
3950 """Returns True if 'server' is resolvable."""
4051 socket_timeout = socket .getdefaulttimeout ()
4152 socket .setdefaulttimeout (1 )
4253 try :
43- socket .gethostbyname ('server' )
44- has_server_host_entry = True
45- except :
46- has_server_host_entry = False
47- socket .setdefaulttimeout (socket_timeout )
48- return has_server_host_entry
54+ try :
55+ socket .gethostbyname ('server' )
56+ return True
57+ except socket .error :
58+ return False
59+ finally :
60+ socket .setdefaulttimeout (socket_timeout )
61+
62+
63+ if HAS_SSL :
64+ import ssl
65+
66+ # Check this all once instead of before every test method below.
67+
68+ # Is MongoDB configured for SSL?
69+ try :
70+ MongoClient (host , port , connectTimeoutMS = 100 , ssl = True )
71+ SIMPLE_SSL = True
72+ except ConnectionFailure :
73+ pass
74+
75+ if SIMPLE_SSL :
76+ # Is MongoDB configured with server.pem and ca.pem from
77+ # mongodb jstests/lib?
78+ try :
79+ MongoClient (host , port , connectTimeoutMS = 100 , ssl = True ,
80+ ssl_certfile = CLIENT_PEM )
81+ CERT_SSL = True
82+ except ConnectionFailure :
83+ pass
84+
85+ if CERT_SSL :
86+ SERVER_IS_RESOLVABLE = is_server_resolvable ()
87+
88+
89+ class TestNoSSLModule (unittest .TestCase ):
90+
91+ def test_no_ssl_module (self ):
92+ # Test that ConfigurationError is raised if the ssl
93+ # module isn't available.
94+ if HAS_SSL :
95+ raise SkipTest (
96+ "The ssl module is available, can't test what happens "
97+ "without it."
98+ )
99+
100+ self .assertRaises (ConfigurationError ,
101+ MongoClient , ssl = True )
102+ self .assertRaises (ConfigurationError ,
103+ MongoReplicaSetClient , ssl = True )
49104
50105
51106class TestSSL (unittest .TestCase ):
52107
53108 def setUp (self ):
109+ if not HAS_SSL :
110+ raise SkipTest ("The ssl module is not available." )
111+
54112 if sys .version .startswith ('3.0' ):
55113 raise SkipTest ("Python 3.0.x has problems "
56114 "with SSL and socket timeouts." )
57115
58- # MongoDB not configured for SSL?
59- try :
60- MongoClient (connectTimeoutMS = 100 , ssl = True )
61- self .simple_ssl = True
62- except ConnectionFailure :
63- self .simple_ssl = False
64-
65- # MongoDB configured with server.pem, ca.pem and crl.pem from
66- # mongodb jstests/lib
67- try :
68- MongoClient (connectTimeoutMS = 100 , ssl = True ,
69- ssl_certfile = CLIENT_PEM )
70- self .cert_ssl = True
71- except ConnectionFailure :
72- self .cert_ssl = False
116+ if not SIMPLE_SSL :
117+ raise SkipTest ("No simple mongod available over SSL" )
73118
74119 def test_config_ssl (self ):
75120 """Tests various ssl configurations"""
@@ -135,42 +180,22 @@ def test_config_ssl(self):
135180 ssl_keyfile = CLIENT_PEM ,
136181 ssl_certfile = CLIENT_PEM )
137182
138- def test_no_ssl (self ):
139- # Tests what happens when ssl is off on the server but you try to
140- # connect to mongodb with ssl=True
141-
142- if HAS_SSL :
143- raise SkipTest (
144- "The ssl module is available, can't test what happens "
145- "without it."
146- )
147-
148- self .assertRaises (ConfigurationError ,
149- MongoClient , ssl = True )
150- self .assertRaises (ConfigurationError ,
151- MongoReplicaSetClient , ssl = True )
152-
153183 def test_simple_ssl (self ):
154184 # Expects the server to be running with ssl and with
155185 # no --sslPEMKeyFile or with --sslWeakCertificateValidation
156-
157- if not HAS_SSL :
158- raise SkipTest ("The ssl module is not available." )
159-
160- if not self .simple_ssl :
161- raise SkipTest ("No simple mongod available over SSL" )
162-
163- client = MongoClient (ssl = True )
186+ client = MongoClient (host , port , ssl = True )
164187 response = client .admin .command ('ismaster' )
165188 if 'setName' in response :
166- client = MongoReplicaSetClient (replicaSet = response ['setName' ],
189+ client = MongoReplicaSetClient (pair ,
190+ replicaSet = response ['setName' ],
167191 w = len (response ['hosts' ]),
168192 ssl = True )
169193
170194 db = client .pymongo_ssl_test
171195 db .test .drop ()
172196 self .assertTrue (db .test .insert ({'ssl' : True }))
173197 self .assertTrue (db .test .find_one ()['ssl' ])
198+ client .drop_database ('pymongo_ssl_test' )
174199
175200 def test_cert_ssl (self ):
176201 # Expects the server to be running with the the server.pem, ca.pem
@@ -181,24 +206,22 @@ def test_cert_ssl(self):
181206 # --sslCRLFile=jstests/libs/crl.pem
182207 #
183208 # Also requires an /etc/hosts entry where "server" is resolvable
184-
185- if not HAS_SSL :
186- raise SkipTest ("The ssl module is not available." )
187-
188- if not self .cert_ssl :
209+ if not CERT_SSL :
189210 raise SkipTest ("No mongod available over SSL with certs" )
190211
191- client = MongoClient (ssl = True , ssl_certfile = CLIENT_PEM )
212+ client = MongoClient (host , port , ssl = True , ssl_certfile = CLIENT_PEM )
192213 response = client .admin .command ('ismaster' )
193214 if 'setName' in response :
194- client = MongoReplicaSetClient (replicaSet = response ['setName' ],
215+ client = MongoReplicaSetClient (pair ,
216+ replicaSet = response ['setName' ],
195217 w = len (response ['hosts' ]),
196218 ssl = True , ssl_certfile = CLIENT_PEM )
197219
198220 db = client .pymongo_ssl_test
199221 db .test .drop ()
200222 self .assertTrue (db .test .insert ({'ssl' : True }))
201223 self .assertTrue (db .test .find_one ()['ssl' ])
224+ client .drop_database ('pymongo_ssl_test' )
202225
203226 def test_cert_ssl_implicitly_set (self ):
204227 # Expects the server to be running with the the server.pem, ca.pem
@@ -209,24 +232,22 @@ def test_cert_ssl_implicitly_set(self):
209232 # --sslCRLFile=jstests/libs/crl.pem
210233 #
211234 # Also requires an /etc/hosts entry where "server" is resolvable
212-
213- if not HAS_SSL :
214- raise SkipTest ("The ssl module is not available." )
215-
216- if not self .cert_ssl :
235+ if not CERT_SSL :
217236 raise SkipTest ("No mongod available over SSL with certs" )
218237
219- client = MongoClient (ssl_certfile = CLIENT_PEM )
238+ client = MongoClient (host , port , ssl_certfile = CLIENT_PEM )
220239 response = client .admin .command ('ismaster' )
221240 if 'setName' in response :
222- client = MongoReplicaSetClient (replicaSet = response ['setName' ],
241+ client = MongoReplicaSetClient (pair ,
242+ replicaSet = response ['setName' ],
223243 w = len (response ['hosts' ]),
224244 ssl_certfile = CLIENT_PEM )
225245
226246 db = client .pymongo_ssl_test
227247 db .test .drop ()
228248 self .assertTrue (db .test .insert ({'ssl' : True }))
229249 self .assertTrue (db .test .find_one ()['ssl' ])
250+ client .drop_database ('pymongo_ssl_test' )
230251
231252 def test_cert_ssl_validation (self ):
232253 # Expects the server to be running with the the server.pem, ca.pem
@@ -237,15 +258,11 @@ def test_cert_ssl_validation(self):
237258 # --sslCRLFile=jstests/libs/crl.pem
238259 #
239260 # Also requires an /etc/hosts entry where "server" is resolvable
240-
241- if not HAS_SSL :
242- raise SkipTest ("The ssl module is not available." )
243-
244- if not self .cert_ssl :
261+ if not CERT_SSL :
245262 raise SkipTest ("No mongod available over SSL with certs" )
246263
247- if not has_server_host_entry () :
248- raise SkipTest ("No hosts entry for 'server' cannot validate "
264+ if not SERVER_IS_RESOLVABLE :
265+ raise SkipTest ("No hosts entry for 'server'. Cannot validate "
249266 "hostname in the certificate" )
250267
251268 client = MongoClient ('server' ,
@@ -267,6 +284,7 @@ def test_cert_ssl_validation(self):
267284 db .test .drop ()
268285 self .assertTrue (db .test .insert ({'ssl' : True }))
269286 self .assertTrue (db .test .find_one ()['ssl' ])
287+ client .drop_database ('pymongo_ssl_test' )
270288
271289 def test_cert_ssl_validation_optional (self ):
272290 # Expects the server to be running with the the server.pem, ca.pem
@@ -277,15 +295,11 @@ def test_cert_ssl_validation_optional(self):
277295 # --sslCRLFile=jstests/libs/crl.pem
278296 #
279297 # Also requires an /etc/hosts entry where "server" is resolvable
280-
281- if not HAS_SSL :
282- raise SkipTest ("The ssl module is not available." )
283-
284- if not self .cert_ssl :
298+ if not CERT_SSL :
285299 raise SkipTest ("No mongod available over SSL with certs" )
286300
287- if not has_server_host_entry () :
288- raise SkipTest ("No hosts entry for 'server' cannot validate "
301+ if not SERVER_IS_RESOLVABLE :
302+ raise SkipTest ("No hosts entry for 'server'. Cannot validate "
289303 "hostname in the certificate" )
290304
291305 client = MongoClient ('server' ,
@@ -307,6 +321,7 @@ def test_cert_ssl_validation_optional(self):
307321 db .test .drop ()
308322 self .assertTrue (db .test .insert ({'ssl' : True }))
309323 self .assertTrue (db .test .find_one ()['ssl' ])
324+ client .drop_database ('pymongo_ssl_test' )
310325
311326 def test_cert_ssl_validation_hostname_fail (self ):
312327 # Expects the server to be running with the the server.pem, ca.pem
@@ -315,36 +330,32 @@ def test_cert_ssl_validation_hostname_fail(self):
315330 # --sslPEMKeyFile=jstests/libs/server.pem
316331 # --sslCAFile=jstests/libs/ca.pem
317332 # --sslCRLFile=jstests/libs/crl.pem
318-
319- if not HAS_SSL :
320- raise SkipTest ("The ssl module is not available." )
321-
322- if not self .cert_ssl :
333+ if not CERT_SSL :
323334 raise SkipTest ("No mongod available over SSL with certs" )
324335
325336 client = MongoClient (ssl = True , ssl_certfile = CLIENT_PEM )
326337 response = client .admin .command ('ismaster' )
327- singleServer = 'setName' not in response
338+ single_server = 'setName' not in response
328339
329- if singleServer :
340+ if single_server :
330341 try :
331- MongoClient ('localhost' ,
332- ssl = True ,
333- ssl_certfile = CLIENT_PEM ,
334- ssl_cert_reqs = ssl .CERT_REQUIRED ,
335- ssl_ca_certs = CA_PEM )
342+ MongoClient (pair ,
343+ ssl = True ,
344+ ssl_certfile = CLIENT_PEM ,
345+ ssl_cert_reqs = ssl .CERT_REQUIRED ,
346+ ssl_ca_certs = CA_PEM )
336347 self .fail ("Invalid hostname should have failed" )
337348 except :
338349 pass
339350 else :
340351 try :
341- MongoReplicaSetClient ('localhost' ,
342- replicaSet = response ['setName' ],
343- w = len (response ['hosts' ]),
344- ssl = True ,
345- ssl_certfile = CLIENT_PEM ,
346- ssl_cert_reqs = ssl .CERT_OPTIONAL ,
347- ssl_ca_certs = CA_PEM )
352+ MongoReplicaSetClient (pair ,
353+ replicaSet = response ['setName' ],
354+ w = len (response ['hosts' ]),
355+ ssl = True ,
356+ ssl_certfile = CLIENT_PEM ,
357+ ssl_cert_reqs = ssl .CERT_OPTIONAL ,
358+ ssl_ca_certs = CA_PEM )
348359 self .fail ("Invalid hostname should have failed" )
349360 except :
350361 pass
0 commit comments