예제 #1
0
def remove_all_users(db):
    if Version.from_client(db.client).at_least(2, 5, 3, -1):
        db.command("dropAllUsersFromDatabase", 1,
                   writeConcern={"w": client_context.w})
    else:
        db = db.client.get_database(
            db.name, write_concern=WriteConcern(w=client_context.w))
        db.system.users.delete_many({})
예제 #2
0
def remove_all_users(db):
    if Version.from_client(db.client).at_least(2, 5, 3, -1):
        db.command("dropAllUsersFromDatabase", 1,
                   writeConcern={"w": client_context.w})
    else:
        db = db.client.get_database(
            db.name, write_concern=WriteConcern(w=client_context.w))
        db.system.users.delete_many({})
예제 #3
0
 def setUp(self):
     super(TestCommandAndReadPreference, self).setUp()
     self.c = ReadPrefTester(
         '%s:%s' % (host, port),
         replicaSet=self.name,
         # Ignore round trip times, to test ReadPreference modes only.
         localThresholdMS=1000*1000)
     if client_context.auth_enabled:
         self.c.admin.authenticate(db_user, db_pwd)
     self.client_version = Version.from_client(self.c)
     self.addCleanup(self.c.drop_database, 'pymongo_test')
 def setUp(self):
     super(TestCommandAndReadPreference, self).setUp()
     self.c = ReadPrefTester(
         '%s:%s' % (host, port),
         replicaSet=self.name,
         # Ignore round trip times, to test ReadPreference modes only.
         localThresholdMS=1000*1000)
     if client_context.auth_enabled:
         self.c.admin.authenticate(db_user, db_pwd)
     self.client_version = Version.from_client(self.c)
     self.addCleanup(self.c.drop_database, 'pymongo_test')
 def setUpClass(cls):
     super(TestCommandAndReadPreference, cls).setUpClass()
     cls.c = ReadPrefTester(
         client_context.pair,
         # Ignore round trip times, to test ReadPreference modes only.
         localThresholdMS=1000*1000)
     cls.client_version = Version.from_client(cls.c)
     # mapReduce fails if the collection does not exist.
     coll = cls.c.pymongo_test.get_collection(
         'test', write_concern=WriteConcern(w=client_context.w))
     coll.insert_one({})
 def setUpClass(cls):
     super(TestCommandAndReadPreference, cls).setUpClass()
     cls.c = ReadPrefTester(
         client_context.pair,
         replicaSet=cls.name,
         # Ignore round trip times, to test ReadPreference modes only.
         localThresholdMS=1000*1000)
     if client_context.auth_enabled:
         cls.c.admin.authenticate(db_user, db_pwd)
     cls.client_version = Version.from_client(cls.c)
     # mapReduce and group fail with no collection
     coll = cls.c.pymongo_test.get_collection(
         'test', write_concern=WriteConcern(w=cls.w))
     coll.insert_one({})
예제 #7
0
 def setUpClass(cls):
     super(TestCommandAndReadPreference, cls).setUpClass()
     cls.c = ReadPrefTester(
         client_context.pair,
         replicaSet=cls.name,
         # Ignore round trip times, to test ReadPreference modes only.
         localThresholdMS=1000 * 1000)
     if client_context.auth_enabled:
         cls.c.admin.authenticate(db_user, db_pwd)
     cls.client_version = Version.from_client(cls.c)
     # mapReduce and group fail with no collection
     coll = cls.c.pymongo_test.get_collection(
         'test', write_concern=WriteConcern(w=cls.w))
     coll.insert_one({})
