42
42
from test .test_pooling_base import get_pool
43
43
from test .test_replica_set_client import TestReplicaSetClientBase
44
44
from test .test_threads import AutoAuthenticateThreads
45
- from test .utils import (is_mongos ,
45
+ from test .utils import (delay ,
46
+ is_mongos ,
46
47
remove_all_users ,
47
48
assertRaisesExactly ,
48
49
one ,
54
55
# YOU MUST RUN KINIT BEFORE RUNNING GSSAPI TESTS.
55
56
GSSAPI_HOST = os .environ .get ('GSSAPI_HOST' )
56
57
GSSAPI_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' )
58
60
59
61
SASL_HOST = os .environ .get ('SASL_HOST' )
60
62
SASL_PORT = int (os .environ .get ('SASL_PORT' , '27017' ))
61
63
SASL_USER = os .environ .get ('SASL_USER' )
62
64
SASL_PASS = os .environ .get ('SASL_PASS' )
63
- SASL_DB = os .environ .get ('SASL_DB' , '$external' )
65
+ SASL_DB = os .environ .get ('SASL_DB' , '$external' )
64
66
65
67
66
68
def setUpModule ():
@@ -81,99 +83,123 @@ class AutoAuthenticateThread(threading.Thread):
81
83
"""Used in testing threaded authentication.
82
84
"""
83
85
84
- def __init__ (self , database ):
86
+ def __init__ (self , collection ):
85
87
super (AutoAuthenticateThread , self ).__init__ ()
86
- self .database = database
87
- self .success = True
88
+ self .collection = collection
89
+ self .success = False
88
90
89
91
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
94
94
95
95
96
96
class TestGSSAPI (unittest .TestCase ):
97
97
98
98
def setUp (self ):
99
99
if not HAVE_KERBEROS :
100
100
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' )
103
104
104
105
def test_gssapi_simple (self ):
105
106
106
107
client = MongoClient (GSSAPI_HOST , GSSAPI_PORT )
108
+ db = client [GSSAPI_DB ]
107
109
# 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 ()
111
112
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 ))
113
115
client = MongoClient (uri )
114
- client . database_names ()
116
+ client [ GSSAPI_DB ]. collection . find_one ()
115
117
116
118
# 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 ()
121
125
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 ))
124
128
client = MongoClient (uri )
125
- client . database_names ()
129
+ client [ GSSAPI_DB ]. collection . find_one ()
126
130
uri = ('mongodb://%s@%s:%d/?authMechanism='
127
131
'GSSAPI;authMechanismProperties=SERVICE_NAME:mongodb' % (
128
- quote_plus (PRINCIPAL ), GSSAPI_HOST , GSSAPI_PORT ))
132
+ quote_plus (GSSAPI_PRINCIPAL ), GSSAPI_HOST , GSSAPI_PORT ))
129
133
client = MongoClient (uri )
130
- client . database_names ()
134
+ client [ GSSAPI_DB ]. collection . find_one ()
131
135
132
136
set_name = client .admin .command ('ismaster' ).get ('setName' )
133
137
if set_name :
134
138
client = MongoReplicaSetClient (GSSAPI_HOST ,
135
139
port = GSSAPI_PORT ,
136
140
replicaSet = set_name )
141
+ db = client [GSSAPI_DB ]
137
142
# 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 ()
141
146
uri = ('mongodb://%s@%s:%d/?authMechanism=GSSAPI;replicaSet'
142
- '=%s' % (quote_plus (PRINCIPAL ),
147
+ '=%s' % (quote_plus (GSSAPI_PRINCIPAL ),
143
148
GSSAPI_HOST , GSSAPI_PORT , str (set_name )))
144
149
client = MongoReplicaSetClient (uri )
145
- client . database_names ()
150
+ client [ GSSAPI_DB ]. collection . find_one ()
146
151
147
152
# 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 ()
152
162
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 )))
157
168
client = MongoReplicaSetClient (uri )
158
- client . database_names ()
169
+ client [ GSSAPI_DB ]. collection . find_one ()
159
170
uri = ('mongodb://%s@%s:%d/?authMechanism=GSSAPI;replicaSet=%s;'
160
171
'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 )))
163
176
client = MongoReplicaSetClient (uri )
164
- client . database_names ()
177
+ client [ GSSAPI_DB ]. collection . find_one ()
165
178
166
179
def test_gssapi_threaded (self ):
167
180
168
181
# Use auto_start_request=True to make sure each thread
169
182
# uses a different socket.
170
183
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." )
173
199
174
200
threads = []
175
201
for _ in xrange (4 ):
176
- threads .append (AutoAuthenticateThread (client . foo ))
202
+ threads .append (AutoAuthenticateThread (collection ))
177
203
for thread in threads :
178
204
thread .start ()
179
205
for thread in threads :
@@ -186,13 +212,15 @@ def test_gssapi_threaded(self):
186
212
client = MongoReplicaSetClient (GSSAPI_HOST ,
187
213
replicaSet = set_name ,
188
214
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 ()
192
220
193
221
threads = []
194
222
for _ in xrange (4 ):
195
- threads .append (AutoAuthenticateThread (client . foo ))
223
+ threads .append (AutoAuthenticateThread (collection ))
196
224
for thread in threads :
197
225
thread .start ()
198
226
for thread in threads :
0 commit comments