def test_db_authenticate_threaded(self):

        db = client_context.client.db
        coll = db.test
        coll.drop()
        coll.insert_one({'_id': 1})

        client_context.create_user(
            'db',
            'user',
            'pass',
            roles=['dbOwner'])
        self.addCleanup(db.command, 'dropUser', 'user')

        db = rs_or_single_client_noauth().db
        db.authenticate('user', 'pass')
        # No error.
        db.authenticate('user', 'pass')

        db = rs_or_single_client_noauth().db
        threads = []
        for _ in range(4):
            threads.append(DBAuthenticateThread(db, 'user', 'pass'))
        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()
            self.assertTrue(thread.success)
Example #2
0
    def test_db_authenticate_threaded(self):

        db = client_context.client.db
        coll = db.test
        coll.drop()
        coll.insert_one({'_id': 1})

        client_context.create_user(
            'db',
            'user',
            'pass',
            roles=['dbOwner'])
        self.addCleanup(db.command, 'dropUser', 'user')

        db = rs_or_single_client_noauth().db
        db.authenticate('user', 'pass')
        # No error.
        db.authenticate('user', 'pass')

        db = rs_or_single_client_noauth().db
        threads = []
        for _ in range(4):
            threads.append(DBAuthenticateThread(db, 'user', 'pass'))
        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()
            self.assertTrue(thread.success)
    def test_auth_from_uri(self):
        self.client.admin.add_user("admin", "pass", roles=["root"])
        self.addCleanup(self.client.admin.remove_user, "admin")
        self.addCleanup(remove_all_users, self.client.pymongo_test)

        self.client.pymongo_test.add_user("user", "pass", roles=["userAdmin", "readWrite"])

        with self.assertRaises(OperationFailure):
            connected(rs_or_single_client("mongodb://*****:*****@%s:%d" % (host, port)))

        # No error.
        connected(rs_or_single_client_noauth("mongodb://*****:*****@%s:%d" % (host, port)))

        # Wrong database.
        uri = "mongodb://*****:*****@%s:%d/pymongo_test" % (host, port)
        with self.assertRaises(OperationFailure):
            connected(rs_or_single_client(uri))

        # No error.
        connected(rs_or_single_client_noauth("mongodb://*****:*****@%s:%d/pymongo_test" % (host, port)))

        # Auth with lazy connection.
        rs_or_single_client(
            "mongodb://*****:*****@%s:%d/pymongo_test" % (host, port), connect=False
        ).pymongo_test.test.find_one()

        # Wrong password.
        bad_client = rs_or_single_client("mongodb://*****:*****@%s:%d/pymongo_test" % (host, port), connect=False)

        self.assertRaises(OperationFailure, bad_client.pymongo_test.test.find_one)
    def test_make_user_readonly(self):
        extra = {}
        if client_context.version.at_least(3, 7, 2):
            extra['mechanisms'] = ['SCRAM-SHA-1']

        # "self.client" is logged in as root.
        auth_db = self.client.pymongo_test

        # Make a read-write user.
        auth_db.add_user('jesse', 'pw', **extra)
        self.addCleanup(remove_all_users, auth_db)

        # Check that we're read-write by default.
        c = rs_or_single_client_noauth(username='******',
                                       password='******',
                                       authSource='pymongo_test')

        c.pymongo_test.collection.insert_one({})

        # Make the user read-only.
        auth_db.add_user('jesse', 'pw', read_only=True, **extra)

        c = rs_or_single_client_noauth(username='******',
                                       password='******',
                                       authSource='pymongo_test')

        self.assertRaises(OperationFailure,
                          c.pymongo_test.collection.insert_one,
                          {})