예제 #8
0
    def test_mongodb_x509_auth(self):
        # Expects the server to be running with the server.pem, ca.pem
        # and crl.pem provided in mongodb and the server tests as well as
        # --auth
        #
        #   --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem
        #   --sslCAFile=/path/to/pymongo/test/certificates/ca.pem
        #   --sslCRLFile=/path/to/pymongo/test/certificates/crl.pem
        #   --auth
        if not CERT_SSL:
            raise SkipTest("No mongod available over SSL with certs")

        if not Version.from_client(ssl_client).at_least(2, 5, 3, -1):
            raise SkipTest("MONGODB-X509 tests require MongoDB 2.5.3 or newer")
        if not server_started_with_auth(ssl_client):
            raise SkipTest('Authentication is not enabled on server')

        self.addCleanup(ssl_client['$external'].logout)
        self.addCleanup(remove_all_users, ssl_client['$external'])

        # Give admin all necessary privileges.
        ssl_client['$external'].add_user(MONGODB_X509_USERNAME, roles=[
            {'role': 'readWriteAnyDatabase', 'db': 'admin'},
            {'role': 'userAdminAnyDatabase', 'db': 'admin'}])

        coll = ssl_client.pymongo_test.test
        self.assertRaises(OperationFailure, coll.count)
        self.assertTrue(ssl_client.admin.authenticate(
            MONGODB_X509_USERNAME, mechanism='MONGODB-X509'))
        coll.drop()
        uri = ('mongodb://%s@%s:%d/?authMechanism='
               'MONGODB-X509' % (
                   quote_plus(MONGODB_X509_USERNAME), host, port))
        # SSL options aren't supported in the URI...
        self.assertTrue(MongoClient(uri,
                                    ssl=True, ssl_certfile=CLIENT_PEM))

        # Should require a username
        uri = ('mongodb://%s:%d/?authMechanism=MONGODB-X509' % (host,
                                                                port))
        client_bad = MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM)
        self.assertRaises(OperationFailure,
                          client_bad.pymongo_test.test.delete_one, {})

        # Auth should fail if username and certificate do not match
        uri = ('mongodb://%s@%s:%d/?authMechanism='
               'MONGODB-X509' % (
                   quote_plus("not the username"), host, port))

        bad_client = MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM)
        with self.assertRaises(OperationFailure):
            bad_client.pymongo_test.test.find_one()

        self.assertRaises(OperationFailure, ssl_client.admin.authenticate,
                          "not the username",
                          mechanism="MONGODB-X509")

        # Invalid certificate (using CA certificate as client certificate)
        uri = ('mongodb://%s@%s:%d/?authMechanism='
               'MONGODB-X509' % (
                   quote_plus(MONGODB_X509_USERNAME), host, port))
        # These tests will raise SSLError (>= 3.2) or ConnectionFailure
        # (2.x) depending on where OpenSSL first sees the PEM file.
        try:
            connected(MongoClient(uri, ssl=True, ssl_certfile=CA_PEM,
                                  serverSelectionTimeoutMS=100))
        except (ssl.SSLError, ConnectionFailure):
            pass
        else:
            self.fail("Invalid certificate accepted.")

        try:
            connected(MongoClient(pair, ssl=True, ssl_certfile=CA_PEM,
                                  serverSelectionTimeoutMS=100))
        except (ssl.SSLError, ConnectionFailure):
            pass
        else:
            self.fail("Invalid certificate accepted.")
예제 #9
0
 def setup_version(self):
     """Set self.version to the server's version."""
     self.version = Version.from_client(self.sync_cx)
예제 #10
0
    def __init__(self):
        """Create a client and grab essential information from the server."""
        self.connected = False
        self.ismaster = {}
        self.w = None
        self.nodes = set()
        self.replica_set_name = None
        self.cmd_line = None
        self.version = Version(-1)  # Needs to be comparable with Version
        self.auth_enabled = False
        self.test_commands_enabled = False
        self.is_mongos = False
        self.is_rs = False
        self.has_ipv6 = False
        self.ssl = False
        self.ssl_cert_none = False
        self.ssl_certfile = False
        self.server_is_resolvable = is_server_resolvable()
        self.ssl_client_options = {}
        self.sessions_enabled = False
        self.client = _connect(host, port)

        if HAVE_SSL and not self.client:
            # Is MongoDB configured for SSL?
            self.client = _connect(host, port, **_SSL_OPTIONS)
            if self.client:
                self.ssl = True
                self.ssl_client_options = _SSL_OPTIONS
                self.ssl_certfile = True
                if _SSL_OPTIONS.get('ssl_cert_reqs') == ssl.CERT_NONE:
                    self.ssl_cert_none = True

        if self.client:
            self.connected = True

            try:
                self.cmd_line = self.client.admin.command('getCmdLineOpts')
            except pymongo.errors.OperationFailure as e:
                msg = e.details.get('errmsg', '')
                if e.code == 13 or 'unauthorized' in msg or 'login' in msg:
                    # Unauthorized.
                    self.auth_enabled = True
                else:
                    raise
            else:
                self.auth_enabled = self._server_started_with_auth()

            if self.auth_enabled:
                # See if db_user already exists.
                if not self._check_user_provided():
                    self.client.admin.add_user(db_user, db_pwd, roles=['root'])

                self.client = _connect(host,
                                       port,
                                       username=db_user,
                                       password=db_pwd,
                                       replicaSet=self.replica_set_name,
                                       **self.ssl_client_options)

                # May not have this if OperationFailure was raised earlier.
                self.cmd_line = self.client.admin.command('getCmdLineOpts')

            self.ismaster = ismaster = self.client.admin.command('isMaster')
            self.sessions_enabled = 'logicalSessionTimeoutMinutes' in ismaster

            if 'setName' in ismaster:
                self.replica_set_name = ismaster['setName']
                self.is_rs = True
                if self.auth_enabled:
                    # It doesn't matter which member we use as the seed here.
                    self.client = pymongo.MongoClient(
                        host,
                        port,
                        username=db_user,
                        password=db_pwd,
                        replicaSet=self.replica_set_name,
                        **self.ssl_client_options)
                else:
                    self.client = pymongo.MongoClient(
                        host,
                        port,
                        replicaSet=self.replica_set_name,
                        **self.ssl_client_options)

                # Get the authoritative ismaster result from the primary.
                self.ismaster = self.client.admin.command('ismaster')
                nodes = [
                    partition_node(node.lower())
                    for node in self.ismaster.get('hosts', [])
                ]
                nodes.extend([
                    partition_node(node.lower())
                    for node in self.ismaster.get('passives', [])
                ])
                nodes.extend([
                    partition_node(node.lower())
                    for node in self.ismaster.get('arbiters', [])
                ])
                self.nodes = set(nodes)
            else:
                self.ismaster = ismaster
                self.nodes = set([(host, port)])
            self.w = len(self.ismaster.get("hosts", [])) or 1
            self.version = Version.from_client(self.client)

            if 'enableTestCommands=1' in self.cmd_line['argv']:
                self.test_commands_enabled = True
            elif 'parsed' in self.cmd_line:
                params = self.cmd_line['parsed'].get('setParameter', [])
                if 'enableTestCommands=1' in params:
                    self.test_commands_enabled = True
                else:
                    params = self.cmd_line['parsed'].get('setParameter', {})
                    if params.get('enableTestCommands') == '1':
                        self.test_commands_enabled = True

            self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid')
            self.has_ipv6 = self._server_started_with_ipv6()
