4242from test .test_pooling_base import get_pool
4343from test .test_replica_set_client import TestReplicaSetClientBase
4444from test .test_threads import AutoAuthenticateThreads
45- from test .utils import (is_mongos ,
45+ from test .utils import (delay ,
46+ is_mongos ,
4647 remove_all_users ,
4748 assertRaisesExactly ,
4849 one ,
5455# YOU MUST RUN KINIT BEFORE RUNNING GSSAPI TESTS.
5556GSSAPI_HOST = os .environ .get ('GSSAPI_HOST' )
5657GSSAPI_PORT = int (os .environ .get ('GSSAPI_PORT' , '27017' ))
57- PRINCIPAL = os .environ .get ('PRINCIPAL' )
58+ GSSAPI_PRINCIPAL = os .environ .get ('GSSAPI_PRINCIPAL' )
59+ GSSAPI_DB = os .environ .get ('GSSAPI_DB' , 'test' )
5860
5961SASL_HOST = os .environ .get ('SASL_HOST' )
6062SASL_PORT = int (os .environ .get ('SASL_PORT' , '27017' ))
6163SASL_USER = os .environ .get ('SASL_USER' )
6264SASL_PASS = os .environ .get ('SASL_PASS' )
63- SASL_DB = os .environ .get ('SASL_DB' , '$external' )
65+ SASL_DB = os .environ .get ('SASL_DB' , '$external' )
6466
6567
6668def setUpModule ():
@@ -81,99 +83,123 @@ class AutoAuthenticateThread(threading.Thread):
8183 """Used in testing threaded authentication.
8284 """
8385
84- def __init__ (self , database ):
86+ def __init__ (self , collection ):
8587 super (AutoAuthenticateThread , self ).__init__ ()
86- self .database = database
87- self .success = True
88+ self .collection = collection
89+ self .success = False
8890
8991 def run (self ):
90- try :
91- self .database .command ('dbstats' )
92- except OperationFailure :
93- self .success = False
92+ assert self .collection .find_one ({'$where' : delay (1 )}) is not None
93+ self .success = True
9494
9595
9696class TestGSSAPI (unittest .TestCase ):
9797
9898 def setUp (self ):
9999 if not HAVE_KERBEROS :
100100 raise SkipTest ('Kerberos module not available.' )
101- if not GSSAPI_HOST or not PRINCIPAL :
102- raise SkipTest ('Must set GSSAPI_HOST and PRINCIPAL to test GSSAPI' )
101+ if not GSSAPI_HOST or not GSSAPI_PRINCIPAL :
102+ raise SkipTest (
103+ 'Must set GSSAPI_HOST and GSSAPI_PRINCIPAL to test GSSAPI' )
103104
104105 def test_gssapi_simple (self ):
105106
106107 client = MongoClient (GSSAPI_HOST , GSSAPI_PORT )
108+ db = client [GSSAPI_DB ]
107109 # Without gssapiServiceName
108- self .assertTrue (client .test .authenticate (PRINCIPAL ,
109- mechanism = 'GSSAPI' ))
110- client .database_names ()
110+ self .assertTrue (db .authenticate (GSSAPI_PRINCIPAL , mechanism = 'GSSAPI' ))
111+ db .collection .find_one ()
111112 uri = ('mongodb://%s@%s:%d/?authMechanism='
112- 'GSSAPI' % (quote_plus (PRINCIPAL ), GSSAPI_HOST , GSSAPI_PORT ))
113+ 'GSSAPI' % (
114+ quote_plus (GSSAPI_PRINCIPAL ), GSSAPI_HOST , GSSAPI_PORT ))
113115 client = MongoClient (uri )
114- client . database_names ()
116+ client [ GSSAPI_DB ]. collection . find_one ()
115117
116118 # With gssapiServiceName
117- self .assertTrue (client .test .authenticate (PRINCIPAL ,
118- mechanism = 'GSSAPI' ,
119- gssapiServiceName = 'mongodb' ))
120- client .database_names ()
119+ client = MongoClient (GSSAPI_HOST , GSSAPI_PORT )
120+ db = client [GSSAPI_DB ]
121+ self .assertTrue (db .authenticate (GSSAPI_PRINCIPAL ,
122+ mechanism = 'GSSAPI' ,
123+ gssapiServiceName = 'mongodb' ))
124+ db .collection .find_one ()
121125 uri = ('mongodb://%s@%s:%d/?authMechanism='
122- 'GSSAPI;gssapiServiceName=mongodb' % (quote_plus ( PRINCIPAL ),
123- GSSAPI_HOST , GSSAPI_PORT ))
126+ 'GSSAPI;gssapiServiceName=mongodb' % (
127+ quote_plus ( GSSAPI_PRINCIPAL ), GSSAPI_HOST , GSSAPI_PORT ))
124128 client = MongoClient (uri )
125- client . database_names ()
129+ client [ GSSAPI_DB ]. collection . find_one ()
126130 uri = ('mongodb://%s@%s:%d/?authMechanism='
127131 'GSSAPI;authMechanismProperties=SERVICE_NAME:mongodb' % (
128- quote_plus (PRINCIPAL ), GSSAPI_HOST , GSSAPI_PORT ))
132+ quote_plus (GSSAPI_PRINCIPAL ), GSSAPI_HOST , GSSAPI_PORT ))
129133 client = MongoClient (uri )
130- client . database_names ()
134+ client [ GSSAPI_DB ]. collection . find_one ()
131135
132136 set_name = client .admin .command ('ismaster' ).get ('setName' )
133137 if set_name :
134138 client = MongoReplicaSetClient (GSSAPI_HOST ,
135139 port = GSSAPI_PORT ,
136140 replicaSet = set_name )
141+ db = client [GSSAPI_DB ]
137142 # Without gssapiServiceName
138- self .assertTrue (client . test . authenticate (PRINCIPAL ,
139- mechanism = 'GSSAPI' ))
140- client . database_names ()
143+ self .assertTrue (db . authenticate (GSSAPI_PRINCIPAL ,
144+ mechanism = 'GSSAPI' ))
145+ db . collection . find_one ()
141146 uri = ('mongodb://%s@%s:%d/?authMechanism=GSSAPI;replicaSet'
142- '=%s' % (quote_plus (PRINCIPAL ),
147+ '=%s' % (quote_plus (GSSAPI_PRINCIPAL ),
143148 GSSAPI_HOST , GSSAPI_PORT , str (set_name )))
144149 client = MongoReplicaSetClient (uri )
145- client . database_names ()
150+ client [ GSSAPI_DB ]. collection . find_one ()
146151
147152 # With gssapiServiceName
148- self .assertTrue (client .test .authenticate (PRINCIPAL ,
149- mechanism = 'GSSAPI' ,
150- gssapiServiceName = 'mongodb' ))
151- client .database_names ()
153+ client = MongoReplicaSetClient (GSSAPI_HOST ,
154+ port = GSSAPI_PORT ,
155+ replicaSet = set_name )
156+ db = client [GSSAPI_DB ]
157+ self .assertTrue (db .authenticate (
158+ GSSAPI_PRINCIPAL ,
159+ mechanism = 'GSSAPI' ,
160+ gssapiServiceName = 'mongodb' ))
161+ db .collection .find_one ()
152162 uri = ('mongodb://%s@%s:%d/?authMechanism=GSSAPI;replicaSet'
153- '=%s;gssapiServiceName=mongodb' % (quote_plus (PRINCIPAL ),
154- GSSAPI_HOST ,
155- GSSAPI_PORT ,
156- str (set_name )))
163+ '=%s;gssapiServiceName=mongodb' % (
164+ quote_plus (GSSAPI_PRINCIPAL ),
165+ GSSAPI_HOST ,
166+ GSSAPI_PORT ,
167+ str (set_name )))
157168 client = MongoReplicaSetClient (uri )
158- client . database_names ()
169+ client [ GSSAPI_DB ]. collection . find_one ()
159170 uri = ('mongodb://%s@%s:%d/?authMechanism=GSSAPI;replicaSet=%s;'
160171 'authMechanismProperties=SERVICE_NAME:mongodb' % (
161- quote_plus (PRINCIPAL ),
162- GSSAPI_HOST , GSSAPI_PORT , str (set_name )))
172+ quote_plus (GSSAPI_PRINCIPAL ),
173+ GSSAPI_HOST ,
174+ GSSAPI_PORT ,
175+ str (set_name )))
163176 client = MongoReplicaSetClient (uri )
164- client . database_names ()
177+ client [ GSSAPI_DB ]. collection . find_one ()
165178
166179 def test_gssapi_threaded (self ):
167180
168181 # Use auto_start_request=True to make sure each thread
169182 # uses a different socket.
170183 client = MongoClient (GSSAPI_HOST , auto_start_request = True )
171- self .assertTrue (client .test .authenticate (PRINCIPAL ,
172- mechanism = 'GSSAPI' ))
184+ db = client [GSSAPI_DB ]
185+ self .assertTrue (db .authenticate (GSSAPI_PRINCIPAL ,
186+ mechanism = 'GSSAPI' ))
187+
188+ # Need one document in the collection. AutoAuthenticateThread does
189+ # collection.find_one with a 1-second delay, forcing it to check out
190+ # multiple sockets from the pool concurrently, proving that
191+ # auto-authentication works with GSSAPI.
192+ collection = db .test
193+ if collection .count () == 0 :
194+ try :
195+ collection .drop ()
196+ collection .insert_one ({'_id' : 1 })
197+ except OperationFailure :
198+ raise SkipTest ("User must be able to write." )
173199
174200 threads = []
175201 for _ in xrange (4 ):
176- threads .append (AutoAuthenticateThread (client . foo ))
202+ threads .append (AutoAuthenticateThread (collection ))
177203 for thread in threads :
178204 thread .start ()
179205 for thread in threads :
@@ -186,13 +212,15 @@ def test_gssapi_threaded(self):
186212 client = MongoReplicaSetClient (GSSAPI_HOST ,
187213 replicaSet = set_name ,
188214 read_preference = preference )
189- self .assertTrue (client .test .authenticate (PRINCIPAL ,
190- mechanism = 'GSSAPI' ))
191- self .assertTrue (client .foo .command ('dbstats' ))
215+ db = client [GSSAPI_DB ]
216+ self .assertTrue (db .authenticate (GSSAPI_PRINCIPAL ,
217+ mechanism = 'GSSAPI' ))
218+ collection = db .test
219+ collection .find_one ()
192220
193221 threads = []
194222 for _ in xrange (4 ):
195- threads .append (AutoAuthenticateThread (client . foo ))
223+ threads .append (AutoAuthenticateThread (collection ))
196224 for thread in threads :
197225 thread .start ()
198226 for thread in threads :
0 commit comments