Example #5
0
    def test_scram_sha1(self):
        host, port = client_context.host, client_context.port

        with ignore_deprecations():
            client = rs_or_single_client_noauth()
            self.assertTrue(
                client.pymongo_test.authenticate('user',
                                                 'pass',
                                                 mechanism='SCRAM-SHA-1'))
            client.pymongo_test.command('dbstats')

        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/pymongo_test?authMechanism=SCRAM-SHA-1'
            % (host, port))
        client.pymongo_test.command('dbstats')

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/pymongo_test?authMechanism=SCRAM-SHA-1'
                   '&replicaSet=%s' %
                   (host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            client.pymongo_test.command('dbstats')
            db = client.get_database('pymongo_test',
                                     read_preference=ReadPreference.SECONDARY)
            db.command('dbstats')
Example #6
0
    def test_make_user_readonly(self):
        # "self.client" is logged in as root.
        auth_db = self.client.pymongo_test

        # Make a read-write user.
        auth_db.add_user('jesse', 'pw')
        self.addCleanup(remove_all_users, auth_db)

        # Check that we're read-write by default.
        c = rs_or_single_client_noauth(username='******',
                                       password='******',
                                       authSource='pymongo_test')

        c.pymongo_test.collection.insert_one({})

        # Make the user read-only.
        auth_db.add_user('jesse', 'pw', read_only=True)

        c = rs_or_single_client_noauth(username='******',
                                       password='******',
                                       authSource='pymongo_test')

        self.assertRaises(OperationFailure,
                          c.pymongo_test.collection.insert_one,
                          {})
    def test_make_user_readonly(self):
        # "self.client" is logged in as root.
        auth_db = self.client.pymongo_test

        # Make a read-write user.
        auth_db.add_user('jesse', 'pw')
        self.addCleanup(remove_all_users, auth_db)

        # Check that we're read-write by default.
        c = rs_or_single_client_noauth(username='******',
                                       password='******',
                                       authSource='pymongo_test')

        c.pymongo_test.collection.insert_one({})

        # Make the user read-only.
        auth_db.add_user('jesse', 'pw', read_only=True)

        c = rs_or_single_client_noauth(username='******',
                                       password='******',
                                       authSource='pymongo_test')

        self.assertRaises(OperationFailure,
                          c.pymongo_test.collection.insert_one,
                          {})
    def test_scram_saslprep(self):
        # Step 4: test SASLprep
        host, port = client_context.host, client_context.port
        # Test the use of SASLprep on passwords. For example,
        # saslprep('\u2136') becomes 'IV' and saslprep('I\u00ADX')
        # becomes 'IX'. SASLprep is only supported when the standard
        # library provides stringprep.
        client_context.create_user(
            'testscram', '\u2168', '\u2163', roles=['dbOwner'],
            mechanisms=['SCRAM-SHA-256'])
        client_context.create_user(
            'testscram', 'IX', 'IX', roles=['dbOwner'],
            mechanisms=['SCRAM-SHA-256'])

        client = rs_or_single_client_noauth(
            username='******', password='******', authSource='testscram')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            username='******', password='******', authSource='testscram',
            authMechanism='SCRAM-SHA-256')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            username='******', password='******', authSource='testscram')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            username='******', password='******', authSource='testscram')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            username='******', password='******', authSource='testscram',
            authMechanism='SCRAM-SHA-256')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            username='******', password='******', authSource='testscram',
            authMechanism='SCRAM-SHA-256')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            'mongodb://\u2168:\u2163@%s:%d/testscram' % (host, port))
        client.testscram.command('dbstats')
        client = rs_or_single_client_noauth(
            'mongodb://\u2168:IV@%s:%d/testscram' % (host, port))
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/testscram' % (host, port))
        client.testscram.command('dbstats')
        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/testscram' % (host, port))
        client.testscram.command('dbstats')
    def test_uri_options(self):
        # Test default to admin
        host, port = client_context.host, client_context.port
        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d' % (host, port))
        self.assertTrue(client.admin.command('dbstats'))

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/?replicaSet=%s' % (
                host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            self.assertTrue(client.admin.command('dbstats'))
            db = client.get_database(
                'admin', read_preference=ReadPreference.SECONDARY)
            self.assertTrue(db.command('dbstats'))

        # Test explicit database
        uri = 'mongodb://*****:*****@%s:%d/pymongo_test' % (host, port)
        client = rs_or_single_client_noauth(uri)
        self.assertRaises(OperationFailure, client.admin.command, 'dbstats')
        self.assertTrue(client.pymongo_test.command('dbstats'))

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/pymongo_test?replicaSet=%s' % (
                host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            self.assertRaises(OperationFailure,
                              client.admin.command, 'dbstats')
            self.assertTrue(client.pymongo_test.command('dbstats'))
            db = client.get_database(
                'pymongo_test', read_preference=ReadPreference.SECONDARY)
            self.assertTrue(db.command('dbstats'))

        # Test authSource
        uri = ('mongodb://*****:*****@%s:%d'
               '/pymongo_test2?authSource=pymongo_test' % (host, port))
        client = rs_or_single_client_noauth(uri)
        self.assertRaises(OperationFailure,
                          client.pymongo_test2.command, 'dbstats')
        self.assertTrue(client.pymongo_test.command('dbstats'))

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/pymongo_test2?replicaSet='
                   '%s;authSource=pymongo_test' % (
                host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            self.assertRaises(OperationFailure,
                              client.pymongo_test2.command, 'dbstats')
            self.assertTrue(client.pymongo_test.command('dbstats'))
            db = client.get_database(
                'pymongo_test', read_preference=ReadPreference.SECONDARY)
            self.assertTrue(db.command('dbstats'))
Example #10
0
    def test_uri_options(self):
        # Test default to admin
        host, port = client_context.host, client_context.port
        client = rs_or_single_client_noauth('mongodb://*****:*****@%s:%d' %
                                            (host, port))
        self.assertTrue(client.admin.command('dbstats'))

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/?replicaSet=%s' %
                   (host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            self.assertTrue(client.admin.command('dbstats'))
            db = client.get_database('admin',
                                     read_preference=ReadPreference.SECONDARY)
            self.assertTrue(db.command('dbstats'))

        # Test explicit database
        uri = 'mongodb://*****:*****@%s:%d/pymongo_test' % (host, port)
        client = rs_or_single_client_noauth(uri)
        self.assertRaises(OperationFailure, client.admin.command, 'dbstats')
        self.assertTrue(client.pymongo_test.command('dbstats'))

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/pymongo_test?replicaSet=%s' %
                   (host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            self.assertRaises(OperationFailure, client.admin.command,
                              'dbstats')
            self.assertTrue(client.pymongo_test.command('dbstats'))
            db = client.get_database('pymongo_test',
                                     read_preference=ReadPreference.SECONDARY)
            self.assertTrue(db.command('dbstats'))

        # Test authSource
        uri = ('mongodb://*****:*****@%s:%d'
               '/pymongo_test2?authSource=pymongo_test' % (host, port))
        client = rs_or_single_client_noauth(uri)
        self.assertRaises(OperationFailure, client.pymongo_test2.command,
                          'dbstats')
        self.assertTrue(client.pymongo_test.command('dbstats'))

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/pymongo_test2?replicaSet='
                   '%s;authSource=pymongo_test' %
                   (host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            self.assertRaises(OperationFailure, client.pymongo_test2.command,
                              'dbstats')
            self.assertTrue(client.pymongo_test.command('dbstats'))
            db = client.get_database('pymongo_test',
                                     read_preference=ReadPreference.SECONDARY)
            self.assertTrue(db.command('dbstats'))
    def test_multiple_logins(self):
        self.client.pymongo_test.add_user('user1', 'pass', roles=['readWrite'])
        self.client.pymongo_test.add_user('user2', 'pass', roles=['readWrite'])
        self.addCleanup(remove_all_users, self.client.pymongo_test)

        client = rs_or_single_client_noauth(
            "mongodb://*****:*****@%s:%d/pymongo_test" % (host, port))

        client.pymongo_test.test.find_one()
        with self.assertRaises(OperationFailure):
            # Can't log in to the same database with multiple users.
            client.pymongo_test.authenticate('user2', 'pass')

        client.pymongo_test.test.find_one()
        client.pymongo_test.logout()
        with self.assertRaises(OperationFailure):
            client.pymongo_test.test.find_one()

        client.pymongo_test.authenticate('user2', 'pass')
        client.pymongo_test.test.find_one()

        with self.assertRaises(OperationFailure):
            client.pymongo_test.authenticate('user1', 'pass')

        client.pymongo_test.test.find_one()
Example #12
0
    def test_multiple_logins(self):
        self.client.pymongo_test.add_user('user1', 'pass', roles=['readWrite'])
        self.client.pymongo_test.add_user('user2', 'pass', roles=['readWrite'])
        self.addCleanup(remove_all_users, self.client.pymongo_test)

        client = rs_or_single_client_noauth(
            "mongodb://*****:*****@%s:%d/pymongo_test" % (host, port))

        client.pymongo_test.test.find_one()
        with self.assertRaises(OperationFailure):
            # Can't log in to the same database with multiple users.
            client.pymongo_test.authenticate('user2', 'pass')

        client.pymongo_test.test.find_one()
        client.pymongo_test.logout()
        with self.assertRaises(OperationFailure):
            client.pymongo_test.test.find_one()

        client.pymongo_test.authenticate('user2', 'pass')
        client.pymongo_test.test.find_one()

        with self.assertRaises(OperationFailure):
            client.pymongo_test.authenticate('user1', 'pass')

        client.pymongo_test.test.find_one()
        def check_auth(username, password):
            c = rs_or_single_client_noauth(
                username=username,
                password=password,
                authSource="pymongo_test")

            c.pymongo_test.collection.find_one()
Example #14
0
 def test_delegated_auth(self):
     self.client.pymongo_test2.foo.drop()
     self.client.pymongo_test2.foo.insert_one({})
     # User definition with no roles in pymongo_test.
     self.client.pymongo_test.add_user('user', 'pass', roles=[])
     # Delegate auth to pymongo_test.
     self.client.pymongo_test2.add_user('user',
                                        userSource='pymongo_test',
                                        roles=['read'])
     auth_c = rs_or_single_client_noauth()
     self.assertRaises(OperationFailure, auth_c.pymongo_test2.foo.find_one)
     # Auth must occur on the db where the user is defined.
     self.assertRaises(OperationFailure, auth_c.pymongo_test2.authenticate,
                       'user', 'pass')
     # Auth directly
     self.assertTrue(auth_c.pymongo_test.authenticate('user', 'pass'))
     self.assertTrue(auth_c.pymongo_test2.foo.find_one())
     auth_c.pymongo_test.logout()
     self.assertRaises(OperationFailure, auth_c.pymongo_test2.foo.find_one)
     # Auth using source
     self.assertTrue(
         auth_c.pymongo_test2.authenticate('user',
                                           'pass',
                                           source='pymongo_test'))
     self.assertTrue(auth_c.pymongo_test2.foo.find_one())
     # Must logout from the db authenticate was called on.
     auth_c.pymongo_test2.logout()
     self.assertRaises(OperationFailure, auth_c.pymongo_test2.foo.find_one)
Example #15
0
 def test_delegated_auth(self):
     self.client.pymongo_test2.foo.drop()
     self.client.pymongo_test2.foo.insert_one({})
     # User definition with no roles in pymongo_test.
     self.client.pymongo_test.add_user('user', 'pass', roles=[])
     # Delegate auth to pymongo_test.
     self.client.pymongo_test2.add_user('user',
                                        userSource='pymongo_test',
                                        roles=['read'])
     auth_c = rs_or_single_client_noauth()
     self.assertRaises(OperationFailure,
                       auth_c.pymongo_test2.foo.find_one)
     # Auth must occur on the db where the user is defined.
     self.assertRaises(OperationFailure,
                       auth_c.pymongo_test2.authenticate,
                       'user', 'pass')
     # Auth directly
     self.assertTrue(auth_c.pymongo_test.authenticate('user', 'pass'))
     self.assertTrue(auth_c.pymongo_test2.foo.find_one())
     auth_c.pymongo_test.logout()
     self.assertRaises(OperationFailure,
                       auth_c.pymongo_test2.foo.find_one)
     # Auth using source
     self.assertTrue(auth_c.pymongo_test2.authenticate(
         'user', 'pass', source='pymongo_test'))
     self.assertTrue(auth_c.pymongo_test2.foo.find_one())
     # Must logout from the db authenticate was called on.
     auth_c.pymongo_test2.logout()
     self.assertRaises(OperationFailure,
                       auth_c.pymongo_test2.foo.find_one)
Example #16
0
    def test_scram_skip_empty_exchange(self):
        listener = WhiteListEventListener("saslStart", "saslContinue")
        client_context.create_user('testscram',
                                   'sha256',
                                   'pwd',
                                   roles=['dbOwner'],
                                   mechanisms=['SCRAM-SHA-256'])

        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram',
                                            event_listeners=[listener])
        client.testscram.command('dbstats')

        if client_context.version < (4, 4, -1):
            # Assert we sent the skipEmptyExchange option.
            first_event = listener.results['started'][0]
            self.assertEqual(first_event.command_name, 'saslStart')
            self.assertEqual(first_event.command['options'],
                             {'skipEmptyExchange': True})

        # Assert the third exchange was skipped on servers that support it.
        # Note that the first exchange occurs on the connection handshake.
        started = listener.started_command_names()
        if client_context.version.at_least(4, 4, -1):
            self.assertEqual(started, ['saslContinue'])
        else:
            self.assertEqual(started,
                             ['saslStart', 'saslContinue', 'saslContinue'])
        def check_auth(username, password):
            c = rs_or_single_client_noauth(
                username=username,
                password=password,
                authSource="pymongo_test")

            c.pymongo_test.collection.find_one()
 def test_readonly(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth(username='******', password='******',
                                      authSource='pymongo_test')
     coll = cli.pymongo_test.test
     coll.find_one()
     self.assertRaises(OperationFailure, coll.bulk_write,
                       [InsertOne({'x': 1})])
Example #19
0
 def test_readonly(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth(username='******', password='******',
                                      authSource='pymongo_test')
     coll = cli.pymongo_test.test
     coll.find_one()
     self.assertRaises(OperationFailure, coll.bulk_write,
                       [InsertOne({'x': 1})])
Example #20
0
 def test_readonly(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth()
     db = cli.pymongo_test
     coll = db.test
     db.authenticate('readonly', 'pw')
     bulk = coll.initialize_ordered_bulk_op()
     bulk.insert({'x': 1})
     self.assertRaises(OperationFailure, bulk.execute)
Example #21
0
 def test_readonly(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth()
     db = cli.pymongo_test
     coll = db.test
     db.authenticate('readonly', 'pw')
     bulk = coll.initialize_ordered_bulk_op()
     bulk.insert({'x': 1})
     self.assertRaises(OperationFailure, bulk.execute)
Example #22
0
 def test_readonly(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth(username='******',
                                      password='******',
                                      authSource='pymongo_test')
     coll = cli.pymongo_test.test
     bulk = coll.initialize_ordered_bulk_op()
     bulk.insert({'x': 1})
     self.assertRaises(OperationFailure, bulk.execute)
    def test_authenticate_multiple(self):
        extra = {}
        if client_context.version.at_least(3, 7, 2):
            extra['mechanisms'] = ['SCRAM-SHA-1']

        # "self.client" is logged in as root.
        self.client.drop_database("pymongo_test")
        self.client.drop_database("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.assertRaises(OperationFailure, users_db.test.find_one)

        admin_db_auth.add_user(
            'ro-admin',
            'pass',
            roles=["userAdmin", "readAnyDatabase"],
            **extra)

        self.addCleanup(client_context.drop_user, 'admin', 'ro-admin')
        users_db_auth.add_user(
            'user', 'pass', roles=["userAdmin", "readWrite"], **extra)
        self.addCleanup(remove_all_users, users_db_auth)

        # 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(None, other_db.test.find_one())
        self.assertRaises(OperationFailure,
                          other_db.test.insert_one, {})

        # Close all sockets.
        client.close()

        # We should still be able to write to the regular user's db.
        self.assertTrue(users_db.test.delete_many({}))

        # 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_one, {})
Example #24
0
    def test_auth_from_uri(self):
        self.client.admin.add_user("admin", "pass", roles=["root"])
        self.addCleanup(self.client.admin.remove_user, 'admin')
        self.addCleanup(remove_all_users, self.client.pymongo_test)

        self.client.pymongo_test.add_user("user",
                                          "pass",
                                          roles=['userAdmin', 'readWrite'])

        with self.assertRaises(OperationFailure):
            connected(rs_or_single_client("mongodb://*****:*****@%s:%d" %
                                          (host, port)))

        # No error.
        connected(
            rs_or_single_client_noauth("mongodb://*****:*****@%s:%d" %
                                       (host, port)))

        # Wrong database.
        uri = "mongodb://*****:*****@%s:%d/pymongo_test" % (host, port)
        with self.assertRaises(OperationFailure):
            connected(rs_or_single_client(uri))

        # No error.
        connected(
            rs_or_single_client_noauth(
                "mongodb://*****:*****@%s:%d/pymongo_test" % (host, port)))

        # Auth with lazy connection.
        rs_or_single_client("mongodb://*****:*****@%s:%d/pymongo_test" %
                            (host, port),
                            connect=False).pymongo_test.test.find_one()

        # Wrong password.
        bad_client = rs_or_single_client(
            "mongodb://*****:*****@%s:%d/pymongo_test" % (host, port),
            connect=False)

        self.assertRaises(OperationFailure,
                          bad_client.pymongo_test.test.find_one)
Example #25
0
    def test_scram_sha1(self):
        host, port = client_context.host, client_context.port
        client = rs_or_single_client_noauth()
        self.assertTrue(client.pymongo_test.authenticate(
            'user', 'pass', mechanism='SCRAM-SHA-1'))
        client.pymongo_test.command('dbstats')

        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/pymongo_test?authMechanism=SCRAM-SHA-1'
            % (host, port))
        client.pymongo_test.command('dbstats')

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/pymongo_test?authMechanism=SCRAM-SHA-1'
                   '&replicaSet=%s' % (host, port,
                                       client_context.replica_set_name))
            client = single_client_noauth(uri)
            client.pymongo_test.command('dbstats')
            db = client.get_database(
                'pymongo_test', read_preference=ReadPreference.SECONDARY)
            db.command('dbstats')
Example #26
0
    def test_gridfs_readonly(self):
        # "self.client" is logged in as root. Make a read-only user.
        auth_db = self.client.test_gridfs_readonly
        auth_db.add_user('readonly', 'pw', readOnly=True)
        self.addCleanup(remove_all_users, auth_db)

        db = rs_or_single_client_noauth().test_gridfs_readonly
        db.authenticate('readonly', 'pw')

        fs = gridfs.GridFS(db)
        file = fs.new_file()
        file._ensure_index()
        fs.list()
    def test_authenticate_multiple(self):
        # "self.client" is logged in as root.
        self.client.drop_database("pymongo_test")
        self.client.drop_database("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.assertRaises(OperationFailure, users_db.test.find_one)

        if client_context.version.at_least(2, 5, 3, -1):
            admin_db_auth.add_user('ro-admin', 'pass',
                                   roles=["userAdmin", "readAnyDatabase"])
        else:
            admin_db_auth.add_user('ro-admin', 'pass', read_only=True)

        self.addCleanup(admin_db_auth.remove_user, 'ro-admin')
        users_db_auth.add_user('user', 'pass',
                               roles=["userAdmin", "readWrite"])
        self.addCleanup(remove_all_users, users_db_auth)

        # 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(None, other_db.test.find_one())
        self.assertRaises(OperationFailure,
                          other_db.test.insert_one, {})

        # Close all sockets.
        client.close()

        # We should still be able to write to the regular user's db.
        self.assertTrue(users_db.test.delete_many({}))

        # 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_one, {})
Example #28
0
 def test_no_remove(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth(username='******',
                                      password='******',
                                      authSource='pymongo_test')
     coll = cli.pymongo_test.test
     bulk = 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')))
Example #29
0
 def test_no_remove(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth()
     db = cli.pymongo_test
     coll = db.test
     db.authenticate('noremove', 'pw')
     bulk = 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 test_no_remove(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth(username='******', password='******',
                                      authSource='pymongo_test')
     coll = cli.pymongo_test.test
     coll.find_one()
     requests = [
         InsertOne({'x': 1}),
         ReplaceOne({'x': 2}, {'x': 2}, upsert=True),
         DeleteMany({}),       # Prohibited.
         InsertOne({'x': 3}),  # Never attempted.
     ]
     self.assertRaises(OperationFailure, coll.bulk_write, requests)
     self.assertEqual(set([1, 2]), set(self.coll.distinct('x')))
Example #31
0
 def test_no_remove(self):
     # We test that an authorization failure aborts the batch and is raised
     # as OperationFailure.
     cli = rs_or_single_client_noauth(username='******', password='******',
                                      authSource='pymongo_test')
     coll = cli.pymongo_test.test
     coll.find_one()
     requests = [
         InsertOne({'x': 1}),
         ReplaceOne({'x': 2}, {'x': 2}, upsert=True),
         DeleteMany({}),       # Prohibited.
         InsertOne({'x': 3}),  # Never attempted.
     ]
     self.assertRaises(OperationFailure, coll.bulk_write, requests)
     self.assertEqual(set([1, 2]), set(self.coll.distinct('x')))
    def setUp(self):
        client_context.client.admin.add_user('admin', 'pass',
                                             roles=['userAdminAnyDatabase',
                                                    'dbAdminAnyDatabase',
                                                    'readWriteAnyDatabase',
                                                    'clusterAdmin'])
        client = rs_or_single_client_noauth(username='******', password='******')
        client.pymongo_test.add_user('user', 'pass',
                                     roles=['userAdmin', 'readWrite'])

        if client_context.is_rs:
            # Make sure the admin user is replicated after calling add_user
            # above. This avoids a race in the replica set tests below.
            client.admin.command('getLastError', w=client_context.w)
        self.client = client
Example #33
0
    def setUp(self):
        client = rs_or_single_client_noauth()
        client_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'])

        if client_context.is_rs:
            # Make sure the admin user is replicated after calling add_user
            # above. This avoids a race in the replica set tests below.
            client.admin.command('getLastError', w=client_context.w)
        self.client = client
    def test_ipv6(self):
        if client_context.auth_enabled:
            auth_str = "%s:%s@" % (db_user, db_pwd)
        else:
            auth_str = ""

        uri = "mongodb://%s[::1]:%d" % (auth_str, port)
        if client_context.is_rs:
            uri += '/?replicaSet=' + client_context.replica_set_name

        client = rs_or_single_client_noauth(uri)
        client.pymongo_test.test.insert_one({"dummy": u("object")})
        client.pymongo_test_bernie.test.insert_one({"dummy": u("object")})

        dbs = client.database_names()
        self.assertTrue("pymongo_test" in dbs)
        self.assertTrue("pymongo_test_bernie" in dbs)
Example #35
0
    def test_ipv6(self):
        if client_context.auth_enabled:
            auth_str = "%s:%s@" % (db_user, db_pwd)
        else:
            auth_str = ""

        uri = "mongodb://%s[::1]:%d" % (auth_str, port)
        if client_context.is_rs:
            uri += '/?replicaSet=' + client_context.replica_set_name

        client = rs_or_single_client_noauth(uri)
        client.pymongo_test.test.insert_one({"dummy": u("object")})
        client.pymongo_test_bernie.test.insert_one({"dummy": u("object")})

        dbs = client.database_names()
        self.assertTrue("pymongo_test" in dbs)
        self.assertTrue("pymongo_test_bernie" in dbs)
Example #36
0
    def test_new_user_cmds(self):
        # "self.client" is logged in as root.
        auth_db = self.client.pymongo_test
        auth_db.add_user("amalia", "password", roles=["userAdmin"])
        self.addCleanup(auth_db.remove_user, "amalia")

        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"})

        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"})
    def test_auto_auth_login(self):
        client = rs_or_single_client_noauth()
        self.assertRaises(OperationFailure, client.auth_test.test.find_one)

        # Admin auth
        client.admin.authenticate(db_user, db_pwd)

        nthreads = 10
        threads = []
        for _ in range(nthreads):
            t = AutoAuthenticateThreads(client.auth_test.test, 10)
            t.start()
            threads.append(t)

        joinall(threads)

        for t in threads:
            self.assertTrue(t.success)
    def test_new_user_cmds(self):
        # "self.client" is logged in as root.
        auth_db = self.client.pymongo_test
        auth_db.add_user("amalia", "password", roles=["userAdmin"])
        self.addCleanup(auth_db.remove_user, "amalia")

        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"})

        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"})
Example #39
0
    def test_auto_auth_login(self):
        client = rs_or_single_client_noauth()
        self.assertRaises(OperationFailure, client.auth_test.test.find_one)

        # Admin auth
        client.admin.authenticate(db_user, db_pwd)

        nthreads = 10
        threads = []
        for _ in range(nthreads):
            t = AutoAuthenticateThreads(client.auth_test.test, 10)
            t.start()
            threads.append(t)

        joinall(threads)

        for t in threads:
            self.assertTrue(t.success)
    def test_make_user_readonly(self):
        # "self.client" is logged in as root.
        auth_db = self.client.pymongo_test
        db = rs_or_single_client_noauth().pymongo_test

        # Make a read-write user.
        auth_db.add_user('jesse', 'pw')
        self.addCleanup(remove_all_users, auth_db)

        # Check that we're read-write by default.
        db.authenticate('jesse', 'pw')
        db.collection.insert_one({})
        db.logout()

        # Make the user read-only.
        auth_db.add_user('jesse', 'pw', read_only=True)

        db.authenticate('jesse', 'pw')
        self.assertRaises(OperationFailure, db.collection.insert_one, {})
Example #41
0
    def test_make_user_readonly(self):
        # "self.client" is logged in as root.
        auth_db = self.client.pymongo_test
        db = rs_or_single_client_noauth().pymongo_test

        # Make a read-write user.
        auth_db.add_user('jesse', 'pw')
        self.addCleanup(remove_all_users, auth_db)

        # Check that we're read-write by default.
        db.authenticate('jesse', 'pw')
        db.collection.insert_one({})
        db.logout()

        # Make the user read-only.
        auth_db.add_user('jesse', 'pw', read_only=True)

        db.authenticate('jesse', 'pw')
        self.assertRaises(OperationFailure, db.collection.insert_one, {})
    def test_auto_auth_login(self):
        # Create the database upfront to workaround SERVER-39167.
        self.client.auth_test.test.insert_one({})
        self.addCleanup(self.client.drop_database, "auth_test")
        client = rs_or_single_client_noauth()
        self.assertRaises(OperationFailure, client.auth_test.test.find_one)

        # Admin auth
        client.admin.authenticate(db_user, db_pwd)

        nthreads = 10
        threads = []
        for _ in range(nthreads):
            t = AutoAuthenticateThreads(client.auth_test.test, 10)
            t.start()
            threads.append(t)

        joinall(threads)

        for t in threads:
            self.assertTrue(t.success)
Example #43
0
    def test_auto_auth_login(self):
        # Create the database upfront to workaround SERVER-39167.
        self.client.auth_test.test.insert_one({})
        self.addCleanup(self.client.drop_database, "auth_test")
        client = rs_or_single_client_noauth()
        self.assertRaises(OperationFailure, client.auth_test.test.find_one)

        # Admin auth
        client.admin.authenticate(db_user, db_pwd)

        nthreads = 10
        threads = []
        for _ in range(nthreads):
            t = AutoAuthenticateThreads(client.auth_test.test, 10)
            t.start()
            threads.append(t)

        joinall(threads)

        for t in threads:
            self.assertTrue(t.success)
    def test_new_user_cmds(self):
        extra = {}
        if client_context.version.at_least(3, 7, 2):
            extra['mechanisms'] = ['SCRAM-SHA-1']

        # "self.client" is logged in as root.
        auth_db = self.client.pymongo_test
        auth_db.add_user("amalia", "password", roles=["userAdmin"], **extra)
        self.addCleanup(client_context.drop_user, "pymongo_test", "amalia")

        db = rs_or_single_client_noauth(username="******",
                                        password="******",
                                        authSource="pymongo_test").pymongo_test

        # This tests the ability to update user attributes.
        db.add_user("amalia", "new_password",
                    customData={"secret": "koalas"}, **extra)

        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"})
Example #45
0
    def test_authenticate_multiple(self):
        # "self.client" is logged in as root.
        self.client.drop_database("pymongo_test")
        self.client.drop_database("pymongo_test1")
        admin_db_auth = self.client.admin
        users_db_auth = self.client.pymongo_test

        admin_db_auth.add_user('ro-admin',
                               'pass',
                               roles=["userAdmin", "readAnyDatabase"])

        self.addCleanup(client_context.drop_user, 'admin', 'ro-admin')
        users_db_auth.add_user('user',
                               'pass',
                               roles=["userAdmin", "readWrite"])
        self.addCleanup(remove_all_users, users_db_auth)

        # Non-root client.
        listener = EventListener()
        client = rs_or_single_client_noauth(event_listeners=[listener])
        admin_db = client.admin
        users_db = client.pymongo_test
        other_db = client.pymongo_test1

        self.assertRaises(OperationFailure, users_db.test.find_one)
        self.assertEqual(listener.started_command_names(), ['find'])
        listener.reset()

        # Regular user should be able to query its own db, but
        # no other.
        users_db.authenticate('user', 'pass')
        if client_context.version.at_least(3, 0):
            self.assertEqual(listener.started_command_names()[0], 'saslStart')
        else:
            self.assertEqual(listener.started_command_names()[0], 'getnonce')

        self.assertEqual(0, users_db.test.count_documents({}))
        self.assertRaises(OperationFailure, other_db.test.find_one)

        listener.reset()
        # Admin read-only user should be able to query any db,
        # but not write.
        admin_db.authenticate('ro-admin', 'pass')
        if client_context.version.at_least(3, 0):
            self.assertEqual(listener.started_command_names()[0], 'saslStart')
        else:
            self.assertEqual(listener.started_command_names()[0], 'getnonce')
        self.assertEqual(None, other_db.test.find_one())
        self.assertRaises(OperationFailure, other_db.test.insert_one, {})

        # Close all sockets.
        client.close()

        listener.reset()
        # We should still be able to write to the regular user's db.
        self.assertTrue(users_db.test.delete_many({}))
        names = listener.started_command_names()
        if client_context.version.at_least(4, 4, -1):
            # No speculation with multiple users (but we do skipEmptyExchange).
            self.assertEqual(names, [
                'saslStart', 'saslContinue', 'saslStart', 'saslContinue',
                'delete'
            ])
        elif client_context.version.at_least(3, 0):
            self.assertEqual(names, [
                'saslStart', 'saslContinue', 'saslContinue', 'saslStart',
                'saslContinue', 'saslContinue', 'delete'
            ])
        else:
            self.assertEqual(names, [
                'getnonce', 'authenticate', 'getnonce', 'authenticate',
                'delete'
            ])

        # And read from other dbs...
        self.assertEqual(0, other_db.test.count_documents({}))

        # But still not write to other dbs.
        self.assertRaises(OperationFailure, other_db.test.insert_one, {})
Example #46
0
    def test_authenticate_add_remove_user(self):
        # "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, auth_db.add_user, "user", '')
        self.assertRaises(TypeError, auth_db.add_user, "user", 'password', 15)
        self.assertRaises(TypeError, auth_db.add_user, "user", 'password',
                          'True')
        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, auth_db.add_user, "user",
                                  "password")
                self.assertRaises(DeprecationWarning, auth_db.add_user, "user",
                                  "password", True)

            with ignore_deprecations():
                self.assertRaises(ConfigurationError,
                                  auth_db.add_user,
                                  "user",
                                  "password",
                                  digestPassword=True)

        # Add / authenticate / remove
        auth_db.add_user("mike", "password", roles=["dbOwner"])
        self.addCleanup(remove_all_users, auth_db)
        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")
        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")
        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")
        self.assertTrue(db.authenticate("Gustave", u"password"))

        if not client_context.version.at_least(2, 5, 3, -1):
            # Add a readOnly user
            with ignore_deprecations():
                auth_db.add_user("Ross", "password", read_only=True)

            db.logout()
            db.authenticate("Ross", u"password")
            self.assertTrue(
                auth_db.system.users.find({
                    "readOnly": True
                }).count())
 def setUp(self):
     client_context.create_user('admin', 'admin', 'pass')
     client_context.create_user(
         'pymongo_test', 'user', 'pass', ['userAdmin', 'readWrite'])
     self.client = rs_or_single_client_noauth(
         username='******', password='******')
    def test_authenticate_add_remove_user(self):
        # "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, auth_db.add_user, "user", '')
        self.assertRaises(TypeError, auth_db.add_user, "user", 'password', 15)
        self.assertRaises(TypeError, auth_db.add_user,
                          "user", 'password', 'True')
        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, auth_db.add_user,
                                  "user", "password")
                self.assertRaises(DeprecationWarning, auth_db.add_user,
                                  "user", "password", True)

            with ignore_deprecations():
                self.assertRaises(ConfigurationError, auth_db.add_user,
                                  "user", "password", digestPassword=True)

        # Add / authenticate / remove
        auth_db.add_user("mike", "password", roles=["dbOwner"])
        self.addCleanup(remove_all_users, auth_db)
        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")
        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"))
        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"))
        self.assertTrue(db.authenticate("Gustave", u("password")))

        if not client_context.version.at_least(2, 5, 3, -1):
            # Add a readOnly user
            with ignore_deprecations():
                auth_db.add_user("Ross", "password", read_only=True)

            db.logout()
            db.authenticate("Ross", u("password"))
            self.assertTrue(
                auth_db.system.users.find({"readOnly": True}).count())
Example #49
0
 def setUp(self):
     client_context.create_user('admin', 'admin', 'pass')
     client_context.create_user('pymongo_test', 'user', 'pass',
                                ['userAdmin', 'readWrite'])
     self.client = rs_or_single_client_noauth(username='******',
                                              password='******')
Example #50
0
    def test_scram(self):
        host, port = client_context.host, client_context.port

        client_context.create_user('testscram',
                                   'sha1',
                                   'pwd',
                                   roles=['dbOwner'],
                                   mechanisms=['SCRAM-SHA-1'])

        client_context.create_user('testscram',
                                   'sha256',
                                   'pwd',
                                   roles=['dbOwner'],
                                   mechanisms=['SCRAM-SHA-256'])

        client_context.create_user('testscram',
                                   'both',
                                   'pwd',
                                   roles=['dbOwner'],
                                   mechanisms=['SCRAM-SHA-1', 'SCRAM-SHA-256'])

        client = rs_or_single_client_noauth(event_listeners=[self.listener])
        self.assertTrue(client.testscram.authenticate('sha1', 'pwd'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertTrue(
            client.testscram.authenticate('sha1',
                                          'pwd',
                                          mechanism='SCRAM-SHA-1'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertRaises(OperationFailure,
                          client.testscram.authenticate,
                          'sha1',
                          'pwd',
                          mechanism='SCRAM-SHA-256')

        self.assertTrue(client.testscram.authenticate('sha256', 'pwd'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertTrue(
            client.testscram.authenticate('sha256',
                                          'pwd',
                                          mechanism='SCRAM-SHA-256'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertRaises(OperationFailure,
                          client.testscram.authenticate,
                          'sha256',
                          'pwd',
                          mechanism='SCRAM-SHA-1')

        self.listener.results.clear()
        self.assertTrue(client.testscram.authenticate('both', 'pwd'))
        started = self.listener.results['started'][0]
        self.assertEqual(started.command.get('mechanism'), 'SCRAM-SHA-256')
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertTrue(
            client.testscram.authenticate('both',
                                          'pwd',
                                          mechanism='SCRAM-SHA-256'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertTrue(
            client.testscram.authenticate('both',
                                          'pwd',
                                          mechanism='SCRAM-SHA-1'))
        client.testscram.command('dbstats')
        client.testscram.logout()

        self.assertRaises(OperationFailure, client.testscram.authenticate,
                          'not-a-user', 'pwd')

        if HAVE_STRINGPREP:
            # Test the use of SASLprep on passwords. For example,
            # saslprep(u'\u2136') becomes u'IV' and saslprep(u'I\u00ADX')
            # becomes u'IX'. SASLprep is only supported when the standard
            # library provides stringprep.
            client_context.create_user('testscram',
                                       u'\u2168',
                                       u'\u2163',
                                       roles=['dbOwner'],
                                       mechanisms=['SCRAM-SHA-256'])

            client_context.create_user('testscram',
                                       u'IX',
                                       u'IX',
                                       roles=['dbOwner'],
                                       mechanisms=['SCRAM-SHA-256'])

            self.assertTrue(client.testscram.authenticate(
                u'\u2168', u'\u2163'))
            client.testscram.command('dbstats')
            client.testscram.logout()
            self.assertTrue(
                client.testscram.authenticate(u'\u2168',
                                              u'\u2163',
                                              mechanism='SCRAM-SHA-256'))
            client.testscram.command('dbstats')
            client.testscram.logout()
            self.assertTrue(client.testscram.authenticate(u'\u2168', u'IV'))
            client.testscram.command('dbstats')
            client.testscram.logout()

            self.assertTrue(client.testscram.authenticate(u'IX', u'I\u00ADX'))
            client.testscram.command('dbstats')
            client.testscram.logout()
            self.assertTrue(
                client.testscram.authenticate(u'IX',
                                              u'I\u00ADX',
                                              mechanism='SCRAM-SHA-256'))
            client.testscram.command('dbstats')
            client.testscram.logout()
            self.assertTrue(client.testscram.authenticate(u'IX', u'IX'))
            client.testscram.command('dbstats')
            client.testscram.logout()

            client = rs_or_single_client_noauth(
                u'mongodb://\u2168:\u2163@%s:%d/testscram' % (host, port))
            client.testscram.command('dbstats')
            client = rs_or_single_client_noauth(
                u'mongodb://\u2168:IV@%s:%d/testscram' % (host, port))
            client.testscram.command('dbstats')

            client = rs_or_single_client_noauth(
                u'mongodb://*****:*****@%s:%d/testscram' % (host, port))
            client.testscram.command('dbstats')
            client = rs_or_single_client_noauth(
                u'mongodb://*****:*****@%s:%d/testscram' % (host, port))
            client.testscram.command('dbstats')

        self.listener.results.clear()
        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/testscram' % (host, port),
            event_listeners=[self.listener])
        client.testscram.command('dbstats')
        if client_context.version.at_least(4, 4, -1):
            # Speculative authentication in 4.4+ sends saslStart with the
            # handshake.
            self.assertEqual(self.listener.results['started'], [])
        else:
            started = self.listener.results['started'][0]
            self.assertEqual(started.command.get('mechanism'), 'SCRAM-SHA-256')

        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/testscram?authMechanism=SCRAM-SHA-1' %
            (host, port))
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/testscram?authMechanism=SCRAM-SHA-256' %
            (host, port))
        client.testscram.command('dbstats')

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/testscram'
                   '?replicaSet=%s' %
                   (host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            client.testscram.command('dbstats')
            db = client.get_database('testscram',
                                     read_preference=ReadPreference.SECONDARY)
            db.command('dbstats')
    def test_scram(self):
        host, port = client_context.host, client_context.port

        client_context.create_user(
            'testscram',
            'sha1',
            'pwd',
            roles=['dbOwner'],
            mechanisms=['SCRAM-SHA-1'])

        client_context.create_user(
            'testscram',
            'sha256',
            'pwd',
            roles=['dbOwner'],
            mechanisms=['SCRAM-SHA-256'])

        client_context.create_user(
            'testscram',
            'both',
            'pwd',
            roles=['dbOwner'],
            mechanisms=['SCRAM-SHA-1', 'SCRAM-SHA-256'])

        client = rs_or_single_client_noauth(
            event_listeners=[self.listener])
        self.assertTrue(
            client.testscram.authenticate('sha1', 'pwd'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertTrue(
            client.testscram.authenticate(
                'sha1', 'pwd', mechanism='SCRAM-SHA-1'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertRaises(
            OperationFailure,
            client.testscram.authenticate,
            'sha1', 'pwd', mechanism='SCRAM-SHA-256')

        self.assertTrue(
            client.testscram.authenticate('sha256', 'pwd'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertTrue(
            client.testscram.authenticate(
                'sha256', 'pwd', mechanism='SCRAM-SHA-256'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertRaises(
            OperationFailure,
            client.testscram.authenticate,
            'sha256', 'pwd', mechanism='SCRAM-SHA-1')

        self.listener.results.clear()
        self.assertTrue(
            client.testscram.authenticate('both', 'pwd'))
        started = self.listener.results['started'][0]
        self.assertEqual(started.command.get('mechanism'), 'SCRAM-SHA-256')
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertTrue(
            client.testscram.authenticate(
                'both', 'pwd', mechanism='SCRAM-SHA-256'))
        client.testscram.command('dbstats')
        client.testscram.logout()
        self.assertTrue(
            client.testscram.authenticate(
                'both', 'pwd', mechanism='SCRAM-SHA-1'))
        client.testscram.command('dbstats')
        client.testscram.logout()

        self.assertRaises(
            OperationFailure,
            client.testscram.authenticate,
            'not-a-user', 'pwd')

        if HAVE_STRINGPREP:
            # Test the use of SASLprep on passwords. For example,
            # saslprep(u'\u2136') becomes u'IV' and saslprep(u'I\u00ADX')
            # becomes u'IX'. SASLprep is only supported when the standard
            # library provides stringprep.
            client_context.create_user(
                'testscram',
                u'\u2168',
                u'\u2163',
                roles=['dbOwner'],
                mechanisms=['SCRAM-SHA-256'])

            client_context.create_user(
                'testscram',
                u'IX',
                u'IX',
                roles=['dbOwner'],
                mechanisms=['SCRAM-SHA-256'])

            self.assertTrue(
                client.testscram.authenticate(u'\u2168', u'\u2163'))
            client.testscram.command('dbstats')
            client.testscram.logout()
            self.assertTrue(
                client.testscram.authenticate(
                    u'\u2168', u'\u2163', mechanism='SCRAM-SHA-256'))
            client.testscram.command('dbstats')
            client.testscram.logout()
            self.assertTrue(
                client.testscram.authenticate(u'\u2168', u'IV'))
            client.testscram.command('dbstats')
            client.testscram.logout()

            self.assertTrue(
                client.testscram.authenticate(u'IX', u'I\u00ADX'))
            client.testscram.command('dbstats')
            client.testscram.logout()
            self.assertTrue(
                client.testscram.authenticate(
                    u'IX', u'I\u00ADX', mechanism='SCRAM-SHA-256'))
            client.testscram.command('dbstats')
            client.testscram.logout()
            self.assertTrue(
                client.testscram.authenticate(u'IX', u'IX'))
            client.testscram.command('dbstats')
            client.testscram.logout()

            client = rs_or_single_client_noauth(
                u'mongodb://\u2168:\u2163@%s:%d/testscram' % (host, port))
            client.testscram.command('dbstats')
            client = rs_or_single_client_noauth(
                u'mongodb://\u2168:IV@%s:%d/testscram' % (host, port))
            client.testscram.command('dbstats')

            client = rs_or_single_client_noauth(
                u'mongodb://*****:*****@%s:%d/testscram' % (host, port))
            client.testscram.command('dbstats')
            client = rs_or_single_client_noauth(
                u'mongodb://*****:*****@%s:%d/testscram' % (host, port))
            client.testscram.command('dbstats')

        self.listener.results.clear()
        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/testscram' % (host, port),
            event_listeners=[self.listener])
        client.testscram.command('dbstats')
        started = self.listener.results['started'][0]
        self.assertEqual(started.command.get('mechanism'), 'SCRAM-SHA-256')

        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/testscram?authMechanism=SCRAM-SHA-1'
            % (host, port))
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(
            'mongodb://*****:*****@%s:%d/testscram?authMechanism=SCRAM-SHA-256'
            % (host, port))
        client.testscram.command('dbstats')

        if client_context.is_rs:
            uri = ('mongodb://*****:*****@%s:%d/testscram'
                   '?replicaSet=%s' % (host, port,
                                       client_context.replica_set_name))
            client = single_client_noauth(uri)
            client.testscram.command('dbstats')
            db = client.get_database(
                'testscram', read_preference=ReadPreference.SECONDARY)
            db.command('dbstats')
    def test_scram(self):
        # Step 1: create users
        client_context.create_user('testscram',
                                   'sha1',
                                   'pwd',
                                   roles=['dbOwner'],
                                   mechanisms=['SCRAM-SHA-1'])
        client_context.create_user('testscram',
                                   'sha256',
                                   'pwd',
                                   roles=['dbOwner'],
                                   mechanisms=['SCRAM-SHA-256'])
        client_context.create_user('testscram',
                                   'both',
                                   'pwd',
                                   roles=['dbOwner'],
                                   mechanisms=['SCRAM-SHA-1', 'SCRAM-SHA-256'])

        # Step 2: verify auth success cases
        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram',
                                            authMechanism='SCRAM-SHA-1')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram')
        client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram',
                                            authMechanism='SCRAM-SHA-256')
        client.testscram.command('dbstats')

        # Step 2: SCRAM-SHA-1 and SCRAM-SHA-256
        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram',
                                            authMechanism='SCRAM-SHA-1')
        client.testscram.command('dbstats')
        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram',
                                            authMechanism='SCRAM-SHA-256')
        client.testscram.command('dbstats')

        self.listener.results.clear()
        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram',
                                            event_listeners=[self.listener])
        client.testscram.command('dbstats')
        if client_context.version.at_least(4, 4, -1):
            # Speculative authentication in 4.4+ sends saslStart with the
            # handshake.
            self.assertEqual(self.listener.results['started'], [])
        else:
            started = self.listener.results['started'][0]
            self.assertEqual(started.command.get('mechanism'), 'SCRAM-SHA-256')

        # Step 3: verify auth failure conditions
        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram',
                                            authMechanism='SCRAM-SHA-256')
        with self.assertRaises(OperationFailure):
            client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram',
                                            authMechanism='SCRAM-SHA-1')
        with self.assertRaises(OperationFailure):
            client.testscram.command('dbstats')

        client = rs_or_single_client_noauth(username='******',
                                            password='******',
                                            authSource='testscram')
        with self.assertRaises(OperationFailure):
            client.testscram.command('dbstats')

        if client_context.is_rs:
            host, port = client_context.host, client_context.port
            uri = ('mongodb://*****:*****@%s:%d/testscram'
                   '?replicaSet=%s' %
                   (host, port, client_context.replica_set_name))
            client = single_client_noauth(uri)
            client.testscram.command('dbstats')
            db = client.get_database('testscram',
                                     read_preference=ReadPreference.SECONDARY)
            db.command('dbstats')