예제 #11
0
    def __init__(self):
        """Create a client and grab essential information from the server."""
        # Seed host. This may be updated further down.
        self.host, self.port = host, port
        self.connected = False
        self.ismaster = {}
        self.w = None
        self.nodes = set()
        self.replica_set_name = None
        self.cmd_line = None
        self.version = Version(-1)  # Needs to be comparable with Version
        self.auth_enabled = False
        self.test_commands_enabled = False
        self.is_mongos = False
        self.is_rs = False
        self.has_ipv6 = False
        self.ssl = False
        self.ssl_cert_none = False
        self.ssl_certfile = False
        self.server_is_resolvable = is_server_resolvable()
        self.ssl_client_options = {}
        self.client = _connect(self.host, self.port)

        if HAVE_SSL and not self.client:
            # Is MongoDB configured for SSL?
            self.client = _connect(self.host, self.port, **_SSL_OPTIONS)
            if self.client:
                self.ssl = True
                self.ssl_client_options = _SSL_OPTIONS
                self.ssl_certfile = True
                if _SSL_OPTIONS.get('ssl_cert_reqs') == ssl.CERT_NONE:
                    self.ssl_cert_none = True

        if self.client:
            self.connected = True
            self.ismaster = self.client.admin.command('ismaster')
            self.w = len(self.ismaster.get("hosts", [])) or 1
            self.nodes = set([(self.host, self.port)])
            self.replica_set_name = self.ismaster.get('setName', '')
            self.version = Version.from_client(self.client)
            if self.replica_set_name:
                self.is_rs = True
                self.client = pymongo.MongoClient(
                    self.ismaster['primary'],
                    replicaSet=self.replica_set_name,
                    **self.ssl_client_options)
                # Force connection
                self.client.admin.command('ismaster')
                self.host, self.port = self.client.primary

                nodes = [partition_node(node.lower())
                         for node in self.ismaster.get('hosts', [])]
                nodes.extend([partition_node(node.lower())
                              for node in self.ismaster.get('passives', [])])
                nodes.extend([partition_node(node.lower())
                              for node in self.ismaster.get('arbiters', [])])
                self.nodes = set(nodes)

            try:
                self.cmd_line = self.client.admin.command('getCmdLineOpts')
            except pymongo.errors.OperationFailure as e:
                msg = e.details.get('errmsg', '')
                if e.code == 13 or 'unauthorized' in msg or 'login' in msg:
                    # Unauthorized.
                    self.auth_enabled = True
                else:
                    raise
            else:
                self.auth_enabled = self._server_started_with_auth()

            if self.auth_enabled:
                # See if db_user already exists.
                self.user_provided = self._check_user_provided()
                if not self.user_provided:
                    roles = {}
                    if self.version.at_least(2, 5, 3, -1):
                        roles = {'roles': ['root']}
                    self.client.admin.add_user(db_user, db_pwd, **roles)
                    self.client.admin.authenticate(db_user, db_pwd)

                # May not have this if OperationFailure was raised earlier.
                self.cmd_line = self.client.admin.command('getCmdLineOpts')

            if 'enableTestCommands=1' in self.cmd_line['argv']:
                self.test_commands_enabled = True
            elif 'parsed' in self.cmd_line:
                params = self.cmd_line['parsed'].get('setParameter', [])
                if 'enableTestCommands=1' in params:
                    self.test_commands_enabled = True
                else:
                    params = self.cmd_line['parsed'].get('setParameter', {})
                    if params.get('enableTestCommands') == '1':
                        self.test_commands_enabled = True

            self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid')
            self.has_ipv6 = self._server_started_with_ipv6()
    def __init__(self):
        """Create a client and grab essential information from the server."""
        self.connected = False
        self.ismaster = {}
        self.w = None
        self.nodes = set()
        self.replica_set_name = None
        self.rs_client = None
        self.cmd_line = None
        self.version = Version(-1)  # Needs to be comparable with Version
        self.auth_enabled = False
        self.test_commands_enabled = False
        self.is_mongos = False
        self.is_rs = False
        self.has_ipv6 = False

        try:
            client = pymongo.MongoClient(host,
                                         port,
                                         serverSelectionTimeoutMS=100)
            client.admin.command('ismaster')  # Can we connect?

            # If so, then reset client to defaults.
            self.client = pymongo.MongoClient(host, port)

        except pymongo.errors.ConnectionFailure:
            self.client = self.rs_or_standalone_client = None
        else:
            self.connected = True
            self.ismaster = self.client.admin.command('ismaster')
            self.w = len(self.ismaster.get("hosts", [])) or 1
            self.nodes = set([(host, port)])
            self.replica_set_name = self.ismaster.get('setName', '')
            self.rs_client = None
            self.version = Version.from_client(self.client)
            if self.replica_set_name:
                self.is_rs = True
                self.rs_client = pymongo.MongoClient(
                    pair, replicaSet=self.replica_set_name)

                nodes = [
                    partition_node(node.lower())
                    for node in self.ismaster.get('hosts', [])
                ]
                nodes.extend([
                    partition_node(node.lower())
                    for node in self.ismaster.get('passives', [])
                ])
                nodes.extend([
                    partition_node(node.lower())
                    for node in self.ismaster.get('arbiters', [])
                ])
                self.nodes = set(nodes)

            self.rs_or_standalone_client = self.rs_client or self.client

            try:
                self.cmd_line = self.client.admin.command('getCmdLineOpts')
            except pymongo.errors.OperationFailure as e:
                msg = e.details.get('errmsg', '')
                if e.code == 13 or 'unauthorized' in msg or 'login' in msg:
                    # Unauthorized.
                    self.auth_enabled = True
                else:
                    raise
            else:
                self.auth_enabled = self._server_started_with_auth()

            if self.auth_enabled:
                # See if db_user already exists.
                self.user_provided = self._check_user_provided()
                if not self.user_provided:
                    roles = {}
                    if self.version.at_least(2, 5, 3, -1):
                        roles = {'roles': ['root']}
                    self.client.admin.add_user(db_user, db_pwd, **roles)
                    self.client.admin.authenticate(db_user, db_pwd)

                if self.rs_client:
                    self.rs_client.admin.authenticate(db_user, db_pwd)

                # May not have this if OperationFailure was raised earlier.
                self.cmd_line = self.client.admin.command('getCmdLineOpts')

            if 'enableTestCommands=1' in self.cmd_line['argv']:
                self.test_commands_enabled = True
            elif 'parsed' in self.cmd_line:
                params = self.cmd_line['parsed'].get('setParameter', [])
                if 'enableTestCommands=1' in params:
                    self.test_commands_enabled = True

            self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid')
            self.has_ipv6 = self._server_started_with_ipv6()
