Simplify auth tests, don't create additional root users.

Don't log out the global test client either; keep it logged in as root and
use it to create additional non-root users to test Database.add_user,
authenticate, logout, and so on.
This commit is contained in:
A. Jesse Jiryu Davis 2014-11-17 17:29:15 -05:00
parent 1732b09155
commit 13cb74a760
2 changed files with 89 additions and 195 deletions

View File

@ -51,11 +51,12 @@ from test import (client_context,
unittest,
host,
port,
pair,
IntegrationTest)
IntegrationTest,
db_user)
from test.utils import (
ignore_deprecations,
remove_all_users,
rs_or_single_client_noauth,
server_started_with_auth)
@ -365,58 +366,58 @@ class TestDatabase(IntegrationTest):
@client_context.require_auth
def test_authenticate_add_remove_user(self):
db = self.client.pymongo_test
# "self.client" is logged in as root.
auth_db = self.client.pymongo_test
db = rs_or_single_client_noauth().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,
self.assertRaises(ValueError, auth_db.add_user, "user", '')
self.assertRaises(TypeError, auth_db.add_user, "user", 'password', 15)
self.assertRaises(ConfigurationError, auth_db.add_user,
"user", 'password', 'True')
self.assertRaises(ConfigurationError, db.add_user,
self.assertRaises(ConfigurationError, auth_db.add_user,
"user", 'password', True, roles=['read'])
if client_context.version.at_least(2, 5, 3, -1):
with warnings.catch_warnings():
warnings.simplefilter("error", DeprecationWarning)
self.assertRaises(DeprecationWarning, db.add_user,
self.assertRaises(DeprecationWarning, auth_db.add_user,
"user", "password")
self.assertRaises(DeprecationWarning, db.add_user,
self.assertRaises(DeprecationWarning, auth_db.add_user,
"user", "password", True)
with ignore_deprecations():
self.assertRaises(ConfigurationError, db.add_user,
self.assertRaises(ConfigurationError, auth_db.add_user,
"user", "password", digestPassword=True)
self.client.admin.add_user("admin", "password",
roles=["root", "userAdminAnyDatabase"])
auth_c = MongoClient(pair)
auth_c.admin.authenticate("admin", "password")
db = auth_c.pymongo_test
try:
# Add / authenticate / remove
db.add_user("mike", "password", roles=["dbOwner"])
auth_db.add_user("mike", "password", roles=["dbOwner"])
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.authenticate("mike", "password")
db.logout()
# Unicode name and password.
db.authenticate(u("mike"), u("password"))
db.logout()
auth_db.remove_user("mike")
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"), roles=["dbOwner"])
self.assertTrue(db.authenticate("Gustave", u("Dor\xe9")))
db.add_user("Gustave", "password", roles=["dbOwner"])
auth_db.add_user("Gustave", u("Dor\xe9"), roles=["dbOwner"])
db.authenticate("Gustave", u("Dor\xe9"))
# Change password.
auth_db.add_user("Gustave", "password", roles=["dbOwner"])
db.logout()
self.assertRaises(OperationFailure,
db.authenticate, "Gustave", u("Dor\xe9"))
@ -425,33 +426,24 @@ class TestDatabase(IntegrationTest):
if not client_context.version.at_least(2, 5, 3, -1):
# Add a readOnly user
with ignore_deprecations():
db.add_user("Ross", "password", read_only=True)
auth_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
db.authenticate("Ross", u("password"))
self.assertTrue(
auth_db.system.users.find({"readOnly": True}).count())
finally:
remove_all_users(db)
db.logout()
auth_c.admin.remove_user("admin")
remove_all_users(auth_db)
@client_context.require_auth
def test_make_user_readonly(self):
auth_c = MongoClient(pair)
admin = auth_c.admin
self.client.admin.add_user('admin', 'pw',
roles=['root', 'userAdminAnyDatabase'])
admin.authenticate('admin', 'pw')
db = auth_c.pymongo_test
# "self.client" is logged in as root.
auth_db = self.client.pymongo_test
db = rs_or_single_client_noauth().pymongo_test
try:
# Make a read-write user.
db.add_user('jesse', 'pw')
admin.logout()
auth_db.add_user('jesse', 'pw')
# Check that we're read-write by default.
db.authenticate('jesse', 'pw')
@ -459,81 +451,54 @@ class TestDatabase(IntegrationTest):
db.logout()
# Make the user read-only.
admin.authenticate('admin', 'pw')
db.add_user('jesse', 'pw', read_only=True)
admin.logout()
auth_db.add_user('jesse', 'pw', read_only=True)
db.authenticate('jesse', 'pw')
self.assertRaises(OperationFailure, db.collection.insert, {})
finally:
# Cleanup
admin.authenticate('admin', 'pw')
remove_all_users(db)
admin.remove_user("admin")
remove_all_users(auth_db)
@client_context.require_version_min(2, 5, 3, -1)
@client_context.require_auth
def test_default_roles(self):
# "Admin" user
with ignore_deprecations():
self.client.admin.add_user('admin', 'pass')
auth_c = MongoClient(pair)
db = auth_c.admin
# "self.client" is logged in as root.
auth_admin = self.client.admin
try:
db.authenticate('admin', 'pass')
info = db.command('usersInfo', 'admin')['users'][0]
info = auth_admin.command('usersInfo', db_user)['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]
auth_admin.add_user('ro-admin', 'pass', read_only=True)
info = auth_admin.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()
auth_admin.remove_user('ro-admin')
# "Non-admin" user
db = auth_c.pymongo_test
self.client.pymongo_test.add_user('user', 'pass')
auth_db = self.client.pymongo_test
auth_db.add_user('user', 'pass')
try:
db.authenticate('user', 'pass')
info = db.command('usersInfo', 'user')['users'][0]
info = auth_db.command('usersInfo', 'user')['users'][0]
self.assertEqual("dbOwner", info['roles'][0]['role'])
db.logout()
# Read only "Non-admin" user
self.client.pymongo_test.add_user('ro-user', 'pass',
read_only=True)
db.authenticate('ro-user', 'pass')
info = db.command('usersInfo', 'ro-user')['users'][0]
auth_db.add_user('ro-user', 'pass', read_only=True)
info = auth_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)
remove_all_users(auth_db)
@client_context.require_version_min(2, 5, 3, -1)
@client_context.require_auth
def test_new_user_cmds(self):
auth_c = MongoClient(pair)
db = auth_c.pymongo_test
self.client.pymongo_test.add_user("amalia", "password",
roles=["userAdmin"])
# "self.client" is logged in as root.
auth_db = self.client.pymongo_test
auth_db.add_user("amalia", "password", roles=["userAdmin"])
db.authenticate("amalia", "password")
try:
db = rs_or_single_client_noauth().pymongo_test
db.authenticate("amalia", "password")
# This tests the ability to update user attributes.
db.add_user("amalia", "new_password",
customData={"secret": "koalas"})
@ -544,61 +509,33 @@ class TestDatabase(IntegrationTest):
self.assertEqual(amalia_user["user"], "amalia")
self.assertEqual(amalia_user["customData"], {"secret": "koalas"})
finally:
db.remove_user("amalia")
@client_context.require_auth
def test_authenticate_and_safe(self):
auth_c = MongoClient(pair)
db = auth_c.auth_test
self.client.auth_test.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")
auth_db.remove_user("amalia")
@client_context.require_auth
def test_authenticate_multiple(self):
# Setup
# "self.client" is logged in as root.
self.client.drop_database("pymongo_test")
self.client.drop_database("pymongo_test1")
auth_c = MongoClient(pair)
users_db = auth_c.pymongo_test
admin_db = auth_c.admin
other_db = auth_c.pymongo_test1
admin_db_auth = self.client.admin
users_db_auth = self.client.pymongo_test
# Non-root client.
client = rs_or_single_client_noauth()
admin_db = client.admin
users_db = client.pymongo_test
other_db = client.pymongo_test1
self.client.admin.add_user(
'admin', 'pass',
roles=["userAdminAnyDatabase", "dbAdmin",
"clusterAdmin", "readWrite"])
try:
self.assertTrue(admin_db.authenticate('admin', 'pass'))
self.assertRaises(OperationFailure, users_db.test.find_one)
if client_context.version.at_least(2, 5, 3, -1):
admin_db.add_user('ro-admin', 'pass',
roles=["userAdmin", "readAnyDatabase"])
admin_db_auth.add_user('ro-admin', 'pass',
roles=["userAdmin", "readAnyDatabase"])
else:
admin_db.add_user('ro-admin', 'pass', read_only=True)
admin_db_auth.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)
users_db_auth.add_user('user', 'pass',
roles=["userAdmin", "readWrite"])
# Regular user should be able to query its own db, but
# no other.
@ -613,22 +550,21 @@ class TestDatabase(IntegrationTest):
self.assertRaises(OperationFailure,
other_db.test.insert, {})
# Force close all sockets
auth_c.disconnect()
# Close all sockets.
client.disconnect()
# We should still be able to write to the regular user's db
# 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...
# But still not write to other dbs.
self.assertRaises(OperationFailure,
other_db.test.insert, {})
# Cleanup
finally:
remove_all_users(users_db)
self.client.admin.remove_user('ro-admin')
self.client.admin.remove_user('admin')
remove_all_users(users_db_auth)
admin_db_auth.remove_user('ro-admin')
def test_id_ordering(self):
# PyMongo attempts to have _id show up first

View File

@ -15,14 +15,13 @@
"""Test that pymongo is thread safe."""
import threading
import traceback
from test import unittest, client_context, IntegrationTest, db_user, db_pwd
from test.utils import (frequent_thread_switches,
joinall,
remove_all_users,
RendezvousThread,
rs_or_single_client)
rs_or_single_client,
rs_or_single_client_noauth)
from test.utils import get_pool
from pymongo.pool import SocketInfo, _closed
from pymongo.errors import AutoReconnect, OperationFailure
@ -39,17 +38,15 @@ class AutoAuthenticateThreads(threading.Thread):
threading.Thread.__init__(self)
self.coll = collection
self.num = num
self.success = True
self.success = False
self.setDaemon(True)
def run(self):
try:
for i in range(self.num):
self.coll.insert({'num':i})
self.coll.find_one({'num':i})
except Exception:
traceback.print_exc()
self.success = False
for i in range(self.num):
self.coll.insert({'num': i})
self.coll.find_one({'num': i})
self.success = True
class SaveAndFind(threading.Thread):
@ -331,56 +328,17 @@ class TestThreadsAuth(IntegrationTest):
def setUpClass(cls):
super(TestThreadsAuth, cls).setUpClass()
def setUp(self):
self.client.admin.add_user('admin-user', 'password',
roles=['clusterAdmin',
'dbAdminAnyDatabase',
'readWriteAnyDatabase',
'userAdminAnyDatabase'])
# client is already authenticated to get around restricted
# localhost exception in MongoDB >= 2.7.1.
self.client.admin.logout()
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')
self.client.admin.remove_user('admin-user')
self.client.admin.logout()
self.client.admin.authenticate(db_user, db_pwd)
def test_auto_auth_login(self):
client = self.client
client.admin.logout()
client = rs_or_single_client_noauth()
self.assertRaises(OperationFailure, client.auth_test.test.find_one)
# Admin auth
client.admin.authenticate("admin-user", "password")
client.admin.authenticate(db_user, db_pwd)
nthreads = 10
threads = []
for _ in range(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.admin.logout()
client.auth_test.authenticate("test-user", "password")
threads = []
for _ in range(nthreads):
t = AutoAuthenticateThreads(client.auth_test.test, 100)
t = AutoAuthenticateThreads(client.auth_test.test, 10)
t.start()
threads.append(t)