diff --git a/test/__init__.py b/test/__init__.py index 9448448fd..e3c5c9a3c 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -19,7 +19,8 @@ import os import warnings import pymongo -from pymongo.errors import ConnectionFailure +from nose.plugins.skip import SkipTest +from pymongo.errors import OperationFailure # hostnames retrieved by MongoReplicaSetClient from isMaster will be of unicode # type in Python 2, so ensure these hostnames are unicodes, too. It makes tests @@ -34,6 +35,66 @@ port2 = int(os.environ.get("DB_PORT2", 27018)) host3 = unicode(os.environ.get("DB_IP3", 'localhost')) port3 = int(os.environ.get("DB_PORT3", 27019)) +db_user = unicode(os.environ.get("DB_USER", "administrator")) +db_pwd = unicode(os.environ.get("DB_PWD", "password")) + + +class AuthContext(object): + + def __init__(self): + self.client = pymongo.MongoClient(host, port) + self.auth_enabled = False + self.restricted_localhost = False + try: + command_line = self.client.admin.command('getCmdLineOpts') + if self._server_started_with_auth(command_line): + self.auth_enabled = True + except OperationFailure, e: + if e.code == 13: + self.auth_enabled = True + self.restricted_localhost = True + else: + raise + + def _server_started_with_auth(self, command_line): + # MongoDB >= 2.0 + if 'parsed' in command_line: + parsed = command_line['parsed'] + # MongoDB >= 2.6 + if 'security' in parsed: + security = parsed['security'] + if 'authorization' in security: + return security['authorization'] == 'enabled' + return security.get('auth', bool(security.get('keyFile'))) + return parsed.get('auth', bool(parsed.get('keyFile'))) + # Legacy + argv = command_line['argv'] + return '--auth' in argv or '--keyFile' in argv + + def add_user_and_log_in(self): + self.client.admin.add_user(db_user, db_pwd, + roles=('userAdminAnyDatabase', + 'readWriteAnyDatabase', + 'dbAdminAnyDatabase', + 'clusterAdmin')) + self.client.admin.authenticate(db_user, db_pwd) + + def remove_user_and_log_out(self): + self.client.admin.remove_user(db_user) + self.client.admin.logout() + self.client.disconnect() + + +auth_context = AuthContext() + + +def skip_restricted_localhost(): + """Skip tests when the localhost exception is restricted (SERVER-12621).""" + if auth_context.restricted_localhost: + raise SkipTest("Cannot test with restricted localhost exception " + "(SERVER-12621).") + + # Make sure warnings are always raised, regardless of # python version. def setup(): @@ -42,16 +103,16 @@ def setup(): def teardown(): - try: - c = pymongo.MongoClient(host, port) - except ConnectionFailure: - # Tests where ssl=True can cause connection failures here. - # Ignore and continue. - return + client = auth_context.client + if auth_context.auth_enabled: + auth_context.add_user_and_log_in() - c.drop_database("pymongo-pooling-tests") - c.drop_database("pymongo_test") - c.drop_database("pymongo_test1") - c.drop_database("pymongo_test2") - c.drop_database("pymongo_test_mike") - c.drop_database("pymongo_test_bernie") + client.drop_database("pymongo-pooling-tests") + client.drop_database("pymongo_test") + client.drop_database("pymongo_test1") + client.drop_database("pymongo_test2") + client.drop_database("pymongo_test_mike") + client.drop_database("pymongo_test_bernie") + + if auth_context.auth_enabled: + auth_context.remove_user_and_log_out() diff --git a/test/test_auth.py b/test/test_auth.py index 17953f20f..767b1c07e 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -15,9 +15,11 @@ """Authentication Tests.""" import os +import socket import sys import threading import unittest +import warnings from urllib import quote_plus @@ -25,12 +27,28 @@ sys.path[0:0] = [""] from nose.plugins.skip import SkipTest -from pymongo import MongoClient, MongoReplicaSetClient +from pymongo import (MongoClient, + MongoReplicaSetClient, + auth) from pymongo.auth import HAVE_KERBEROS -from pymongo.errors import OperationFailure, ConfigurationError +from pymongo.errors import (OperationFailure, + ConfigurationError, + ConnectionFailure, + AutoReconnect) from pymongo.read_preferences import ReadPreference -from test import version, host, port -from test.utils import is_mongos, server_started_with_auth +from test import version, host, port, pair, auth_context +from test.test_bulk import BulkTestBase +from test.test_client import get_client +from test.test_pooling_base import get_pool +from test.test_replica_set_client import TestReplicaSetClientBase +from test.test_threads import AutoAuthenticateThreads +from test.utils import (is_mongos, + remove_all_users, + assertRaisesExactly, + one, + catch_warnings, + TestRequestMixin, + joinall) # YOU MUST RUN KINIT BEFORE RUNNING GSSAPI TESTS. GSSAPI_HOST = os.environ.get('GSSAPI_HOST') @@ -44,6 +62,20 @@ SASL_PASS = os.environ.get('SASL_PASS') SASL_DB = os.environ.get('SASL_DB', '$external') +def setUpModule(): + if not auth_context.auth_enabled: + raise SkipTest("Server not started with --auth.") + if (is_mongos(auth_context.client) and + not version.at_least(auth_context.client, (2, 0, 0))): + raise SkipTest("Auth with sharding requires MongoDB >= 2.0.0") + auth_context.add_user_and_log_in() + + +def tearDownModule(): + if auth_context.auth_enabled: + auth_context.remove_user_and_log_out() + + class AutoAuthenticateThread(threading.Thread): """Used in testing threaded authentication. """ @@ -230,17 +262,13 @@ class TestAuthURIOptions(unittest.TestCase): def setUp(self): client = MongoClient(host, port) - # Sharded auth not supported before MongoDB 2.0 - if is_mongos(client) and not version.at_least(client, (2, 0, 0)): - raise SkipTest("Auth with sharding requires MongoDB >= 2.0.0") - if not server_started_with_auth(client): - raise SkipTest('Authentication is not enabled on server') response = client.admin.command('ismaster') self.set_name = str(response.get('setName', '')) - client.admin.add_user('admin', 'pass', roles=['userAdminAnyDatabase', - 'dbAdminAnyDatabase', - 'readWriteAnyDatabase', - 'clusterAdmin']) + auth_context.client.admin.add_user('admin', 'pass', + roles=['userAdminAnyDatabase', + 'dbAdminAnyDatabase', + 'readWriteAnyDatabase', + 'clusterAdmin']) client.admin.authenticate('admin', 'pass') client.pymongo_test.add_user('user', 'pass', roles=['userAdmin', 'readWrite']) @@ -314,19 +342,18 @@ class TestDelegatedAuth(unittest.TestCase): def setUp(self): self.client = MongoClient(host, port) - if not version.at_least(self.client, (2, 4, 0)): + authed_client = auth_context.client + if not version.at_least(authed_client, (2, 4, 0)): raise SkipTest('Delegated authentication requires MongoDB >= 2.4.0') - if not server_started_with_auth(self.client): - raise SkipTest('Authentication is not enabled on server') - if version.at_least(self.client, (2, 5, 3, -1)): + if version.at_least(authed_client, (2, 5, 3, -1)): raise SkipTest('Delegated auth does not exist in MongoDB >= 2.5.3') # Give admin all privileges. - self.client.admin.add_user('admin', 'pass', - roles=['readAnyDatabase', - 'readWriteAnyDatabase', - 'userAdminAnyDatabase', - 'dbAdminAnyDatabase', - 'clusterAdmin']) + authed_client.admin.add_user('admin', 'pass', + roles=['readAnyDatabase', + 'readWriteAnyDatabase', + 'userAdminAnyDatabase', + 'dbAdminAnyDatabase', + 'clusterAdmin']) def tearDown(self): self.client.admin.authenticate('admin', 'pass') @@ -370,5 +397,730 @@ class TestDelegatedAuth(unittest.TestCase): self.client.pymongo_test2.foo.find_one) +class TestClientAuth(unittest.TestCase): + + def test_copy_db(self): + authed_client = auth_context.client + if is_mongos(authed_client): + raise SkipTest("SERVER-6427") + + c = MongoClient(host, port) + + authed_client.admin.add_user("admin", "password") + c.admin.authenticate("admin", "password") + c.drop_database("pymongo_test1") + c.pymongo_test.test.insert({"foo": "bar"}) + + try: + c.pymongo_test.add_user("mike", "password") + + self.assertRaises(OperationFailure, c.copy_database, + "pymongo_test", "pymongo_test1", + username="foo", password="bar") + self.assertFalse("pymongo_test1" in c.database_names()) + + self.assertRaises(OperationFailure, c.copy_database, + "pymongo_test", "pymongo_test1", + username="mike", password="bar") + self.assertFalse("pymongo_test1" in c.database_names()) + + c.copy_database("pymongo_test", "pymongo_test1", + username="mike", password="password") + self.assertTrue("pymongo_test1" in c.database_names()) + self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"]) + finally: + # Cleanup + remove_all_users(c.pymongo_test) + c.admin.remove_user("admin") + c.disconnect() + + def test_auth_from_uri(self): + c = MongoClient(host, port) + auth_context.client.admin.add_user("admin", "pass") + c.admin.authenticate("admin", "pass") + try: + c.pymongo_test.add_user("user", "pass", + roles=['userAdmin', 'readWrite']) + + self.assertRaises(ConfigurationError, MongoClient, + "mongodb://foo:bar@%s:%d" % (host, port)) + self.assertRaises(ConfigurationError, MongoClient, + "mongodb://admin:bar@%s:%d" % (host, port)) + self.assertRaises(ConfigurationError, MongoClient, + "mongodb://user:pass@%s:%d" % (host, port)) + MongoClient("mongodb://admin:pass@%s:%d" % (host, port)) + + self.assertRaises(ConfigurationError, MongoClient, + "mongodb://admin:pass@%s:%d/pymongo_test" % + (host, port)) + self.assertRaises(ConfigurationError, MongoClient, + "mongodb://user:foo@%s:%d/pymongo_test" % + (host, port)) + MongoClient("mongodb://user:pass@%s:%d/pymongo_test" % + (host, port)) + + # Auth with lazy connection. + MongoClient( + "mongodb://user:pass@%s:%d/pymongo_test" % (host, port), + _connect=False).pymongo_test.test.find_one() + + # Wrong password. + bad_client = MongoClient( + "mongodb://user:wrong@%s:%d/pymongo_test" % (host, port), + _connect=False) + + self.assertRaises(OperationFailure, + bad_client.pymongo_test.test.find_one) + + finally: + # Clean up. + remove_all_users(c.pymongo_test) + c.admin.remove_user('admin') + + def test_lazy_auth_raises_operation_failure(self): + lazy_client = MongoClient( + "mongodb://user:wrong@%s:%d/pymongo_test" % (host, port), + _connect=False) + + assertRaisesExactly( + OperationFailure, lazy_client.test.collection.find_one) + + def test_unix_socket(self): + authed_client = auth_context.client + if not hasattr(socket, "AF_UNIX"): + raise SkipTest("UNIX-sockets are not supported on this system") + if (sys.platform == 'darwin' and + not version.at_least(authed_client, (2, 7, 1))): + raise SkipTest("SERVER-8492") + + mongodb_socket = '/tmp/mongodb-27017.sock' + if not os.access(mongodb_socket, os.R_OK): + raise SkipTest("Socket file is not accessable") + + self.assertTrue(MongoClient("mongodb://%s" % mongodb_socket)) + + authed_client.admin.add_user('admin', 'pass') + + try: + client = MongoClient("mongodb://%s" % mongodb_socket) + client.admin.authenticate('admin', 'pass') + client.pymongo_test.test.save({"dummy": "object"}) + + # Confirm we can read via the socket + dbs = client.database_names() + self.assertTrue("pymongo_test" in dbs) + + # Confirm it fails with a missing socket + self.assertRaises(ConnectionFailure, MongoClient, + "mongodb:///tmp/none-existent.sock") + finally: + authed_client.admin.remove_user('admin') + + def test_auth_network_error(self): + # Make sure there's no semaphore leak if we get a network error + # when authenticating a new socket with cached credentials. + auth_client = get_client() + + auth_context.client.admin.add_user('admin', 'password') + auth_client.admin.authenticate('admin', 'password') + try: + # Get a client with one socket so we detect if it's leaked. + c = get_client(max_pool_size=1, waitQueueTimeoutMS=1) + + # Simulate an authenticate() call on a different socket. + credentials = auth._build_credentials_tuple( + 'MONGODB-CR', 'admin', + unicode('admin'), unicode('password'), + {}) + + c._cache_credentials('test', credentials, connect=False) + + # Cause a network error on the actual socket. + pool = get_pool(c) + socket_info = one(pool.sockets) + socket_info.sock.close() + + # In __check_auth, the client authenticates its socket with the + # new credential, but gets a socket.error. Should be reraised as + # AutoReconnect. + self.assertRaises(AutoReconnect, c.test.collection.find_one) + + # No semaphore leak, the pool is allowed to make a new socket. + c.test.collection.find_one() + finally: + auth_client.admin.remove_user('admin') + + +class TestDatabaseAuth(unittest.TestCase): + def setUp(self): + self.client = MongoClient(host, port) + + def test_authenticate_add_remove_user(self): + authed_client = auth_context.client + db = authed_client.pymongo_test + + # Configuration errors + self.assertRaises(ValueError, db.add_user, "user", '') + self.assertRaises(TypeError, db.add_user, "user", 'password', 15) + self.assertRaises(ConfigurationError, db.add_user, + "user", 'password', 'True') + self.assertRaises(ConfigurationError, db.add_user, + "user", 'password', True, roles=['read']) + + if version.at_least(authed_client, (2, 5, 3, -1)): + ctx = catch_warnings() + try: + warnings.simplefilter("error", DeprecationWarning) + self.assertRaises(DeprecationWarning, db.add_user, + "user", "password") + self.assertRaises(DeprecationWarning, db.add_user, + "user", "password", True) + finally: + ctx.exit() + + self.assertRaises(ConfigurationError, db.add_user, + "user", "password", digestPassword=True) + + authed_client.admin.add_user("admin", "password") + self.client.admin.authenticate("admin", "password") + db = self.client.pymongo_test + + try: + # Add / authenticate / remove + db.add_user("mike", "password") + self.assertRaises(TypeError, db.authenticate, 5, "password") + self.assertRaises(TypeError, db.authenticate, "mike", 5) + self.assertRaises(OperationFailure, + db.authenticate, "mike", "not a real password") + self.assertRaises(OperationFailure, + db.authenticate, "faker", "password") + self.assertTrue(db.authenticate("mike", "password")) + db.logout() + self.assertTrue(db.authenticate(u"mike", u"password")) + db.remove_user("mike") + db.logout() + + self.assertRaises(OperationFailure, + db.authenticate, "mike", "password") + + # Add / authenticate / change password + self.assertRaises(OperationFailure, + db.authenticate, "Gustave", u"Dor\xe9") + db.add_user("Gustave", u"Dor\xe9") + self.assertTrue(db.authenticate("Gustave", u"Dor\xe9")) + db.add_user("Gustave", "password") + db.logout() + self.assertRaises(OperationFailure, + db.authenticate, "Gustave", u"Dor\xe9") + self.assertTrue(db.authenticate("Gustave", u"password")) + + if not version.at_least(authed_client, (2, 5, 3, -1)): + # Add a readOnly user + db.add_user("Ross", "password", read_only=True) + db.logout() + self.assertTrue(db.authenticate("Ross", u"password")) + self.assertTrue( + db.system.users.find({"readOnly": True}).count()) + db.logout() + + # Cleanup + finally: + remove_all_users(db) + self.client.admin.remove_user("admin") + self.client.admin.logout() + + def test_make_user_readonly(self): + admin = self.client.admin + auth_context.client.admin.add_user('admin', 'pw') + admin.authenticate('admin', 'pw') + + db = self.client.pymongo_test + + try: + # Make a read-write user. + db.add_user('jesse', 'pw') + admin.logout() + + # Check that we're read-write by default. + db.authenticate('jesse', 'pw') + db.collection.insert({}) + db.logout() + + # Make the user read-only. + admin.authenticate('admin', 'pw') + db.add_user('jesse', 'pw', read_only=True) + admin.logout() + + db.authenticate('jesse', 'pw') + self.assertRaises(OperationFailure, db.collection.insert, {}) + finally: + # Cleanup + admin.authenticate('admin', 'pw') + remove_all_users(db) + admin.remove_user("admin") + admin.logout() + + def test_default_roles(self): + authed_client = auth_context.client + if not version.at_least(authed_client, (2, 5, 3, -1)): + raise SkipTest("Default roles only exist in MongoDB >= 2.5.3") + + # "Admin" user + db = self.client.admin + authed_client.admin.add_user('admin', 'pass') + try: + db.authenticate('admin', 'pass') + info = db.command('usersInfo', 'admin')['users'][0] + self.assertEqual("root", info['roles'][0]['role']) + + # Read only "admin" user + db.add_user('ro-admin', 'pass', read_only=True) + db.logout() + db.authenticate('ro-admin', 'pass') + info = db.command('usersInfo', 'ro-admin')['users'][0] + self.assertEqual("readAnyDatabase", info['roles'][0]['role']) + db.logout() + + # Cleanup + finally: + db.authenticate('admin', 'pass') + db.remove_user('ro-admin') + db.remove_user('admin') + db.logout() + + db.connection.disconnect() + + # "Non-admin" user + db = self.client.pymongo_test + authed_client.pymongo_test.add_user('user', 'pass') + try: + db.authenticate('user', 'pass') + info = db.command('usersInfo', 'user')['users'][0] + self.assertEqual("dbOwner", info['roles'][0]['role']) + + # Read only "Non-admin" user + db.add_user('ro-user', 'pass', read_only=True) + db.logout() + db.authenticate('ro-user', 'pass') + info = db.command('usersInfo', 'ro-user')['users'][0] + self.assertEqual("read", info['roles'][0]['role']) + db.logout() + + # Cleanup + finally: + db.authenticate('user', 'pass') + remove_all_users(db) + db.logout() + + def test_new_user_cmds(self): + authed_client = auth_context.client + if not version.at_least(authed_client, (2, 5, 3, -1)): + raise SkipTest("User manipulation through commands " + "requires MongoDB >= 2.5.3") + + db = self.client.pymongo_test + authed_client.pymongo_test.add_user("amalia", "password", + roles=["userAdmin"]) + db.authenticate("amalia", "password") + try: + # This tests the ability to update user attributes. + db.add_user("amalia", "new_password", + customData={"secret": "koalas"}) + + user_info = db.command("usersInfo", "amalia") + self.assertTrue(user_info["users"]) + amalia_user = user_info["users"][0] + self.assertEqual(amalia_user["user"], "amalia") + self.assertEqual(amalia_user["customData"], {"secret": "koalas"}) + finally: + db.remove_user("amalia") + db.logout() + + def test_authenticate_and_safe(self): + db = auth_context.client.auth_test + + db.add_user("bernie", "password", + roles=["userAdmin", "dbAdmin", "readWrite"]) + db.authenticate("bernie", "password") + try: + db.test.remove({}) + self.assertTrue(db.test.insert({"bim": "baz"})) + self.assertEqual(1, db.test.count()) + + self.assertEqual(1, + db.test.update({"bim": "baz"}, + {"$set": {"bim": "bar"}}).get('n')) + + self.assertEqual(1, + db.test.remove({}).get('n')) + + self.assertEqual(0, db.test.count()) + finally: + db.remove_user("bernie") + db.logout() + + def test_authenticate_and_request(self): + # Database.authenticate() needs to be in a request - check that it + # always runs in a request, and that it restores the request state + # (in or not in a request) properly when it's finished. + self.assertFalse(self.client.auto_start_request) + db = self.client.pymongo_test + auth_context.client.pymongo_test.add_user( + "mike", "password", + roles=["userAdmin", "dbAdmin", "readWrite"]) + try: + self.assertFalse(self.client.in_request()) + self.assertTrue(db.authenticate("mike", "password")) + self.assertFalse(self.client.in_request()) + + request_cx = get_client(auto_start_request=True) + request_db = request_cx.pymongo_test + self.assertTrue(request_db.authenticate("mike", "password")) + self.assertTrue(request_cx.in_request()) + finally: + db.authenticate("mike", "password") + db.remove_user("mike") + db.logout() + request_db.logout() + + def test_authenticate_multiple(self): + client = get_client() + authed_client = auth_context.client + if (is_mongos(authed_client) and not + version.at_least(authed_client, (2, 2, 0))): + raise SkipTest("Need mongos >= 2.2.0") + + # Setup + authed_client.pymongo_test.test.drop() + authed_client.pymongo_test1.test.drop() + users_db = client.pymongo_test + admin_db = client.admin + other_db = client.pymongo_test1 + + authed_client.admin.add_user('admin', 'pass', + roles=["userAdminAnyDatabase", "dbAdmin", + "clusterAdmin", "readWrite"]) + try: + self.assertTrue(admin_db.authenticate('admin', 'pass')) + + if version.at_least(self.client, (2, 5, 3, -1)): + admin_db.add_user('ro-admin', 'pass', + roles=["userAdmin", "readAnyDatabase"]) + else: + admin_db.add_user('ro-admin', 'pass', read_only=True) + + users_db.add_user('user', 'pass', + roles=["userAdmin", "readWrite"]) + + admin_db.logout() + self.assertRaises(OperationFailure, users_db.test.find_one) + + # Regular user should be able to query its own db, but + # no other. + users_db.authenticate('user', 'pass') + self.assertEqual(0, users_db.test.count()) + self.assertRaises(OperationFailure, other_db.test.find_one) + + # Admin read-only user should be able to query any db, + # but not write. + admin_db.authenticate('ro-admin', 'pass') + self.assertEqual(0, other_db.test.count()) + self.assertRaises(OperationFailure, + other_db.test.insert, {}) + + # Force close all sockets + client.disconnect() + + # We should still be able to write to the regular user's db + self.assertTrue(users_db.test.remove()) + # And read from other dbs... + self.assertEqual(0, other_db.test.count()) + # But still not write to other dbs... + self.assertRaises(OperationFailure, + other_db.test.insert, {}) + + # Cleanup + finally: + admin_db.logout() + users_db.logout() + admin_db.authenticate('admin', 'pass') + remove_all_users(users_db) + admin_db.remove_user('ro-admin') + admin_db.remove_user('admin') + + +class TestReplicaSetClientAuth(TestReplicaSetClientBase, TestRequestMixin): + + def test_init_disconnected_with_auth_failure(self): + c = MongoReplicaSetClient( + "mongodb://user:pass@somedomainthatdoesntexist", replicaSet="rs", + connectTimeoutMS=1, _connect=False) + + self.assertRaises(ConnectionFailure, c.pymongo_test.test.find_one) + + def test_init_disconnected_with_auth(self): + c = self._get_client() + + auth_context.client.admin.add_user("admin", "pass") + c.admin.authenticate("admin", "pass") + try: + c.pymongo_test.add_user("user", "pass", + roles=['readWrite', 'userAdmin']) + + # Auth with lazy connection. + host = one(self.hosts) + uri = "mongodb://user:pass@%s:%d/pymongo_test?replicaSet=%s" % ( + host[0], host[1], self.name) + + authenticated_client = MongoReplicaSetClient(uri, _connect=False) + authenticated_client.pymongo_test.test.find_one() + + # Wrong password. + bad_uri = ("mongodb://user:wrong@%s:%d/pymongo_test?replicaSet=%s" + % (host[0], host[1], self.name)) + + bad_client = MongoReplicaSetClient(bad_uri, _connect=False) + self.assertRaises( + OperationFailure, bad_client.pymongo_test.test.find_one) + + finally: + # Clean up. + remove_all_users(c.pymongo_test) + c.admin.remove_user('admin') + + def test_lazy_auth_raises_operation_failure(self): + lazy_client = MongoReplicaSetClient( + "mongodb://user:wrong@%s/pymongo_test" % pair, + replicaSet=self.name, + _connect=False) + + assertRaisesExactly( + OperationFailure, lazy_client.test.collection.find_one) + + def test_copy_db(self): + c = self._get_client() + + auth_context.client.admin.add_user("admin", "password") + c.admin.authenticate("admin", "password") + c.drop_database("pymongo_test1") + c.pymongo_test.test.insert({"foo": "bar"}) + + try: + c.pymongo_test.add_user("mike", "password") + + self.assertRaises(OperationFailure, c.copy_database, + "pymongo_test", "pymongo_test1", + username="foo", password="bar") + self.assertFalse("pymongo_test1" in c.database_names()) + + self.assertRaises(OperationFailure, c.copy_database, + "pymongo_test", "pymongo_test1", + username="mike", password="bar") + self.assertFalse("pymongo_test1" in c.database_names()) + + c.copy_database("pymongo_test", "pymongo_test1", + username="mike", password="password") + self.assertTrue("pymongo_test1" in c.database_names()) + res = c.pymongo_test1.test.find_one(_must_use_master=True) + self.assertEqual("bar", res["foo"]) + finally: + # Cleanup + remove_all_users(c.pymongo_test) + c.admin.remove_user("admin") + c.close() + + def test_auth_network_error(self): + # Make sure there's no semaphore leak if we get a network error + # when authenticating a new socket with cached credentials. + auth_client = self._get_client() + + auth_context.client.admin.add_user('admin', 'password') + auth_client.admin.authenticate('admin', 'password') + try: + # Get a client with one socket so we detect if it's leaked. + c = self._get_client(max_pool_size=1, waitQueueTimeoutMS=1) + + # Simulate an authenticate() call on a different socket. + credentials = auth._build_credentials_tuple( + 'MONGODB-CR', 'admin', + unicode('admin'), unicode('password'), + {}) + + c._cache_credentials('test', credentials, connect=False) + + # Cause a network error on the actual socket. + pool = get_pool(c) + socket_info = one(pool.sockets) + socket_info.sock.close() + + # In __check_auth, the client authenticates its socket with the + # new credential, but gets a socket.error. Should be reraised as + # AutoReconnect. + self.assertRaises(AutoReconnect, c.test.collection.find_one) + + # No semaphore leak, the pool is allowed to make a new socket. + c.test.collection.find_one() + finally: + auth_client.admin.remove_user('admin') + + +class TestBulkAuthorization(BulkTestBase): + + def setUp(self): + super(TestBulkAuthorization, self).setUp() + self.client = client = get_client() + authed_client = auth_context.client + if not version.at_least(authed_client, (2, 5, 3)): + raise SkipTest('Need at least MongoDB 2.5.3 with auth') + + db = client.pymongo_test + self.coll = db.test + + authed_client.pymongo_test.test.drop() + authed_client.pymongo_test.add_user('dbOwner', 'pw', roles=['dbOwner']) + db.authenticate('dbOwner', 'pw') + db.add_user('readonly', 'pw', roles=['read']) + db.command( + 'createRole', 'noremove', + privileges=[{ + 'actions': ['insert', 'update', 'find'], + 'resource': {'db': 'pymongo_test', 'collection': 'test'} + }], + roles=[]) + + db.add_user('noremove', 'pw', roles=['noremove']) + db.logout() + + def test_readonly(self): + # We test that an authorization failure aborts the batch and is raised + # as OperationFailure. + db = self.client.pymongo_test + db.authenticate('readonly', 'pw') + bulk = self.coll.initialize_ordered_bulk_op() + bulk.insert({'x': 1}) + self.assertRaises(OperationFailure, bulk.execute) + + def test_no_remove(self): + # We test that an authorization failure aborts the batch and is raised + # as OperationFailure. + db = self.client.pymongo_test + db.authenticate('noremove', 'pw') + bulk = self.coll.initialize_ordered_bulk_op() + bulk.insert({'x': 1}) + bulk.find({'x': 2}).upsert().replace_one({'x': 2}) + bulk.find({}).remove() # Prohibited. + bulk.insert({'x': 3}) # Never attempted. + self.assertRaises(OperationFailure, bulk.execute) + self.assertEqual(set([1, 2]), set(self.coll.distinct('x'))) + + def tearDown(self): + db = self.client.pymongo_test + db.logout() + db.authenticate('dbOwner', 'pw') + db.command('dropRole', 'noremove') + remove_all_users(db) + db.logout() + + +class BaseTestThreadsAuth(object): + """ + Base test class for TestThreadsAuth and TestThreadsAuthReplicaSet. (This is + not itself a unittest.TestCase, otherwise it'd be run twice -- once when + nose imports this module, and once when nose imports + test_threads_replica_set_connection.py, which imports this module.) + """ + def _get_client(self): + """ + Intended for overriding in TestThreadsAuthReplicaSet. This method + returns a MongoClient here, and a MongoReplicaSetClient in + test_threads_replica_set_connection.py. + """ + # Regular test client + return get_client() + + def setUp(self): + client = self._get_client() + self.client = client + auth_context.client.admin.add_user('admin-user', 'password', + roles=['clusterAdmin', + 'dbAdminAnyDatabase', + 'readWriteAnyDatabase', + 'userAdminAnyDatabase']) + self.client.admin.authenticate("admin-user", "password") + self.client.auth_test.add_user("test-user", "password", + roles=['readWrite']) + + def tearDown(self): + # Remove auth users from databases + self.client.admin.authenticate("admin-user", "password") + self.client.drop_database('auth_test') + remove_all_users(self.client.auth_test) + self.client.admin.remove_user('admin-user') + # Clear client reference so that RSC's monitor thread + # dies. + self.client = None + + def test_auto_auth_login(self): + client = self._get_client() + self.assertRaises(OperationFailure, client.auth_test.test.find_one) + + # Admin auth + client = self._get_client() + client.admin.authenticate("admin-user", "password") + + nthreads = 10 + threads = [] + for _ in xrange(nthreads): + t = AutoAuthenticateThreads(client.auth_test.test, 100) + t.start() + threads.append(t) + + joinall(threads) + + for t in threads: + self.assertTrue(t.success) + + # Database-specific auth + client = self._get_client() + client.auth_test.authenticate("test-user", "password") + + threads = [] + for _ in xrange(nthreads): + t = AutoAuthenticateThreads(client.auth_test.test, 100) + t.start() + threads.append(t) + + joinall(threads) + + for t in threads: + self.assertTrue(t.success) + + +class TestThreadsAuth(BaseTestThreadsAuth, unittest.TestCase): + pass + + +class TestThreadsAuthReplicaSet(TestReplicaSetClientBase, BaseTestThreadsAuth): + + def setUp(self): + """ + Prepare to test all the same things that TestThreads tests, but do it + with a replica-set client + """ + TestReplicaSetClientBase.setUp(self) + BaseTestThreadsAuth.setUp(self) + + def tearDown(self): + TestReplicaSetClientBase.tearDown(self) + BaseTestThreadsAuth.tearDown(self) + + def _get_client(self): + """ + Override TestThreadsAuth, so its tests run on a MongoReplicaSetClient + instead of a regular MongoClient. + """ + return MongoReplicaSetClient(pair, replicaSet=self.name) + + if __name__ == "__main__": unittest.main() diff --git a/test/test_binary.py b/test/test_binary.py index 522f5302c..10721bb2e 100644 --- a/test/test_binary.py +++ b/test/test_binary.py @@ -33,9 +33,14 @@ from bson.binary import * from bson.py3compat import b, binary_type from bson.son import SON from nose.plugins.skip import SkipTest +from test import skip_restricted_localhost from test.test_client import get_client from pymongo.mongo_client import MongoClient + +setUpModule = skip_restricted_localhost + + class TestBinary(unittest.TestCase): def test_binary(self): a_string = "hello world" diff --git a/test/test_bulk.py b/test/test_bulk.py index ffaefe643..1476c2dcd 100644 --- a/test/test_bulk.py +++ b/test/test_bulk.py @@ -23,12 +23,13 @@ sys.path[0:0] = [""] from bson import InvalidDocument, SON from pymongo.errors import BulkWriteError, InvalidOperation, OperationFailure -from test import version +from test import version, skip_restricted_localhost from test.test_client import get_client -from test.utils import (oid_generated_on_client, - remove_all_users, - server_started_with_auth, - server_started_with_nojournal) +from test.utils import oid_generated_on_client + + +setUpModule = skip_restricted_localhost + class BulkTestBase(unittest.TestCase): @@ -1135,63 +1136,5 @@ class TestBulkNoResults(BulkTestBase): self.assertTrue(self.coll.find_one({'_id': 1}) is None) -class TestBulkAuthorization(BulkTestBase): - - def setUp(self): - super(TestBulkAuthorization, self).setUp() - self.client = client = get_client() - if (not server_started_with_auth(client) - or not version.at_least(client, (2, 5, 3))): - raise SkipTest('Need at least MongoDB 2.5.3 with auth') - - db = client.pymongo_test - self.coll = db.test - self.coll.remove() - - db.add_user('dbOwner', 'pw', roles=['dbOwner']) - db.authenticate('dbOwner', 'pw') - db.add_user('readonly', 'pw', roles=['read']) - db.command( - 'createRole', 'noremove', - privileges=[{ - 'actions': ['insert', 'update', 'find'], - 'resource': {'db': 'pymongo_test', 'collection': 'test'} - }], - roles=[]) - - db.add_user('noremove', 'pw', roles=['noremove']) - db.logout() - - def test_readonly(self): - # We test that an authorization failure aborts the batch and is raised - # as OperationFailure. - db = self.client.pymongo_test - db.authenticate('readonly', 'pw') - bulk = self.coll.initialize_ordered_bulk_op() - bulk.insert({'x': 1}) - self.assertRaises(OperationFailure, bulk.execute) - - def test_no_remove(self): - # We test that an authorization failure aborts the batch and is raised - # as OperationFailure. - db = self.client.pymongo_test - db.authenticate('noremove', 'pw') - bulk = self.coll.initialize_ordered_bulk_op() - bulk.insert({'x': 1}) - bulk.find({'x': 2}).upsert().replace_one({'x': 2}) - bulk.find({}).remove() # Prohibited. - bulk.insert({'x': 3}) # Never attempted. - self.assertRaises(OperationFailure, bulk.execute) - self.assertEqual(set([1, 2]), set(self.coll.distinct('x'))) - - def tearDown(self): - db = self.client.pymongo_test - db.logout() - db.authenticate('dbOwner', 'pw') - db.command('dropRole', 'noremove') - remove_all_users(db) - db.logout() - - if __name__ == "__main__": unittest.main() diff --git a/test/test_client.py b/test/test_client.py index 01cb00d1c..377a2f05c 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -34,20 +34,18 @@ from bson.tz_util import utc from pymongo.mongo_client import MongoClient from pymongo.database import Database from pymongo.pool import SocketInfo -from pymongo import auth, thread_util, common +from pymongo import thread_util from pymongo.errors import (AutoReconnect, ConfigurationError, ConnectionFailure, InvalidName, - OperationFailure, - PyMongoError) -from test import version, host, port, pair + OperationFailure) +from test import version, host, port, pair, skip_restricted_localhost from test.pymongo_mocks import MockClient from test.utils import (assertRaisesExactly, catch_warnings, delay, is_mongos, - remove_all_users, server_is_master_with_slave, server_started_with_auth, TestRequestMixin, @@ -55,8 +53,9 @@ from test.utils import (assertRaisesExactly, _TestExhaustCursorMixin, lazy_client_trial, NTHREADS, - get_pool, - one) + get_pool) + +setUpModule = skip_restricted_localhost def get_client(*args, **kwargs): @@ -266,36 +265,6 @@ class TestClient(unittest.TestCase, TestRequestMixin): self.assertTrue("pymongo_test2" in c.database_names()) self.assertEqual("bar", c.pymongo_test2.test.find_one()["foo"]) - # See SERVER-6427 for mongos - if not is_mongos(c) and server_started_with_auth(c): - - c.drop_database("pymongo_test1") - - c.admin.add_user("admin", "password") - c.admin.authenticate("admin", "password") - try: - c.pymongo_test.add_user("mike", "password") - - self.assertRaises(OperationFailure, c.copy_database, - "pymongo_test", "pymongo_test1", - username="foo", password="bar") - self.assertFalse("pymongo_test1" in c.database_names()) - - self.assertRaises(OperationFailure, c.copy_database, - "pymongo_test", "pymongo_test1", - username="mike", password="bar") - self.assertFalse("pymongo_test1" in c.database_names()) - - c.copy_database("pymongo_test", "pymongo_test1", - username="mike", password="password") - self.assertTrue("pymongo_test1" in c.database_names()) - self.assertEqual("bar", c.pymongo_test1.test.find_one()["foo"]) - finally: - # Cleanup - remove_all_users(c.pymongo_test) - c.admin.remove_user("admin") - c.disconnect() - def test_iteration(self): client = MongoClient(host, port) @@ -347,75 +316,13 @@ class TestClient(unittest.TestCase, TestRequestMixin): c = MongoClient(uri, _connect=False) self.assertEqual(Database(c, 'foo'), c.get_default_database()) - def test_auth_from_uri(self): - c = MongoClient(host, port) - # Sharded auth not supported before MongoDB 2.0 - if is_mongos(c) and not version.at_least(c, (2, 0, 0)): - raise SkipTest("Auth with sharding requires MongoDB >= 2.0.0") - if not server_started_with_auth(c): - raise SkipTest('Authentication is not enabled on server') - - c.admin.add_user("admin", "pass") - c.admin.authenticate("admin", "pass") - try: - c.pymongo_test.add_user("user", "pass", roles=['userAdmin', 'readWrite']) - - self.assertRaises(ConfigurationError, MongoClient, - "mongodb://foo:bar@%s:%d" % (host, port)) - self.assertRaises(ConfigurationError, MongoClient, - "mongodb://admin:bar@%s:%d" % (host, port)) - self.assertRaises(ConfigurationError, MongoClient, - "mongodb://user:pass@%s:%d" % (host, port)) - MongoClient("mongodb://admin:pass@%s:%d" % (host, port)) - - self.assertRaises(ConfigurationError, MongoClient, - "mongodb://admin:pass@%s:%d/pymongo_test" % - (host, port)) - self.assertRaises(ConfigurationError, MongoClient, - "mongodb://user:foo@%s:%d/pymongo_test" % - (host, port)) - MongoClient("mongodb://user:pass@%s:%d/pymongo_test" % - (host, port)) - - # Auth with lazy connection. - MongoClient( - "mongodb://user:pass@%s:%d/pymongo_test" % (host, port), - _connect=False).pymongo_test.test.find_one() - - # Wrong password. - bad_client = MongoClient( - "mongodb://user:wrong@%s:%d/pymongo_test" % (host, port), - _connect=False) - - self.assertRaises(OperationFailure, - bad_client.pymongo_test.test.find_one) - - finally: - # Clean up. - remove_all_users(c.pymongo_test) - remove_all_users(c.admin) - - def test_lazy_auth_raises_operation_failure(self): - # Check if we have the prerequisites to run this test. - c = MongoClient(host, port) - if not server_started_with_auth(c): - raise SkipTest('Authentication is not enabled on server') - - if is_mongos(c) and not version.at_least(c, (2, 0, 0)): - raise SkipTest("Auth with sharding requires MongoDB >= 2.0.0") - - lazy_client = MongoClient( - "mongodb://user:wrong@%s:%d/pymongo_test" % (host, port), - _connect=False) - - assertRaisesExactly( - OperationFailure, lazy_client.test.collection.find_one) - def test_unix_socket(self): if not hasattr(socket, "AF_UNIX"): raise SkipTest("UNIX-sockets are not supported on this system") + client = MongoClient(host, port) if (sys.platform == 'darwin' and - server_started_with_auth(MongoClient(host, port))): + server_started_with_auth(client) and + not version.at_least(client, (2, 7, 1))): raise SkipTest("SERVER-8492") mongodb_socket = '/tmp/mongodb-27017.sock' @@ -1001,42 +908,6 @@ with client.start_request() as request: client = get_client(_connect=False) client.pymongo_test.test.remove(w=0) - def test_auth_network_error(self): - # Make sure there's no semaphore leak if we get a network error - # when authenticating a new socket with cached credentials. - auth_client = get_client() - if not server_started_with_auth(auth_client): - raise SkipTest('Authentication is not enabled on server') - - auth_client.admin.add_user('admin', 'password') - auth_client.admin.authenticate('admin', 'password') - try: - # Get a client with one socket so we detect if it's leaked. - c = get_client(max_pool_size=1, waitQueueTimeoutMS=1) - - # Simulate an authenticate() call on a different socket. - credentials = auth._build_credentials_tuple( - 'MONGODB-CR', 'admin', - unicode('admin'), unicode('password'), - {}) - - c._cache_credentials('test', credentials, connect=False) - - # Cause a network error on the actual socket. - pool = get_pool(c) - socket_info = one(pool.sockets) - socket_info.sock.close() - - # In __check_auth, the client authenticates its socket with the - # new credential, but gets a socket.error. Should be reraised as - # AutoReconnect. - self.assertRaises(AutoReconnect, c.test.collection.find_one) - - # No semaphore leak, the pool is allowed to make a new socket. - c.test.collection.find_one() - finally: - remove_all_users(auth_client.admin) - class TestClientLazyConnect(unittest.TestCase, _TestLazyConnectMixin): def _get_client(self, **kwargs): diff --git a/test/test_collection.py b/test/test_collection.py index 3fdcb9e32..f65d3f6db 100644 --- a/test/test_collection.py +++ b/test/test_collection.py @@ -53,8 +53,7 @@ from pymongo.errors import (DocumentTooLarge, from test.test_client import get_client from test.utils import (catch_warnings, enable_text_search, get_pool, is_mongos, joinall, oid_generated_on_client) -from test import (qcheck, - version) +from test import qcheck, version, skip_restricted_localhost have_uuid = True try: @@ -63,6 +62,9 @@ except ImportError: have_uuid = False +setUpModule = skip_restricted_localhost + + class TestCollection(unittest.TestCase): def setUp(self): diff --git a/test/test_common.py b/test/test_common.py index 462a19526..e9c7f3fff 100644 --- a/test/test_common.py +++ b/test/test_common.py @@ -30,7 +30,7 @@ from pymongo.connection import Connection from pymongo.mongo_client import MongoClient from pymongo.mongo_replica_set_client import MongoReplicaSetClient from pymongo.errors import ConfigurationError, OperationFailure -from test import host, port, pair, version +from test import host, port, pair, version, skip_restricted_localhost from test.utils import catch_warnings, drop_collections have_uuid = True @@ -40,6 +40,9 @@ except ImportError: have_uuid = False +setUpModule = skip_restricted_localhost + + class TestCommon(unittest.TestCase): def test_baseobject(self): diff --git a/test/test_cursor.py b/test/test_cursor.py index ead450275..184733dbd 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -37,12 +37,15 @@ from pymongo.database import Database from pymongo.errors import (InvalidOperation, OperationFailure, ExecutionTimeout) -from test import version +from test import version, skip_restricted_localhost from test.test_client import get_client from test.utils import (catch_warnings, is_mongos, get_command_line, server_started_with_auth) +setUpModule = skip_restricted_localhost + + class TestCursor(unittest.TestCase): def setUp(self): diff --git a/test/test_database.py b/test/test_database.py index bb6960a5a..aa3e00dce 100644 --- a/test/test_database.py +++ b/test/test_database.py @@ -15,7 +15,6 @@ """Test the database module.""" import datetime -import os import re import sys import warnings @@ -39,7 +38,6 @@ from pymongo import (ALL, from pymongo.collection import Collection from pymongo.database import Database from pymongo.errors import (CollectionInvalid, - ConfigurationError, ExecutionTimeout, InvalidName, OperationFailure) @@ -47,12 +45,15 @@ from pymongo.son_manipulator import (AutoReference, NamespaceInjector, SONManipulator, ObjectIdShuffler) -from test import version +from test import version, skip_restricted_localhost from test.utils import (catch_warnings, get_command_line, - is_mongos, remove_all_users, server_started_with_auth) + is_mongos, server_started_with_auth) from test.test_client import get_client +setUpModule = skip_restricted_localhost + + class TestDatabase(unittest.TestCase): def setUp(self): @@ -358,319 +359,6 @@ class TestDatabase(unittest.TestCase): self.assertEqual(auth._password_digest("Gustave", u"Dor\xe9"), u"81e0e2364499209f466e75926a162d73") - def test_authenticate_add_remove_user(self): - if (is_mongos(self.client) and not - version.at_least(self.client, (2, 0, 0))): - raise SkipTest("Auth with sharding requires MongoDB >= 2.0.0") - if not server_started_with_auth(self.client): - raise SkipTest('Authentication is not enabled on server') - - db = self.client.pymongo_test - - # Configuration errors - self.assertRaises(ValueError, db.add_user, "user", '') - self.assertRaises(TypeError, db.add_user, "user", 'password', 15) - self.assertRaises(ConfigurationError, db.add_user, - "user", 'password', 'True') - self.assertRaises(ConfigurationError, db.add_user, - "user", 'password', True, roles=['read']) - - if version.at_least(self.client, (2, 5, 3, -1)): - ctx = catch_warnings() - try: - warnings.simplefilter("error", DeprecationWarning) - self.assertRaises(DeprecationWarning, db.add_user, - "user", "password") - self.assertRaises(DeprecationWarning, db.add_user, - "user", "password", True) - finally: - ctx.exit() - - self.assertRaises(ConfigurationError, db.add_user, - "user", "password", digestPassword=True) - - self.client.admin.add_user("admin", "password") - self.client.admin.authenticate("admin", "password") - - try: - # Add / authenticate / remove - db.add_user("mike", "password") - self.assertRaises(TypeError, db.authenticate, 5, "password") - self.assertRaises(TypeError, db.authenticate, "mike", 5) - self.assertRaises(OperationFailure, - db.authenticate, "mike", "not a real password") - self.assertRaises(OperationFailure, - db.authenticate, "faker", "password") - self.assertTrue(db.authenticate("mike", "password")) - db.logout() - self.assertTrue(db.authenticate(u"mike", u"password")) - db.remove_user("mike") - db.logout() - - self.assertRaises(OperationFailure, - db.authenticate, "mike", "password") - - # Add / authenticate / change password - self.assertRaises(OperationFailure, - db.authenticate, "Gustave", u"Dor\xe9") - db.add_user("Gustave", u"Dor\xe9") - self.assertTrue(db.authenticate("Gustave", u"Dor\xe9")) - db.add_user("Gustave", "password") - db.logout() - self.assertRaises(OperationFailure, - db.authenticate, "Gustave", u"Dor\xe9") - self.assertTrue(db.authenticate("Gustave", u"password")) - - if not version.at_least(self.client, (2, 5, 3, -1)): - # Add a readOnly user - db.add_user("Ross", "password", read_only=True) - db.logout() - self.assertTrue(db.authenticate("Ross", u"password")) - self.assertTrue(db.system.users.find({"readOnly": True}).count()) - db.logout() - - # Cleanup - finally: - remove_all_users(db) - self.client.admin.remove_user("admin") - self.client.admin.logout() - - def test_make_user_readonly(self): - if (is_mongos(self.client) - and not version.at_least(self.client, (2, 0, 0))): - raise SkipTest('Auth with sharding requires MongoDB >= 2.0.0') - - if not server_started_with_auth(self.client): - raise SkipTest('Authentication is not enabled on server') - - admin = self.client.admin - admin.add_user('admin', 'pw') - admin.authenticate('admin', 'pw') - - db = self.client.pymongo_test - - try: - # Make a read-write user. - db.add_user('jesse', 'pw') - admin.logout() - - # Check that we're read-write by default. - db.authenticate('jesse', 'pw') - db.collection.insert({}) - db.logout() - - # Make the user read-only. - admin.authenticate('admin', 'pw') - db.add_user('jesse', 'pw', read_only=True) - admin.logout() - - db.authenticate('jesse', 'pw') - self.assertRaises(OperationFailure, db.collection.insert, {}) - finally: - # Cleanup - admin.authenticate('admin', 'pw') - remove_all_users(db) - admin.remove_user("admin") - admin.logout() - - def test_default_roles(self): - if not version.at_least(self.client, (2, 5, 3, -1)): - raise SkipTest("Default roles only exist in MongoDB >= 2.5.3") - if not server_started_with_auth(self.client): - raise SkipTest('Authentication is not enabled on server') - - # "Admin" user - db = self.client.admin - db.add_user('admin', 'pass') - try: - db.authenticate('admin', 'pass') - info = db.command('usersInfo', 'admin')['users'][0] - self.assertEqual("root", info['roles'][0]['role']) - - # Read only "admin" user - db.add_user('ro-admin', 'pass', read_only=True) - db.logout() - db.authenticate('ro-admin', 'pass') - info = db.command('usersInfo', 'ro-admin')['users'][0] - self.assertEqual("readAnyDatabase", info['roles'][0]['role']) - db.logout() - - # Cleanup - finally: - db.authenticate('admin', 'pass') - remove_all_users(db) - db.logout() - - db.connection.disconnect() - - # "Non-admin" user - db = self.client.pymongo_test - db.add_user('user', 'pass') - try: - db.authenticate('user', 'pass') - info = db.command('usersInfo', 'user')['users'][0] - self.assertEqual("dbOwner", info['roles'][0]['role']) - - # Read only "Non-admin" user - db.add_user('ro-user', 'pass', read_only=True) - db.logout() - db.authenticate('ro-user', 'pass') - info = db.command('usersInfo', 'ro-user')['users'][0] - self.assertEqual("read", info['roles'][0]['role']) - db.logout() - - # Cleanup - finally: - db.authenticate('user', 'pass') - remove_all_users(db) - db.logout() - - def test_new_user_cmds(self): - if not version.at_least(self.client, (2, 5, 3, -1)): - raise SkipTest("User manipulation through commands " - "requires MongoDB >= 2.5.3") - if not server_started_with_auth(self.client): - raise SkipTest('Authentication is not enabled on server') - - db = self.client.pymongo_test - db.add_user("amalia", "password", roles=["userAdmin"]) - db.authenticate("amalia", "password") - try: - # This tests the ability to update user attributes. - db.add_user("amalia", "new_password", - customData={"secret": "koalas"}) - - user_info = db.command("usersInfo", "amalia") - self.assertTrue(user_info["users"]) - amalia_user = user_info["users"][0] - self.assertEqual(amalia_user["user"], "amalia") - self.assertEqual(amalia_user["customData"], {"secret": "koalas"}) - finally: - db.remove_user("amalia") - db.logout() - - def test_authenticate_and_safe(self): - if (is_mongos(self.client) and not - version.at_least(self.client, (2, 0, 0))): - raise SkipTest("Auth with sharding requires MongoDB >= 2.0.0") - if not server_started_with_auth(self.client): - raise SkipTest('Authentication is not enabled on server') - db = self.client.auth_test - - db.add_user("bernie", "password", - roles=["userAdmin", "dbAdmin", "readWrite"]) - db.authenticate("bernie", "password") - try: - db.test.remove({}) - self.assertTrue(db.test.insert({"bim": "baz"})) - self.assertEqual(1, db.test.count()) - - self.assertEqual(1, - db.test.update({"bim": "baz"}, - {"$set": {"bim": "bar"}}).get('n')) - - self.assertEqual(1, - db.test.remove({}).get('n')) - - self.assertEqual(0, db.test.count()) - finally: - db.remove_user("bernie") - db.logout() - - def test_authenticate_and_request(self): - if (is_mongos(self.client) and not - version.at_least(self.client, (2, 0, 0))): - raise SkipTest("Auth with sharding requires MongoDB >= 2.0.0") - if not server_started_with_auth(self.client): - raise SkipTest('Authentication is not enabled on server') - - # Database.authenticate() needs to be in a request - check that it - # always runs in a request, and that it restores the request state - # (in or not in a request) properly when it's finished. - self.assertFalse(self.client.auto_start_request) - db = self.client.pymongo_test - db.add_user("mike", "password", - roles=["userAdmin", "dbAdmin", "readWrite"]) - try: - self.assertFalse(self.client.in_request()) - self.assertTrue(db.authenticate("mike", "password")) - self.assertFalse(self.client.in_request()) - - request_cx = get_client(auto_start_request=True) - request_db = request_cx.pymongo_test - self.assertTrue(request_db.authenticate("mike", "password")) - self.assertTrue(request_cx.in_request()) - finally: - db.authenticate("mike", "password") - db.remove_user("mike") - db.logout() - request_db.logout() - - def test_authenticate_multiple(self): - client = get_client() - if (is_mongos(client) and not - version.at_least(self.client, (2, 2, 0))): - raise SkipTest("Need mongos >= 2.2.0") - if not server_started_with_auth(client): - raise SkipTest("Authentication is not enabled on server") - - # Setup - users_db = client.pymongo_test - admin_db = client.admin - other_db = client.pymongo_test1 - users_db.test.remove() - other_db.test.remove() - - admin_db.add_user('admin', 'pass', - roles=["userAdminAnyDatabase", "dbAdmin", - "clusterAdmin", "readWrite"]) - try: - self.assertTrue(admin_db.authenticate('admin', 'pass')) - - if version.at_least(self.client, (2, 5, 3, -1)): - admin_db.add_user('ro-admin', 'pass', - roles=["userAdmin", "readAnyDatabase"]) - else: - admin_db.add_user('ro-admin', 'pass', read_only=True) - - users_db.add_user('user', 'pass', - roles=["userAdmin", "readWrite"]) - - admin_db.logout() - self.assertRaises(OperationFailure, users_db.test.find_one) - - # Regular user should be able to query its own db, but - # no other. - users_db.authenticate('user', 'pass') - self.assertEqual(0, users_db.test.count()) - self.assertRaises(OperationFailure, other_db.test.find_one) - - # Admin read-only user should be able to query any db, - # but not write. - admin_db.authenticate('ro-admin', 'pass') - self.assertEqual(0, other_db.test.count()) - self.assertRaises(OperationFailure, - other_db.test.insert, {}) - - # Force close all sockets - client.disconnect() - - # We should still be able to write to the regular user's db - self.assertTrue(users_db.test.remove()) - # And read from other dbs... - self.assertEqual(0, other_db.test.count()) - # But still not write to other dbs... - self.assertRaises(OperationFailure, - other_db.test.insert, {}) - - # Cleanup - finally: - admin_db.logout() - users_db.logout() - admin_db.authenticate('admin', 'pass') - remove_all_users(users_db) - remove_all_users(admin_db) - def test_id_ordering(self): # PyMongo attempts to have _id show up first # when you iterate key/value pairs in a document. @@ -1020,6 +708,5 @@ class TestDatabase(unittest.TestCase): self.assertEqual('value', out.get('value')) - if __name__ == "__main__": unittest.main() diff --git a/test/test_grid_file.py b/test/test_grid_file.py index e3f4329e6..12a9baaea 100644 --- a/test/test_grid_file.py +++ b/test/test_grid_file.py @@ -39,7 +39,10 @@ from gridfs.errors import (NoFile, from pymongo import MongoClient from pymongo.errors import ConnectionFailure from test.test_client import get_client -from test import qcheck +from test import qcheck, skip_restricted_localhost + + +setUpModule = skip_restricted_localhost class TestGridFile(unittest.TestCase): diff --git a/test/test_gridfs.py b/test/test_gridfs.py index c3afe7d32..959717403 100644 --- a/test/test_gridfs.py +++ b/test/test_gridfs.py @@ -32,11 +32,15 @@ from gridfs.errors import (FileExists, NoFile) from pymongo.errors import ConnectionFailure from pymongo.mongo_client import MongoClient from pymongo.read_preferences import ReadPreference +from test import skip_restricted_localhost from test.test_client import get_client from test.test_replica_set_client import TestReplicaSetClientBase from test.utils import catch_warnings, joinall +setUpModule = skip_restricted_localhost + + class JustWrite(threading.Thread): def __init__(self, fs, n): diff --git a/test/test_json_util.py b/test/test_json_util.py index 82ce286b5..46cedd363 100644 --- a/test/test_json_util.py +++ b/test/test_json_util.py @@ -37,6 +37,7 @@ from bson.son import RE_TYPE from bson.timestamp import Timestamp from bson.tz_util import utc +from test import skip_restricted_localhost from test.test_client import get_client PY3 = sys.version_info[0] == 3 @@ -221,6 +222,7 @@ class TestJsonUtil(unittest.TestCase): self.assertEqual('{"$code": "return z", "$scope": {"z": 2}}', res) def test_cursor(self): + skip_restricted_localhost() db = self.db db.drop_collection("test") diff --git a/test/test_legacy_connections.py b/test/test_legacy_connections.py index 0308f8141..54ca472e7 100644 --- a/test/test_legacy_connections.py +++ b/test/test_legacy_connections.py @@ -27,11 +27,14 @@ import pymongo from pymongo.connection import Connection from pymongo.replica_set_connection import ReplicaSetConnection from pymongo.errors import ConfigurationError -from test import host, port, pair +from test import host, port, pair, skip_restricted_localhost from test.test_replica_set_client import TestReplicaSetClientBase from test.utils import catch_warnings, get_pool +setUpModule = skip_restricted_localhost + + class TestConnection(unittest.TestCase): def test_connection(self): c = Connection(host, port) diff --git a/test/test_master_slave_connection.py b/test/test_master_slave_connection.py index 28c38069e..45d6c9575 100644 --- a/test/test_master_slave_connection.py +++ b/test/test_master_slave_connection.py @@ -15,7 +15,6 @@ """Test for master slave connections.""" import datetime -import os import sys import threading import time @@ -36,10 +35,16 @@ from pymongo.database import Database from pymongo.mongo_client import MongoClient from pymongo.collection import Collection from pymongo.master_slave_connection import MasterSlaveConnection -from test import host, port, host2, port2, host3, port3 +from test import (host, port, + host2, port2, + host3, port3, + skip_restricted_localhost) from test.utils import TestRequestMixin, catch_warnings, get_pool +setUpModule = skip_restricted_localhost + + class TestMasterSlaveConnection(unittest.TestCase, TestRequestMixin): def setUp(self): diff --git a/test/test_mongos_ha.py b/test/test_mongos_ha.py index 3032f5a37..c2fe70557 100644 --- a/test/test_mongos_ha.py +++ b/test/test_mongos_ha.py @@ -21,9 +21,13 @@ import unittest sys.path[0:0] = [""] from pymongo.errors import AutoReconnect +from test import skip_restricted_localhost from test.pymongo_mocks import MockClient +setUpModule = skip_restricted_localhost + + class FindOne(threading.Thread): def __init__(self, client): super(FindOne, self).__init__() diff --git a/test/test_objectid.py b/test/test_objectid.py index d7b950542..82383ac11 100644 --- a/test/test_objectid.py +++ b/test/test_objectid.py @@ -18,14 +18,13 @@ import datetime import pickle import unittest import sys -import time sys.path[0:0] = [""] from nose.plugins.skip import SkipTest from bson.errors import InvalidId from bson.objectid import ObjectId -from bson.py3compat import b, binary_type +from bson.py3compat import b from bson.tz_util import (FixedOffset, utc) diff --git a/test/test_pooling.py b/test/test_pooling.py index 1aa07d095..9bc78b484 100644 --- a/test/test_pooling.py +++ b/test/test_pooling.py @@ -23,13 +23,16 @@ sys.path[0:0] = [""] from nose.plugins.skip import SkipTest -from test import host, port +from test import host, port, skip_restricted_localhost from test.test_pooling_base import ( _TestPooling, _TestMaxPoolSize, _TestMaxOpenSockets, _TestPoolSocketSharing, _TestWaitQueueMultiple, one) from test.utils import get_pool +setUpModule = skip_restricted_localhost + + class TestPoolingThreads(_TestPooling, unittest.TestCase): use_greenlets = False diff --git a/test/test_pooling_gevent.py b/test/test_pooling_gevent.py index 88bb2c083..0605c34fc 100644 --- a/test/test_pooling_gevent.py +++ b/test/test_pooling_gevent.py @@ -23,13 +23,16 @@ from nose.plugins.skip import SkipTest from pymongo import pool from pymongo.errors import ConfigurationError -from test import host, port +from test import host, port, skip_restricted_localhost from test.utils import looplet from test.test_pooling_base import ( _TestPooling, _TestMaxPoolSize, _TestMaxOpenSockets, _TestPoolSocketSharing, _TestWaitQueueMultiple, has_gevent) +setUpModule = skip_restricted_localhost + + class TestPoolingGevent(_TestPooling, unittest.TestCase): """Apply all the standard pool tests with greenlets and Gevent""" use_greenlets = True diff --git a/test/test_pymongo.py b/test/test_pymongo.py index a861b1f78..033169296 100644 --- a/test/test_pymongo.py +++ b/test/test_pymongo.py @@ -15,7 +15,6 @@ """Test the pymongo module itself.""" import unittest -import os import sys sys.path[0:0] = [""] diff --git a/test/test_read_preferences.py b/test/test_read_preferences.py index 04d406b62..4b672531e 100644 --- a/test/test_read_preferences.py +++ b/test/test_read_preferences.py @@ -31,10 +31,13 @@ from pymongo.errors import ConfigurationError from test.test_replica_set_client import TestReplicaSetClientBase from test.test_client import get_client -from test import version, utils, host, port +from test import version, utils, host, port, skip_restricted_localhost from test.utils import catch_warnings +setUpModule = skip_restricted_localhost + + class TestReadPreferencesBase(TestReplicaSetClientBase): def setUp(self): super(TestReadPreferencesBase, self).setUp() diff --git a/test/test_replica_set_client.py b/test/test_replica_set_client.py index 7f58a3465..ee3acbf6f 100644 --- a/test/test_replica_set_client.py +++ b/test/test_replica_set_client.py @@ -35,7 +35,7 @@ from bson.son import SON from bson.tz_util import utc from pymongo.mongo_client import MongoClient from pymongo.read_preferences import ReadPreference -from pymongo.member import PRIMARY, SECONDARY, OTHER +from pymongo.member import SECONDARY from pymongo.mongo_replica_set_client import MongoReplicaSetClient from pymongo.mongo_replica_set_client import _partition_node, have_gevent from pymongo.database import Database @@ -45,16 +45,17 @@ from pymongo.errors import (AutoReconnect, ConnectionFailure, InvalidName, OperationFailure, InvalidOperation) -from pymongo import auth -from test import version, port, pair +from test import version, port, pair, skip_restricted_localhost, auth_context from test.pymongo_mocks import MockReplicaSetClient from test.utils import ( delay, assertReadFrom, assertReadFromAll, read_from_which_host, - remove_all_users, assertRaisesExactly, TestRequestMixin, one, - server_started_with_auth, pools_from_rs_client, get_pool, + assertRaisesExactly, TestRequestMixin, one, pools_from_rs_client, get_pool, _TestLazyConnectMixin, _TestExhaustCursorMixin) +setUpModule = skip_restricted_localhost + + class TestReplicaSetClientAgainstStandalone(unittest.TestCase): """This is a funny beast -- we want to run tests for MongoReplicaSetClient but only if the database at DB_IP and DB_PORT is a standalone. @@ -83,7 +84,10 @@ class TestReplicaSetClientBase(unittest.TestCase): self.arbiters = set([_partition_node(h) for h in response.get("arbiters", [])]) - repl_set_status = client.admin.command('replSetGetStatus') + # Cannot run replSetGetStatus in MongoDB >= 2.7.1 under auth once a + # user has been added. + repl_set_status = auth_context.client.admin.command( + 'replSetGetStatus') primary_info = [ m for m in repl_set_status['members'] if m['stateStr'] == 'PRIMARY' @@ -168,44 +172,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): self.assertRaises(ConnectionFailure, c.pymongo_test.test.find_one) - def test_init_disconnected_with_auth_failure(self): - c = MongoReplicaSetClient( - "mongodb://user:pass@somedomainthatdoesntexist", replicaSet="rs", - connectTimeoutMS=1, _connect=False) - - self.assertRaises(ConnectionFailure, c.pymongo_test.test.find_one) - - def test_init_disconnected_with_auth(self): - c = self._get_client() - if not server_started_with_auth(c): - raise SkipTest('Authentication is not enabled on server') - - c.admin.add_user("admin", "pass") - c.admin.authenticate("admin", "pass") - try: - c.pymongo_test.add_user("user", "pass", roles=['readWrite', 'userAdmin']) - - # Auth with lazy connection. - host = one(self.hosts) - uri = "mongodb://user:pass@%s:%d/pymongo_test?replicaSet=%s" % ( - host[0], host[1], self.name) - - authenticated_client = MongoReplicaSetClient(uri, _connect=False) - authenticated_client.pymongo_test.test.find_one() - - # Wrong password. - bad_uri = "mongodb://user:wrong@%s:%d/pymongo_test?replicaSet=%s" % ( - host[0], host[1], self.name) - - bad_client = MongoReplicaSetClient(bad_uri, _connect=False) - self.assertRaises( - OperationFailure, bad_client.pymongo_test.test.find_one) - - finally: - # Clean up. - remove_all_users(c.pymongo_test) - remove_all_users(c.admin) - def test_connect(self): assertRaisesExactly(ConnectionFailure, MongoReplicaSetClient, "somedomainthatdoesntexist.org:27017", @@ -341,20 +307,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): finally: socket.socket.sendall = old_sendall - def test_lazy_auth_raises_operation_failure(self): - # Check if we have the prerequisites to run this test. - c = self._get_client() - if not server_started_with_auth(c): - raise SkipTest('Authentication is not enabled on server') - - lazy_client = MongoReplicaSetClient( - "mongodb://user:wrong@%s/pymongo_test" % pair, - replicaSet=self.name, - _connect=False) - - assertRaisesExactly( - OperationFailure, lazy_client.test.collection.find_one) - def test_operations(self): c = self._get_client() @@ -466,35 +418,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): self.assertTrue("pymongo_test2" in c.database_names()) self.assertEqual("bar", c.pymongo_test2.test.find_one()["foo"]) - if version.at_least(c, (1, 3, 3, 1)) and server_started_with_auth(c): - c.drop_database("pymongo_test1") - - c.admin.add_user("admin", "password") - c.admin.authenticate("admin", "password") - try: - c.pymongo_test.add_user("mike", "password") - - self.assertRaises(OperationFailure, c.copy_database, - "pymongo_test", "pymongo_test1", - username="foo", password="bar") - self.assertFalse("pymongo_test1" in c.database_names()) - - self.assertRaises(OperationFailure, c.copy_database, - "pymongo_test", "pymongo_test1", - username="mike", password="bar") - self.assertFalse("pymongo_test1" in c.database_names()) - - c.copy_database("pymongo_test", "pymongo_test1", - username="mike", password="password") - self.assertTrue("pymongo_test1" in c.database_names()) - res = c.pymongo_test1.test.find_one(_must_use_master=True) - self.assertEqual("bar", res["foo"]) - finally: - # Cleanup - remove_all_users(c.pymongo_test) - c.admin.remove_user("admin") - c.close() - def test_get_default_database(self): host = one(self.hosts) uri = "mongodb://%s:%d/foo?replicaSet=%s" % ( @@ -1127,42 +1050,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase, TestRequestMixin): self.assertFalse(client.alive()) - def test_auth_network_error(self): - # Make sure there's no semaphore leak if we get a network error - # when authenticating a new socket with cached credentials. - auth_client = self._get_client() - if not server_started_with_auth(auth_client): - raise SkipTest('Authentication is not enabled on server') - - auth_client.admin.add_user('admin', 'password') - auth_client.admin.authenticate('admin', 'password') - try: - # Get a client with one socket so we detect if it's leaked. - c = self._get_client(max_pool_size=1, waitQueueTimeoutMS=1) - - # Simulate an authenticate() call on a different socket. - credentials = auth._build_credentials_tuple( - 'MONGODB-CR', 'admin', - unicode('admin'), unicode('password'), - {}) - - c._cache_credentials('test', credentials, connect=False) - - # Cause a network error on the actual socket. - pool = get_pool(c) - socket_info = one(pool.sockets) - socket_info.sock.close() - - # In __check_auth, the client authenticates its socket with the - # new credential, but gets a socket.error. Should be reraised as - # AutoReconnect. - self.assertRaises(AutoReconnect, c.test.collection.find_one) - - # No semaphore leak, the pool is allowed to make a new socket. - c.test.collection.find_one() - finally: - remove_all_users(auth_client.admin) - class TestReplicaSetWireVersion(unittest.TestCase): def test_wire_version(self): diff --git a/test/test_replica_set_reconfig.py b/test/test_replica_set_reconfig.py index 43bc5a0e2..58763246c 100644 --- a/test/test_replica_set_reconfig.py +++ b/test/test_replica_set_reconfig.py @@ -21,9 +21,13 @@ sys.path[0:0] = [""] from pymongo.errors import ConfigurationError, ConnectionFailure from pymongo import ReadPreference +from test import skip_restricted_localhost from test.pymongo_mocks import MockClient, MockReplicaSetClient +setUpModule = skip_restricted_localhost + + class TestSecondaryBecomesStandalone(unittest.TestCase): # An administrator removes a secondary from a 3-node set and # brings it back up as standalone, without updating the other diff --git a/test/test_threads.py b/test/test_threads.py index c21f9fbf9..b2f478e71 100644 --- a/test/test_threads.py +++ b/test/test_threads.py @@ -18,14 +18,15 @@ import unittest import threading import traceback -from nose.plugins.skip import SkipTest - -from test.utils import (joinall, remove_all_users, - server_started_with_auth, RendezvousThread) +from test import skip_restricted_localhost +from test.utils import joinall, RendezvousThread from test.test_client import get_client from test.utils import get_pool from pymongo.pool import SocketInfo, _closed -from pymongo.errors import AutoReconnect, OperationFailure +from pymongo.errors import AutoReconnect + + +setUpModule = skip_restricted_localhost class AutoAuthenticateThreads(threading.Thread): @@ -299,87 +300,9 @@ class BaseTestThreads(object): self.assertTrue(t.passed, "%s threw exception" % t) -class BaseTestThreadsAuth(object): - """ - Base test class for TestThreadsAuth and TestThreadsAuthReplicaSet. (This is - not itself a unittest.TestCase, otherwise it'd be run twice -- once when - nose imports this module, and once when nose imports - test_threads_replica_set_connection.py, which imports this module.) - """ - def _get_client(self): - """ - Intended for overriding in TestThreadsAuthReplicaSet. This method - returns a MongoClient here, and a MongoReplicaSetClient in - test_threads_replica_set_connection.py. - """ - # Regular test client - return get_client() - - def setUp(self): - client = self._get_client() - if not server_started_with_auth(client): - raise SkipTest("Authentication is not enabled on server") - self.client = client - self.client.admin.add_user('admin-user', 'password', - roles=['clusterAdmin', - 'dbAdminAnyDatabase', - 'readWriteAnyDatabase', - 'userAdminAnyDatabase']) - self.client.admin.authenticate("admin-user", "password") - self.client.auth_test.add_user("test-user", "password", - roles=['readWrite']) - - def tearDown(self): - # Remove auth users from databases - self.client.admin.authenticate("admin-user", "password") - remove_all_users(self.client.auth_test) - self.client.drop_database('auth_test') - remove_all_users(self.client.admin) - # Clear client reference so that RSC's monitor thread - # dies. - self.client = None - - def test_auto_auth_login(self): - client = self._get_client() - self.assertRaises(OperationFailure, client.auth_test.test.find_one) - - # Admin auth - client = self._get_client() - client.admin.authenticate("admin-user", "password") - - nthreads = 10 - threads = [] - for _ in xrange(nthreads): - t = AutoAuthenticateThreads(client.auth_test.test, 100) - t.start() - threads.append(t) - - joinall(threads) - - for t in threads: - self.assertTrue(t.success) - - # Database-specific auth - client = self._get_client() - client.auth_test.authenticate("test-user", "password") - - threads = [] - for _ in xrange(nthreads): - t = AutoAuthenticateThreads(client.auth_test.test, 100) - t.start() - threads.append(t) - - joinall(threads) - - for t in threads: - self.assertTrue(t.success) - class TestThreads(BaseTestThreads, unittest.TestCase): pass -class TestThreadsAuth(BaseTestThreadsAuth, unittest.TestCase): - pass - if __name__ == "__main__": unittest.main() diff --git a/test/test_threads_replica_set_client.py b/test/test_threads_replica_set_client.py index 23b517670..613847de3 100644 --- a/test/test_threads_replica_set_client.py +++ b/test/test_threads_replica_set_client.py @@ -16,10 +16,12 @@ import unittest -from pymongo.mongo_replica_set_client import MongoReplicaSetClient +from test import skip_restricted_localhost +from test.test_threads import BaseTestThreads +from test.test_replica_set_client import TestReplicaSetClientBase -from test.test_threads import BaseTestThreads, BaseTestThreadsAuth -from test.test_replica_set_client import TestReplicaSetClientBase, pair + +setUpModule = skip_restricted_localhost class TestThreadsReplicaSet(TestReplicaSetClientBase, BaseTestThreads): @@ -39,31 +41,6 @@ class TestThreadsReplicaSet(TestReplicaSetClientBase, BaseTestThreads): return TestReplicaSetClientBase._get_client(self, **kwargs) -class TestThreadsAuthReplicaSet(TestReplicaSetClientBase, BaseTestThreadsAuth): - - def setUp(self): - """ - Prepare to test all the same things that TestThreads tests, but do it - with a replica-set client - """ - TestReplicaSetClientBase.setUp(self) - BaseTestThreadsAuth.setUp(self) - - def tearDown(self): - TestReplicaSetClientBase.tearDown(self) - BaseTestThreadsAuth.tearDown(self) - - def _get_client(self): - """ - Override TestThreadsAuth, so its tests run on a MongoReplicaSetClient - instead of a regular MongoClient. - """ - return MongoReplicaSetClient(pair, replicaSet=self.name) - - if __name__ == "__main__": - suite = unittest.TestSuite([ - unittest.makeSuite(TestThreadsReplicaSet), - unittest.makeSuite(TestThreadsAuthReplicaSet) - ]) + suite = unittest.makeSuite(TestThreadsReplicaSet) unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/test/utils.py b/test/utils.py index e7b7f52c8..b1737de41 100644 --- a/test/utils.py +++ b/test/utils.py @@ -92,10 +92,8 @@ def server_started_with_auth(client): # MongoDB >= 2.6 if 'security' in parsed: security = parsed['security'] - # >= rc3 if 'authorization' in security: return security['authorization'] == 'enabled' - # < rc3 return security.get('auth', False) or bool(security.get('keyFile')) return parsed.get('auth', False) or bool(parsed.get('keyFile')) # Legacy