예제 #13
0
    def __init__(self):
        """Create a client and grab essential information from the server."""
        self.connected = False
        self.ismaster = {}
        self.w = None
        self.nodes = set()
        self.replica_set_name = None
        self.rs_client = None
        self.cmd_line = None
        self.version = Version(-1)  # Needs to be comparable with Version
        self.auth_enabled = False
        self.test_commands_enabled = False
        self.is_mongos = False
        self.is_rs = False
        self.has_ipv6 = False

        try:
            client = pymongo.MongoClient(host, port,
                                         serverSelectionTimeoutMS=100)
            client.admin.command('ismaster')  # Can we connect?

            # If so, then reset client to defaults.
            self.client = pymongo.MongoClient(host, port)

        except pymongo.errors.ConnectionFailure:
            self.client = None
        else:
            self.connected = True
            self.ismaster = self.client.admin.command('ismaster')
            self.w = len(self.ismaster.get("hosts", [])) or 1
            self.nodes = set([(host, port)])
            self.replica_set_name = self.ismaster.get('setName', '')
            self.rs_client = None
            self.version = Version.from_client(self.client)
            if self.replica_set_name:
                self.is_rs = True
                self.rs_client = pymongo.MongoClient(
                    pair, replicaSet=self.replica_set_name)

                nodes = [partition_node(node)
                         for node in self.ismaster.get('hosts', [])]
                nodes.extend([partition_node(node)
                              for node in self.ismaster.get('passives', [])])
                nodes.extend([partition_node(node)
                              for node in self.ismaster.get('arbiters', [])])
                self.nodes = set(nodes)

            self.rs_or_standalone_client = self.rs_client or self.client

            try:
                self.cmd_line = self.client.admin.command('getCmdLineOpts')
            except pymongo.errors.OperationFailure as e:
                msg = e.details.get('errmsg', '')
                if e.code == 13 or 'unauthorized' in msg or 'login' in msg:
                    # Unauthorized.
                    self.auth_enabled = True
                else:
                    raise
            else:
                self.auth_enabled = self._server_started_with_auth()

            if self.auth_enabled:
                # See if db_user already exists.
                self.user_provided = self._check_user_provided()
                if not self.user_provided:
                    roles = {}
                    if self.version.at_least(2, 5, 3, -1):
                        roles = {'roles': ['root']}
                    self.client.admin.add_user(db_user, db_pwd, **roles)
                    self.client.admin.authenticate(db_user, db_pwd)

                if self.rs_client:
                    self.rs_client.admin.authenticate(db_user, db_pwd)

                # May not have this if OperationFailure was raised earlier.
                self.cmd_line = self.client.admin.command('getCmdLineOpts')

            if 'enableTestCommands=1' in self.cmd_line['argv']:
                self.test_commands_enabled = True
            elif 'parsed' in self.cmd_line:
                params = self.cmd_line['parsed'].get('setParameter', [])
                if 'enableTestCommands=1' in params:
                    self.test_commands_enabled = True

            self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid')
            self.has_ipv6 = self._server_started_with_ipv6()
