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