예제 #14
0
    def _init_client(self):
        self.client = self._connect(host, port)

        if self.client is not None:
            # Return early when connected to dataLake as mongohoused does not
            # support the getCmdLineOpts command and is tested without TLS.
            build_info = self.client.admin.command('buildInfo')
            if 'dataLake' in build_info:
                self.is_data_lake = True
                self.auth_enabled = True
                self.client = self._connect(host,
                                            port,
                                            username=db_user,
                                            password=db_pwd)
                self.connected = True
                return

        if HAVE_SSL and not self.client:
            # Is MongoDB configured for SSL?
            self.client = self._connect(host, port, **TLS_OPTIONS)
            if self.client:
                self.tls = True
                self.default_client_options.update(TLS_OPTIONS)
                self.ssl_certfile = True

        if self.client:
            self.connected = True

            try:
                self.cmd_line = self.client.admin.command('getCmdLineOpts')
            except pymongo.errors.OperationFailure as e:
                msg = e.details.get('errmsg', '')
                if e.code == 13 or 'unauthorized' in msg or 'login' in msg:
                    # Unauthorized.
                    self.auth_enabled = True
                else:
                    raise
            else:
                self.auth_enabled = self._server_started_with_auth()

            if self.auth_enabled:
                # See if db_user already exists.
                if not self._check_user_provided():
                    _create_user(self.client.admin, db_user, db_pwd)

                self.client = self._connect(host,
                                            port,
                                            username=db_user,
                                            password=db_pwd,
                                            replicaSet=self.replica_set_name,
                                            **self.default_client_options)

                # May not have this if OperationFailure was raised earlier.
                self.cmd_line = self.client.admin.command('getCmdLineOpts')

            self.server_status = self.client.admin.command('serverStatus')
            if self.storage_engine == "mmapv1":
                # MMAPv1 does not support retryWrites=True.
                self.default_client_options['retryWrites'] = False

            ismaster = self.ismaster
            self.sessions_enabled = 'logicalSessionTimeoutMinutes' in ismaster

            if 'setName' in ismaster:
                self.replica_set_name = str(ismaster['setName'])
                self.is_rs = True
                if self.auth_enabled:
                    # It doesn't matter which member we use as the seed here.
                    self.client = pymongo.MongoClient(
                        host,
                        port,
                        username=db_user,
                        password=db_pwd,
                        replicaSet=self.replica_set_name,
                        **self.default_client_options)
                else:
                    self.client = pymongo.MongoClient(
                        host,
                        port,
                        replicaSet=self.replica_set_name,
                        **self.default_client_options)

                # Get the authoritative ismaster result from the primary.
                ismaster = self.ismaster
                nodes = [
                    partition_node(node.lower())
                    for node in ismaster.get('hosts', [])
                ]
                nodes.extend([
                    partition_node(node.lower())
                    for node in ismaster.get('passives', [])
                ])
                nodes.extend([
                    partition_node(node.lower())
                    for node in ismaster.get('arbiters', [])
                ])
                self.nodes = set(nodes)
            else:
                self.nodes = set([(host, port)])
            self.w = len(ismaster.get("hosts", [])) or 1
            self.version = Version.from_client(self.client)
            self.server_parameters = self.client.admin.command(
                'getParameter', '*')

            if 'enableTestCommands=1' in self.cmd_line['argv']:
                self.test_commands_enabled = True
            elif 'parsed' in self.cmd_line:
                params = self.cmd_line['parsed'].get('setParameter', [])
                if 'enableTestCommands=1' in params:
                    self.test_commands_enabled = True
                else:
                    params = self.cmd_line['parsed'].get('setParameter', {})
                    if params.get('enableTestCommands') == '1':
                        self.test_commands_enabled = True

            self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid')
            self.has_ipv6 = self._server_started_with_ipv6()
            if self.is_mongos:
                # Check for another mongos on the next port.
                address = self.client.address
                next_address = address[0], address[1] + 1
                self.mongoses.append(address)
                mongos_client = self._connect(*next_address,
                                              **self.default_client_options)
                if mongos_client:
                    ismaster = mongos_client.admin.command('ismaster')
                    if ismaster.get('msg') == 'isdbgrid':
                        self.mongoses.append(next_address)
예제 #15
0
 def setup_version(self):
     """Set self.version to the server's version."""
     self.version = Version.from_client(self.sync_cx)
예제 #16
0
    def test_mongodb_x509_auth(self):
        # Expects the server to be running with the server.pem and ca.pem
        # as well as --auth
        #
        #   --sslPEMKeyFile=/path/to/pymongo/test/certificates/server.pem
        #   --sslCAFile=/path/to/pymongo/test/certificates/ca.pem
        #   --auth
        if not CERT_SSL:
            raise SkipTest("No mongod available over SSL with certs")

        if not Version.from_client(ssl_client).at_least(2, 5, 3, -1):
            raise SkipTest("MONGODB-X509 tests require MongoDB 2.5.3 or newer")
        if not server_started_with_auth(ssl_client):
            raise SkipTest('Authentication is not enabled on server')

        self.addCleanup(ssl_client['$external'].logout)
        self.addCleanup(remove_all_users, ssl_client['$external'])
        self.addCleanup(remove_all_users, ssl_client.admin)

        ssl_client.admin.add_user('admin', 'pass')
        ssl_client.admin.authenticate('admin', 'pass')

        # Give admin all necessary privileges.
        ssl_client['$external'].add_user(MONGODB_X509_USERNAME,
                                         roles=[{
                                             'role': 'readWriteAnyDatabase',
                                             'db': 'admin'
                                         }, {
                                             'role': 'userAdminAnyDatabase',
                                             'db': 'admin'
                                         }])

        ssl_client.admin.logout()

        coll = ssl_client.pymongo_test.test
        self.assertRaises(OperationFailure, coll.count)
        self.assertTrue(
            ssl_client.admin.authenticate(MONGODB_X509_USERNAME,
                                          mechanism='MONGODB-X509'))
        coll.drop()
        uri = ('mongodb://%s@%s:%d/?authMechanism='
               'MONGODB-X509' %
               (quote_plus(MONGODB_X509_USERNAME), host, port))
        # SSL options aren't supported in the URI...
        self.assertTrue(MongoClient(uri, ssl=True, ssl_certfile=CLIENT_PEM))

        # Should require a username
        uri = ('mongodb://%s:%d/?authMechanism=MONGODB-X509' % (host, port))
        client_bad = MongoClient(uri,
                                 ssl=True,
                                 ssl_cert_reqs="CERT_NONE",
                                 ssl_certfile=CLIENT_PEM)
        self.assertRaises(OperationFailure,
                          client_bad.pymongo_test.test.delete_one, {})

        # Auth should fail if username and certificate do not match
        uri = ('mongodb://%s@%s:%d/?authMechanism='
               'MONGODB-X509' % (quote_plus("not the username"), host, port))

        bad_client = MongoClient(uri,
                                 ssl=True,
                                 ssl_cert_reqs="CERT_NONE",
                                 ssl_certfile=CLIENT_PEM)
        with self.assertRaises(OperationFailure):
            bad_client.pymongo_test.test.find_one()

        self.assertRaises(OperationFailure,
                          ssl_client.admin.authenticate,
                          "not the username",
                          mechanism="MONGODB-X509")

        # Invalid certificate (using CA certificate as client certificate)
        uri = ('mongodb://%s@%s:%d/?authMechanism='
               'MONGODB-X509' %
               (quote_plus(MONGODB_X509_USERNAME), host, port))
        try:
            connected(
                MongoClient(uri,
                            ssl=True,
                            ssl_cert_reqs="CERT_NONE",
                            ssl_certfile=CA_PEM,
                            serverSelectionTimeoutMS=100))
        except OperationFailure:
            pass
        else:
            self.fail("Invalid certificate accepted.")
예제 #17
0
    def __init__(self):
        """Create a client and grab essential information from the server."""
        # Seed host. This may be updated further down.
        self.host, self.port = host, port
        self.connected = False
        self.ismaster = {}
        self.w = None
        self.nodes = set()
        self.replica_set_name = None
        self.rs_client = None
        self.cmd_line = None
        self.version = Version(-1)  # Needs to be comparable with Version
        self.auth_enabled = False
        self.test_commands_enabled = False
        self.is_mongos = False
        self.is_rs = False
        self.has_ipv6 = False
        self.ssl_cert_none = False
        self.ssl_certfile = False
        self.server_is_resolvable = is_server_resolvable()

        self.client = self.rs_or_standalone_client = None

        def connect(**kwargs):
            try:
                client = pymongo.MongoClient(self.host,
                                             self.port,
                                             serverSelectionTimeoutMS=100,
                                             **kwargs)
                client.admin.command('ismaster')  # Can we connect?
                # If connected, then return client with default timeout
                return pymongo.MongoClient(self.host, self.port, **kwargs)
            except pymongo.errors.ConnectionFailure:
                return None

        self.client = connect()

        if HAVE_SSL and not self.client:
            # Is MongoDB configured for SSL?
            self.client = connect(ssl=True, ssl_cert_reqs=ssl.CERT_NONE)
            if self.client:
                self.ssl_cert_none = True

            # Can client connect with certfile?
            client = connect(
                ssl=True,
                ssl_cert_reqs=ssl.CERT_NONE,
                ssl_certfile=CLIENT_PEM,
            )
            if client:
                self.ssl_certfile = True
                self.client = client

        if self.client:
            self.connected = True
            self.ismaster = self.client.admin.command('ismaster')
            self.w = len(self.ismaster.get("hosts", [])) or 1
            self.nodes = set([(self.host, self.port)])
            self.replica_set_name = self.ismaster.get('setName', '')
            self.rs_client = None
            self.version = Version.from_client(self.client)
            if self.replica_set_name:
                self.is_rs = True
                self.rs_client = pymongo.MongoClient(
                    self.ismaster['primary'], replicaSet=self.replica_set_name)
                # Force connection
                self.rs_client.admin.command('ismaster')
                self.host, self.port = self.rs_client.primary
                self.client = connect()

                nodes = [
                    partition_node(node.lower())
                    for node in self.ismaster.get('hosts', [])
                ]
                nodes.extend([
                    partition_node(node.lower())
                    for node in self.ismaster.get('passives', [])
                ])
                nodes.extend([
                    partition_node(node.lower())
                    for node in self.ismaster.get('arbiters', [])
                ])
                self.nodes = set(nodes)

            self.rs_or_standalone_client = self.rs_client or self.client

            try:
                self.cmd_line = self.client.admin.command('getCmdLineOpts')
            except pymongo.errors.OperationFailure as e:
                msg = e.details.get('errmsg', '')
                if e.code == 13 or 'unauthorized' in msg or 'login' in msg:
                    # Unauthorized.
                    self.auth_enabled = True
                else:
                    raise
            else:
                self.auth_enabled = self._server_started_with_auth()

            if self.auth_enabled:
                # See if db_user already exists.
                self.user_provided = self._check_user_provided()
                if not self.user_provided:
                    roles = {}
                    if self.version.at_least(2, 5, 3, -1):
                        roles = {'roles': ['root']}
                    self.client.admin.add_user(db_user, db_pwd, **roles)
                    self.client.admin.authenticate(db_user, db_pwd)

                if self.rs_client:
                    self.rs_client.admin.authenticate(db_user, db_pwd)

                # May not have this if OperationFailure was raised earlier.
                self.cmd_line = self.client.admin.command('getCmdLineOpts')

            if 'enableTestCommands=1' in self.cmd_line['argv']:
                self.test_commands_enabled = True
            elif 'parsed' in self.cmd_line:
                params = self.cmd_line['parsed'].get('setParameter', [])
                if 'enableTestCommands=1' in params:
                    self.test_commands_enabled = True

            self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid')
            self.has_ipv6 = self._server_started_with_ipv6()

        # Do this after we connect so we know who the primary is.
        self.pair = "%s:%d" % (self.host, self.port)
예제 #18
0
    def _init_client(self):
        self.client = self._connect(host, port)
        if HAVE_SSL and not self.client:
            # Is MongoDB configured for SSL?
            self.client = self._connect(host, port, **_SSL_OPTIONS)
            if self.client:
                self.ssl = True
                self.default_client_options.update(_SSL_OPTIONS)
                self.ssl_certfile = True
                if _SSL_OPTIONS.get('ssl_cert_reqs') == ssl.CERT_NONE:
                    self.ssl_cert_none = True

        if self.client:
            self.connected = True

            try:
                self.cmd_line = self.client.admin.command('getCmdLineOpts')
            except pymongo.errors.OperationFailure as e:
                msg = e.details.get('errmsg', '')
                if e.code == 13 or 'unauthorized' in msg or 'login' in msg:
                    # Unauthorized.
                    self.auth_enabled = True
                else:
                    raise
            else:
                self.auth_enabled = self._server_started_with_auth()

            if self.auth_enabled:
                # See if db_user already exists.
                if not self._check_user_provided():
                    _create_user(self.client.admin, db_user, db_pwd)

                self.client = self._connect(
                    host, port, username=db_user, password=db_pwd,
                    replicaSet=self.replica_set_name,
                    **self.default_client_options)

                # May not have this if OperationFailure was raised earlier.
                self.cmd_line = self.client.admin.command('getCmdLineOpts')

            self.server_status = self.client.admin.command('serverStatus')
            self.ismaster = ismaster = self.client.admin.command('isMaster')
            self.sessions_enabled = 'logicalSessionTimeoutMinutes' in ismaster

            if 'setName' in ismaster:
                self.replica_set_name = str(ismaster['setName'])
                self.is_rs = True
                if self.auth_enabled:
                    # It doesn't matter which member we use as the seed here.
                    self.client = pymongo.MongoClient(
                        host,
                        port,
                        username=db_user,
                        password=db_pwd,
                        replicaSet=self.replica_set_name,
                        **self.default_client_options)
                else:
                    self.client = pymongo.MongoClient(
                        host,
                        port,
                        replicaSet=self.replica_set_name,
                        **self.default_client_options)

                # Get the authoritative ismaster result from the primary.
                self.ismaster = self.client.admin.command('ismaster')
                nodes = [partition_node(node.lower())
                         for node in self.ismaster.get('hosts', [])]
                nodes.extend([partition_node(node.lower())
                              for node in self.ismaster.get('passives', [])])
                nodes.extend([partition_node(node.lower())
                              for node in self.ismaster.get('arbiters', [])])
                self.nodes = set(nodes)
            else:
                self.ismaster = ismaster
                self.nodes = set([(host, port)])
            self.w = len(self.ismaster.get("hosts", [])) or 1
            self.version = Version.from_client(self.client)

            if 'enableTestCommands=1' in self.cmd_line['argv']:
                self.test_commands_enabled = True
            elif 'parsed' in self.cmd_line:
                params = self.cmd_line['parsed'].get('setParameter', [])
                if 'enableTestCommands=1' in params:
                    self.test_commands_enabled = True
                else:
                    params = self.cmd_line['parsed'].get('setParameter', {})
                    if params.get('enableTestCommands') == '1':
                        self.test_commands_enabled = True

            self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid')
            self.has_ipv6 = self._server_started_with_ipv6()
            if self.is_mongos:
                # Check for another mongos on the next port.
                address = self.client.address
                next_address = address[0], address[1] + 1
                self.mongoses.append(address)
                mongos_client = self._connect(*next_address,
                                              **self.default_client_options)
                if mongos_client:
                    ismaster = mongos_client.admin.command('ismaster')
                    if ismaster.get('msg') == 'isdbgrid':
                        self.mongoses.append(next_address)
예제 #19
0
    def __init__(self):
        """Create a client and grab essential information from the server."""
        self.connected = False
        self.ismaster = {}
        self.w = None
        self.nodes = set()
        self.replica_set_name = None
        self.cmd_line = None
        self.version = Version(-1)  # Needs to be comparable with Version
        self.auth_enabled = False
        self.test_commands_enabled = False
        self.is_mongos = False
        self.is_rs = False
        self.has_ipv6 = False
        self.ssl = False
        self.ssl_cert_none = False
        self.ssl_certfile = False
        self.server_is_resolvable = is_server_resolvable()
        self.ssl_client_options = {}
        self.client = _connect(host, port)

        if HAVE_SSL and not self.client:
            # Is MongoDB configured for SSL?
            self.client = _connect(host, port, **_SSL_OPTIONS)
            if self.client:
                self.ssl = True
                self.ssl_client_options = _SSL_OPTIONS
                self.ssl_certfile = True
                if _SSL_OPTIONS.get('ssl_cert_reqs') == ssl.CERT_NONE:
                    self.ssl_cert_none = True

        if self.client:
            self.connected = True
            ismaster = self.client.admin.command('ismaster')
            if 'setName' in ismaster:
                self.replica_set_name = ismaster['setName']
                self.is_rs = True
                # It doesn't matter which member we use as the seed here.
                self.client = pymongo.MongoClient(
                    host,
                    port,
                    replicaSet=self.replica_set_name,
                    **self.ssl_client_options)
                # Get the authoritative ismaster result from the primary.
                self.ismaster = self.client.admin.command('ismaster')
                nodes = [partition_node(node.lower())
                         for node in self.ismaster.get('hosts', [])]
                nodes.extend([partition_node(node.lower())
                              for node in self.ismaster.get('passives', [])])
                nodes.extend([partition_node(node.lower())
                              for node in self.ismaster.get('arbiters', [])])
                self.nodes = set(nodes)
            else:
                self.ismaster = ismaster
                self.nodes = set([(host, port)])
            self.w = len(self.ismaster.get("hosts", [])) or 1
            self.version = Version.from_client(self.client)

            try:
                self.cmd_line = self.client.admin.command('getCmdLineOpts')
            except pymongo.errors.OperationFailure as e:
                msg = e.details.get('errmsg', '')
                if e.code == 13 or 'unauthorized' in msg or 'login' in msg:
                    # Unauthorized.
                    self.auth_enabled = True
                else:
                    raise
            else:
                self.auth_enabled = self._server_started_with_auth()

            if self.auth_enabled:
                # See if db_user already exists.
                self.user_provided = self._check_user_provided()
                if not self.user_provided:
                    roles = {}
                    if self.version.at_least(2, 5, 3, -1):
                        roles = {'roles': ['root']}
                    self.client.admin.add_user(db_user, db_pwd, **roles)
                    self.client.admin.authenticate(db_user, db_pwd)

                # May not have this if OperationFailure was raised earlier.
                self.cmd_line = self.client.admin.command('getCmdLineOpts')

            if 'enableTestCommands=1' in self.cmd_line['argv']:
                self.test_commands_enabled = True
            elif 'parsed' in self.cmd_line:
                params = self.cmd_line['parsed'].get('setParameter', [])
                if 'enableTestCommands=1' in params:
                    self.test_commands_enabled = True
                else:
                    params = self.cmd_line['parsed'].get('setParameter', {})
                    if params.get('enableTestCommands') == '1':
                        self.test_commands_enabled = True

            self.is_mongos = (self.ismaster.get('msg') == 'isdbgrid')
            self.has_ipv6 = self._server_started_with_ipv6()
예제 #20
0
def _all_users(db):
    if Version.from_client(db.client).at_least(2, 5, 3, -1):
        return set(u['user'] for u in db.command('usersInfo').get('users', []))
    else:
        return set(u['user'] for u in db.system.users.find())